pkg/objectmodifier/stage.go (103 lines of code) (raw):

package objectmodifier import ( "context" "errors" "fmt" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" cdPipeApi "github.com/epam/edp-cd-pipeline-operator/v2/api/v1" "github.com/epam/edp-cd-pipeline-operator/v2/controllers/helper" "github.com/epam/edp-cd-pipeline-operator/v2/pkg/util/consts" ) // StageModifier is an interface for modifying stage object. type StageModifier interface { Apply(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) } // StageModifierFunc is a function that implements StageModifier interface. type StageModifierFunc func(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) // Apply implements StageModifier interface. func (f StageModifierFunc) Apply(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) { return f(ctx, stage) } // StageBatchModifier is a modifier that applies a list of modifiers. type StageBatchModifier struct { k8sClient client.Writer modifiers []StageModifier } // NewStageBatchModifier returns a new instance of StageBatchModifier. func NewStageBatchModifier(k8sClient client.Client, modifiers []StageModifier) *StageBatchModifier { return &StageBatchModifier{k8sClient: k8sClient, modifiers: modifiers} } // NewStageBatchModifierAll returns a new instance of StageBatchModifier with all the modifiers. func NewStageBatchModifierAll(k8sClient client.Client, scheme *runtime.Scheme) *StageBatchModifier { modifiers := []StageModifier{ StageModifierFunc(setStageLabel), newStageOwnerRefModifier(k8sClient, scheme), } return &StageBatchModifier{k8sClient: k8sClient, modifiers: modifiers} } // Apply applies all the modifiers to the stage. func (m *StageBatchModifier) Apply(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) { patch := client.MergeFrom(stage.DeepCopy()) needToPatch := false for _, modifier := range m.modifiers { changed, err := modifier.Apply(ctx, stage) if err != nil { return false, fmt.Errorf("failed to apply modifier: %w", err) } if changed { needToPatch = true } } if needToPatch { if err := m.k8sClient.Patch(ctx, stage, patch); err != nil { return false, fmt.Errorf("failed to patch stage: %w", err) } return true, nil } return false, nil } // setStageLabel sets label to stage object. func setStageLabel(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) { log := ctrl.LoggerFrom(ctx) log.Info("Trying to update labels for stage") if stage == nil { return false, errors.New("failed to update stage labels: stage is nil") } labels := stage.GetLabels() if labels == nil { labels = make(map[string]string) } if _, ok := labels[cdPipeApi.StageCdPipelineLabelName]; ok { log.Info("Stage already has label", "label", cdPipeApi.StageCdPipelineLabelName) return false, nil } labels[cdPipeApi.StageCdPipelineLabelName] = stage.Spec.CdPipeline stage.SetLabels(labels) log.Info("Stage labels were updated", "labels", labels) return true, nil } // stageOwnerRefModifier sets CDPipeline owner reference to stage object. type stageOwnerRefModifier struct { k8sClient client.Client scheme *runtime.Scheme } // newStageOwnerRefModifier returns a new instance of stageOwnerRefModifier. func newStageOwnerRefModifier(k8sClient client.Client, scheme *runtime.Scheme) *stageOwnerRefModifier { return &stageOwnerRefModifier{k8sClient: k8sClient, scheme: scheme} } // Apply sets CDPipeline owner reference to stage object. func (m *stageOwnerRefModifier) Apply(ctx context.Context, stage *cdPipeApi.Stage) (bool, error) { log := ctrl.LoggerFrom(ctx) log.Info("Trying to update owner reference for stage") if stage == nil { return false, errors.New("failed to update stage owner reference: stage is nil") } if ow := helper.GetOwnerReference(consts.CDPipelineKind, stage.GetOwnerReferences()); ow != nil { log.Info("CDPipeline owner reference already exists") return false, nil } pipeline := &cdPipeApi.CDPipeline{} if err := m.k8sClient.Get(ctx, client.ObjectKey{ Namespace: stage.Namespace, Name: stage.Spec.CdPipeline, }, pipeline); err != nil { return false, fmt.Errorf("cdpipeline %s doesn't exist: %w", stage.Spec.CdPipeline, err) } if err := controllerutil.SetControllerReference(pipeline, stage, m.scheme); err != nil { return false, fmt.Errorf("couldn't set CDPipeline %s owner ref: %w", stage.Spec.CdPipeline, err) } log.Info("CDPipeline owner reference was updated") return true, nil }