diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 9559c4fde9..80637ab009 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v4.0.1 with: go-version: 1.19 - uses: actions/checkout@v3.1.0 diff --git a/.github/workflows/gh-pages.yaml b/.github/workflows/gh-pages.yaml index c3fce6b8bc..89df548ebd 100644 --- a/.github/workflows/gh-pages.yaml +++ b/.github/workflows/gh-pages.yaml @@ -24,7 +24,7 @@ jobs: with: python-version: 3.x - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v4.0.1 with: go-version: 1.19 - name: build diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 26ff28b01c..87d385a9d6 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -36,7 +36,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v4.0.1 with: go-version: ${{ env.GOLANG_VERSION }} - name: Checkout code @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v4.0.1 with: go-version: ${{ env.GOLANG_VERSION }} id: go @@ -103,7 +103,7 @@ jobs: - name: Checkout code uses: actions/checkout@v3.1.0 - name: Setup Golang - uses: actions/setup-go@v4 + uses: actions/setup-go@v4.0.1 with: go-version: ${{ env.GOLANG_VERSION }} # k8s codegen generates files into GOPATH location instead of the GitHub git checkout location diff --git a/.github/workflows/image-reuse.yaml b/.github/workflows/image-reuse.yaml index f2171f099f..cc5dc45c11 100644 --- a/.github/workflows/image-reuse.yaml +++ b/.github/workflows/image-reuse.yaml @@ -69,12 +69,12 @@ jobs: if: ${{ github.ref_type != 'tag'}} - name: Setup Golang - uses: actions/setup-go@6edd4406fa81c3da01a34fa6f6343087c207a568 # v3.5.0 + uses: actions/setup-go@v4.0.1 # v3.5.0 with: go-version: ${{ inputs.go-version }} - name: Install cosign - uses: sigstore/cosign-installer@dd6b2e2b610a11fd73dd187a43d57cc1394e35f9 # v3.0.5 + uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1 with: cosign-release: 'v2.0.2' diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c40d377f86..87d4aa6335 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -91,7 +91,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Golang - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 with: go-version: ${{ env.GOLANG_VERSION }} diff --git a/Makefile b/Makefile index 2ebb183635..638498ff85 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ ifdef IMAGE_NAMESPACE IMAGE_PREFIX=${IMAGE_NAMESPACE}/ endif -# protoc,my.proto +## protoc,my.proto define protoc # protoc $(1) PATH=${DIST_DIR}:$$PATH protoc \ @@ -66,22 +66,26 @@ endef .PHONY: all all: controller image -# downloads vendor files needed by tools.go (i.e. go_install) +##@ Development .PHONY: go-mod-vendor -go-mod-vendor: +go-mod-vendor: ## downloads vendor files needed by tools.go (i.e. go_install) go mod tidy go mod vendor +.PHONY: lint +lint: go-mod-vendor ## run all linters + golangci-lint run --fix + .PHONY: install-go-tools-local -install-go-tools-local: go-mod-vendor +install-go-tools-local: go-mod-vendor ## install all go tools ./hack/installers/install-codegen-go-tools.sh .PHONY: install-protoc-local -install-protoc-local: +install-protoc-local: ## install protoc tool ./hack/installers/install-protoc.sh .PHONY: install-devtools-local -install-devtools-local: +install-devtools-local: ## install dev tools ./hack/installers/install-dev-tools.sh # Installs all tools required to build and test locally @@ -94,6 +98,8 @@ APIMACHINERY_PKGS=k8s.io/apimachinery/pkg/util/intstr,+k8s.io/apimachinery/pkg/a .PHONY: install-toolchain install-toolchain: install-go-tools-local install-protoc-local +##@ Code Generation + # generates all auto-generated code .PHONY: codegen codegen: go-mod-vendor gen-proto gen-k8scodegen gen-openapi gen-mocks gen-crd manifests docs @@ -104,7 +110,7 @@ gen-proto: k8s-proto api-proto ui-proto # generates the .proto files affected by changes to types.go .PHONY: k8s-proto -k8s-proto: go-mod-vendor $(TYPES) +k8s-proto: go-mod-vendor $(TYPES) ## generate kubernetes protobuf files PATH=${DIST_DIR}:$$PATH go-to-protobuf \ --go-header-file=./hack/custom-boilerplate.go.txt \ --packages=github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1 \ @@ -117,44 +123,42 @@ k8s-proto: go-mod-vendor $(TYPES) # generates *.pb.go, *.pb.gw.go, swagger from .proto files .PHONY: api-proto -api-proto: go-mod-vendor k8s-proto +api-proto: go-mod-vendor k8s-proto ## generate api protobuf files $(call protoc,pkg/apiclient/rollout/rollout.proto) # generates ui related proto files .PHONY: ui-proto -ui-proto: +ui-proto: ## generate ui protobuf files yarn --cwd ui run protogen # generates k8s client, informer, lister, deepcopy from types.go .PHONY: gen-k8scodegen -gen-k8scodegen: go-mod-vendor +gen-k8scodegen: go-mod-vendor ## generate kubernetes codegen files ./hack/update-codegen.sh # generates ./manifests/crds/ .PHONY: gen-crd -gen-crd: install-go-tools-local +gen-crd: install-go-tools-local ## generate crd manifests go run ./hack/gen-crd-spec/main.go # generates mock files from interfaces .PHONY: gen-mocks -gen-mocks: install-go-tools-local +gen-mocks: install-go-tools-local ## generate mock files ./hack/update-mocks.sh # generates openapi_generated.go .PHONY: gen-openapi -gen-openapi: $(DIST_DIR)/openapi-gen +gen-openapi: $(DIST_DIR)/openapi-gen ## generate openapi files PATH=${DIST_DIR}:$$PATH openapi-gen \ --go-header-file ${CURRENT_DIR}/hack/custom-boilerplate.go.txt \ --input-dirs github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1 \ --output-package github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1 \ --report-filename pkg/apis/api-rules/violation_exceptions.list -.PHONY: controller -controller: - CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/rollouts-controller ./cmd/rollouts-controller +##@ Plugins .PHONY: plugin -plugin: ui/dist +plugin: ui/dist ## build plugin cp -r ui/dist/app/* server/static CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME} ./cmd/kubectl-argo-rollouts @@ -163,28 +167,30 @@ ui/dist: yarn --cwd ui build .PHONY: plugin-linux -plugin-linux: ui/dist +plugin-linux: ui/dist ## build plugin for linux cp -r ui/dist/app/* server/static CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-linux-amd64 ./cmd/kubectl-argo-rollouts CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-linux-arm64 ./cmd/kubectl-argo-rollouts .PHONY: plugin-darwin -plugin-darwin: ui/dist +plugin-darwin: ui/dist ## build plugin for darwin cp -r ui/dist/app/* server/static CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-darwin-amd64 ./cmd/kubectl-argo-rollouts CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-darwin-arm64 ./cmd/kubectl-argo-rollouts .PHONY: plugin-windows -plugin-windows: ui/dist +plugin-windows: ui/dist ## build plugin for windows cp -r ui/dist/app/* server/static CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/${PLUGIN_CLI_NAME}-windows-amd64 ./cmd/kubectl-argo-rollouts -.PHONY: docs -docs: - go run ./hack/gen-docs/main.go +##@ Build + +.PHONY: controller +controller: ## build controller binary + CGO_ENABLED=0 go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/rollouts-controller ./cmd/rollouts-controller .PHONY: builder-image -builder-image: +builder-image: ## build builder image DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)argo-rollouts-ci-builder:$(IMAGE_TAG) --target builder . @if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) ; fi @@ -198,25 +204,34 @@ else endif @if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)argo-rollouts:$(IMAGE_TAG) ; fi + +# Build sample plugin with debug info +# https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html +.PHONY: build-sample-metric-plugin-debug +build-sample-metric-plugin-debug: ## build sample metric plugin with debug info + go build -gcflags="all=-N -l" -o metric-plugin test/cmd/metrics-plugin-sample/main.go + +.PHONY: build-sample-traffic-plugin-debug +build-sample-traffic-plugin-debug: ## build sample traffic plugin with debug info + go build -gcflags="all=-N -l" -o traffic-plugin test/cmd/trafficrouter-plugin-sample/main.go + .PHONY: plugin-image -plugin-image: +plugin-image: ## build plugin image DOCKER_BUILDKIT=1 docker build --target kubectl-argo-rollouts -t $(IMAGE_PREFIX)kubectl-argo-rollouts:$(IMAGE_TAG) . if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)kubectl-argo-rollouts:$(IMAGE_TAG) ; fi -.PHONY: lint -lint: go-mod-vendor - golangci-lint run --fix +##@ Test .PHONY: test -test: test-kustomize +test: test-kustomize ## run all tests @make test-unit .PHONY: test-kustomize -test-kustomize: +test-kustomize: ## run kustomize tests ./test/kustomize/test.sh .PHONY: start-e2e -start-e2e: +start-e2e: ## start e2e test environment go run ./cmd/rollouts-controller/main.go --instance-id ${E2E_INSTANCE_ID} --loglevel debug --kloglevel 6 .PHONY: test-e2e @@ -224,55 +239,63 @@ test-e2e: install-devtools-local ${DIST_DIR}/gotestsum --rerun-fails-report=rerunreport.txt --junitfile=junit.xml --format=testname --packages="./test/e2e" --rerun-fails=5 -- -timeout 60m -count 1 --tags e2e -p ${E2E_PARALLEL} -parallel ${E2E_PARALLEL} -v --short ./test/e2e ${E2E_TEST_OPTIONS} .PHONY: test-unit - test-unit: install-devtools-local + test-unit: install-devtools-local ## run unit tests ${DIST_DIR}/gotestsum --junitfile=junit.xml --format=testname -- -covermode=count -coverprofile=coverage.out `go list ./... | grep -v ./test/cmd/metrics-plugin-sample` .PHONY: coverage -coverage: test +coverage: test ## run coverage tests go tool cover -html=coverage.out -o coverage.html open coverage.html .PHONY: manifests -manifests: +manifests: ## generate manifests e.g. CRD, RBAC etc. ./hack/update-manifests.sh .PHONY: clean -clean: +clean: ## clean up build artifacts -rm -rf ${CURRENT_DIR}/dist -rm -rf ${CURRENT_DIR}/ui/dist .PHONY: precheckin precheckin: test lint +##@ Docs + +# convenience target to run `mkdocs serve` using a docker container +.PHONY: serve-docs +serve-docs: docs ## serve docs locally + docker run --rm -it -p 8000:8000 -v ${CURRENT_DIR}:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8000 + +.PHONY: docs +docs: ## build docs + go run ./hack/gen-docs/main.go + +##@ Release + .PHONY: release-docs -release-docs: docs +release-docs: docs ## build and deploy docs docker run --rm -it \ -v ~/.ssh:/root/.ssh \ -v ${CURRENT_DIR}:/docs \ -v ~/.gitconfig:/root/.gitconfig \ squidfunk/mkdocs-material gh-deploy -r ${GIT_REMOTE_REPO} -# convenience target to run `mkdocs serve` using a docker container -.PHONY: serve-docs -serve-docs: docs - docker run --rm -it -p 8000:8000 -v ${CURRENT_DIR}:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8000 - .PHONY: release-precheck -release-precheck: manifests +release-precheck: manifests ## precheck release @if [ "$(GIT_TREE_STATE)" != "clean" ]; then echo 'git tree state is $(GIT_TREE_STATE)' ; exit 1; fi @if [ -z "$(GIT_TAG)" ]; then echo 'commit must be tagged to perform release' ; exit 1; fi @if [ "$(GIT_TAG)" != "v`cat VERSION`" ]; then echo 'VERSION does not match git tag'; exit 1; fi .PHONY: release-plugins -release-plugins: +release-plugins: ## build and push plugins ./hack/build-release-plugins.sh .PHONY: release release: release-precheck precheckin image plugin-image release-plugins .PHONY: trivy -trivy: +trivy: ## run trivy scan @trivy fs --clear-cache @trivy fs . @@ -280,13 +303,6 @@ trivy: checksums: shasum -a 256 ./dist/kubectl-argo-rollouts-* | awk -F './dist/' '{print $$1 $$2}' > ./dist/argo-rollouts-checksums.txt -# Build sample plugin with debug info -# https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html -.PHONY: build-sample-metric-plugin-debug -build-sample-metric-plugin-debug: - go build -gcflags="all=-N -l" -o metric-plugin test/cmd/metrics-plugin-sample/main.go - -.PHONY: build-sample-traffic-plugin-debug -build-sample-traffic-plugin-debug: - go build -gcflags="all=-N -l" -o traffic-plugin test/cmd/trafficrouter-plugin-sample/main.go +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) diff --git a/analysis/analysis.go b/analysis/analysis.go index c826280d19..fb307e62e0 100644 --- a/analysis/analysis.go +++ b/analysis/analysis.go @@ -711,8 +711,13 @@ func calculateNextReconcileTime(run *v1alpha1.AnalysisRun, metrics []v1alpha1.Me func (c *Controller) garbageCollectMeasurements(run *v1alpha1.AnalysisRun, measurementRetentionMetricNamesMap map[string]*v1alpha1.MeasurementRetention, limit int) error { var errors []error + resolvedArgsMetric, err := getResolvedMetricsWithoutSecrets(run.Spec.Metrics, run.Spec.Args) + if err != nil { + return fmt.Errorf("failed to resolve args on metrics during garbage collection: %w", err) + } + metricsByName := make(map[string]v1alpha1.Metric) - for _, metric := range run.Spec.Metrics { + for _, metric := range resolvedArgsMetric { metricsByName[metric.Name] = metric } diff --git a/analysis/analysis_test.go b/analysis/analysis_test.go index ed12da2dca..cec3446b89 100644 --- a/analysis/analysis_test.go +++ b/analysis/analysis_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/argoproj/argo-rollouts/metric" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -1099,6 +1101,102 @@ func TestTrimMeasurementHistory(t *testing.T) { } } +func TestGarbageCollectArgResolution(t *testing.T) { + f := newFixture(t) + defer f.Close() + c, _, _ := f.newController(noResyncPeriodFunc) + + c.newProvider = func(logCtx log.Entry, metric v1alpha1.Metric) (metric.Provider, error) { + assert.Equal(t, "https://prometheus.kubeaddons:8080", metric.Provider.Prometheus.Address) + return f.provider, nil + } + + f.provider.On("GarbageCollect", mock.Anything, mock.Anything, mock.Anything).Return(nil) + run := &v1alpha1.AnalysisRun{ + Spec: v1alpha1.AnalysisRunSpec{ + Metrics: []v1alpha1.Metric{ + { + Name: "metric1", + Interval: "60s", + Provider: v1alpha1.MetricProvider{ + Prometheus: &v1alpha1.PrometheusMetric{ + Address: "https://prometheus.kubeaddons:{{args.port}}", + }, + }, + }, + { + Name: "metric2", + Interval: "60s", + Provider: v1alpha1.MetricProvider{ + Prometheus: &v1alpha1.PrometheusMetric{ + Address: "https://prometheus.kubeaddons:{{args.port}}", + }, + }, + }, + }, + }, + Status: v1alpha1.AnalysisRunStatus{ + Phase: v1alpha1.AnalysisPhaseRunning, + MetricResults: []v1alpha1.MetricResult{ + { + Name: "metric1", + Phase: v1alpha1.AnalysisPhaseRunning, + Measurements: []v1alpha1.Measurement{ + { + Value: "1", + Phase: v1alpha1.AnalysisPhaseSuccessful, + StartedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + FinishedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + }, + { + Value: "2", + Phase: v1alpha1.AnalysisPhaseSuccessful, + StartedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + FinishedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + }, + }, + }, + { + Name: "metric2", + Measurements: []v1alpha1.Measurement{ + { + Value: "2", + Phase: v1alpha1.AnalysisPhaseSuccessful, + StartedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + FinishedAt: timePtr(metav1.NewTime(time.Now().Add(-60 * time.Second))), + }, + { + Value: "3", + Phase: v1alpha1.AnalysisPhaseSuccessful, + StartedAt: timePtr(metav1.NewTime(time.Now().Add(-30 * time.Second))), + FinishedAt: timePtr(metav1.NewTime(time.Now().Add(-30 * time.Second))), + }, + { + Value: "4", + Phase: v1alpha1.AnalysisPhaseSuccessful, + StartedAt: timePtr(metav1.NewTime(time.Now().Add(-30 * time.Second))), + FinishedAt: timePtr(metav1.NewTime(time.Now().Add(-30 * time.Second))), + }, + }, + }, + }, + }, + } + run.Spec.Args = append(run.Spec.Args, v1alpha1.Argument{ + Name: "port", + Value: pointer.String("8080"), + }) + var measurementRetentionMetricsMap = map[string]*v1alpha1.MeasurementRetention{} + measurementRetentionMetricsMap["metric2"] = &v1alpha1.MeasurementRetention{MetricName: "metric2", Limit: 2} + err := c.garbageCollectMeasurements(run, measurementRetentionMetricsMap, 1) + assert.Nil(t, err) + assert.Len(t, run.Status.MetricResults[0].Measurements, 1) + assert.Equal(t, "2", run.Status.MetricResults[0].Measurements[0].Value) + assert.Len(t, run.Status.MetricResults[1].Measurements, 2) + assert.Equal(t, "3", run.Status.MetricResults[1].Measurements[0].Value) + assert.Equal(t, "4", run.Status.MetricResults[1].Measurements[1].Value) +} + func TestResolveMetricArgsUnableToSubstitute(t *testing.T) { f := newFixture(t) defer f.Close() diff --git a/controller/metrics/client.go b/controller/metrics/client.go index 01367745ef..b800a74bd8 100644 --- a/controller/metrics/client.go +++ b/controller/metrics/client.go @@ -27,7 +27,7 @@ func (m *K8sRequestsCountProvider) IncKubernetesRequest(resourceInfo kubeclientm namespace := resourceInfo.Namespace kind := resourceInfo.Kind statusCode := strconv.Itoa(resourceInfo.StatusCode) - if resourceInfo.Verb == kubeclientmetrics.List { + if resourceInfo.Verb == kubeclientmetrics.List || kind == "events" || kind == "replicasets" { name = "N/A" } if resourceInfo.Verb == kubeclientmetrics.Unknown { diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index a325587804..a37ad29fc0 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -104,6 +104,12 @@ Then run the e2e tests: make test-e2e ``` +To run a subset of e2e tests, you need to specify the suite with `-run`, and the specific test regex with `-testify.m`. + +``` +E2E_TEST_OPTIONS="-run 'TestCanarySuite' -testify.m 'TestCanaryScaleDownOnAbortNoTrafficRouting'" make test-e2e +``` + ## Controller architecture Argo Rollouts is actually a collection of individual controllers diff --git a/docs/features/kustomize/rollout_cr_schema.json b/docs/features/kustomize/rollout_cr_schema.json index d980188a93..9d11edb202 100644 --- a/docs/features/kustomize/rollout_cr_schema.json +++ b/docs/features/kustomize/rollout_cr_schema.json @@ -17124,6 +17124,22 @@ "type": "array", "x-kubernetes-patch-merge-key": "metricName", "x-kubernetes-patch-strategy": "merge" + }, + "templates": { + "items": { + "properties": { + "clusterScope": { + "type": "boolean" + }, + "templateName": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array", + "x-kubernetes-patch-merge-key": "templateName", + "x-kubernetes-patch-strategy": "merge" } }, "type": "object" @@ -17204,6 +17220,22 @@ "type": "array", "x-kubernetes-patch-merge-key": "metricName", "x-kubernetes-patch-strategy": "merge" + }, + "templates": { + "items": { + "properties": { + "clusterScope": { + "type": "boolean" + }, + "templateName": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array", + "x-kubernetes-patch-merge-key": "templateName", + "x-kubernetes-patch-strategy": "merge" } }, "type": "object" @@ -17292,6 +17324,22 @@ "type": "array", "x-kubernetes-patch-merge-key": "metricName", "x-kubernetes-patch-strategy": "merge" + }, + "templates": { + "items": { + "properties": { + "clusterScope": { + "type": "boolean" + }, + "templateName": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array", + "x-kubernetes-patch-merge-key": "templateName", + "x-kubernetes-patch-strategy": "merge" } }, "type": "object" diff --git a/docs/migrating.md b/docs/migrating.md index ee603a2999..62e3494e3d 100644 --- a/docs/migrating.md +++ b/docs/migrating.md @@ -50,11 +50,11 @@ spec: ## Reference Deployment From Rollout -Instead of removing Deployment you can scale-down in to zero and reference from the Rollout resource: +Instead of removing Deployment you can scale it down to zero and reference it from the Rollout resource: 1. Create a Rollout resource. 1. Reference an existing Deployment using `workloadRef` field. -1. Scale-down existing Deployment by changing `replicas` field of an existing Deployment to zero. +1. Scale-down an existing Deployment by changing `replicas` field of an existing Deployment to zero. 1. To perform an update, the change should be made to the Pod template field of the Deployment. Below is an example of a Rollout resource referencing a Deployment. @@ -150,7 +150,8 @@ When converting a Rollout to a Deployment, it involves changing three fields: When a rollout is referencing to a deployment: -1. Scale-up the Deployment by changing `replicas` field of an existing Rollout to zero. -1. Scale-down existing Rollout by changing `replicas` field of an existing Rollout to zero. +1. Scale-up an existing Deployment by changing its `replicas` field to a desired number of pods. +1. Wait for the Deployment pods to become Ready. +1. Scale-down an existing Rollout by changing its `replicas` field to zero. Please refer to [Running Rollout and Deployment side-by-side](#running-rollout-and-deployment-side-by-side) and [Traffic Management During Migration](#traffic-management-during-migration) for caveats. diff --git a/go.mod b/go.mod index 204841b650..465afc74fa 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ require ( github.com/argoproj/notifications-engine v0.4.0 github.com/argoproj/pkg v0.13.6 github.com/aws/aws-sdk-go-v2 v1.18.1 - github.com/aws/aws-sdk-go-v2/config v1.18.26 - github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.0 - github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.11 + github.com/aws/aws-sdk-go-v2/config v1.18.27 + github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.2 + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.13 github.com/blang/semver v3.5.1+incompatible github.com/bombsimon/logrusr/v4 v4.0.0 github.com/evanphx/json-patch/v5 v5.6.0 @@ -24,7 +24,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/newrelic/newrelic-client-go v1.1.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.15.1 + github.com/prometheus/client_golang v1.16.0 github.com/prometheus/client_model v0.3.0 github.com/prometheus/common v0.42.0 github.com/prometheus/common/sigv4 v0.1.0 @@ -36,9 +36,9 @@ require ( github.com/stretchr/testify v1.8.4 github.com/tj/assert v0.0.3 github.com/valyala/fasttemplate v1.2.2 - google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 - google.golang.org/grpc v1.55.0 - google.golang.org/protobuf v1.30.0 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.56.2 + google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.25.8 k8s.io/apiextensions-apiserver v0.25.8 @@ -57,7 +57,7 @@ require ( ) require ( - cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.27 // indirect @@ -82,15 +82,15 @@ require ( github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20220708192748-b73dcb041214 // indirect github.com/aws/aws-sdk-go v1.44.116 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.25 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.13.26 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.11 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.11 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect @@ -157,7 +157,7 @@ require ( github.com/opsgenie/opsgenie-go-sdk-v2 v1.2.13 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/slack-go/slack v0.12.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect @@ -169,11 +169,11 @@ require ( go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect golang.org/x/crypto v0.5.0 // indirect golang.org/x/mod v0.8.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45 // indirect diff --git a/go.sum b/go.sum index 2dadb09918..d21daece7d 100644 --- a/go.sum +++ b/go.sum @@ -19,8 +19,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf 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/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -101,35 +101,32 @@ github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2z github.com/aws/aws-sdk-go v1.44.39/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.116 h1:NpLIhcvLWXJZAEwvPj3TDHeqp7DleK6ZUVYyW01WNHY= github.com/aws/aws-sdk-go v1.44.116/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/aws/aws-sdk-go-v2 v1.18.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.18.1 h1:+tefE750oAb7ZQGzla6bLkOwfcQCEtC5y2RqoqCeqKo= github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= -github.com/aws/aws-sdk-go-v2/config v1.18.26 h1:ivCHcSmKd1+9rBlqVsxZHB35eCW88KWbMdG2VL3BuBw= -github.com/aws/aws-sdk-go-v2/config v1.18.26/go.mod h1:NVmd//z/PNl7U+ZU2EnuffxOA060JWzgbH3BnqQrUoY= -github.com/aws/aws-sdk-go-v2/credentials v1.13.25 h1:5wROoMcUC7nAE66e0b3IIht6Tos76M4HC+GQw8MeqxU= -github.com/aws/aws-sdk-go-v2/credentials v1.13.25/go.mod h1:W9I2660WXSwZQ23mM1Ks72+UGeyirIxuU7/KzN7daeA= +github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= +github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26 h1:qmU+yhKmOCyujmuPY7tf5MxR/RKyZrOPO3V4DobiTUk= +github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 h1:LxK/bitrAr4lnh9LnIS6i7zWbCOdMsfzKFBI6LUCS0I= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34 h1:A5UqQEmPaCFpedKouS4v+dHCTUo2sKqhoKO9U5kxyWo= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.27/go.mod h1:UrHnn3QV/d0pBZ6QBAEQcqFLf8FAzLmoUfPVIueOvoM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28 h1:srIVS45eQuewqz6fKKu6ZGXaq6FuFg5NzgQBAM6g8Y4= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 h1:LWA+3kDM8ly001vJ1X1waCuLJdtTl48gwkPKWy9sosI= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.0 h1:sSzrsKQULJmPtmu6By4wR6g0701nGqonssKOy35uOd0= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.0/go.mod h1:t5mizLPjCYafXoHCXOHJU7z4OvLbY70Echvb1ciBTV4= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.11 h1:IN2XMTLmhIEL5e3o+tY9JsLFSAxmjgM8gI7W2+CPrpw= -github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.11/go.mod h1:oPHYtcocUcfHOE7qygtvyZMw82nedCKZSop/R9jxlAM= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.2 h1:PWGu2JhCb/XJlJ7SSFJq76pxk4xWsN76nZxh7TzMHx0= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.26.2/go.mod h1:2KOZkkzMDZCo/aLzPhys06mHNkiU74u85aMJA3PLRvg= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.13 h1:g/Kzed9qNdvz5p7Av3ffavD19eN11deWqlHgR2JuXuw= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.13/go.mod h1:BNkuX97Xp8meRKwZkWlXajo3u4cP/B3TC+YsadbOfaM= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 h1:bkRyG4a929RCnpVSTvLM2j/T4ls015ZhhYApbmYs15s= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.11 h1:cNrMc266RsZJ8V1u1OQQONKcf9HmfxQFqgcpY7ZJBhY= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.11/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.11 h1:h2VhtCE5PBiJefmlVCjJRSzBfFcQeAE10SXIGkXw1jQ= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.11/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.1 h1:ehPTnLR/es8TL1fpBfq8qw9cAwOpQr47fLmZD9yhHjk= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.1/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 h1:nneMBM2p79PGWBQovYO/6Xnc2ryRMw3InnDJq1FHkSY= +github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 h1:2qTR7IFk7/0IN/adSFhYu9Xthr0zVFTgBrmPldILn80= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 h1:XFJ2Z6sNUUcAz9poj+245DMkrHE4h2j5I9/xD50RHfE= +github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= @@ -596,8 +593,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= -github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -616,8 +613,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -812,16 +809,16 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/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-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= 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= @@ -833,7 +830,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -899,13 +896,13 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220406155245-289d7a0edf71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -915,8 +912,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/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.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= @@ -1042,8 +1039,8 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D 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-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= 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= @@ -1059,8 +1056,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= 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= @@ -1075,8 +1072,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= diff --git a/pkg/apiclient/rollout/rollout.swagger.json b/pkg/apiclient/rollout/rollout.swagger.json index a34dbc3181..68b207b930 100755 --- a/pkg/apiclient/rollout/rollout.swagger.json +++ b/pkg/apiclient/rollout/rollout.swagger.json @@ -1224,7 +1224,7 @@ "items": { "$ref": "#/definitions/github.com.argoproj.argo_rollouts.pkg.apis.rollouts.v1alpha1.RolloutAnalysisTemplate" }, - "title": "Templates reference to a list of analysis templates to combine for an AnalysisRun" + "title": "Templates reference to a list of analysis templates to combine for an AnalysisRun\n+patchMergeKey=templateName\n+patchStrategy=merge" }, "args": { "type": "array", diff --git a/pkg/apis/rollouts/v1alpha1/generated.proto b/pkg/apis/rollouts/v1alpha1/generated.proto index 639bee70ed..ab5c65258e 100644 --- a/pkg/apis/rollouts/v1alpha1/generated.proto +++ b/pkg/apis/rollouts/v1alpha1/generated.proto @@ -1159,6 +1159,8 @@ message Rollout { // RolloutAnalysis defines a template that is used to create a analysisRun message RolloutAnalysis { // Templates reference to a list of analysis templates to combine for an AnalysisRun + // +patchMergeKey=templateName + // +patchStrategy=merge repeated RolloutAnalysisTemplate templates = 1; // Args the arguments that will be added to the AnalysisRuns diff --git a/pkg/apis/rollouts/v1alpha1/openapi_generated.go b/pkg/apis/rollouts/v1alpha1/openapi_generated.go index f4bf7ead1d..79251e03a0 100644 --- a/pkg/apis/rollouts/v1alpha1/openapi_generated.go +++ b/pkg/apis/rollouts/v1alpha1/openapi_generated.go @@ -3524,6 +3524,12 @@ func schema_pkg_apis_rollouts_v1alpha1_RolloutAnalysis(ref common.ReferenceCallb Type: []string{"object"}, Properties: map[string]spec.Schema{ "templates": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-patch-merge-key": "templateName", + "x-kubernetes-patch-strategy": "merge", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Templates reference to a list of analysis templates to combine for an AnalysisRun", Type: []string{"array"}, @@ -3620,6 +3626,12 @@ func schema_pkg_apis_rollouts_v1alpha1_RolloutAnalysisBackground(ref common.Refe Type: []string{"object"}, Properties: map[string]spec.Schema{ "templates": { + VendorExtensible: spec.VendorExtensible{ + Extensions: spec.Extensions{ + "x-kubernetes-patch-merge-key": "templateName", + "x-kubernetes-patch-strategy": "merge", + }, + }, SchemaProps: spec.SchemaProps{ Description: "Templates reference to a list of analysis templates to combine for an AnalysisRun", Type: []string{"array"}, diff --git a/pkg/apis/rollouts/v1alpha1/types.go b/pkg/apis/rollouts/v1alpha1/types.go index bf9209b994..6f93585fd9 100755 --- a/pkg/apis/rollouts/v1alpha1/types.go +++ b/pkg/apis/rollouts/v1alpha1/types.go @@ -695,8 +695,10 @@ type RolloutAnalysisBackground struct { // RolloutAnalysis defines a template that is used to create a analysisRun type RolloutAnalysis struct { - //Templates reference to a list of analysis templates to combine for an AnalysisRun - Templates []RolloutAnalysisTemplate `json:"templates,omitempty" protobuf:"bytes,1,rep,name=templates"` + // Templates reference to a list of analysis templates to combine for an AnalysisRun + // +patchMergeKey=templateName + // +patchStrategy=merge + Templates []RolloutAnalysisTemplate `json:"templates,omitempty" patchStrategy:"merge" patchMergeKey:"templateName" protobuf:"bytes,1,rep,name=templates"` // Args the arguments that will be added to the AnalysisRuns // +patchMergeKey=name // +patchStrategy=merge diff --git a/rollout/canary_test.go b/rollout/canary_test.go index 56445f3978..1811f6a4c4 100644 --- a/rollout/canary_test.go +++ b/rollout/canary_test.go @@ -427,7 +427,6 @@ func TestResetCurrentStepIndexOnStepChange(t *testing.T) { newConditions := generateConditionsPatch(true, conditions.ReplicaSetUpdatedReason, r2, false, "", false) expectedPatch := fmt.Sprintf(expectedPatchWithoutPodHash, expectedCurrentPodHash, expectedCurrentStepHash, newConditions) assert.Equal(t, calculatePatch(r2, expectedPatch), patch) - } func TestResetCurrentStepIndexOnPodSpecChange(t *testing.T) { @@ -469,7 +468,6 @@ func TestResetCurrentStepIndexOnPodSpecChange(t *testing.T) { expectedPatch := fmt.Sprintf(expectedPatchWithoutPodHash, expectedCurrentPodHash, newConditions) assert.Equal(t, calculatePatch(r2, expectedPatch), patch) - } func TestCanaryRolloutCreateFirstReplicasetNoSteps(t *testing.T) { @@ -708,7 +706,6 @@ func TestCanaryRolloutScaleDownOldRsDontScaleDownTooMuch(t *testing.T) { assert.Equal(t, int32(0), *updatedRS1.Spec.Replicas) updatedRS2 := f.getUpdatedReplicaSet(updatedRS2Index) assert.Equal(t, int32(4), *updatedRS2.Spec.Replicas) - } // TestCanaryDontScaleDownOldRsDuringInterruptedUpdate tests when we need to prevent scale down an @@ -1019,9 +1016,8 @@ func TestSyncRolloutWaitAddToQueue(t *testing.T) { c, i, k8sI := f.newController(func() time.Duration { return 30 * time.Minute }) f.runController(key, true, false, c, i, k8sI) - //When the controller starts, it will enqueue the rollout while syncing the informer and during the reconciliation step + // When the controller starts, it will enqueue the rollout while syncing the informer and during the reconciliation step assert.Equal(t, 2, f.enqueuedObjects[key]) - } func TestSyncRolloutIgnoreWaitOutsideOfReconciliationPeriod(t *testing.T) { @@ -1034,7 +1030,7 @@ func TestSyncRolloutIgnoreWaitOutsideOfReconciliationPeriod(t *testing.T) { }, { Pause: &v1alpha1.RolloutPause{ - Duration: v1alpha1.DurationFromInt(3600), //1 hour + Duration: v1alpha1.DurationFromInt(3600), // 1 hour }, }, } @@ -1068,9 +1064,8 @@ func TestSyncRolloutIgnoreWaitOutsideOfReconciliationPeriod(t *testing.T) { key := fmt.Sprintf("%s/%s", r2.Namespace, r2.Name) c, i, k8sI := f.newController(func() time.Duration { return 30 * time.Minute }) f.runController(key, true, false, c, i, k8sI) - //When the controller starts, it will enqueue the rollout so we expect the rollout to enqueue at least once. + // When the controller starts, it will enqueue the rollout so we expect the rollout to enqueue at least once. assert.Equal(t, 1, f.enqueuedObjects[key]) - } func TestSyncRolloutWaitIncrementStepIndex(t *testing.T) { @@ -1084,7 +1079,8 @@ func TestSyncRolloutWaitIncrementStepIndex(t *testing.T) { Pause: &v1alpha1.RolloutPause{ Duration: v1alpha1.DurationFromInt(5), }, - }, { + }, + { Pause: &v1alpha1.RolloutPause{}, }, } @@ -1236,6 +1232,7 @@ func TestCanarySVCSelectors(t *testing.T) { }, }, } + rc := rolloutContext{ log: logutil.WithRollout(rollout), reconcilerBase: reconcilerBase{ @@ -1266,6 +1263,7 @@ func TestCanarySVCSelectors(t *testing.T) { }, }, } + stopchan := make(chan struct{}) defer close(stopchan) informers.Start(stopchan) @@ -1286,6 +1284,124 @@ func TestCanarySVCSelectors(t *testing.T) { } } +func TestCanarySVCSelectorsBasicCanaryAbortServiceSwitchBack(t *testing.T) { + for _, tc := range []struct { + canaryReplicas int32 + canaryAvailReplicas int32 + shouldAbortRollout bool + shouldTargetNewRS bool + }{ + {2, 2, false, true}, // Rollout, canaryService should point at the canary RS + {2, 2, true, false}, // Rollout aborted, canaryService should point at the stable RS + } { + namespace := "namespace" + selectorLabel := "selector-labels-test" + selectorNewRSVal := "new-rs-xxx" + selectorStableRSVal := "stable-rs-xxx" + stableService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "stable", + Namespace: namespace, + Annotations: map[string]string{v1alpha1.ManagedByRolloutsKey: selectorLabel}, + Labels: map[string]string{ + v1alpha1.DefaultRolloutUniqueLabelKey: selectorStableRSVal, + }, + }, + } + canaryService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "canary", + Namespace: namespace, + Annotations: map[string]string{v1alpha1.ManagedByRolloutsKey: selectorLabel}, + }, + } + kubeclient := k8sfake.NewSimpleClientset(stableService, canaryService) + informers := k8sinformers.NewSharedInformerFactory(kubeclient, 0) + servicesLister := informers.Core().V1().Services().Lister() + + rollout := &v1alpha1.Rollout{ + ObjectMeta: metav1.ObjectMeta{ + Name: selectorLabel, + Namespace: namespace, + }, + Spec: v1alpha1.RolloutSpec{ + Strategy: v1alpha1.RolloutStrategy{ + Canary: &v1alpha1.CanaryStrategy{ + StableService: stableService.Name, + CanaryService: canaryService.Name, + }, + }, + }, + } + + pc := pauseContext{ + rollout: rollout, + } + if tc.shouldAbortRollout { + pc.AddAbort("Add Abort") + } + + rc := rolloutContext{ + log: logutil.WithRollout(rollout), + pauseContext: &pc, + reconcilerBase: reconcilerBase{ + servicesLister: servicesLister, + kubeclientset: kubeclient, + recorder: record.NewFakeEventRecorder(), + }, + rollout: rollout, + newRS: &v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "canary", + Namespace: namespace, + Labels: map[string]string{ + v1alpha1.DefaultRolloutUniqueLabelKey: selectorNewRSVal, + }, + }, + Spec: v1.ReplicaSetSpec{ + Replicas: pointer.Int32Ptr(tc.canaryReplicas), + }, + Status: v1.ReplicaSetStatus{ + AvailableReplicas: tc.canaryAvailReplicas, + }, + }, + stableRS: &v1.ReplicaSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "stable", + Namespace: namespace, + Labels: map[string]string{ + v1alpha1.DefaultRolloutUniqueLabelKey: selectorStableRSVal, + }, + }, + Spec: v1.ReplicaSetSpec{ + Replicas: pointer.Int32Ptr(tc.canaryReplicas), + }, + Status: v1.ReplicaSetStatus{ + AvailableReplicas: tc.canaryAvailReplicas, + }, + }, + } + + stopchan := make(chan struct{}) + defer close(stopchan) + informers.Start(stopchan) + informers.WaitForCacheSync(stopchan) + err := rc.reconcileStableAndCanaryService() + assert.NoError(t, err, "unable to reconcileStableAndCanaryService") + updatedCanarySVC, err := servicesLister.Services(rc.rollout.Namespace).Get(canaryService.Name) + assert.NoError(t, err, "unable to get updated canary service") + if tc.shouldTargetNewRS { + assert.Equal(t, selectorNewRSVal, updatedCanarySVC.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey], + "canary SVC should have newRS selector label when newRS has %d replicas and %d AvailableReplicas", + tc.canaryReplicas, tc.canaryAvailReplicas) + } else { + assert.Equal(t, selectorStableRSVal, updatedCanarySVC.Spec.Selector[v1alpha1.DefaultRolloutUniqueLabelKey], + "canary SVC should have stableRS selector label when newRS has %d replicas and %d AvailableReplicas", + tc.canaryReplicas, tc.canaryAvailReplicas) + } + } +} + func TestCanaryRolloutWithInvalidCanaryServiceName(t *testing.T) { f := newFixture(t) defer f.Close() diff --git a/rollout/service.go b/rollout/service.go index de63f527b3..f808cb55fc 100644 --- a/rollout/service.go +++ b/rollout/service.go @@ -257,6 +257,15 @@ func (c *rolloutContext) reconcileStableAndCanaryService() error { if err != nil { return err } + + if c.pauseContext != nil && c.pauseContext.IsAborted() && c.rollout.Spec.Strategy.Canary.TrafficRouting == nil { + err = c.ensureSVCTargets(c.rollout.Spec.Strategy.Canary.CanaryService, c.stableRS, true) + if err != nil { + return err + } + return nil + } + err = c.ensureSVCTargets(c.rollout.Spec.Strategy.Canary.CanaryService, c.newRS, true) if err != nil { return err diff --git a/rollout/trafficrouting.go b/rollout/trafficrouting.go index c00eb66e1b..1b694d517a 100644 --- a/rollout/trafficrouting.go +++ b/rollout/trafficrouting.go @@ -143,11 +143,7 @@ func (c *rolloutContext) reconcileTrafficRouting() error { c.newStatus.Canary.Weights = nil return nil } - if reconcilers == nil { - // Not using traffic routing - c.newStatus.Canary.Weights = nil - return nil - } + c.log.Infof("Found %d TrafficRouting Reconcilers", len(reconcilers)) // iterate over the list of trafficReconcilers for _, reconciler := range reconcilers { diff --git a/test/e2e/canary_test.go b/test/e2e/canary_test.go index 00b588c598..fe22175074 100644 --- a/test/e2e/canary_test.go +++ b/test/e2e/canary_test.go @@ -443,7 +443,7 @@ spec: port: 80 periodSeconds: 30 strategy: - canary: + canary: steps: - setWeight: 20 - pause: {} @@ -539,7 +539,24 @@ func (s *CanarySuite) TestCanaryScaleDownOnAbort() { AbortRollout(). WaitForRolloutStatus("Degraded"). Then(). - //Expect that the canary service selector has been moved back to stable + // Expect that the canary service selector has been moved back to stable + ExpectServiceSelector("canary-scaledowndelay-canary", map[string]string{"app": "canary-scaledowndelay", "rollouts-pod-template-hash": "66597877b7"}, false). + When(). + Sleep(3*time.Second). + Then(). + ExpectRevisionPodCount("2", 0) +} + +func (s *CanarySuite) TestCanaryScaleDownOnAbortNoTrafficRouting() { + s.Given(). + HealthyRollout(`@functional/canary-scaledownonabortnotrafficrouting.yaml`). + When(). + UpdateSpec(). // update to revision 2 + WaitForRolloutStatus("Paused"). + AbortRollout(). + WaitForRolloutStatus("Degraded"). + Then(). + // Expect that the canary service selector has been moved back to stable ExpectServiceSelector("canary-scaledowndelay-canary", map[string]string{"app": "canary-scaledowndelay", "rollouts-pod-template-hash": "66597877b7"}, false). When(). Sleep(3*time.Second). @@ -590,7 +607,7 @@ func (s *CanarySuite) TestCanaryDynamicStableScale() { WaitForRevisionPodCount("2", 1). Then(). ExpectRevisionPodCount("1", 4). - //Assert that the canary service selector is still not set to stable rs because of dynamic stable scale still in progress + // Assert that the canary service selector is still not set to stable rs because of dynamic stable scale still in progress Assert(func(t *fixtures.Then) { canarySvc, stableSvc := t.GetServices() assert.NotEqual(s.T(), canarySvc.Spec.Selector["rollouts-pod-template-hash"], stableSvc.Spec.Selector["rollouts-pod-template-hash"]) @@ -599,7 +616,7 @@ func (s *CanarySuite) TestCanaryDynamicStableScale() { MarkPodsReady("1", 1). // mark last remaining stable pod as ready (4/4 stable are ready) WaitForRevisionPodCount("2", 0). Then(). - //Expect that the canary service selector is now set to stable because of dynamic stable scale is over and we have all pods up on stable rs + // Expect that the canary service selector is now set to stable because of dynamic stable scale is over and we have all pods up on stable rs ExpectServiceSelector("dynamic-stable-scale-canary", map[string]string{"app": "dynamic-stable-scale", "rollouts-pod-template-hash": "868d98995b"}, false). ExpectRevisionPodCount("1", 4) } diff --git a/test/e2e/functional/canary-scaledownonabortnotrafficrouting.yaml b/test/e2e/functional/canary-scaledownonabortnotrafficrouting.yaml new file mode 100644 index 0000000000..0c42735db3 --- /dev/null +++ b/test/e2e/functional/canary-scaledownonabortnotrafficrouting.yaml @@ -0,0 +1,91 @@ +apiVersion: v1 +kind: Service +metadata: + name: canary-scaledowndelay-root +spec: + type: NodePort + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: canary-scaledowndelay +--- +apiVersion: v1 +kind: Service +metadata: + name: canary-scaledowndelay-canary +spec: + type: NodePort + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: canary-scaledowndelay +--- +apiVersion: v1 +kind: Service +metadata: + name: canary-scaledowndelay-stable +spec: + type: NodePort + ports: + - port: 80 + targetPort: http + protocol: TCP + name: http + selector: + app: canary-scaledowndelay +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: canary-scaledowndelay-ingress + annotations: + kubernetes.io/ingress.class: alb +spec: + rules: + - http: + paths: + - path: /* + pathType: Prefix + backend: + service: + name: canary-scaledowndelay-root + port: + name: use-annotation +--- +apiVersion: argoproj.io/v1alpha1 +kind: Rollout +metadata: + name: canary-scaledownd-on-abort +spec: + selector: + matchLabels: + app: canary-scaledowndelay + template: + metadata: + labels: + app: canary-scaledowndelay + spec: + containers: + - name: canary-scaledowndelay + image: nginx:1.19-alpine + ports: + - name: http + containerPort: 80 + protocol: TCP + resources: + requests: + memory: 16Mi + cpu: 5m + strategy: + canary: + canaryService: canary-scaledowndelay-canary + stableService: canary-scaledowndelay-stable + steps: + - setWeight: 50 + - pause: {}