From 7f0be4c18c5420538e5c79291cb9a035e87402d6 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Fri, 13 Dec 2024 14:10:27 +0100 Subject: [PATCH] feat(directives): add `compose-output` directive Signed-off-by: Hidde Beydals --- internal/directives/output_composer.go | 73 +++++++++++++++++++ .../directives/schemas/compose-output.json | 6 ++ internal/directives/zz_config_types.go | 2 + ui/src/gen/directives/compose-output.json | 6 ++ 4 files changed, 87 insertions(+) create mode 100644 internal/directives/output_composer.go create mode 100644 internal/directives/schemas/compose-output.json create mode 100644 ui/src/gen/directives/compose-output.json diff --git a/internal/directives/output_composer.go b/internal/directives/output_composer.go new file mode 100644 index 000000000..1ef9c6f4f --- /dev/null +++ b/internal/directives/output_composer.go @@ -0,0 +1,73 @@ +package directives + +import ( + "context" + "fmt" + + "github.com/xeipuuv/gojsonschema" + + kargoapi "github.com/akuity/kargo/api/v1alpha1" +) + +func init() { + builtins.RegisterPromotionStepRunner(newOutputComposer(), nil) +} + +// outputComposer is an implementation of the PromotionStepRunner interface +// that allows composing outputs from previous steps into new outputs. +// +// It works based on the PromotionStepContext.Config field allowing to an +// arbitrary number of key-value pairs to be exported as outputs. +// Because the values are allowed to be expressions and can contain +// references to outputs from previous steps, this allows for remapping +// the outputs of previous steps to new keys, or even combining them +// into new structures. +type outputComposer struct { + schemaLoader gojsonschema.JSONLoader +} + +// newOutputComposer returns an implementation of the PromotionStepRunner +// interface that composes output from previous steps into new output. +func newOutputComposer() PromotionStepRunner { + r := &outputComposer{} + r.schemaLoader = getConfigSchemaLoader(r.Name()) + return r +} + +// Name implements the PromotionStepRunner interface. +func (c *outputComposer) Name() string { + return "compose-output" +} + +// RunPromotionStep implements the PromotionStepRunner interface. +func (c *outputComposer) RunPromotionStep( + _ 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[ComposeOutput](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(cfg) +} + +func (c *outputComposer) runPromotionStep( + cfg ComposeOutput, +) (PromotionStepResult, error) { + var output = make(map[string]any, len(cfg)) + for k, v := range cfg { + output[k] = v + } + return PromotionStepResult{ + Status: kargoapi.PromotionPhaseSucceeded, + Output: output, + }, nil +} diff --git a/internal/directives/schemas/compose-output.json b/internal/directives/schemas/compose-output.json new file mode 100644 index 000000000..76421df1d --- /dev/null +++ b/internal/directives/schemas/compose-output.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "ComposeOutput", + "type": "object", + "minProperties": 1 +} diff --git a/internal/directives/zz_config_types.go b/internal/directives/zz_config_types.go index e09b38c60..c1d89150b 100644 --- a/internal/directives/zz_config_types.go +++ b/internal/directives/zz_config_types.go @@ -4,6 +4,8 @@ package directives type CommonDefs interface{} +type ComposeOutput map[string]interface{} + type ArgoCDUpdateConfig struct { Apps []ArgoCDAppUpdate `json:"apps"` FromOrigin *AppFromOrigin `json:"fromOrigin,omitempty"` diff --git a/ui/src/gen/directives/compose-output.json b/ui/src/gen/directives/compose-output.json new file mode 100644 index 000000000..b168b74f6 --- /dev/null +++ b/ui/src/gen/directives/compose-output.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "ComposeOutput", + "type": "object", + "minProperties": 1 +} \ No newline at end of file