From 0102acee44ad091b3ec6e00bf51d6466332bd175 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Fri, 13 Dec 2024 12:09:59 +0100 Subject: [PATCH] chore(directives): wire inputs into engine Signed-off-by: Hidde Beydals --- internal/controller/promotions/promotions.go | 1 + internal/directives/outputs_composer.go | 70 ++++++++++++++++++++ internal/directives/promotions.go | 14 ++++ 3 files changed, 85 insertions(+) create mode 100644 internal/directives/outputs_composer.go diff --git a/internal/controller/promotions/promotions.go b/internal/controller/promotions/promotions.go index 57014318d..e82a30211 100644 --- a/internal/controller/promotions/promotions.go +++ b/internal/controller/promotions/promotions.go @@ -471,6 +471,7 @@ func (r *reconciler) promote( Kind: step.Uses, Alias: step.As, Retry: step.Retry, + Inputs: step.Inputs, Config: step.Config.Raw, } } diff --git a/internal/directives/outputs_composer.go b/internal/directives/outputs_composer.go new file mode 100644 index 000000000..99f61e5a9 --- /dev/null +++ b/internal/directives/outputs_composer.go @@ -0,0 +1,70 @@ +package directives + +import ( + "context" + "fmt" + + "github.com/xeipuuv/gojsonschema" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" +) + +func init() { + builtins.RegisterPromotionStepRunner(newOutputsComposer(), nil) +} + +// outputsComposer is an implementation of the PromotionStepRunner interface that +// allows composing outputs from previous steps into new outputs. +type outputsComposer struct { + schemaLoader gojsonschema.JSONLoader +} + +// newOutputsComposer returns an implementation of the PromotionStepRunner +// interface that composes outputs from previous steps into new outputs. +func newOutputsComposer() PromotionStepRunner { + r := &outputsComposer{} + r.schemaLoader = getConfigSchemaLoader(r.Name()) + return r +} + +// Name implements the PromotionStepRunner interface. +func (c *outputsComposer) Name() string { + return "compose-outputs" +} + +// RunPromotionStep implements the PromotionStepRunner interface. +func (c *outputsComposer) RunPromotionStep( + ctx context.Context, + stepCtx *PromotionStepContext, +) (PromotionStepResult, error) { + // Validate the configuration against the JSON Schema. + if err := validate(c.schemaLoader, gojsonschema.NewGoLoader(stepCtx.Config), c.Name()); err != nil { + return PromotionStepResult{Status: kargoapi.PromotionPhaseErrored}, err + } + + // Convert the configuration into a typed object. + cfg, err := ConfigToStruct[ComposeOutputs](stepCtx.Config) + if err != nil { + return PromotionStepResult{Status: kargoapi.PromotionPhaseErrored}, + fmt.Errorf("could not convert config into %s config: %w", c.Name(), err) + } + + return c.runPromotionStep(ctx, stepCtx, cfg) +} + +func (c *outputsComposer) runPromotionStep( + ctx context.Context, + stepCtx *PromotionStepContext, + cfg ComposeOutputs, +) (PromotionStepResult, error) { + for newKey, f := range cfg.Fields { + stepState, ok := stepCtx.SharedState[f.FromStep] + if !ok { + return PromotionStepResult{Status: kargoapi.PromotionPhaseFailed}, + fmt.Errorf("unable to compose output %q from step %q: step not found", newKey, f.FromStep) + } + + + } + return PromotionStepResult{Status: kargoapi.PromotionPhaseSucceeded}, nil +} diff --git a/internal/directives/promotions.go b/internal/directives/promotions.go index a4af12e14..f14caac46 100644 --- a/internal/directives/promotions.go +++ b/internal/directives/promotions.go @@ -96,6 +96,8 @@ type PromotionStep struct { Alias string // Retry is the retry configuration for the PromotionStep. Retry *kargoapi.PromotionStepRetry + // Inputs is a list of inputs to be made available to the Config of this step. + Inputs []kargoapi.PromotionStepInput // Config is an opaque JSON to be passed to the PromotionStepRunner executing // this step. Config []byte @@ -144,6 +146,8 @@ func (s *PromotionStep) GetConfig( return nil, err } + inputs := s.GetInputs() + evaledCfgJSON, err := expressions.EvaluateJSONTemplate( s.Config, map[string]any{ @@ -153,6 +157,7 @@ func (s *PromotionStep) GetConfig( "stage": promoCtx.Stage, }, "vars": vars, + "inputs": inputs, "secrets": promoCtx.Secrets, "outputs": state, }, @@ -212,6 +217,15 @@ func (s *PromotionStep) GetVars(promoCtx PromotionContext) (map[string]any, erro return vars, nil } +// GetInputs returns the inputs of the PromotionStep as a map. +func (s *PromotionStep) GetInputs() map[string]any { + inputs := make(map[string]any, len(s.Inputs)) + for _, i := range s.Inputs { + inputs[i.Name] = i.Value + } + return inputs +} + // PromotionResult is the result of a user-defined promotion process executed by // the Engine. It aggregates the status and output of the individual // PromotionStepResults returned by the PromotionStepRunner executing each