From 376b360296290434457a66477453b7e7d5c4b348 Mon Sep 17 00:00:00 2001 From: Andrew Durbin Date: Mon, 30 Dec 2024 17:25:18 -0700 Subject: [PATCH] kubevirt: upgrade k3s,multus,kubevirt,cdi,longhorn A kube container generation number is tracked in cluster-update.sh and compared to an 'applied' version in the persistent node fs /var/lib. When the applied version is behind it triggers component upgrades. cluster-update.sh uses an inline command in the zedkube micro service to publish status updates to zedagent which will trigger info messages (ZInfoKubeClusterUpdateStatus) to a controller. Signed-off-by: Andrew Durbin --- .spdxignore | 1 + pkg/kube/Dockerfile | 7 + pkg/kube/cluster-init.sh | 3 + pkg/kube/cluster-update.sh | 247 ++++++ pkg/kube/update-component/README | 1 + pkg/kube/update-component/cdi.go | 92 +++ .../update-component/expected_versions.yaml | 7 + pkg/kube/update-component/go.mod | 100 +++ pkg/kube/update-component/go.sum | 734 ++++++++++++++++++ pkg/kube/update-component/kubevirt.go | 99 +++ pkg/kube/update-component/longhorn.go | 176 +++++ pkg/kube/update-component/multus.go | 97 +++ .../update-component/settings_longhorn.yaml | 9 + pkg/kube/update-component/upgrades.go | 373 +++++++++ .../cmd/zedagent/handleedgenodecluster.go | 130 ++++ pkg/pillar/cmd/zedagent/nokube.go | 36 + pkg/pillar/cmd/zedagent/reportinfo.go | 2 +- pkg/pillar/cmd/zedagent/zedagent.go | 55 ++ pkg/pillar/cmd/zedkube/zedkube.go | 93 +++ pkg/pillar/kubeapi/infotypes.go | 115 +++ pkg/pillar/zedbox/zedbox.go | 2 +- 21 files changed, 2377 insertions(+), 2 deletions(-) create mode 100644 pkg/kube/update-component/README create mode 100644 pkg/kube/update-component/cdi.go create mode 100644 pkg/kube/update-component/expected_versions.yaml create mode 100644 pkg/kube/update-component/go.mod create mode 100644 pkg/kube/update-component/go.sum create mode 100644 pkg/kube/update-component/kubevirt.go create mode 100644 pkg/kube/update-component/longhorn.go create mode 100644 pkg/kube/update-component/multus.go create mode 100644 pkg/kube/update-component/settings_longhorn.yaml create mode 100644 pkg/kube/update-component/upgrades.go create mode 100644 pkg/pillar/cmd/zedagent/handleedgenodecluster.go create mode 100644 pkg/pillar/cmd/zedagent/nokube.go create mode 100644 pkg/pillar/kubeapi/infotypes.go diff --git a/.spdxignore b/.spdxignore index 5f0bd8391b..0704facf9e 100644 --- a/.spdxignore +++ b/.spdxignore @@ -16,3 +16,4 @@ pkg/kube/descheduler_rbac.yaml pkg/kube/lh-cfg-v1.6.2.yaml pkg/vtpm/swtpm-vtpm/vendor/ pkg/dom0-ztools/rootfs/usr/bin/rungetty.sh +pkg/kube/update-component/vendor/ diff --git a/pkg/kube/Dockerfile b/pkg/kube/Dockerfile index 9e816f7319..5695fe6f74 100644 --- a/pkg/kube/Dockerfile +++ b/pkg/kube/Dockerfile @@ -20,13 +20,20 @@ COPY cert-gen /plugins/cert-gen WORKDIR /plugins/cert-gen RUN GO111MODULE=on CGO_ENABLED=0 go build -v -ldflags "-s -w" -o /out/usr/bin/cert-gen . +COPY update-component /plugins/update-component +WORKDIR /plugins/update-component +RUN GO111MODULE=on go build -v -ldflags "-s -w" -mod=vendor -o /out/usr/bin/update-component . + FROM scratch COPY --from=build /out/ / COPY cluster-init.sh /usr/bin/ COPY cluster-utils.sh /usr/bin/ COPY cgconfig.conf /etc +# upgrades COPY cluster-update.sh /usr/bin/ +COPY update-component/expected_versions.yaml /etc/ +COPY update-component/settings_longhorn.yaml /etc/ # k3s COPY install-etcdctl.sh /usr/bin/ diff --git a/pkg/kube/cluster-init.sh b/pkg/kube/cluster-init.sh index 443bf5bcad..7695723cd0 100755 --- a/pkg/kube/cluster-init.sh +++ b/pkg/kube/cluster-init.sh @@ -613,6 +613,8 @@ logmsg "Using ZFS persistent storage" setup_prereqs +Update_CheckNodeComponents + if [ -f /var/lib/convert-to-single-node ]; then logmsg "remove /var/lib and copy saved single node /var/lib" @@ -862,6 +864,7 @@ fi check_kubeconfig_yaml_files check_and_remove_excessive_k3s_logs check_and_run_vnc + Update_CheckClusterComponents wait_for_item "wait" sleep 15 done diff --git a/pkg/kube/cluster-update.sh b/pkg/kube/cluster-update.sh index dd75967a3a..e6bdab7a40 100644 --- a/pkg/kube/cluster-update.sh +++ b/pkg/kube/cluster-update.sh @@ -2,7 +2,254 @@ # # Copyright (c) 2024 Zededa, Inc. # SPDX-License-Identifier: Apache-2.0 +K3S_VERSION=v1.28.5+k3s1 +EdgeNodeInfoPath="/persist/status/zedagent/EdgeNodeInfo/global.json" + +# +# Handle any migrations needed due to updated cluster-init.sh +# This is expected to be bumped any time: +# - a migration is needed (new path for something) +# - a version bump of: K3s, multus, kubevirt, cdi, longhorn +# +KUBE_VERSION=1 +APPLIED_KUBE_VERSION_PATH="/var/lib/applied-kube-version" +update_Version_Set() { + version=$1 + echo "$version" > "$APPLIED_KUBE_VERSION_PATH" +} + +update_Version_Get() { + if [ ! -f "$APPLIED_KUBE_VERSION_PATH" ]; then + # First Boot + echo "0" + fi + cat "$APPLIED_KUBE_VERSION_PATH" +} + +# +# update_Failed() +# Mark failure if Status == COMP_STATUS_FAILED and DestinationKubeUpdateVersion == KUBE_VERSION +# This allows: +# - update retry control for a given version +# - recovery update if the eve os version is updated to another release (with a different cluster-init.sh) +# +UPDATE_STATUS_PATH=/persist/status/zedkube/KubeClusterUpdateStatus/global.json +update_Failed() { + if [ -f $UPDATE_STATUS_PATH ]; then + if [ "$(jq --arg gen $KUBE_VERSION '.Status==4 and .DestinationKubeUpdateVersion==$gen' < $UPDATE_STATUS_PATH)" = "true" ]; then + return 0 + fi + fi + return 1 +} + +trigger_k3s_selfextraction() { + # Run some k3s cli command so that binaries are self-extracted + /usr/bin/k3s check-config >> "$INSTALL_LOG" 2>&1 +} link_multus_into_k3s() { ln -s /var/lib/cni/bin/multus /var/lib/rancher/k3s/data/current/bin/multus } + +update_k3s() { + logmsg "Installing K3S version $K3S_VERSION on $HOSTNAME" + mkdir -p /var/lib/k3s/bin + /usr/bin/curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=${K3S_VERSION} INSTALL_K3S_SKIP_ENABLE=true INSTALL_K3S_SKIP_START=true INSTALL_K3S_BIN_DIR=/var/lib/k3s/bin sh - + sleep 5 + logmsg "Initializing K3S version $K3S_VERSION" + ln -s /var/lib/k3s/bin/* /usr/bin + trigger_k3s_selfextraction + link_multus_into_k3s + touch /var/lib/k3s_installed_unpacked +} + +# k3s_get_version: return version in form "vW.X.Y+k3sZ" +k3s_get_version() { + if [ ! -f /var/lib/k3s/bin/k3s ]; then + echo "v0.0.0+k3s0" + return + fi + /var/lib/k3s/bin/k3s --version | awk '$1=="k3s" {print $3}' | tr -d '\n' +} + +# Run on every boot before k3s starts +Update_CheckNodeComponents() { + applied_version=$(update_Version_Get) + if [ "$KUBE_VERSION" = "$applied_version" ]; then + return + fi + + if update_Failed; then + return + fi + logmsg "update_HandleNode: version:$KUBE_VERSION appliedversion:$applied_version continuing" + + # Handle version specific node migrations here + + # Handle node specific updates, just k3s for now + if [ "$(k3s_get_version)" != "$K3S_VERSION" ]; then + publishUpdateStatus "k3s" "download" + update_k3s + current_k3s_version=$(k3s_get_version) + if [ "$current_k3s_version" != "$K3S_VERSION" ]; then + logmsg "k3s version mismatch after install:$current_k3s_version" + publishUpdateStatus "k3s" "failed" "version mismatch after install:$current_k3s_version" + else + logmsg "k3s installed and unpacked or copied" + publishUpdateStatus "k3s" "completed" + fi + fi +} + +# Run on every boot after k3s is started +Update_CheckClusterComponents() { + wait_for_item "update_cluster_pre" + + applied_version=$(update_Version_Get) + if [ "$KUBE_VERSION" = "$applied_version" ]; then + return + fi + + if update_Failed; then + return + fi + + if ! update_isClusterReady; then + return + fi + logmsg "update_HandleCluster: version:$KUBE_VERSION appliedversion:$applied_version continuing" + + # Handle cluster wide component updates + for comp in multus kubevirt cdi longhorn; do + while ! update_Component_CheckReady "$comp"; do + logmsg "Component: $comp not ready on existing version" + sleep 60 + done + logmsg "Component: $comp ready on existing version" + if update_Component_IsRunningExpectedVersion "$comp"; then + logmsg "Component:$comp running expected version, continuing" + publishUpdateStatus "$comp" "completed" + continue + fi + if ! update_Component "$comp"; then + logmsg "Not continuing with further updates after component:${comp} update failed" + break + fi + done + + update_Version_Set "$KUBE_VERSION" + wait_for_item "update_cluster_post" +} + +Update_RunDescheduler() { + # Don't run unless it has been installed + if [ ! -f /var/lib/descheduler_initialized ]; then + return + fi + # Only run once per boot + if [ -f /tmp/descheduler-ran ]; then + return + fi + + if [ ! -f $EdgeNodeInfoPath ]; then + return + fi + # is api ready + if ! update_isClusterReady; then + return + fi + # node ready and allowing scheduling + node=$(jq -r '.DeviceName' < $EdgeNodeInfoPath | tr -d '\n' | tr '[:upper:]' '[:lower:]') + node_count_ready=$(kubectl get "node/${node}" | grep -v SchedulingDisabled | grep -cw Ready ) + if [ "$node_count_ready" -ne 1 ]; then + return + fi + # Job lives persistently in cluster, cleanup after old runs + if kubectl -n kube-system get job/descheduler-job; then + kubectl -n kube-system delete job/descheduler-job + fi + kubectl apply -f /etc/descheduler-job.yaml + touch /tmp/descheduler-ran +} + +update_isClusterReady() { + if ! kubectl cluster-info; then + return 1 + fi + + if ! update_Helper_APIResponding; then + return 1 + fi + return 0 +} + +# +# Handle kube component updates +# +COMP_UPDATE_PATH="/usr/bin/update-component" + +update_Helper_APIResponding() { + if $COMP_UPDATE_PATH --check-api-ready; then + return 0 + fi + return 1 +} +update_Component_CheckReady() { + comp=$1 + if $COMP_UPDATE_PATH --versions-file /etc/expected_versions.yaml --component "$comp" --check-comp-ready; then + return 0 + fi + return 1 +} +update_Component_Uptime() { + comp=$1 + $COMP_UPDATE_PATH --versions-file /etc/expected_versions.yaml --component "$comp" --get-uptime +} +update_Component_IsRunningExpectedVersion() { + comp=$1 + if $COMP_UPDATE_PATH --versions-file /etc/expected_versions.yaml --component "$comp" --compare; then + return 0 + fi + return 1 +} + +update_Component() { + comp=$1 + # Run go app to check and apply updates and block until new version is ready + publishUpdateStatus "$comp" "in_progress" + if $COMP_UPDATE_PATH --versions-file /etc/expected_versions.yaml --component "$comp" --upgrade; then + publishUpdateStatus "$comp" "completed" + return 0 + fi + upgrade_log_path="/persist/kubelog/upgrade-component.log" + logmsg "update_Component comp:${comp} error starting update, see $upgrade_log_path" + publishUpdateStatus "$comp" "failed" "error in $upgrade_log_path" + return 1 +} + +publishUpdateStatus() { + component=$1 + status=$2 + errorstr="" + if [ ! -x $3 ]; then + errorstr=$3 + fi + + # If gen==0, then we are in the initial boot not updating, just installing first versions at most-likely first + # boot of the device. Don't publish as this will trigger zedagent to claim baseos_updating. + cur_version=$(update_Version_Get) + if [ "$cur_version" = "0" ]; then + return + fi + + node=$(jq -r '.DeviceName' < /persist/status/zedagent/EdgeNodeInfo/global.json | tr -d '\n') + logmsg "publishUpdateStatus() $node $component $status" + + pillarRootfs=/hostfs/containers/services/pillar/rootfs + LD_LIBRARY_PATH=${pillarRootfs}/usr/lib/ ${pillarRootfs}/opt/zededa/bin/zedkube pubKubeClusterUpdateStatus "$node" "$component" "$status" "$KUBE_VERSION" "$errorstr" + rc=$? + if [ $rc -ne 0 ]; then + logmsg "publishUpdateStatus() $node $component $status in error:$rc" + fi +} diff --git a/pkg/kube/update-component/README b/pkg/kube/update-component/README new file mode 100644 index 0000000000..37dd7c453a --- /dev/null +++ b/pkg/kube/update-component/README @@ -0,0 +1 @@ +./upgrades -c -d -n kube3 -l kubevirt,cdi,longhorn -f upgrades.yaml -u diff --git a/pkg/kube/update-component/cdi.go b/pkg/kube/update-component/cdi.go new file mode 100644 index 0000000000..6c70841d2c --- /dev/null +++ b/pkg/kube/update-component/cdi.go @@ -0,0 +1,92 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/Masterminds/semver" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + cdiNamespace = "cdi" + compCdiDeploymentOperator = "cdi-operator" +) + +type cdiComponent struct { + commonComponent +} + +func (ctx *cdiComponent) GetVersion() (string, error) { + cs := ctx.cs + cdiDeployment, err := cs.AppsV1().Deployments(cdiNamespace).Get(context.Background(), compCdiDeploymentOperator, metav1.GetOptions{}) + if cdiDeployment == nil || err != nil { + return "", fmt.Errorf("failed to get cdi deployment/%s: %v", compCdiDeploymentOperator, err) + } + env := cdiDeployment.Spec.Template.Spec.Containers[0].Env + for _, e := range env { + if e.Name == "OPERATOR_VERSION" { + return e.Value, nil + } + } + return "", nil +} + +func (ctx *cdiComponent) UpgradeSupported(sourceVer string, destVer string) error { + destV, err := semver.NewVersion(destVer) + if err != nil { + return err + } + c, err := semver.NewConstraint(">=" + sourceVer) + if err != nil { + return err + } + if !c.Check(destV) { + return fmt.Errorf("version constraints deny %s->%s", sourceVer, destVer) + } + return nil +} + +func (ctx *cdiComponent) Uptime(version string) (time.Time, error) { + cs := ctx.cs + cdiDeployment, err := cs.AppsV1().Deployments(cdiNamespace).Get(context.Background(), compCdiDeploymentOperator, metav1.GetOptions{}) + if cdiDeployment == nil || err != nil { + return time.Time{}, fmt.Errorf("failed to get cdi deployment/%s: %v", compCdiDeploymentOperator, err) + } + for _, condition := range cdiDeployment.Status.Conditions { + if condition.Reason == "MinimumReplicasAvailable" && condition.Status == v1.ConditionTrue { + return condition.LastTransitionTime.Time, nil + } + } + return time.Time{}, fmt.Errorf("failed to get uptime for cdi deployment/%s", compCdiDeploymentOperator) +} + +func (ctx *cdiComponent) Ready(version string) error { + cs := ctx.cs + cdiDeployment, err := cs.AppsV1().Deployments(cdiNamespace).Get(context.Background(), compCdiDeploymentOperator, metav1.GetOptions{}) + if cdiDeployment == nil || err != nil { + return fmt.Errorf("failed to get deployment/%s: %v", compCdiDeploymentOperator, err) + } + for _, cdiContainer := range cdiDeployment.Spec.Template.Spec.Containers { + imageTagParts := strings.Split(cdiContainer.Image, ":") + imageVersion := imageTagParts[len(imageTagParts)-1] + if version != imageVersion { + return fmt.Errorf("CDI not yet online at version: %s", version) + } + } + if cdiDeployment.Status.ReadyReplicas != cdiDeployment.Status.Replicas { + return fmt.Errorf("insufficient cdi readiness for deployment: %s", compCdiDeploymentOperator) + } + return nil +} + +func (ctx *cdiComponent) UpgradeStart(version string) error { + yamlPath := "https://github.com/kubevirt/containerized-data-importer/releases/download/" + version + "/cdi-operator.yaml" + return ctx.KubectlApply(yamlPath) +} diff --git a/pkg/kube/update-component/expected_versions.yaml b/pkg/kube/update-component/expected_versions.yaml new file mode 100644 index 0000000000..3c002cb51f --- /dev/null +++ b/pkg/kube/update-component/expected_versions.yaml @@ -0,0 +1,7 @@ +# Copyright (c) 2025 Zededa, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +multus: "v3.9.3" +kubevirt: "v1.1.0-dirty" +cdi: "v1.57.1" +longhorn: "v1.6.3" diff --git a/pkg/kube/update-component/go.mod b/pkg/kube/update-component/go.mod new file mode 100644 index 0000000000..9014523404 --- /dev/null +++ b/pkg/kube/update-component/go.mod @@ -0,0 +1,100 @@ +module upgrades + +go 1.22 + +require ( + github.com/Masterminds/semver v1.5.0 + github.com/longhorn/longhorn-manager v1.6.1 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 + gopkg.in/yaml.v2 v2.4.0 + k8s.io/api v0.29.3 + k8s.io/apimachinery v0.29.3 + k8s.io/client-go v12.0.0+incompatible + kubevirt.io/client-go v1.2.0 +) + +replace ( + k8s.io/api => k8s.io/api v0.26.3 + k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.26.3 + k8s.io/apimachinery => k8s.io/apimachinery v0.26.3 + k8s.io/apiserver => k8s.io/apiserver v0.26.3 + k8s.io/cli-runtime => k8s.io/cli-runtime v0.26.3 + k8s.io/client-go => k8s.io/client-go v0.26.3 + k8s.io/cloud-provider => k8s.io/cloud-provider v0.26.3 + k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.26.3 + k8s.io/code-generator => k8s.io/code-generator v0.26.3 + k8s.io/component-base => k8s.io/component-base v0.26.3 + k8s.io/cri-api => k8s.io/cri-api v0.26.3 + k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.26.3 + k8s.io/klog => k8s.io/klog v0.4.0 + k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.26.3 + k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.26.3 + k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 + k8s.io/kube-proxy => k8s.io/kube-proxy v0.26.3 + k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.26.3 + k8s.io/kubectl => k8s.io/kubectl v0.26.3 + k8s.io/kubelet => k8s.io/kubelet v0.26.3 + k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.26.3 + k8s.io/metrics => k8s.io/metrics v0.26.3 + k8s.io/node-api => k8s.io/node-api v0.26.3 + k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.26.3 + k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.26.3 + k8s.io/sample-controller => k8s.io/sample-controller v0.26.3 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/go-kit/kit v0.13.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/glog v1.1.0 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/jinzhu/copier v0.3.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20191119172530-79f836b90111 // indirect + github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 // indirect + github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 // indirect + github.com/openshift/custom-resource-status v1.1.2 // indirect + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.68.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.3.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.28.1 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f // indirect + k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect + kubevirt.io/api v0.0.0-20240305214914-ae817ad5212e // indirect + kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 // indirect + kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 // indirect + sigs.k8s.io/controller-runtime v0.16.1 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect +) diff --git a/pkg/kube/update-component/go.sum b/pkg/kube/update-component/go.sum new file mode 100644 index 0000000000..77207493ae --- /dev/null +++ b/pkg/kube/update-component/go.sum @@ -0,0 +1,734 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v2.10.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= +github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ= +github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.0.0-20171009183408-7fe0c75c13ab/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20191119172530-79f836b90111 h1:Lq6HJa0JqSg5ko/mkizFWlpIrY7845g9Dzz9qeD5aXI= +github.com/k8snetworkplumbingwg/network-attachment-definition-client v0.0.0-20191119172530-79f836b90111/go.mod h1:MP2HbArq3QT+oVp8pmtHNZnSnkhdkHtDnc7h6nJXmBU= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0 h1:nHHjmvjitIiyPlUHk/ofpgvBcNcawJLtf4PYHORLjAA= +github.com/kubernetes-csi/external-snapshotter/client/v4 v4.2.0/go.mod h1:YBCo4DoEeDndqvAn6eeu0vWM7QdXmHEeI9cFWplmBys= +github.com/longhorn/longhorn-manager v1.6.1 h1:gS+rCWp9XxGcE3ldXE6s1Eqfm0v8/wt4RnvKdmg4IBU= +github.com/longhorn/longhorn-manager v1.6.1/go.mod h1:7YhiMQaVwOcAJ3KNBs6BuC+XN9IIBEDNsuiy87rfNIk= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/openshift/api v0.0.0-20210105115604-44119421ec6b/go.mod h1:aqU5Cq+kqKKPbDMqxo9FojgDeSpNJI7iuskjXjtojDg= +github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183 h1:t/CahSnpqY46sQR01SoS+Jt0jtjgmhgE6lFmRnO4q70= +github.com/openshift/api v0.0.0-20230503133300-8bbcb7ca7183/go.mod h1:4VWG+W22wrB4HfBL88P40DxLEpSOaiBVxUnfalfJo9k= +github.com/openshift/build-machinery-go v0.0.0-20200917070002-f171684f77ab/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= +github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47 h1:+TEY29DK0XhqB7HFC9OfV8qf3wffSyi7MWv3AP28DGQ= +github.com/openshift/client-go v0.0.0-20210112165513-ebc401615f47/go.mod h1:u7NRAjtYVAKokiI9LouzTv4mhds8P4S1TwdVAfbjKSk= +github.com/openshift/custom-resource-status v1.1.2 h1:C3DL44LEbvlbItfd8mT5jWrqPfHnSOQoQf/sypqA6A4= +github.com/openshift/custom-resource-status v1.1.2/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.68.0 h1:yl9ceUSUBo9woQIO+8eoWpcxZkdZgm89g+rVvu37TUw= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.68.0/go.mod h1:9Uuu3pEU2jB8PwuqkHvegQ0HV/BlZRJUyfTYAqfdVF8= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= +k8s.io/api v0.26.3/go.mod h1:PXsqwPMXBSBcL1lJ9CYDKy7kIReUydukS5JiRlxC3qE= +k8s.io/apiextensions-apiserver v0.26.3 h1:5PGMm3oEzdB1W/FTMgGIDmm100vn7IaUP5er36dB+YE= +k8s.io/apiextensions-apiserver v0.26.3/go.mod h1:jdA5MdjNWGP+njw1EKMZc64xAT5fIhN6VJrElV3sfpQ= +k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= +k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= +k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= +k8s.io/code-generator v0.26.3/go.mod h1:ryaiIKwfxEJEaywEzx3dhWOydpVctKYbqLajJf0O8dI= +k8s.io/gengo v0.0.0-20190907103519-ebc107f98eab/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +kubevirt.io/api v0.0.0-20240305214914-ae817ad5212e h1:BHZ4F6sHJBpyhPICTXkcbFNYOe6m0sNuiBosnCT98AY= +kubevirt.io/api v0.0.0-20240305214914-ae817ad5212e/go.mod h1:SbeR9ma4EwnaOZEUkh/lNz0kzYm5LPpEDE30vKXC5Zg= +kubevirt.io/client-go v1.2.0 h1:KniuG2wse98++ecRCWTZEl0wLZAQiRn+HdvzlpyekgA= +kubevirt.io/client-go v1.2.0/go.mod h1:ib4Ewy6u/+4J7w79mz0rxaJjsAbPvzJjYWQqGsrN7pM= +kubevirt.io/containerized-data-importer-api v1.57.0-alpha1 h1:IWo12+ei3jltSN5jQN1xjgakfvRSF3G3Rr4GXVOOy2I= +kubevirt.io/containerized-data-importer-api v1.57.0-alpha1/go.mod h1:Y/8ETgHS1GjO89bl682DPtQOYEU/1ctPFBz6Sjxm4DM= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90 h1:QMrd0nKP0BGbnxTqakhDZAUhGKxPiPiN5gSDqKUmGGc= +kubevirt.io/controller-lifecycle-operator-sdk/api v0.0.0-20220329064328-f3cc58c6ed90/go.mod h1:018lASpFYBsYN6XwmA2TIrPCx6e0gviTd/ZNtSitKgc= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/controller-runtime v0.16.1 h1:+15lzrmHsE0s2kNl0Dl8cTchI5Cs8qofo5PGcPrV9z0= +sigs.k8s.io/controller-runtime v0.16.1/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/pkg/kube/update-component/kubevirt.go b/pkg/kube/update-component/kubevirt.go new file mode 100644 index 0000000000..508ea3b4b1 --- /dev/null +++ b/pkg/kube/update-component/kubevirt.go @@ -0,0 +1,99 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "fmt" + "time" + + "github.com/Masterminds/semver" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "kubevirt.io/client-go/kubecli" +) + +const ( + kubevirtNamespace = "kubevirt" + compKubevirtDeploymentOperator = "virt-operator" + compKubevirtDeploymentController = "virt-controller" +) + +type kubevirtComponent struct { + commonComponent +} + +func (ctx *kubevirtComponent) GetVersion() (string, error) { + kubeConfig, err := GetKubeConfig() + if err != nil { + return "", fmt.Errorf("can't get kubeconfig %v", err) + } + kvClient, err := kubecli.GetKubevirtClientFromRESTConfig(kubeConfig) + if err != nil { + return "", fmt.Errorf("can't get kubevirt client %v", err) + } + kubeVirt, err := kvClient.KubeVirt(kubevirtNamespace).Get("kubevirt", &metav1.GetOptions{}) + if err != nil { + return "", fmt.Errorf("can't fetch kubevirt version %v", err) + } + return kubeVirt.Status.OperatorVersion, nil +} + +func (ctx *kubevirtComponent) UpgradeSupported(sourceVer string, destVer string) error { + destV, err := semver.NewVersion(destVer) + if err != nil { + return err + } + c, err := semver.NewConstraint(">=" + sourceVer) + if err != nil { + return err + } + if !c.Check(destV) { + return fmt.Errorf("version constraints deny %s->%s", sourceVer, destVer) + } + return nil +} + +func (ctx *kubevirtComponent) Uptime(version string) (time.Time, error) { + cs := ctx.cs + lowestRdyTime := time.Time{} + selector := "kubevirt.io=" + compKubevirtDeploymentController + pods, err := cs.CoreV1().Pods(kubevirtNamespace).List(context.Background(), metav1.ListOptions{ + LabelSelector: selector, + }) + if pods == nil || err != nil { + return lowestRdyTime, fmt.Errorf("failed to get pods by selector %s: %v", selector, err) + } + + for _, pod := range pods.Items { + for _, condition := range pod.Status.Conditions { + if condition.Type == "Ready" && condition.Status == "True" { + if condition.LastTransitionTime.Time.After(lowestRdyTime) { + lowestRdyTime = condition.LastTransitionTime.Time + } + } + } + } + if time.Time.IsZero(lowestRdyTime) { + return lowestRdyTime, fmt.Errorf("failed to get uptime for kubevirt deployment/%s", compKubevirtDeploymentController) + } + + return lowestRdyTime, nil +} + +func (ctx *kubevirtComponent) Ready(version string) error { + cs := ctx.cs + kvDeployment, err := cs.AppsV1().Deployments(kubevirtNamespace).Get(context.Background(), compKubevirtDeploymentController, metav1.GetOptions{}) + if kvDeployment == nil || err != nil { + return fmt.Errorf("failed to list kubevirt deployment for version %s: %v", version, err) + } + if kvDeployment.Status.ReadyReplicas != kvDeployment.Status.Replicas { + return fmt.Errorf("insufficient kubevirt readiness for deployment: %s", compKubevirtDeploymentController) + } + return nil +} + +func (ctx *kubevirtComponent) UpgradeStart(version string) error { + yamlPath := "https://github.com/kubevirt/kubevirt/releases/download/" + version + "/kubevirt-operator.yaml" + return ctx.KubectlApply(yamlPath) +} diff --git a/pkg/kube/update-component/longhorn.go b/pkg/kube/update-component/longhorn.go new file mode 100644 index 0000000000..5d9f30047a --- /dev/null +++ b/pkg/kube/update-component/longhorn.go @@ -0,0 +1,176 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "fmt" + "log" + "os" + "strings" + "time" + + "github.com/Masterminds/semver" + "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" + "github.com/longhorn/longhorn-manager/k8s/pkg/client/clientset/versioned" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + longhornNamespace = "longhorn-system" + compLonghornDeployment = "longhorn-driver-deployer" + longhornSettingsYamlPath = "/etc/settings_longhorn.yaml" +) + +type longhornComponent struct { + commonComponent +} + +func (ctx *longhornComponent) GetVersion() (string, error) { + cs := ctx.cs + lhDriverDeployer, err := cs.AppsV1().Deployments(longhornNamespace).Get(context.Background(), compLonghornDeployment, metav1.GetOptions{}) + if lhDriverDeployer == nil || err != nil { + return "", fmt.Errorf("failed to list longhorn deployment/%s: %v", compLonghornDeployment, err) + } + lhImage := lhDriverDeployer.Spec.Template.Spec.Containers[0].Image + imageParts := strings.Split(lhImage, ":") + if len(imageParts) < 2 { + return "", fmt.Errorf("failed to parse longhorn image: %v", lhImage) + } + return imageParts[1], nil +} +func (ctx *longhornComponent) UpgradeSupported(sourceVer string, destVer string) error { + destV, err := semver.NewVersion(destVer) + if err != nil { + return err + } + c, err := semver.NewConstraint(">=" + sourceVer) + if err != nil { + return err + } + if !c.Check(destV) { + return fmt.Errorf("version constraints deny %s->%s", sourceVer, destVer) + } + return nil +} +func (ctx *longhornComponent) Uptime(version string) (time.Time, error) { + // Return lowest ready condition time of all nodes found + lowestRdyTime := time.Time{} + + config, err := GetKubeConfig() + if err != nil { + return lowestRdyTime, err + } + lhClient, err := versioned.NewForConfig(config) + if err != nil { + return lowestRdyTime, err + } + lhNodes, err := lhClient.LonghornV1beta2().Nodes(longhornNamespace).List(context.Background(), metav1.ListOptions{}) + if lhNodes == nil || err != nil { + return lowestRdyTime, fmt.Errorf("failed to list longhorn nodes: %v", err) + } + + for _, node := range lhNodes.Items { + for _, condition := range node.Status.Conditions { + if condition.Type == "Ready" && condition.Status == v1beta2.ConditionStatusTrue { + lhNodeRdyTime, err := time.Parse(time.RFC3339, condition.LastTransitionTime) + if err != nil { + log.Printf("longhorn node timestamp:%s parse err:%v", condition.LastTransitionTime, err) + continue + } + if lhNodeRdyTime.Compare(lowestRdyTime) == 1 { + lowestRdyTime = lhNodeRdyTime + } + } + } + } + if time.Time.IsZero(lowestRdyTime) { + return lowestRdyTime, fmt.Errorf("failed to get uptime for longhorn nodes") + } + return lowestRdyTime, nil +} +func (ctx *longhornComponent) Ready(version string) error { + cs := ctx.cs + + // + // 1. Check for longhorn-manager daemonset at correct version + // + lhMgrDs, err := cs.AppsV1().DaemonSets(longhornNamespace).Get(context.Background(), "longhorn-manager", metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to get longhorn-manager daemonsets: %v", err) + } + if lhMgrDs.Status.NumberReady != lhMgrDs.Status.DesiredNumberScheduled { + return fmt.Errorf("longhorn-manager daemonset is not ready") + } + if lhMgrDs.Spec.Template.GetLabels()["app.kubernetes.io/version"] != version { + return fmt.Errorf("longhorn-manager daemonset version mismatch, running:%s", lhMgrDs.Spec.Template.GetLabels()["app.kubernetes.io/version"]) + } + + // + // 2. Check for all three longhorn daemonsets ready + // + lhDaemonsets, err := cs.AppsV1().DaemonSets(longhornNamespace). + List(context.Background(), metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("failed to list longhorn daemonsets: %v", err) + } + if len(lhDaemonsets.Items) != 3 { + return fmt.Errorf("expected 3 longhorn daemonsets, got %d", len(lhDaemonsets.Items)) + } + for _, lhDaemonset := range lhDaemonsets.Items { + if lhDaemonset.Status.NumberReady != lhDaemonset.Status.DesiredNumberScheduled { + return fmt.Errorf("longhorn daemonset %s is not ready", lhDaemonset.Name) + } + } + + // + // 3. check if all longhorn volumes are using new engine image + // + config, err := GetKubeConfig() + if err != nil { + return err + } + lhClient, err := versioned.NewForConfig(config) + if err != nil { + return err + } + lhVols, err := lhClient.LonghornV1beta2().Volumes(longhornNamespace).List(context.Background(), metav1.ListOptions{}) + if lhVols == nil || err != nil { + return fmt.Errorf("failed to list longhorn volumes: %v", err) + } + for _, lhVol := range lhVols.Items { + if !strings.HasSuffix(lhVol.Spec.Image, version) { + return fmt.Errorf("longhorn volume %s still on engine:%s", lhVol.Name, lhVol.Spec.Image) + } + } + + return nil +} + +func getLonghornDefaultEngineImage() (string, error) { + config, err := GetKubeConfig() + if err != nil { + return "", err + } + lhClient, err := versioned.NewForConfig(config) + if err != nil { + return "", err + } + lhSetting, err := lhClient.LonghornV1beta2().Settings(longhornNamespace).Get(context.Background(), "default-engine-image", metav1.GetOptions{}) + if err != nil { + return "", fmt.Errorf("failed to get longhorn settings: %v", err) + } + return lhSetting.Value, nil +} + +func (ctx *longhornComponent) UpgradeStart(version string) error { + if _, err := os.Stat(longhornSettingsYamlPath); err == nil { + err := ctx.KubectlApply(longhornSettingsYamlPath) + if err != nil { + return fmt.Errorf("unable to apply longhorn pre-upgrade settings: %v", err) + } + } + yamlPath := "https://raw.githubusercontent.com/longhorn/longhorn/" + version + "/deploy/longhorn.yaml" + return ctx.KubectlApply(yamlPath) +} diff --git a/pkg/kube/update-component/multus.go b/pkg/kube/update-component/multus.go new file mode 100644 index 0000000000..860a6ca04d --- /dev/null +++ b/pkg/kube/update-component/multus.go @@ -0,0 +1,97 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/Masterminds/semver" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + multusNamespace = "kube-system" + compMultusDaemonset = "kube-multus-ds-amd64" +) + +type multusComponent struct { + commonComponent +} + +func (ctx *multusComponent) GetVersion() (string, error) { + cs := ctx.cs + multusDaemonset, err := cs.AppsV1().DaemonSets(multusNamespace).Get(context.Background(), compMultusDaemonset, metav1.GetOptions{}) + if multusDaemonset == nil || err != nil { + return "", fmt.Errorf("failed to get daemonset/%s: %v", compMultusDaemonset, err) + } + image := multusDaemonset.Spec.Template.Spec.Containers[0].Image + imageParts := strings.Split(image, ":") + if len(imageParts) < 2 { + return "", fmt.Errorf("failed to parse multus image: %v", image) + } + return imageParts[1], nil +} + +func (ctx *multusComponent) UpgradeSupported(sourceVer string, destVer string) error { + destV, err := semver.NewVersion(destVer) + if err != nil { + return err + } + c, err := semver.NewConstraint(">=" + sourceVer) + if err != nil { + return err + } + if !c.Check(destV) { + return fmt.Errorf("version constraints deny %s->%s", sourceVer, destVer) + } + return nil +} + +func (ctx *multusComponent) Uptime(version string) (time.Time, error) { + cs := ctx.cs + lowestRdyTime := time.Time{} + pods, err := cs.CoreV1().Pods(multusNamespace).List(context.Background(), metav1.ListOptions{ + LabelSelector: "app=multus", + }) + if pods == nil || err != nil { + return lowestRdyTime, fmt.Errorf("failed to get pods by selector %s: %v", "app=multus", err) + } + + for _, pod := range pods.Items { + for _, condition := range pod.Status.Conditions { + if condition.Type == "Ready" && condition.Status == "True" { + if condition.LastTransitionTime.Time.After(lowestRdyTime) { + lowestRdyTime = condition.LastTransitionTime.Time + } + } + } + } + if time.Time.IsZero(lowestRdyTime) { + return lowestRdyTime, fmt.Errorf("failed to get uptime for app=multus pods") + } + return lowestRdyTime, nil +} + +func (ctx *multusComponent) Ready(version string) error { + cs := ctx.cs + multusDaemonset, err := cs.AppsV1().DaemonSets(multusNamespace).Get(context.Background(), compMultusDaemonset, metav1.GetOptions{}) + if multusDaemonset == nil || err != nil { + return fmt.Errorf("failed to get daemonset/%s: %v", compMultusDaemonset, err) + } + if multusDaemonset.Status.NumberReady != multusDaemonset.Status.DesiredNumberScheduled { + return fmt.Errorf("insufficient multus readiness for daemonset %s", compMultusDaemonset) + } + return nil +} + +func (ctx *multusComponent) UpgradeStart(version string) error { + // Lookup table for custom multus yaml from version string to absolute file path in kube service container + var multusInstallYamlTable = map[string]string{ + "v3.9.3": " /etc/multus-daemonset-new.yaml", + } + return ctx.KubectlApply(multusInstallYamlTable[version]) +} diff --git a/pkg/kube/update-component/settings_longhorn.yaml b/pkg/kube/update-component/settings_longhorn.yaml new file mode 100644 index 0000000000..ffa9300905 --- /dev/null +++ b/pkg/kube/update-component/settings_longhorn.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Zededa, Inc. +# SPDX-License-Identifier: Apache-2.0 +--- +apiVersion: longhorn.io/v1beta2 +kind: Setting +metadata: + name: concurrent-automatic-engine-upgrade-per-node-limit + namespace: longhorn-system +value: "1" diff --git a/pkg/kube/update-component/upgrades.go b/pkg/kube/update-component/upgrades.go new file mode 100644 index 0000000000..2ed495a586 --- /dev/null +++ b/pkg/kube/update-component/upgrades.go @@ -0,0 +1,373 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +// +// A kubernetes component/app upgrade wrapper. +// - guard against incompatible versions +// - easier parsing of uptime/readiness instead of in bash scripts +// +// Examples: +// Compare running/expected versions: upgrade-component --component longhorn --versions-file /usr/bin/expected_versions.yaml --compare +// Upgrade: upgrade-component --component longhorn --versions-file /usr/bin/expected_versions.yaml -upgrade +// + +import ( + "context" + "flag" + "fmt" + "log" + "os" + "os/exec" + "strings" + "time" + + "gopkg.in/natefinch/lumberjack.v2" + "gopkg.in/yaml.v2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +const ( + // All Supported Components + compNameMultus = "multus" + compNameKubevirt = "kubevirt" + compNameCdi = "cdi" + compNameLonghorn = "longhorn" + + expectedUptimePostUpgrade = time.Second * 30 + upgradePollWaitSeconds = 30 + kubeConfigFile = "/etc/rancher/k3s/k3s.yaml" + + emptyVersion = "v0.0.0" + + logfileDir = "/persist/kubelog/" + logfile = logfileDir + "upgrade-component.log" + logMaxSize = 10 // 10 Mbytes in size + logMaxBackups = 3 // old log files to retain + logMaxAge = 365 // days to retain old log files +) + +var ( + ForceUpgrade = false // ForceUpgrade : Ignore component version constraints and request upgrade + logFile *lumberjack.Logger +) + +// componentsNewVersionsTable is a map of versions the system will upgrade to +var componentNewVersionsTable = map[string]string{ + compNameMultus: emptyVersion, + compNameKubevirt: emptyVersion, + compNameCdi: emptyVersion, + compNameLonghorn: emptyVersion, +} + +// KubeComponent implements upgrade processing for various kubernetes apps/components +type KubeComponent interface { + GetVersion() (string, error) + + UpgradeSupported(sourceVer string, destVer string) error + + // Caller should be expecting a time stamp for when the app reached condition ready + // Error will return (time.Now(), err) so uptimestamp will never stop increasing + Uptime(version string) (time.Time, error) + + // Ready is a function that returns nil if the component is online + // Is the specified component online at the requested version? + Ready(version string) error + + // ComponentUpgradeStart is a function that initiates an upgrade of the component to the specified version + UpgradeStart(version string) error +} + +type commonComponent struct { + cs *kubernetes.Clientset +} + +func (ctx *commonComponent) KubectlApply(path string) error { + cmd := exec.Command("kubectl", "apply", "-f", path) + var outStr strings.Builder + var errStr strings.Builder + cmd.Stdout = &outStr + cmd.Stderr = &errStr + err := cmd.Run() + if err != nil { + rc := cmd.ProcessState.ExitCode() + return fmt.Errorf("apply %s, rc: %d, stdout: %s, stderr: %s, err: %v", path, rc, outStr.String(), errStr.String(), err) + } + log.Printf("apply %s, stdout: %s, stderr: %s\n", path, outStr.String(), errStr.String()) + return nil +} + +// GetKubeConfig : Get handle to Kubernetes config +func GetKubeConfig() (*rest.Config, error) { + // Build the configuration from the kubeconfig file + config, err := clientcmd.BuildConfigFromFlags("", kubeConfigFile) + if err != nil { + return nil, err + } + return config, nil +} + +// GetClientSet : Get handle to kubernetes clientset +func GetClientSet() (*kubernetes.Clientset, error) { + + // Build the configuration from the provided kubeconfig file + config, err := GetKubeConfig() + if err != nil { + return nil, err + } + + // Create the Kubernetes clientset + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + + return clientset, nil +} + +// Versions is a structure to map the expected upgrade versions +// +// in a yaml file of the kube service container +type Versions struct { + Multus string `yaml:"multus"` + Kubevirt string `yaml:"kubevirt"` + Cdi string `yaml:"cdi"` + Longhorn string `yaml:"longhorn"` +} + +func getComponentHandler(cs *kubernetes.Clientset, comp string) KubeComponent { + common := commonComponent{cs: cs} + switch comp { + case compNameMultus: + return &multusComponent{common} + case compNameKubevirt: + return &kubevirtComponent{common} + case compNameCdi: + return &cdiComponent{common} + case compNameLonghorn: + return &longhornComponent{common} + } + return nil +} + +func main() { + // Actions + beginUpgradesPtr := flag.Bool("upgrade", false, "Begin upgrades") + onlyCompareVersionPtr := flag.Bool("compare", false, "Just compare current version, return 0 for matching, 1 for not matching") + checkCompReadyFlag := flag.Bool("check-comp-ready", false, "Check if component is ready, according to its daemonsets (rc 0 for success)") + checkAPIReadyFlag := flag.Bool("check-api-ready", false, "Check if api is responding, (rc 0 for success)") + getCompUptimeFlag := flag.Bool("get-uptime", false, "Print component uptime in seconds") + + // Options + forcePtr := flag.Bool("f", false, "Force: skip uptime checks and version constraints") + versionsFilePtr := flag.String("versions-file", "", "Versions file") + componentPtr := flag.String("component", "", "Component to upgrade") + flag.Parse() + + ForceUpgrade = *forcePtr + + // + // Setup Logging + // + if _, err := os.Stat(logfileDir); os.IsNotExist(err) { + if err := os.MkdirAll(logfileDir, 0755); err != nil { + os.Exit(1) + } + } + logFile = &lumberjack.Logger{ + Filename: logfile, // Path to the log file. + MaxSize: logMaxSize, // Maximum size in megabytes before rotation. + MaxBackups: logMaxBackups, // Maximum number of old log files to retain. + MaxAge: logMaxAge, // Maximum number of days to retain old log files. + Compress: true, // Whether to compress rotated log files. + LocalTime: true, // Use the local time zone for file names. + } + log.SetOutput(logFile) + defer logFile.Close() + + // + // Get Kubernetes handle + // + clientset, err := GetClientSet() + if err != nil { + log.Printf("Failed to get clientset %v\n", err) + os.Exit(1) + } + + // + // A basic lightweight call to see if k3s is running + // + if *checkAPIReadyFlag { + nodes, err := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{}) + if err != nil || (len(nodes.Items) < 1) { + os.Exit(1) + } + os.Exit(0) + } + + // + // Read in destination upgrade versions + // + if *versionsFilePtr != "" { + if _, err := os.Stat(*versionsFilePtr); err == nil { + var versions = Versions{} + yamlData, err := os.ReadFile(*versionsFilePtr) + if err != nil { + log.Print(fmt.Errorf("unable to read in versions file at path:%s err:%v", *versionsFilePtr, err)) + os.Exit(1) + } + err = yaml.UnmarshalStrict(yamlData, &versions) + if err != nil { + log.Print(err.Error()) + os.Exit(1) + } + if versions.Multus != "" { + componentNewVersionsTable[compNameMultus] = versions.Multus + } + if versions.Kubevirt != "" { + componentNewVersionsTable[compNameKubevirt] = versions.Kubevirt + } + if versions.Cdi != "" { + componentNewVersionsTable[compNameCdi] = versions.Cdi + } + if versions.Longhorn != "" { + componentNewVersionsTable[compNameLonghorn] = versions.Longhorn + } + } + } + + // + // Read in running (source) versions + // + component := *componentPtr + var componentCurrentVersions = map[string]string{ + compNameMultus: "", + compNameKubevirt: "", + compNameLonghorn: "", + compNameCdi: "", + } + compHandler := getComponentHandler(clientset, component) + currentVersion, err := compHandler.GetVersion() + if err != nil { + log.Printf("Error retrieving version for component: %s, error: %v\n", component, err) + os.Exit(1) + } + componentCurrentVersions[component] = currentVersion + + ready := false + var uptimeSeconds float64 + if err := compHandler.Ready(currentVersion); err == nil { + ready = true + uptimeStamp, err := compHandler.Uptime(currentVersion) + if err != nil { + log.Printf("Component: " + component + " uptime err:" + err.Error()) + os.Exit(1) + } else { + uptimeSeconds = time.Since(uptimeStamp).Seconds() + } + } + + // + // Determine if upgrade necessary + // + if *onlyCompareVersionPtr { + log.Printf("Component:%s ready:%v running:%s expected_version:%s uptime_seconds:%f", + component, ready, componentCurrentVersions[component], componentNewVersionsTable[component], uptimeSeconds) + if componentCurrentVersions[component] == componentNewVersionsTable[component] { + os.Exit(0) + } + os.Exit(1) + } + + // + // Is it ready, 1 is bool true but 0 is success unix code + // + if *checkCompReadyFlag { + if !ready { + os.Exit(1) + } + os.Exit(0) + } + + // + // Comp Uptime printed + // + if *getCompUptimeFlag { + fmt.Print(uint64(uptimeSeconds)) + os.Exit(0) + } + + // + // Begin Update + // + if *beginUpgradesPtr { + // + // Pre-Upgrade Health Check + // + log.Print("Checking component health pre-upgrade") + currentVersion := componentCurrentVersions[component] + for { + if err := compHandler.Ready(currentVersion); err != nil { + log.Print("Component: " + component + " is not ready at version:" + currentVersion + " err: " + err.Error()) + time.Sleep(upgradePollWaitSeconds * time.Second) + } else { + log.Print("Component: " + component + " is ready") + break + } + } + + // + // Version compatibility check + // + newVersion := componentNewVersionsTable[component] + log.Printf("new-phase:upgrade-start component:%s srcVer:%s dstVer:%s\n", component, currentVersion, newVersion) + err = compHandler.UpgradeSupported(currentVersion, newVersion) + if err != nil && !ForceUpgrade { + log.Printf("Component: %s denied upgrade srcVer:%s dstVer:%s err:%v\n", component, currentVersion, newVersion, err) + } else { + err = compHandler.UpgradeStart(newVersion) + if err != nil { + log.Printf("Component: %s upgrade init srcVer:%s dstVer:%s error: %v\n", component, currentVersion, newVersion, err) + os.Exit(1) + } + + log.Printf("new-phase:post-upgrade ver:%s component:%s\n", newVersion, component) + var updated = false + for !updated { + time.Sleep(upgradePollWaitSeconds * time.Second) + foundVersion, err := compHandler.GetVersion() + if err != nil { + log.Printf("post-upgrade component:%s get version err:%v\n", component, err) + os.Exit(1) + } + log.Printf("post-upgrade component:%s version:%s waiting for version:%s\n", component, foundVersion, newVersion) + if foundVersion == newVersion { + updated = true + componentCurrentVersions[component] = newVersion + } + } + + // + // Wait for new version to reach running/ready + // + var acceptableUptime = false + for !acceptableUptime { + time.Sleep(upgradePollWaitSeconds * time.Second) + uptime, err := compHandler.Uptime(newVersion) + if err != nil { + log.Printf("post-upgrade uptime get error:%v", err) + continue + } + uptimeDuration := time.Since(uptime) + if uptimeDuration >= expectedUptimePostUpgrade { + acceptableUptime = true + } + log.Printf("Waiting for steady uptime of component:%s, uptime_seconds:%f", component, uptimeDuration.Seconds()) + } + } + } +} diff --git a/pkg/pillar/cmd/zedagent/handleedgenodecluster.go b/pkg/pillar/cmd/zedagent/handleedgenodecluster.go new file mode 100644 index 0000000000..30571edf17 --- /dev/null +++ b/pkg/pillar/cmd/zedagent/handleedgenodecluster.go @@ -0,0 +1,130 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//go:build kubevirt + +package zedagent + +import ( + "bytes" + "time" + + "github.com/golang/protobuf/ptypes" + "github.com/lf-edge/eve-api/go/info" + "github.com/lf-edge/eve/pkg/pillar/kubeapi" + "github.com/lf-edge/eve/pkg/pillar/pubsub" + "google.golang.org/protobuf/proto" +) + +func kubeClusterUpdateStatusTask(ctxPtr *zedagentContext, triggerClusterUpdateInfo <-chan destinationBitset) { + wdName := agentName + "clusterupdatestatus" + + stillRunning := time.NewTicker(30 * time.Second) + ctxPtr.ps.StillRunning(wdName, warningTime, errorTime) + ctxPtr.ps.RegisterFileWatchdog(wdName) + + for { + select { + case dest := <-triggerClusterUpdateInfo: + start := time.Now() + log.Function("kubeClusterUpdateStatusTask got message") + + publishKubeClusterUpdateStatus(ctxPtr, dest) + ctxPtr.iteration++ + log.Function("kubeClusterUpdateStatusTask done with message") + ctxPtr.ps.CheckMaxTimeTopic(wdName, "clusterupdatestatus", start, + warningTime, errorTime) + case <-stillRunning.C: + } + ctxPtr.ps.StillRunning(wdName, warningTime, errorTime) + } +} + +// PublishHardwareInfoToZedCloud send ZInfoHardware message +func publishKubeClusterUpdateStatus(ctx *zedagentContext, dest destinationBitset) { + items := ctx.subClusterUpdateStatus.GetAll() + psKubeUpdateStatusGlb, ok := items["global"].(kubeapi.KubeClusterUpdateStatus) + if !ok { + return + } + + // Setup Container + var UpdateStatusInfo = &info.ZInfoMsg{} + key := devUUID.String() + "kubeclusterupdatestatus" + bailOnHTTPErr := true + infoType := new(info.ZInfoTypes) + *infoType = info.ZInfoTypes_ZiKubeClusterUpdateStatus + UpdateStatusInfo.Ztype = *infoType + UpdateStatusInfo.DevId = *proto.String(devUUID.String()) + UpdateStatusInfo.AtTimeStamp = ptypes.TimestampNow() + log.Functionf("publishKubeClusterUpdateStatus uuid %s", key) + + updateStatus := new(info.ZInfoKubeClusterUpdateStatus) + + updateStatus.Component = psKubeUpdateStatusGlb.Component.KubeComp() + updateStatus.Status = psKubeUpdateStatusGlb.Status.KubeCompUpdateStatus() + updateStatus.CurrentNode = psKubeUpdateStatusGlb.CurrentNode + updateStatus.Error = nil + if !psKubeUpdateStatusGlb.ErrorTime.IsZero() { + updateStatus.Error = encodeErrorInfo(psKubeUpdateStatusGlb.ErrorAndTime.ErrorDescription) + } + + UpdateStatusInfo.InfoContent = new(info.ZInfoMsg_ClusterUpdateInfo) + if x, ok := UpdateStatusInfo.GetInfoContent().(*info.ZInfoMsg_ClusterUpdateInfo); ok { + x.ClusterUpdateInfo = updateStatus + } + + log.Functionf("publishKubeClusterUpdateStatus sending %v", UpdateStatusInfo) + data, err := proto.Marshal(UpdateStatusInfo) + if err != nil { + log.Errorf("publishKubeClusterUpdateStatus proto marshaling error: %v", err) + return + } + + buf := bytes.NewBuffer(data) + if buf == nil { + log.Errorf("publishKubeClusterUpdateStatus malloc error") + return + } + size := int64(proto.Size(UpdateStatusInfo)) + + log.Function("publishKubeClusterUpdateStatus to controller") + queueInfoToDest(ctx, dest, key, buf, size, bailOnHTTPErr, false, false, + info.ZInfoTypes_ZiKubeClusterUpdateStatus) +} + +func isKubeClusterUpdating(ctx *zedagentContext) bool { + if ctx == nil { + return false + } + if ctx.subClusterUpdateStatus == nil { + return false + } + items := ctx.subClusterUpdateStatus.GetAll() + if status, ok := items["global"].(kubeapi.KubeClusterUpdateStatus); ok { + if (status.Component == kubeapi.COMP_LONGHORN) && (status.Status == kubeapi.COMP_STATUS_COMPLETED) { + return false + } + return true + } + return false +} + +func initKubeSubs(ctx *zedagentContext) { + ctx.subClusterUpdateStatus, err = ps.NewSubscription(pubsub.SubscriptionOptions{ + AgentName: agentName, + MyAgentName: agentName, + TopicImpl: kubeapi.KubeClusterUpdateStatus{}, + Persistent: true, + Activate: false, //need to have the zedagentCtx.subClusterUpdateStatus set before activation + Ctx: ctx, + CreateHandler: handleClusterUpdateStatusCreate, + ModifyHandler: handleClusterUpdateStatusModify, + WarningTime: warningTime, + ErrorTime: errorTime, + }) + if err != nil { + log.Fatal(err) + } + ctx.subClusterUpdateStatus.Activate() +} diff --git a/pkg/pillar/cmd/zedagent/nokube.go b/pkg/pillar/cmd/zedagent/nokube.go new file mode 100644 index 0000000000..2253ebddf2 --- /dev/null +++ b/pkg/pillar/cmd/zedagent/nokube.go @@ -0,0 +1,36 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//go:build !kubevirt + +package zedagent + +// only used in HV=kubevirt, see handleedgenodecluster.go +func kubeClusterUpdateStatusTask(ctxPtr *zedagentContext, triggerClusterUpdateInfo <-chan destinationBitset) { + return +} + +// only used in HV=kubevirt, see handleedgenodecluster.go +func publishKubeClusterUpdateStatus(ctx *zedagentContext, dest destinationBitset) { + return +} + +// only used in HV=kubevirt, see handleedgenodecluster.go +func kubeClusterInfoTask(ctxPtr *zedagentContext, triggerClusterInfo <-chan destinationBitset) { + return +} + +// only used in HV=kubevirt, see handleedgenodecluster.go +func publishKubeClusterInfo(ctx *zedagentContext, dest destinationBitset) { + return +} + +// only used in HV=kubevirt, see handleedgenodecluster.go +func isKubeClusterUpdating(ctx *zedagentContext) bool { + return false +} + +// only used in HV=kubevirt, see handleedgenodecluster.go +func initKubeSubs(ctx *zedagentContext) { + return +} diff --git a/pkg/pillar/cmd/zedagent/reportinfo.go b/pkg/pillar/cmd/zedagent/reportinfo.go index 75a7ac5a75..f0361fd9f0 100644 --- a/pkg/pillar/cmd/zedagent/reportinfo.go +++ b/pkg/pillar/cmd/zedagent/reportinfo.go @@ -1300,7 +1300,7 @@ func getDeviceState(ctx *zedagentContext) types.DeviceState { if ctx.maintenanceMode { return types.DEVICE_STATE_MAINTENANCE_MODE } - if isUpdating(ctx) { + if isUpdating(ctx) || isKubeClusterUpdating(ctx) { return types.DEVICE_STATE_BASEOS_UPDATING } if ctx.rebootCmd || ctx.deviceReboot { diff --git a/pkg/pillar/cmd/zedagent/zedagent.go b/pkg/pillar/cmd/zedagent/zedagent.go index 62d4fc2df1..fd0a7a6e4c 100644 --- a/pkg/pillar/cmd/zedagent/zedagent.go +++ b/pkg/pillar/cmd/zedagent/zedagent.go @@ -111,6 +111,7 @@ type zedagentContext struct { triggerHwInfo chan<- destinationBitset triggerLocationInfo chan<- destinationBitset triggerNTPSourcesInfo chan<- destinationBitset + triggerClusterUpdateInfo chan<- destinationBitset triggerObjectInfo chan<- infoForObjectKey zbootRestarted bool // published by baseosmgr subOnboardStatus pubsub.Subscription @@ -153,6 +154,7 @@ type zedagentContext struct { subCipherMetricsZR pubsub.Subscription subCipherMetricsWwan pubsub.Subscription subPatchEnvelopeUsage pubsub.Subscription + subClusterUpdateStatus pubsub.Subscription zedcloudMetrics *zedcloud.AgentMetrics fatalFlag bool // From command line arguments hangFlag bool // From command line arguments @@ -338,12 +340,14 @@ func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, ar triggerHwInfo := make(chan destinationBitset, 1) triggerLocationInfo := make(chan destinationBitset, 1) triggerNTPSourcesInfo := make(chan destinationBitset, 1) + triggerClusterUpdateInfo := make(chan destinationBitset, 1) triggerObjectInfo := make(chan infoForObjectKey, 1) zedagentCtx.flowlogQueue = flowlogQueue zedagentCtx.triggerDeviceInfo = triggerDeviceInfo zedagentCtx.triggerHwInfo = triggerHwInfo zedagentCtx.triggerLocationInfo = triggerLocationInfo zedagentCtx.triggerNTPSourcesInfo = triggerNTPSourcesInfo + zedagentCtx.triggerClusterUpdateInfo = triggerClusterUpdateInfo zedagentCtx.triggerObjectInfo = triggerObjectInfo // Initialize all zedagent publications. @@ -508,6 +512,11 @@ func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, ar go ntpSourcesTimerTask(zedagentCtx, handleChannel, triggerNTPSourcesInfo) getconfigCtx.ntpSourcesTickerHandle = <-handleChannel + // Initial publish of KubeClusterUpdateStatus + log.Noticef("Creating %s at %s", "kubeClusterUpdateStatusTask", agentlog.GetMyStack()) + go kubeClusterUpdateStatusTask(zedagentCtx, triggerClusterUpdateInfo) + triggerPublishKubeClusterUpdateStatus(zedagentCtx) + //trigger channel for localProfile state machine getconfigCtx.sideController.localProfileTrigger = make(chan Notify, 1) //process saved local profile @@ -784,6 +793,7 @@ func mainEventLoop(zedagentCtx *zedagentContext, stillRunning *time.Ticker) { dnsCtx := zedagentCtx.dnsCtx hwInfoTiker := time.NewTicker(3 * time.Hour) + kubeClusterUpdateTicker := time.NewTicker(1 * time.Minute) for { select { @@ -1059,6 +1069,12 @@ func mainEventLoop(zedagentCtx *zedagentContext, stillRunning *time.Ticker) { case change := <-zedagentCtx.subEdgeviewStatus.MsgChan(): zedagentCtx.subEdgeviewStatus.ProcessChange(change) + case <-kubeClusterUpdateTicker.C: + triggerPublishKubeClusterUpdateStatus(zedagentCtx) + + case change := <-zedagentCtx.subClusterUpdateStatus.MsgChan(): + zedagentCtx.subClusterUpdateStatus.ProcessChange(change) + case <-stillRunning.C: // Fault injection if zedagentCtx.fatalFlag { @@ -1987,6 +2003,8 @@ func initPostOnboardSubs(zedagentCtx *zedagentContext) { if err != nil { log.Fatal(err) } + + initKubeSubs(zedagentCtx) } func triggerPublishHwInfoToDest(ctxPtr *zedagentContext, dest destinationBitset) { @@ -2006,6 +2024,42 @@ func triggerPublishHwInfo(ctxPtr *zedagentContext) { triggerPublishHwInfoToDest(ctxPtr, AllDest) } +func handleClusterUpdateStatusCreate(ctxArg interface{}, key string, + configArg interface{}) { + handleClusterUpdateStatusImpl(ctxArg, key, configArg, nil) +} +func handleClusterUpdateStatusModify(ctxArg interface{}, key string, + configArg interface{}, oldStatusArg interface{}) { + handleClusterUpdateStatusImpl(ctxArg, key, configArg, oldStatusArg) +} +func handleClusterUpdateStatusImpl(ctxArg interface{}, key string, + statusArg interface{}, oldStatusArg interface{}) { + ctx, ok := ctxArg.(*zedagentContext) + if !ok { + log.Errorf("handleClusterUpdateStatusImpl invalid type in ctxArg: %v", ctxArg) + return + } + state := getDeviceState(ctx) + log.Noticef("handleClusterUpdateStatusImpl key:%s devicestate:%s", key, state) + triggerPublishKubeClusterUpdateStatus(ctx) +} + +func triggerPublishKubeClusterUpdateStatusToDest(ctxPtr *zedagentContext, dest destinationBitset) { + log.Function("Triggered PublishKubeClusterUpdateStatus") + select { + case ctxPtr.triggerClusterUpdateInfo <- dest: + // Do nothing more + default: + // This occurs if we are already trying to send + // and we get a second and third trigger before that is complete. + log.Warnf("Failed to send on PublishKubeClusterUpdateStatus") + } +} + +func triggerPublishKubeClusterUpdateStatus(ctxPtr *zedagentContext) { + triggerPublishKubeClusterUpdateStatusToDest(ctxPtr, AllDest) +} + func triggerPublishDevInfoToDest(ctxPtr *zedagentContext, dest destinationBitset) { log.Function("Triggered PublishDeviceInfo") @@ -2112,6 +2166,7 @@ func triggerPublishAllInfo(ctxPtr *zedagentContext, dest destinationBitset) { } triggerPublishLocationToDest(ctxPtr, dest) triggerPublishNTPSourcesToDest(ctxPtr, dest) + triggerPublishKubeClusterUpdateStatusToDest(ctxPtr, dest) }() } diff --git a/pkg/pillar/cmd/zedkube/zedkube.go b/pkg/pillar/cmd/zedkube/zedkube.go index 6823139f3e..99b8e73c6c 100644 --- a/pkg/pillar/cmd/zedkube/zedkube.go +++ b/pkg/pillar/cmd/zedkube/zedkube.go @@ -7,6 +7,7 @@ package zedkube import ( "net/http" + "strconv" "strings" "sync" "time" @@ -31,6 +32,8 @@ const ( logcollectInterval = 30 // run VNC file vmiVNCFileName = "/run/zedkube/vmiVNC.run" + + inlineCmdKubeClusterUpdateStatus = "pubKubeClusterUpdateStatus" ) var ( @@ -76,6 +79,76 @@ type zedkube struct { statusServerWG sync.WaitGroup } +func inlineUsage() int { + log.Errorf("Usage: zedkube %s ", inlineCmdKubeClusterUpdateStatus) + return 1 +} + +func runCommand(ps *pubsub.PubSub, command string, args []string) int { + if args == nil { + return inlineUsage() + } + switch command { + case inlineCmdKubeClusterUpdateStatus: + if args == nil { + return inlineUsage() + } + node := args[0] + comp := kubeapi.KubeCompFromStr(args[1]) + status := kubeapi.KubeCompUpdateStatusFromStr(args[2]) + + dest_kube_version := uint32(0) + val, err := strconv.ParseInt(args[3], 10, 32) + if err != nil { + log.Errorf("zedkube %s unable to parse dest_version:%s err:%v", inlineCmdKubeClusterUpdateStatus, args[3], err) + return 1 + } + dest_kube_version = uint32(val) + + error_str := "" + if len(args) == 5 { + error_str = args[4] + } + + pubKubeClusterUpdateStatus, err := ps.NewPublication( + pubsub.PublicationOptions{ + AgentName: "zedagent", + TopicType: kubeapi.KubeClusterUpdateStatus{}, + Persistent: true, + }) + if err != nil { + log.Fatal(err) + return 2 + } + if (comp == kubeapi.COMP_UNKNOWN) && (status == kubeapi.COMP_STATUS_UNKNOWN) { + if _, err := pubKubeClusterUpdateStatus.Get("global"); err == nil { + pubKubeClusterUpdateStatus.Unpublish("global") + } + } else { + upStatusObj := kubeapi.KubeClusterUpdateStatus{ + CurrentNode: node, + Component: comp, + Status: status, + DestinationKubeUpdateVersion: dest_kube_version, + } + if status == kubeapi.COMP_STATUS_FAILED { + if error_str == "" { + error_str = inlineCmdKubeClusterUpdateStatus + " " + strings.Join(args, " ") + } + upStatusObj.SetError(error_str, time.Now()) + } + pubKubeClusterUpdateStatus.Publish("global", upStatusObj) + } + default: + log.Errorf("Unknown command %s", command) + return 99 + } + + ps.StillRunning("zedkube", warningTime, errorTime) + time.Sleep(time.Second * 1) + return 0 +} + // Run - an zedkube run func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, arguments []string, baseDir string) int { logger = loggerArg @@ -84,6 +157,26 @@ func Run(ps *pubsub.PubSub, loggerArg *logrus.Logger, logArg *base.LogObject, ar zedkubeCtx := zedkube{ globalConfig: types.DefaultConfigItemValueMap(), } + + // do we run a single command, or long-running service? + // if any args defined, will run that single command and exit. + // otherwise, will run the agent + var ( + command string + args []string + ) + if len(arguments) > 0 { + command = arguments[0] + } + if len(arguments) > 1 { + args = arguments[1:] + } + + // if an explicit command was given, run that command and return, else run the agent + if command != "" { + return runCommand(ps, command, args) + } + agentbase.Init(&zedkubeCtx, logger, log, agentName, agentbase.WithPidFile(), agentbase.WithWatchdog(ps, warningTime, errorTime), diff --git a/pkg/pillar/kubeapi/infotypes.go b/pkg/pillar/kubeapi/infotypes.go new file mode 100644 index 0000000000..61893e5e6a --- /dev/null +++ b/pkg/pillar/kubeapi/infotypes.go @@ -0,0 +1,115 @@ +// Copyright (c) 2025 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +//go:build kubevirt + +package kubeapi + +import ( + "github.com/lf-edge/eve-api/go/info" + "github.com/lf-edge/eve/pkg/pillar/types" +) + +type KubeCompUpdateStatus uint8 + +const ( + COMP_STATUS_UNKNOWN KubeCompUpdateStatus = iota + 0 // UNKNOWN Unable to determine + COMP_STATUS_DOWNLOAD // DOWNLOAD begun + COMP_STATUS_DOWNLOAD_FAILED // DOWNLOAD_FAILED + COMP_STATUS_IN_PROGRESS // IN_PROGRESS update in progress + COMP_STATUS_FAILED // FAILED update + COMP_STATUS_COMPLETED // COMPLETE update +) + +func KubeCompUpdateStatusFromStr(status string) KubeCompUpdateStatus { + switch status { + case "download": + return COMP_STATUS_DOWNLOAD + case "download_failed": + return COMP_STATUS_DOWNLOAD_FAILED + case "in_progress": + return COMP_STATUS_IN_PROGRESS + case "failed": + return COMP_STATUS_FAILED + case "completed": + return COMP_STATUS_COMPLETED + default: + return COMP_STATUS_UNKNOWN + } +} + +func (state KubeCompUpdateStatus) KubeCompUpdateStatus() info.KubeCompUpdateStatus { + switch state { + case COMP_STATUS_DOWNLOAD: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_DOWNLOAD + case COMP_STATUS_DOWNLOAD_FAILED: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_DOWNLOAD_FAILED + case COMP_STATUS_IN_PROGRESS: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_IN_PROGRESS + case COMP_STATUS_FAILED: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_FAILED + case COMP_STATUS_COMPLETED: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_COMPLETED + default: + return info.KubeCompUpdateStatus_KUBE_COMP_UPDATE_STATUS_UNSPECIFIED + } +} + +type KubeComp uint8 + +const ( + COMP_UNKNOWN KubeComp = iota + 0 + COMP_CONTAINERD + COMP_K3S + COMP_MULTUS + COMP_KUBEVIRT + COMP_CDI + COMP_LONGHORN +) + +func KubeCompFromStr(compStr string) KubeComp { + switch compStr { + case "containerd": + return COMP_CONTAINERD + case "k3s": + return COMP_K3S + case "multus": + return COMP_MULTUS + case "kubevirt": + return COMP_KUBEVIRT + case "cdi": + return COMP_CDI + case "longhorn": + return COMP_LONGHORN + } + return COMP_UNKNOWN +} + +func (comp KubeComp) KubeComp() info.KubeComp { + switch comp { + case COMP_CONTAINERD: + return info.KubeComp_KUBE_COMP_CONTAINERD + case COMP_K3S: + return info.KubeComp_KUBE_COMP_K3S + case COMP_MULTUS: + return info.KubeComp_KUBE_COMP_MULTUS + case COMP_KUBEVIRT: + return info.KubeComp_KUBE_COMP_KUBEVIRT + case COMP_CDI: + return info.KubeComp_KUBE_COMP_CDI + case COMP_LONGHORN: + return info.KubeComp_KUBE_COMP_LONGHORN + } + return info.KubeComp_KUBE_COMP_UNSPECIFIED +} + +type KubeClusterUpdateStatus struct { + CurrentNode string + Component KubeComp + Status KubeCompUpdateStatus + DestinationKubeUpdateVersion uint32 + + // error strings across all steps/StorageStatus + // ErrorAndTime provides SetErrorNow() and ClearError() + types.ErrorAndTime +} diff --git a/pkg/pillar/zedbox/zedbox.go b/pkg/pillar/zedbox/zedbox.go index ad75295e09..b0894a5e91 100644 --- a/pkg/pillar/zedbox/zedbox.go +++ b/pkg/pillar/zedbox/zedbox.go @@ -95,7 +95,7 @@ var ( "volumemgr": {f: volumemgr.Run}, "waitforaddr": {f: waitforaddr.Run, inline: inlineAlways}, "zedagent": {f: zedagent.Run}, - "zedkube": {f: zedkube.Run}, + "zedkube": {f: zedkube.Run, inline: inlineAlways}, "zedmanager": {f: zedmanager.Run}, "zedrouter": {f: zedrouter.Run}, "ipcmonitor": {f: ipcmonitor.Run, inline: inlineAlways},