diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index f2949a66..13e2bda0 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -36,7 +36,7 @@ type RunHistoryPolicy struct { } type RemediationStrategy struct { - AutoApply bool `json:"autoApply,omitempty"` + AutoApply *bool `json:"autoApply,omitempty"` ApplyWithoutPlanArtifact *bool `json:"applyWithoutPlanArtifact,omitempty"` OnError OnErrorRemediationStrategy `json:"onError,omitempty"` } @@ -56,30 +56,15 @@ type TerragruntConfig struct { } func GetTerraformVersion(repository *TerraformRepository, layer *TerraformLayer) string { - version := repository.Spec.TerraformConfig.Version - if len(layer.Spec.TerraformConfig.Version) > 0 { - version = layer.Spec.TerraformConfig.Version - } - return version + return chooseString(repository.Spec.TerraformConfig.Version, layer.Spec.TerraformConfig.Version) } func GetTerragruntVersion(repository *TerraformRepository, layer *TerraformLayer) string { - version := repository.Spec.TerraformConfig.TerragruntConfig.Version - if len(layer.Spec.TerraformConfig.TerragruntConfig.Version) > 0 { - version = layer.Spec.TerraformConfig.TerragruntConfig.Version - } - return version + return chooseString(repository.Spec.TerraformConfig.TerragruntConfig.Version, layer.Spec.TerraformConfig.TerragruntConfig.Version) } func GetTerragruntEnabled(repository *TerraformRepository, layer *TerraformLayer) bool { - enabled := false - if repository.Spec.TerraformConfig.TerragruntConfig.Enabled != nil { - enabled = *repository.Spec.TerraformConfig.TerragruntConfig.Enabled - } - if layer.Spec.TerraformConfig.TerragruntConfig.Enabled != nil { - enabled = *layer.Spec.TerraformConfig.TerragruntConfig.Enabled - } - return enabled + return chooseBool(repository.Spec.TerraformConfig.TerragruntConfig.Enabled, layer.Spec.TerraformConfig.TerragruntConfig.Enabled, false) } func GetOverrideRunnerSpec(repository *TerraformRepository, layer *TerraformLayer) OverrideRunnerSpec { @@ -110,44 +95,21 @@ func GetRunHistoryPolicy(repository *TerraformRepository, layer *TerraformLayer) } func GetApplyWithoutPlanArtifactEnabled(repository *TerraformRepository, layer *TerraformLayer) bool { - enabled := false - if repository.Spec.RemediationStrategy.ApplyWithoutPlanArtifact != nil { - enabled = *repository.Spec.RemediationStrategy.ApplyWithoutPlanArtifact - } - if layer.Spec.RemediationStrategy.ApplyWithoutPlanArtifact != nil { - enabled = *layer.Spec.RemediationStrategy.ApplyWithoutPlanArtifact - } - return enabled + return chooseBool(repository.Spec.RemediationStrategy.ApplyWithoutPlanArtifact, layer.Spec.RemediationStrategy.ApplyWithoutPlanArtifact, false) } -func GetRemediationStrategy(repo *TerraformRepository, layer *TerraformLayer) RemediationStrategy { - result := RemediationStrategy{ - AutoApply: false, - } - if repo.Spec.RemediationStrategy.AutoApply { - result.AutoApply = true - } - if layer.Spec.RemediationStrategy.AutoApply { - result.AutoApply = true - } - return result +func GetAutoApplyEnabled(repo *TerraformRepository, layer *TerraformLayer) bool { + return chooseBool(repo.Spec.RemediationStrategy.AutoApply, layer.Spec.RemediationStrategy.AutoApply, false) } -func mergeImagePullSecrets(a, b []corev1.LocalObjectReference) []corev1.LocalObjectReference { - result := []corev1.LocalObjectReference{} - temp := map[string]string{} - - for _, elt := range a { - temp[elt.Name] = "" - } - for _, elt := range b { - temp[elt.Name] = "" +func chooseBool(a, b *bool, defaultVal bool) bool { + if b != nil { + return *b } - - for k := range temp { - result = append(result, corev1.LocalObjectReference{Name: k}) + if a != nil { + return *a } - return result + return defaultVal } func chooseString(a, b string) string { @@ -174,6 +136,23 @@ func chooseInt(a, b *int, d int) *int { return &d } +func mergeImagePullSecrets(a, b []corev1.LocalObjectReference) []corev1.LocalObjectReference { + result := []corev1.LocalObjectReference{} + temp := map[string]string{} + + for _, elt := range a { + temp[elt.Name] = "" + } + for _, elt := range b { + temp[elt.Name] = "" + } + + for k := range temp { + result = append(result, corev1.LocalObjectReference{Name: k}) + } + return result +} + func mergeEnvFrom(a, b []corev1.EnvFromSource) []corev1.EnvFromSource { result := []corev1.EnvFromSource{} tempSecret := map[string]string{} diff --git a/api/v1alpha1/common_test.go b/api/v1alpha1/common_test.go index c35691af..933592e4 100644 --- a/api/v1alpha1/common_test.go +++ b/api/v1alpha1/common_test.go @@ -237,6 +237,42 @@ func TestGetApplyWithoutPlanArtifactEnabled(t *testing.T) { layer *configv1alpha1.TerraformLayer expected bool }{ + { + "DisabledInRepositoryEnabledInLayer", + &configv1alpha1.TerraformRepository{ + Spec: configv1alpha1.TerraformRepositorySpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + ApplyWithoutPlanArtifact: &[]bool{false}[0], + }, + }, + }, + &configv1alpha1.TerraformLayer{ + Spec: configv1alpha1.TerraformLayerSpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + ApplyWithoutPlanArtifact: &[]bool{true}[0], + }, + }, + }, + true, + }, + { + "EnabledInRepositoryDisabledInLayer", + &configv1alpha1.TerraformRepository{ + Spec: configv1alpha1.TerraformRepositorySpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + ApplyWithoutPlanArtifact: &[]bool{true}[0], + }, + }, + }, + &configv1alpha1.TerraformLayer{ + Spec: configv1alpha1.TerraformLayerSpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + ApplyWithoutPlanArtifact: &[]bool{false}[0], + }, + }, + }, + false, + }, { "OnlyRepositoryEnabling", &configv1alpha1.TerraformRepository{ @@ -261,46 +297,125 @@ func TestGetApplyWithoutPlanArtifactEnabled(t *testing.T) { }, true, }, + } + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + result := configv1alpha1.GetApplyWithoutPlanArtifactEnabled(tc.repository, tc.layer) + if tc.expected != result { + t.Errorf("different enabled status computed: expected %t go %t", tc.expected, result) + } + }) + } +} + +func TestGetAutoApplyEnabled(t *testing.T) { + tt := []struct { + name string + repository *configv1alpha1.TerraformRepository + layer *configv1alpha1.TerraformLayer + expected bool + }{ + { + "EnabledInRepositoryDisabledInLayer", + &configv1alpha1.TerraformRepository{ + Spec: configv1alpha1.TerraformRepositorySpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{true}[0], + }, + }, + }, + &configv1alpha1.TerraformLayer{ + Spec: configv1alpha1.TerraformLayerSpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{false}[0], + }, + }, + }, + false, + }, { "DisabledInRepositoryEnabledInLayer", &configv1alpha1.TerraformRepository{ Spec: configv1alpha1.TerraformRepositorySpec{ RemediationStrategy: configv1alpha1.RemediationStrategy{ - ApplyWithoutPlanArtifact: &[]bool{false}[0], + AutoApply: &[]bool{false}[0], }, }, }, &configv1alpha1.TerraformLayer{ Spec: configv1alpha1.TerraformLayerSpec{ RemediationStrategy: configv1alpha1.RemediationStrategy{ - ApplyWithoutPlanArtifact: &[]bool{true}[0], + AutoApply: &[]bool{true}[0], }, }, }, true, }, { - "EnabledInRepositoryDisabledInLayer", + "EnabledInRepositoryEnabledInLayer", &configv1alpha1.TerraformRepository{ Spec: configv1alpha1.TerraformRepositorySpec{ RemediationStrategy: configv1alpha1.RemediationStrategy{ - ApplyWithoutPlanArtifact: &[]bool{true}[0], + AutoApply: &[]bool{true}[0], }, }, }, &configv1alpha1.TerraformLayer{ Spec: configv1alpha1.TerraformLayerSpec{ RemediationStrategy: configv1alpha1.RemediationStrategy{ - ApplyWithoutPlanArtifact: &[]bool{false}[0], + AutoApply: &[]bool{true}[0], + }, + }, + }, + true, + }, + { + "DisabledInRepositoryDisabledInLayer", + &configv1alpha1.TerraformRepository{ + Spec: configv1alpha1.TerraformRepositorySpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{false}[0], + }, + }, + }, + &configv1alpha1.TerraformLayer{ + Spec: configv1alpha1.TerraformLayerSpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{false}[0], }, }, }, false, }, + { + "OnlyRepositoryEnabling", + &configv1alpha1.TerraformRepository{ + Spec: configv1alpha1.TerraformRepositorySpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{true}[0], + }, + }, + }, + &configv1alpha1.TerraformLayer{}, + true, + }, + { + "OnlyLayerEnabling", + &configv1alpha1.TerraformRepository{}, + &configv1alpha1.TerraformLayer{ + Spec: configv1alpha1.TerraformLayerSpec{ + RemediationStrategy: configv1alpha1.RemediationStrategy{ + AutoApply: &[]bool{true}[0], + }, + }, + }, + true, + }, } + for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { - result := configv1alpha1.GetApplyWithoutPlanArtifactEnabled(tc.repository, tc.layer) + result := configv1alpha1.GetAutoApplyEnabled(tc.repository, tc.layer) if tc.expected != result { t.Errorf("different enabled status computed: expected %t go %t", tc.expected, result) } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 83b8a16d..c92b9a21 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,4 +1,5 @@ //go:build !ignore_autogenerated +// +build !ignore_autogenerated /* Copyright 2022. @@ -157,6 +158,11 @@ func (in *OverrideRunnerSpec) DeepCopy() *OverrideRunnerSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RemediationStrategy) DeepCopyInto(out *RemediationStrategy) { *out = *in + if in.AutoApply != nil { + in, out := &in.AutoApply, &out.AutoApply + *out = new(bool) + **out = **in + } if in.ApplyWithoutPlanArtifact != nil { in, out := &in.ApplyWithoutPlanArtifact, &out.ApplyWithoutPlanArtifact *out = new(bool) diff --git a/internal/controllers/terraformlayer/states.go b/internal/controllers/terraformlayer/states.go index 812dea3d..6c0fd414 100644 --- a/internal/controllers/terraformlayer/states.go +++ b/internal/controllers/terraformlayer/states.go @@ -70,8 +70,8 @@ type ApplyNeeded struct{} func (s *ApplyNeeded) getHandler() Handler { return func(ctx context.Context, r *Reconciler, layer *configv1alpha1.TerraformLayer, repository *configv1alpha1.TerraformRepository) (ctrl.Result, *configv1alpha1.TerraformRun) { log := log.WithContext(ctx) - remediationStrategy := configv1alpha1.GetRemediationStrategy(repository, layer) - if !remediationStrategy.AutoApply { + autoApply := configv1alpha1.GetAutoApplyEnabled(repository, layer) + if !autoApply { log.Infof("layer %s is in dry mode, no action taken", layer.Name) return ctrl.Result{RequeueAfter: r.Config.Controller.Timers.DriftDetection}, nil } diff --git a/internal/controllers/terraformpullrequest/layer.go b/internal/controllers/terraformpullrequest/layer.go index 1dfa0fe7..a2e37f03 100644 --- a/internal/controllers/terraformpullrequest/layer.go +++ b/internal/controllers/terraformpullrequest/layer.go @@ -92,7 +92,7 @@ func generateTempLayers(pr *configv1alpha1.TerraformPullRequest, layers []config TerraformConfig: layer.Spec.TerraformConfig, Repository: layer.Spec.Repository, RemediationStrategy: configv1alpha1.RemediationStrategy{ - AutoApply: false, + AutoApply: &[]bool{false}[0], }, OverrideRunnerSpec: layer.Spec.OverrideRunnerSpec, },