diff --git a/.github/workflows/init-branch-release.yaml b/.github/workflows/init-branch-release.yaml index 861f76b2..07416c6b 100644 --- a/.github/workflows/init-branch-release.yaml +++ b/.github/workflows/init-branch-release.yaml @@ -57,7 +57,7 @@ jobs: git diff - name: Create pull request - uses: peter-evans/create-pull-request@v7.0.5 + uses: peter-evans/create-pull-request@v7.0.6 with: commit-message: "Bump version to ${{ inputs.TARGET_VERSION }}" title: "Bump version to ${{ inputs.TARGET_VERSION }} on ${{ inputs.TARGET_BRANCH }} branch" diff --git a/.github/workflows/pull_request-helm.yaml b/.github/workflows/pull_request-helm.yaml index 8bb5d602..b3f80eb1 100644 --- a/.github/workflows/pull_request-helm.yaml +++ b/.github/workflows/pull_request-helm.yaml @@ -16,7 +16,7 @@ env: jobs: - helm-validation: + helm-chart-validation: permissions: contents: read @@ -42,6 +42,24 @@ jobs: with: charts: deployments/kubernetes/chart/reloader + helm-version-validation: + needs: helm-chart-validation + + permissions: + contents: read + + runs-on: ubuntu-latest + name: Helm Version Validation + if: ${{ contains(github.event.pull_request.labels.*.name, 'release/helm-chart') }} + + steps: + + - name: Check out code + uses: actions/checkout@v4 + with: + ref: ${{github.event.pull_request.head.sha}} + fetch-depth: 0 + - name: Add Stakater Helm Repo run: | helm repo add stakater https://stakater.github.io/stakater-charts diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 8c0b96b0..46e2566b 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -25,7 +25,7 @@ env: jobs: qa: - uses: stakater/.github/.github/workflows/pull_request_doc_qa.yaml@v0.0.106 + uses: stakater/.github/.github/workflows/pull_request_doc_qa.yaml@v0.0.114 with: MD_CONFIG: .github/md_config.json DOC_SRC: README.md diff --git a/.github/workflows/pull_request_docs.yaml b/.github/workflows/pull_request_docs.yaml index cbd7c433..163ba907 100644 --- a/.github/workflows/pull_request_docs.yaml +++ b/.github/workflows/pull_request_docs.yaml @@ -15,7 +15,7 @@ on: jobs: qa: - uses: stakater/.github/.github/workflows/pull_request_doc_qa.yaml@v0.0.106 + uses: stakater/.github/.github/workflows/pull_request_doc_qa.yaml@v0.0.114 with: MD_CONFIG: .github/md_config.json DOC_SRC: docs diff --git a/.github/workflows/push-helm-chart.yaml b/.github/workflows/push-helm-chart.yaml index 404bb496..7c836322 100644 --- a/.github/workflows/push-helm-chart.yaml +++ b/.github/workflows/push-helm-chart.yaml @@ -15,14 +15,14 @@ env: REGISTRY: ghcr.io jobs: - build: + verify-and-push-helm-chart: permissions: contents: read packages: write # to push artifacts to `ghcr.io` - name: Build - if: github.event.pull_request.merged == true + name: Verify and Push Helm Chart + if: ${{ (github.event.pull_request.merged == true) && (contains(github.event.pull_request.labels.*.name, 'release/helm-chart')) }} runs-on: ubuntu-latest steps: diff --git a/.github/workflows/push-pr-image.yaml b/.github/workflows/push-pr-image.yaml index 27917441..ae051b93 100644 --- a/.github/workflows/push-pr-image.yaml +++ b/.github/workflows/push-pr-image.yaml @@ -5,6 +5,15 @@ on: branches: - master types: [ labeled ] + paths: + - '!.markdownlint.yaml' + - '!.vale.ini' + - '!Dockerfile-docs' + - '!docs-nginx.conf' + - '!docs/**' + - '!theme_common' + - '!theme_override' + - '!deployments/kubernetes/chart/reloader/**' env: DOCKER_FILE_PATH: Dockerfile diff --git a/.vale.ini b/.vale.ini index b753dba6..3a737bb4 100644 --- a/.vale.ini +++ b/.vale.ini @@ -1,7 +1,7 @@ StylesPath = styles MinAlertLevel = warning -Packages = https://github.com/stakater/vale-package/releases/download/v0.0.44/Stakater.zip +Packages = https://github.com/stakater/vale-package/releases/download/v0.0.47/Stakater.zip Vocab = Stakater # Only check MarkDown files diff --git a/README.md b/README.md index ebaad021..98e6bc80 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ We can also specify a specific configmap or secret which would trigger rolling u To do this either set the auto annotation to `"false"` (`reloader.stakater.com/auto: "false"`) or remove it altogether, and use annotations for [Configmap](.#Configmap) or [Secret](.#Secret). It's also possible to enable auto reloading for all resources, by setting the `--auto-reload-all` flag. -In this case, all resources that do not have the auto annotation (or its typed version) set to `"false"`, will be reloaded automatically when their ConfigMaps or Secrets are updated. +In this case, all resources that do not have the auto annotation (or its typed version) set to `"false"`, will be reloaded automatically when their Configmaps or Secrets are updated. Notice that setting the auto annotation to an undefined value counts as false as-well. ### Configmap @@ -173,6 +173,7 @@ spec: - you may want to prevent watching certain resources with the `--resources-to-ignore` flag - you can configure logging in JSON format with the `--log-format=json` option - you can configure the "reload strategy" with the `--reload-strategy=` option (details below) +- you can configure rollout reload strategy with `reloader.stakater.com/rollout-strategy` annotation, `restart` or `rollout` values are available (defaults to `rollout`) ## Reload Strategies @@ -209,8 +210,8 @@ Reloader can be configured to ignore the resources `secrets` and `configmaps` by | Argument | Description | |----------------------------------|----------------------| -| --resources-to-ignore=configMaps | To ignore configMaps | -| --resources-to-ignore=secrets | To ignore secrets | +| `--resources-to-ignore=configMaps` | To ignore configmaps | +| `--resources-to-ignore=secrets` | To ignore secrets | **Note:** At one time only one of these resource can be ignored, trying to do it will cause error in Reloader. Workaround for ignoring both resources is by scaling down the Reloader pods to `0`. @@ -328,7 +329,7 @@ helm uninstall {{RELEASE_NAME}} -n {{NAMESPACE}} | `reloader.isArgoRollouts` | Enable Argo `Rollouts`. Valid value are either `true` or `false` | boolean | `false` | | `reloader.isOpenshift` | Enable OpenShift DeploymentConfigs. Valid value are either `true` or `false` | boolean | `false` | | `reloader.ignoreSecrets` | To ignore secrets. Valid value are either `true` or `false`. Either `ignoreSecrets` or `ignoreConfigMaps` can be ignored, not both at the same time | boolean | `false` | -| `reloader.ignoreConfigMaps` | To ignore configMaps. Valid value are either `true` or `false` | boolean | `false` | +| `reloader.ignoreConfigMaps` | To ignore configmaps. Valid value are either `true` or `false` | boolean | `false` | | `reloader.reloadOnCreate` | Enable reload on create events. Valid value are either `true` or `false` | boolean | `false` | | `reloader.reloadOnDelete` | Enable reload on delete events. Valid value are either `true` or `false` | boolean | `false` | | `reloader.syncAfterRestart` | Enable sync after Reloader restarts for **Add** events, works only when reloadOnCreate is `true`. Valid value are either `true` or `false` | boolean | `false` | @@ -384,7 +385,7 @@ helm uninstall {{RELEASE_NAME}} -n {{NAMESPACE}} #### Additional Remarks -- Both `namespaceSelector` & `resourceLabelSelector` can be used together. If they are then both conditions must be met for the configmap or secret to be eligible to trigger reload events. (e.g. If a configMap matches `resourceLabelSelector` but `namespaceSelector` does not match the namespace the configmap is in, it will be ignored). +- Both `namespaceSelector` & `resourceLabelSelector` can be used together. If they are then both conditions must be met for the configmap or secret to be eligible to trigger reload events. (e.g. If a configmap matches `resourceLabelSelector` but `namespaceSelector` does not match the namespace the configmap is in, it will be ignored). - At one time only one of the resources `ignoreConfigMaps` or `ignoreSecrets` can be ignored, trying to do both will cause error in helm template compilation - Reloading of OpenShift (DeploymentConfig) and/or Argo `Rollouts` has to be enabled explicitly because it might not be always possible to use it on a cluster with restricted permissions - `isOpenShift` Recent versions of OpenShift (tested on 4.13.3) require the specified user to be in an `uid` range which is dynamically assigned by the namespace. The solution is to unset the runAsUser variable via ``deployment.securityContext.runAsUser=null`` and let OpenShift assign it at install @@ -462,6 +463,8 @@ _Helm chart versioning_: The Reloader Helm chart is maintained in [this reposito Helm chart will be released to the chart registry whenever files in `deployments/kubernetes/chart/reloader/**` change on the main branch. +Helm Chart will be released by the maintainers, on labelling a PR with `release/helm-chart` and pre-maturely updating the `version` field in `Chart.yaml` file. + ## Changelog View the [releases page](https://github.com/stakater/Reloader/releases) to see what has changed in each release. diff --git a/deployments/kubernetes/chart/reloader/Chart.yaml b/deployments/kubernetes/chart/reloader/Chart.yaml index cf6d5900..85663f23 100644 --- a/deployments/kubernetes/chart/reloader/Chart.yaml +++ b/deployments/kubernetes/chart/reloader/Chart.yaml @@ -4,7 +4,7 @@ apiVersion: v1 name: reloader description: Reloader chart that runs on kubernetes version: 1.2.2 -appVersion: v1.2.0 +appVersion: v1.2.1 keywords: - Reloader - kubernetes diff --git a/deployments/kubernetes/chart/reloader/values.yaml b/deployments/kubernetes/chart/reloader/values.yaml index ba698c77..48aab846 100644 --- a/deployments/kubernetes/chart/reloader/values.yaml +++ b/deployments/kubernetes/chart/reloader/values.yaml @@ -96,11 +96,11 @@ reloader: labels: provider: stakater group: com.stakater.platform - version: v1.2.0 + version: v1.2.1 image: name: ghcr.io/stakater/reloader base: stakater/reloader - tag: v1.2.0 + tag: v1.2.1 pullPolicy: IfNotPresent # Support for extra environment variables. env: diff --git a/internal/pkg/callbacks/rolling_upgrade.go b/internal/pkg/callbacks/rolling_upgrade.go index 4ba6207e..11da5aae 100644 --- a/internal/pkg/callbacks/rolling_upgrade.go +++ b/internal/pkg/callbacks/rolling_upgrade.go @@ -2,10 +2,11 @@ package callbacks import ( "context" - "time" "fmt" + "time" "github.com/sirupsen/logrus" + "github.com/stakater/Reloader/internal/pkg/options" "github.com/stakater/Reloader/pkg/kube" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" @@ -329,11 +330,15 @@ func UpdateDeploymentConfig(clients kube.Clients, namespace string, resource run // UpdateRollout performs rolling upgrade on rollout func UpdateRollout(clients kube.Clients, namespace string, resource runtime.Object) error { + var err error rollout := resource.(*argorolloutv1alpha1.Rollout) - rolloutBefore, _ := clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts(namespace).Get(context.TODO(), rollout.Name, meta_v1.GetOptions{}) - logrus.Warnf("Before: %+v", rolloutBefore.Spec.Template.Spec.Containers[0].Env) - logrus.Warnf("After: %+v", rollout.Spec.Template.Spec.Containers[0].Env) - _, err := clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts(namespace).Patch(context.TODO(), rollout.Name, patchtypes.MergePatchType, []byte(fmt.Sprintf(`{"spec": {"restartAt": "%s"}}`, time.Now().Format(time.RFC3339))), meta_v1.PatchOptions{FieldManager: "Reloader"}) + strategy := rollout.GetAnnotations()[options.RolloutStrategyAnnotation] + switch options.ToArgoRolloutStrategy(strategy) { + case options.RestartStrategy: + _, err = clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts(namespace).Patch(context.TODO(), rollout.Name, patchtypes.MergePatchType, []byte(fmt.Sprintf(`{"spec": {"restartAt": "%s"}}`, time.Now().Format(time.RFC3339))), meta_v1.PatchOptions{FieldManager: "Reloader"}) + case options.RolloutStrategy: + _, err = clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts(namespace).Update(context.TODO(), rollout, meta_v1.UpdateOptions{FieldManager: "Reloader"}) + } return err } diff --git a/internal/pkg/callbacks/rolling_upgrade_test.go b/internal/pkg/callbacks/rolling_upgrade_test.go new file mode 100644 index 00000000..4923490d --- /dev/null +++ b/internal/pkg/callbacks/rolling_upgrade_test.go @@ -0,0 +1,105 @@ +package callbacks_test + +import ( + "context" + "testing" + "time" + + argorolloutv1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + argorollouts "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned/fake" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + watch "k8s.io/apimachinery/pkg/watch" + + "github.com/stakater/Reloader/internal/pkg/callbacks" + "github.com/stakater/Reloader/internal/pkg/options" + "github.com/stakater/Reloader/internal/pkg/testutil" + "github.com/stakater/Reloader/pkg/kube" +) + +var ( + clients = kube.Clients{ArgoRolloutClient: argorollouts.NewSimpleClientset()} +) + +// TestUpdateRollout test update rollout strategy annotation +func TestUpdateRollout(t *testing.T) { + namespace := "test-ns" + + cases := map[string]struct { + name string + strategy string + isRestart bool + }{ + "test-without-strategy": { + name: "defaults to rollout strategy", + strategy: "", + isRestart: false, + }, + "test-with-restart-strategy": { + name: "triggers a restart strategy", + strategy: "restart", + isRestart: true, + }, + "test-with-rollout-strategy": { + name: "triggers a rollout strategy", + strategy: "rollout", + isRestart: false, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + rollout, err := testutil.CreateRollout( + clients.ArgoRolloutClient, name, namespace, + map[string]string{options.RolloutStrategyAnnotation: tc.strategy}, + ) + if err != nil { + t.Errorf("creating rollout: %v", err) + } + modifiedChan := watchRollout(rollout.Name, namespace) + + err = callbacks.UpdateRollout(clients, namespace, rollout) + if err != nil { + t.Errorf("updating rollout: %v", err) + } + rollout, err = clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts( + namespace).Get(context.TODO(), rollout.Name, meta_v1.GetOptions{}) + + if err != nil { + t.Errorf("getting rollout: %v", err) + } + if isRestartStrategy(rollout) == tc.isRestart { + t.Errorf("Should not be a restart strategy") + } + select { + case <-modifiedChan: + // object has been modified + case <-time.After(1 * time.Second): + t.Errorf("Rollout has not been updated") + } + }) + } +} + +func isRestartStrategy(rollout *argorolloutv1alpha1.Rollout) bool { + return rollout.Spec.RestartAt == nil +} + +func watchRollout(name, namespace string) chan interface{} { + timeOut := int64(1) + modifiedChan := make(chan interface{}) + watcher, _ := clients.ArgoRolloutClient.ArgoprojV1alpha1().Rollouts(namespace).Watch(context.Background(), meta_v1.ListOptions{TimeoutSeconds: &timeOut}) + go watchModified(watcher, name, modifiedChan) + return modifiedChan +} + +func watchModified(watcher watch.Interface, name string, modifiedChan chan interface{}) { + for event := range watcher.ResultChan() { + item := event.Object.(*argorolloutv1alpha1.Rollout) + if item.Name == name { + switch event.Type { + case watch.Modified: + modifiedChan <- nil + } + return + } + } +} diff --git a/internal/pkg/options/flags.go b/internal/pkg/options/flags.go index c252defe..081acc3e 100644 --- a/internal/pkg/options/flags.go +++ b/internal/pkg/options/flags.go @@ -2,6 +2,15 @@ package options import "github.com/stakater/Reloader/internal/pkg/constants" +type ArgoRolloutStrategy int + +const ( + // RestartStrategy is the annotation value for restart strategy for rollouts + RestartStrategy ArgoRolloutStrategy = iota + // RolloutStrategy is the annotation value for rollout strategy for rollouts + RolloutStrategy +) + var ( // Auto reload all resources when their corresponding configmaps/secrets are updated AutoReloadAll = false @@ -27,6 +36,8 @@ var ( // SearchMatchAnnotation is an annotation to tag secrets to be found with // AutoSearchAnnotation SearchMatchAnnotation = "reloader.stakater.com/match" + // RolloutStrategyAnnotation is an annotation to define rollout update strategy + RolloutStrategyAnnotation = "reloader.stakater.com/rollout-strategy" // LogFormat is the log format to use (json, or empty string for default) LogFormat = "" // LogLevel is the log level to use (trace, debug, info, warning, error, fatal and panic) @@ -45,3 +56,14 @@ var ( // Url to send a request to instead of triggering a reload WebhookUrl = "" ) + +func ToArgoRolloutStrategy(s string) ArgoRolloutStrategy { + switch s { + case "restart": + return RestartStrategy + case "rollout": + fallthrough + default: + return RolloutStrategy + } +} diff --git a/internal/pkg/testutil/kube.go b/internal/pkg/testutil/kube.go index 3faa1d22..be488e28 100644 --- a/internal/pkg/testutil/kube.go +++ b/internal/pkg/testutil/kube.go @@ -10,6 +10,8 @@ import ( "strings" "time" + argorolloutv1alpha1 "github.com/argoproj/argo-rollouts/pkg/apis/rollouts/v1alpha1" + argorollout "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned" openshiftv1 "github.com/openshift/api/apps/v1" appsclient "github.com/openshift/client-go/apps/clientset/versioned" "github.com/sirupsen/logrus" @@ -69,16 +71,16 @@ func DeleteNamespace(namespace string, client kubernetes.Interface) { } } -func getObjectMeta(namespace string, name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool) metav1.ObjectMeta { +func getObjectMeta(namespace string, name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool, extraAnnotations map[string]string) metav1.ObjectMeta { return metav1.ObjectMeta{ Name: name, Namespace: namespace, Labels: map[string]string{"firstLabel": "temp"}, - Annotations: getAnnotations(name, autoReload, secretAutoReload, configmapAutoReload), + Annotations: getAnnotations(name, autoReload, secretAutoReload, configmapAutoReload, extraAnnotations), } } -func getAnnotations(name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool) map[string]string { +func getAnnotations(name string, autoReload bool, secretAutoReload bool, configmapAutoReload bool, extraAnnotations map[string]string) map[string]string { annotations := make(map[string]string) if autoReload { annotations[options.ReloaderAutoAnnotation] = "true" @@ -90,13 +92,15 @@ func getAnnotations(name string, autoReload bool, secretAutoReload bool, configm annotations[options.ConfigmapReloaderAutoAnnotation] = "true" } - if len(annotations) > 0 { - return annotations - } else { - return map[string]string{ + if !(len(annotations) > 0) { + annotations = map[string]string{ options.ConfigmapUpdateOnChangeAnnotation: name, options.SecretUpdateOnChangeAnnotation: name} } + for k, v := range extraAnnotations { + annotations[k] = v + } + return annotations } func getEnvVarSources(name string) []v1.EnvFromSource { @@ -342,7 +346,7 @@ func getPodTemplateSpecWithInitContainerAndEnv(name string) v1.PodTemplateSpec { func GetDeployment(namespace string, deploymentName string) *appsv1.Deployment { replicaset := int32(1) return &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -361,7 +365,7 @@ func GetDeploymentConfig(namespace string, deploymentConfigName string) *openshi replicaset := int32(1) podTemplateSpecWithVolume := getPodTemplateSpecWithVolumes(deploymentConfigName) return &openshiftv1.DeploymentConfig{ - ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false, map[string]string{}), Spec: openshiftv1.DeploymentConfigSpec{ Replicas: replicaset, Strategy: openshiftv1.DeploymentStrategy{ @@ -376,7 +380,7 @@ func GetDeploymentConfig(namespace string, deploymentConfigName string) *openshi func GetDeploymentWithInitContainer(namespace string, deploymentName string) *appsv1.Deployment { replicaset := int32(1) return &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -394,7 +398,7 @@ func GetDeploymentWithInitContainer(namespace string, deploymentName string) *ap func GetDeploymentWithInitContainerAndEnv(namespace string, deploymentName string) *appsv1.Deployment { replicaset := int32(1) return &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -411,7 +415,7 @@ func GetDeploymentWithInitContainerAndEnv(namespace string, deploymentName strin func GetDeploymentWithEnvVars(namespace string, deploymentName string) *appsv1.Deployment { replicaset := int32(1) return &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -429,7 +433,7 @@ func GetDeploymentConfigWithEnvVars(namespace string, deploymentConfigName strin replicaset := int32(1) podTemplateSpecWithEnvVars := getPodTemplateSpecWithEnvVars(deploymentConfigName) return &openshiftv1.DeploymentConfig{ - ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentConfigName, false, false, false, map[string]string{}), Spec: openshiftv1.DeploymentConfigSpec{ Replicas: replicaset, Strategy: openshiftv1.DeploymentStrategy{ @@ -443,7 +447,7 @@ func GetDeploymentConfigWithEnvVars(namespace string, deploymentConfigName strin func GetDeploymentWithEnvVarSources(namespace string, deploymentName string) *appsv1.Deployment { replicaset := int32(1) return &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, true, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -460,7 +464,7 @@ func GetDeploymentWithEnvVarSources(namespace string, deploymentName string) *ap func GetDeploymentWithPodAnnotations(namespace string, deploymentName string, both bool) *appsv1.Deployment { replicaset := int32(1) deployment := &appsv1.Deployment{ - ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false), + ObjectMeta: getObjectMeta(namespace, deploymentName, false, false, false, map[string]string{}), Spec: appsv1.DeploymentSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -475,7 +479,7 @@ func GetDeploymentWithPodAnnotations(namespace string, deploymentName string, bo if !both { deployment.ObjectMeta.Annotations = nil } - deployment.Spec.Template.ObjectMeta.Annotations = getAnnotations(deploymentName, true, false, false) + deployment.Spec.Template.ObjectMeta.Annotations = getAnnotations(deploymentName, true, false, false, map[string]string{}) return deployment } @@ -483,9 +487,9 @@ func GetDeploymentWithTypedAutoAnnotation(namespace string, deploymentName strin replicaset := int32(1) var objectMeta metav1.ObjectMeta if resourceType == SecretResourceType { - objectMeta = getObjectMeta(namespace, deploymentName, false, true, false) + objectMeta = getObjectMeta(namespace, deploymentName, false, true, false, map[string]string{}) } else if resourceType == ConfigmapResourceType { - objectMeta = getObjectMeta(namespace, deploymentName, false, false, true) + objectMeta = getObjectMeta(namespace, deploymentName, false, false, true, map[string]string{}) } return &appsv1.Deployment{ @@ -537,7 +541,7 @@ func GetDeploymentWithExcludeAnnotation(namespace string, deploymentName string, // GetDaemonSet provides daemonset for testing func GetDaemonSet(namespace string, daemonsetName string) *appsv1.DaemonSet { return &appsv1.DaemonSet{ - ObjectMeta: getObjectMeta(namespace, daemonsetName, false, false, false), + ObjectMeta: getObjectMeta(namespace, daemonsetName, false, false, false, map[string]string{}), Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -552,7 +556,7 @@ func GetDaemonSet(namespace string, daemonsetName string) *appsv1.DaemonSet { func GetDaemonSetWithEnvVars(namespace string, daemonSetName string) *appsv1.DaemonSet { return &appsv1.DaemonSet{ - ObjectMeta: getObjectMeta(namespace, daemonSetName, true, false, false), + ObjectMeta: getObjectMeta(namespace, daemonSetName, true, false, false, map[string]string{}), Spec: appsv1.DaemonSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -568,7 +572,7 @@ func GetDaemonSetWithEnvVars(namespace string, daemonSetName string) *appsv1.Dae // GetStatefulSet provides statefulset for testing func GetStatefulSet(namespace string, statefulsetName string) *appsv1.StatefulSet { return &appsv1.StatefulSet{ - ObjectMeta: getObjectMeta(namespace, statefulsetName, false, false, false), + ObjectMeta: getObjectMeta(namespace, statefulsetName, false, false, false, map[string]string{}), Spec: appsv1.StatefulSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -584,7 +588,7 @@ func GetStatefulSet(namespace string, statefulsetName string) *appsv1.StatefulSe // GetStatefulSet provides statefulset for testing func GetStatefulSetWithEnvVar(namespace string, statefulsetName string) *appsv1.StatefulSet { return &appsv1.StatefulSet{ - ObjectMeta: getObjectMeta(namespace, statefulsetName, true, false, false), + ObjectMeta: getObjectMeta(namespace, statefulsetName, true, false, false, map[string]string{}), Spec: appsv1.StatefulSetSpec{ Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"secondLabel": "temp"}, @@ -1071,3 +1075,28 @@ func VerifyResourceAnnotationUpdate(clients kube.Clients, config util.Config, up func GetSHAfromEmptyData() string { return crypto.GenerateSHA("") } + +// GetRollout provides rollout for testing +func GetRollout(namespace string, rolloutName string, annotations map[string]string) *argorolloutv1alpha1.Rollout { + replicaset := int32(1) + return &argorolloutv1alpha1.Rollout{ + ObjectMeta: getObjectMeta(namespace, rolloutName, false, false, false, annotations), + Spec: argorolloutv1alpha1.RolloutSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"secondLabel": "temp"}, + }, + Replicas: &replicaset, + Template: getPodTemplateSpecWithVolumes(rolloutName), + }, + } +} + +// CreateRollout creates a rolout in given namespace and returns the Rollout +func CreateRollout(client argorollout.Interface, rolloutName string, namespace string, annotations map[string]string) (*argorolloutv1alpha1.Rollout, error) { + logrus.Infof("Creating Rollout") + rolloutClient := client.ArgoprojV1alpha1().Rollouts(namespace) + rolloutObj := GetRollout(namespace, rolloutName, annotations) + rollout, err := rolloutClient.Create(context.TODO(), rolloutObj, metav1.CreateOptions{}) + time.Sleep(3 * time.Second) + return rollout, err +}