diff --git a/backend/pipeline.yaml b/backend/pipeline.yaml index 9f125507a..ce674e614 100644 --- a/backend/pipeline.yaml +++ b/backend/pipeline.yaml @@ -7,7 +7,7 @@ resourceGroups: steps: - name: deploy action: Shell - command: ["/bin/bash", "-c", "make -f Makefile.deploy deploy"] + command: ["/bin/bash", "-c", "make deploy"] env: - name: ARO_HCP_IMAGE_ACR configRef: svcAcrName diff --git a/setup-env.mk b/setup-env.mk index dab2c7654..47427bf00 100644 --- a/setup-env.mk +++ b/setup-env.mk @@ -1,21 +1,24 @@ SHELL = /bin/bash -SHELLFLAGS = -eu -o pipefail -c +SHELLFLAGS = -eu -o pipefail + +ifndef EV2 +ifndef RUNS_IN_TEMPLATIZE PROJECT_ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) DEPLOY_ENV ?= personal-dev PIPELINE ?= pipeline.yaml PIPELINE_STEP ?= deploy HASH = $(shell echo -n "$(DEPLOY_ENV)$(PIPELINE)$(PIPELINE_STEP)" | md5) -ENV_VARS_FILE ?= /tmp/deploy.${HASH}.cfg +ENV_VARS_FILE ?= ${TMPDIR}/deploy.${HASH}.cfg # Target to generate the environment variables file $(ENV_VARS_FILE): ${PROJECT_ROOT_DIR}/config/config.yaml ${PIPELINE} ${PROJECT_ROOT_DIR}/templatize.sh ${MAKEFILE_LIST} - @echo "generate env vars" + @echo "generate env vars file ${ENV_VARS_FILE}" @${PROJECT_ROOT_DIR}/templatize.sh ${DEPLOY_ENV} \ -p ${PIPELINE} \ - -s ${PIPELINE_STEP} > $@ + -s ${PIPELINE_STEP} > $(ENV_VARS_FILE) # Include the environment variables file if it exists -ifndef EV2 -include ${ENV_VARS_FILE} endif +endif diff --git a/templatize.sh b/templatize.sh index 7f2730029..92ef70ad8 100755 --- a/templatize.sh +++ b/templatize.sh @@ -128,7 +128,7 @@ if [ -n "$INPUT" ] && [ -n "$OUTPUT" ]; then --output=${OUTPUT} \ ${EXTRA_ARGS} elif [ -n "$PIPELINE" ] && [ -n "$PIPELINE_STEP" ]; then - $TEMPLATIZE run-pipeline \ + $TEMPLATIZE pipeline inspect \ --config-file=${CONFIG_FILE} \ --cloud=${CLOUD} \ --deploy-env=${DEPLOY_ENV} \ @@ -137,7 +137,8 @@ elif [ -n "$PIPELINE" ] && [ -n "$PIPELINE_STEP" ]; then --stamp=${CXSTAMP} \ --pipeline-file=${PIPELINE} \ --step=${PIPELINE_STEP} \ - --dump-step-vars + --aspect vars \ + --format Makefile else $TEMPLATIZE inspect \ --config-file=${CONFIG_FILE} \ diff --git a/tooling/templatize/Makefile b/tooling/templatize/Makefile new file mode 100644 index 000000000..e98657da0 --- /dev/null +++ b/tooling/templatize/Makefile @@ -0,0 +1,19 @@ + +SHELL = /bin/bash + +# Define the binary name +BINARY = templatize + +# Define the source files +SOURCES = $(shell find . -name '*.go') + +# Build the binary +$(BINARY): $(SOURCES) $(MAKEFILE_LIST) + @echo "rebuild templatize" + go build -o $(BINARY) . + +# Clean the build artifacts +clean: + rm -f $(BINARY) + +.PHONY: clean diff --git a/tooling/templatize/cmd/pipeline/cmd.go b/tooling/templatize/cmd/pipeline/cmd.go new file mode 100644 index 000000000..4e7c74626 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/cmd.go @@ -0,0 +1,25 @@ +package pipeline + +import ( + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/inspect" + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/run" +) + +func NewCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "pipeline", + Short: "pipeline", + Long: "pipeline", + SilenceUsage: true, + TraverseChildren: true, + CompletionOptions: cobra.CompletionOptions{ + HiddenDefaultCmd: true, + }, + } + cmd.AddCommand(run.NewCommand()) + cmd.AddCommand(inspect.NewCommand()) + + return cmd +} diff --git a/tooling/templatize/cmd/pipeline/inspect/cmd.go b/tooling/templatize/cmd/pipeline/inspect/cmd.go new file mode 100644 index 000000000..5bcb19c36 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/inspect/cmd.go @@ -0,0 +1,42 @@ +package inspect + +import ( + "context" + "log" + "os" + "os/signal" + "syscall" + + "github.com/spf13/cobra" +) + +func NewCommand() *cobra.Command { + opts := DefaultOptions() + cmd := &cobra.Command{ + Use: "inspect", + Short: "inspect aspects of a pipeline.yaml file", + Long: "inspect aspects of a pipeline.yaml file", + RunE: func(cmd *cobra.Command, args []string) error { + ctx, stop := signal.NotifyContext(cmd.Context(), os.Interrupt, syscall.SIGTERM) + defer stop() + + return runInspect(ctx, opts) + }, + } + if err := BindOptions(opts, cmd); err != nil { + log.Fatal(err) + } + return cmd +} + +func runInspect(ctx context.Context, opts *RawInspectOptions) error { + validated, err := opts.Validate() + if err != nil { + return err + } + completed, err := validated.Complete() + if err != nil { + return err + } + return completed.RunInspect(ctx) +} diff --git a/tooling/templatize/cmd/pipeline/inspect/options.go b/tooling/templatize/cmd/pipeline/inspect/options.go new file mode 100644 index 000000000..209f1eb6a --- /dev/null +++ b/tooling/templatize/cmd/pipeline/inspect/options.go @@ -0,0 +1,110 @@ +package inspect + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/options" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func DefaultOptions() *RawInspectOptions { + return &RawInspectOptions{ + PipelineOptions: options.DefaultOptions(), + } +} + +func BindOptions(opts *RawInspectOptions, cmd *cobra.Command) error { + err := options.BindOptions(opts.PipelineOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().StringVar(&opts.Aspect, "aspect", opts.Aspect, "aspect of the pipeline to inspect") + cmd.Flags().StringVar(&opts.Format, "format", opts.Format, "output format") + return nil +} + +type RawInspectOptions struct { + PipelineOptions *options.RawPipelineOptions + Aspect string + Format string +} + +// validatedInspectOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedInspectOptions struct { + *RawInspectOptions + *options.ValidatedPipelineOptions +} + +type ValidatedInspectOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedInspectOptions +} + +// completedRunOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedInspectOptions struct { + PipelineOptions *options.PipelineOptions + Aspect string + Format string +} + +type InspectOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedInspectOptions +} + +func (o *RawInspectOptions) Validate() (*ValidatedInspectOptions, error) { + validatedPipelineOptions, err := o.PipelineOptions.Validate() + if err != nil { + return nil, err + } + // todo validate aspect + return &ValidatedInspectOptions{ + validatedInspectOptions: &validatedInspectOptions{ + RawInspectOptions: o, + ValidatedPipelineOptions: validatedPipelineOptions, + }, + }, nil +} + +func (o *ValidatedInspectOptions) Complete() (*InspectOptions, error) { + completed, err := o.ValidatedPipelineOptions.Complete() + if err != nil { + return nil, err + } + + return &InspectOptions{ + completedInspectOptions: &completedInspectOptions{ + PipelineOptions: completed, + Aspect: o.Aspect, + Format: o.Format, + }, + }, nil +} + +func (o *InspectOptions) RunInspect(ctx context.Context) error { + rolloutOptions := o.PipelineOptions.RolloutOptions + variables, err := rolloutOptions.Options.ConfigProvider.GetVariables( + rolloutOptions.Cloud, + rolloutOptions.DeployEnv, + rolloutOptions.Region, + config.NewConfigReplacements( + rolloutOptions.Region, + rolloutOptions.RegionShort, + rolloutOptions.Stamp, + ), + ) + if err != nil { + return err + } + return o.PipelineOptions.Pipeline.Inspect(ctx, &pipeline.PipelineInspectOptions{ + Vars: variables, + Region: rolloutOptions.Region, + Step: o.PipelineOptions.Step, + Aspect: o.Aspect, + Format: o.Format, + }) +} diff --git a/tooling/templatize/cmd/run/options.go b/tooling/templatize/cmd/pipeline/options/options.go similarity index 52% rename from tooling/templatize/cmd/run/options.go rename to tooling/templatize/cmd/pipeline/options/options.go index fed985620..43cebe5ba 100644 --- a/tooling/templatize/cmd/run/options.go +++ b/tooling/templatize/cmd/pipeline/options/options.go @@ -1,30 +1,28 @@ -package run +package options import ( - "context" "fmt" "os" "github.com/spf13/cobra" options "github.com/Azure/ARO-HCP/tooling/templatize/cmd" - "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" ) -func DefaultOptions() *RawRunOptions { - return &RawRunOptions{ +func DefaultOptions() *RawPipelineOptions { + return &RawPipelineOptions{ RolloutOptions: options.DefaultRolloutOptions(), } } -func BindOptions(opts *RawRunOptions, cmd *cobra.Command) error { +func BindOptions(opts *RawPipelineOptions, cmd *cobra.Command) error { err := options.BindRolloutOptions(opts.RolloutOptions, cmd) if err != nil { return fmt.Errorf("failed to bind options: %w", err) } cmd.Flags().StringVar(&opts.PipelineFile, "pipeline-file", opts.PipelineFile, "pipeline file path") - cmd.Flags().BoolVar(&opts.DryRun, "dry-run", opts.DryRun, "validate the pipeline without executing it") + cmd.Flags().StringVar(&opts.Step, "step", opts.Step, "run only a specific step in the pipeline") for _, flag := range []string{"pipeline-file"} { if err := cmd.MarkFlagFilename(flag); err != nil { @@ -38,36 +36,36 @@ func BindOptions(opts *RawRunOptions, cmd *cobra.Command) error { } // RawRunOptions holds input values. -type RawRunOptions struct { +type RawPipelineOptions struct { RolloutOptions *options.RawRolloutOptions PipelineFile string - DryRun bool + Step string } -// validatedRunOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. -type validatedRunOptions struct { - *RawRunOptions +// validatedPipelineOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedPipelineOptions struct { + *RawPipelineOptions *options.ValidatedRolloutOptions } -type ValidatedRunOptions struct { +type ValidatedPipelineOptions struct { // Embed a private pointer that cannot be instantiated outside of this package. - *validatedRunOptions + *validatedPipelineOptions } -// completedRunOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. -type completedRunOptions struct { +// completedPipelineOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedPipelineOptions struct { RolloutOptions *options.RolloutOptions Pipeline *pipeline.Pipeline - DryRun bool + Step string } -type RunOptions struct { +type PipelineOptions struct { // Embed a private pointer that cannot be instantiated outside of this package. - *completedRunOptions + *completedPipelineOptions } -func (o *RawRunOptions) Validate() (*ValidatedRunOptions, error) { +func (o *RawPipelineOptions) Validate() (*ValidatedPipelineOptions, error) { validatedRolloutOptions, err := o.RolloutOptions.Validate() if err != nil { return nil, err @@ -77,15 +75,15 @@ func (o *RawRunOptions) Validate() (*ValidatedRunOptions, error) { return nil, fmt.Errorf("pipeline file %s does not exist", o.PipelineFile) } - return &ValidatedRunOptions{ - validatedRunOptions: &validatedRunOptions{ - RawRunOptions: o, + return &ValidatedPipelineOptions{ + validatedPipelineOptions: &validatedPipelineOptions{ + RawPipelineOptions: o, ValidatedRolloutOptions: validatedRolloutOptions, }, }, nil } -func (o *ValidatedRunOptions) Complete() (*RunOptions, error) { +func (o *ValidatedPipelineOptions) Complete() (*PipelineOptions, error) { completed, err := o.ValidatedRolloutOptions.Complete() if err != nil { return nil, err @@ -96,32 +94,11 @@ func (o *ValidatedRunOptions) Complete() (*RunOptions, error) { return nil, fmt.Errorf("failed to load pipeline file %s: %w", o.PipelineFile, err) } - return &RunOptions{ - completedRunOptions: &completedRunOptions{ + return &PipelineOptions{ + completedPipelineOptions: &completedPipelineOptions{ RolloutOptions: completed, Pipeline: pipeline, - DryRun: o.DryRun, + Step: o.Step, }, }, nil } - -func (o *RunOptions) RunPipeline(ctx context.Context) error { - variables, err := o.RolloutOptions.Options.ConfigProvider.GetVariables( - o.RolloutOptions.Cloud, - o.RolloutOptions.DeployEnv, - o.RolloutOptions.Region, - config.NewConfigReplacements( - o.RolloutOptions.Region, - o.RolloutOptions.RegionShort, - o.RolloutOptions.Stamp, - ), - ) - if err != nil { - return err - } - return o.Pipeline.Run(ctx, &pipeline.PipelineRunOptions{ - DryRun: o.DryRun, - Vars: variables, - Region: o.RolloutOptions.Region, - }) -} diff --git a/tooling/templatize/cmd/run/cmd.go b/tooling/templatize/cmd/pipeline/run/cmd.go similarity index 97% rename from tooling/templatize/cmd/run/cmd.go rename to tooling/templatize/cmd/pipeline/run/cmd.go index b7e21459f..1edcc0059 100644 --- a/tooling/templatize/cmd/run/cmd.go +++ b/tooling/templatize/cmd/pipeline/run/cmd.go @@ -13,7 +13,7 @@ import ( func NewCommand() *cobra.Command { opts := DefaultOptions() cmd := &cobra.Command{ - Use: "run-pipeline", + Use: "run", Short: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster", Long: "run a pipeline.yaml file towards an Azure Resourcegroup / AKS cluster", RunE: func(cmd *cobra.Command, args []string) error { diff --git a/tooling/templatize/cmd/pipeline/run/options.go b/tooling/templatize/cmd/pipeline/run/options.go new file mode 100644 index 000000000..ca3adf675 --- /dev/null +++ b/tooling/templatize/cmd/pipeline/run/options.go @@ -0,0 +1,105 @@ +package run + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline/options" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline" +) + +func DefaultOptions() *RawRunOptions { + return &RawRunOptions{ + PipelineOptions: options.DefaultOptions(), + } +} + +func BindOptions(opts *RawRunOptions, cmd *cobra.Command) error { + err := options.BindOptions(opts.PipelineOptions, cmd) + if err != nil { + return fmt.Errorf("failed to bind options: %w", err) + } + cmd.Flags().BoolVar(&opts.DryRun, "dry-run", opts.DryRun, "validate the pipeline without executing it") + return nil +} + +type RawRunOptions struct { + PipelineOptions *options.RawPipelineOptions + DryRun bool +} + +// validatedRunOptions is a private wrapper that enforces a call of Validate() before Complete() can be invoked. +type validatedRunOptions struct { + *RawRunOptions + *options.ValidatedPipelineOptions +} + +type ValidatedRunOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *validatedRunOptions +} + +// completedRunOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked. +type completedRunOptions struct { + PipelineOptions *options.PipelineOptions + DryRun bool +} + +type RunOptions struct { + // Embed a private pointer that cannot be instantiated outside of this package. + *completedRunOptions +} + +func (o *RawRunOptions) Validate() (*ValidatedRunOptions, error) { + validatedPipelineOptions, err := o.PipelineOptions.Validate() + if err != nil { + return nil, err + } + // todo validate + return &ValidatedRunOptions{ + validatedRunOptions: &validatedRunOptions{ + RawRunOptions: o, + ValidatedPipelineOptions: validatedPipelineOptions, + }, + }, nil +} + +func (o *ValidatedRunOptions) Complete() (*RunOptions, error) { + completed, err := o.ValidatedPipelineOptions.Complete() + if err != nil { + return nil, err + } + + return &RunOptions{ + completedRunOptions: &completedRunOptions{ + PipelineOptions: completed, + DryRun: o.DryRun, + }, + }, nil +} + +func (o *RunOptions) RunPipeline(ctx context.Context) error { + rolloutOptions := o.PipelineOptions.RolloutOptions + variables, err := rolloutOptions.Options.ConfigProvider.GetVariables( + rolloutOptions.Cloud, + rolloutOptions.DeployEnv, + rolloutOptions.Region, + config.NewConfigReplacements( + rolloutOptions.Region, + rolloutOptions.RegionShort, + rolloutOptions.Stamp, + ), + ) + if err != nil { + return err + } + return o.PipelineOptions.Pipeline.Run(ctx, &pipeline.PipelineRunOptions{ + DryRun: o.DryRun, + Vars: variables, + Region: rolloutOptions.Region, + Step: o.PipelineOptions.Step, + }) +} diff --git a/tooling/templatize/main.go b/tooling/templatize/main.go index a7075646b..7e2dce851 100644 --- a/tooling/templatize/main.go +++ b/tooling/templatize/main.go @@ -7,7 +7,7 @@ import ( "github.com/Azure/ARO-HCP/tooling/templatize/cmd/generate" "github.com/Azure/ARO-HCP/tooling/templatize/cmd/inspect" - "github.com/Azure/ARO-HCP/tooling/templatize/cmd/run" + "github.com/Azure/ARO-HCP/tooling/templatize/cmd/pipeline" ) func main() { @@ -23,7 +23,7 @@ func main() { } cmd.AddCommand(generate.NewCommand()) cmd.AddCommand(inspect.NewCommand()) - cmd.AddCommand(run.NewCommand()) + cmd.AddCommand(pipeline.NewCommand()) cmd.SetHelpCommand(&cobra.Command{Hidden: true}) if err := cmd.Execute(); err != nil { diff --git a/tooling/templatize/pkg/config/types.go b/tooling/templatize/pkg/config/types.go index 727e35ab0..67bf538c5 100644 --- a/tooling/templatize/pkg/config/types.go +++ b/tooling/templatize/pkg/config/types.go @@ -13,21 +13,21 @@ type configProviderImpl struct { type Variables map[string]any func (v Variables) GetByPath(path string) (interface{}, bool) { - keys := strings.Split(path, ".") - var current interface{} = v - - for _, key := range keys { - if m, ok := current.(Variables); ok { - current, ok = m[key] - if !ok { - return nil, false - } - } else { - return nil, false - } - } - - return current, true + keys := strings.Split(path, ".") + var current interface{} = v + + for _, key := range keys { + if m, ok := current.(Variables); ok { + current, ok = m[key] + if !ok { + return nil, false + } + } else { + return nil, false + } + } + + return current, true } func NewVariableOverrides() VariableOverrides { diff --git a/tooling/templatize/pkg/pipeline/inspect.go b/tooling/templatize/pkg/pipeline/inspect.go new file mode 100644 index 000000000..5ed262a74 --- /dev/null +++ b/tooling/templatize/pkg/pipeline/inspect.go @@ -0,0 +1,64 @@ +package pipeline + +import ( + "context" + "fmt" + "strings" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" +) + +type StepInspectScope func(*step, *PipelineInspectOptions) error + +var stepInspectScopes = map[string]StepInspectScope{ + "vars": inspectVars, +} + +func init() { + // Initialize the map with function pointers + stepInspectScopes["vars"] = inspectVars +} + +type PipelineInspectOptions struct { + Aspect string + Format string + Step string + Region string + Vars config.Variables +} + +func (p *Pipeline) Inspect(ctx context.Context, options *PipelineInspectOptions) error { + for _, rg := range p.ResourceGroups { + for _, step := range rg.Steps { + if step.Name == options.Step { + if inspectFunc, ok := stepInspectScopes[options.Aspect]; ok { + err := inspectFunc(step, options) + if err != nil { + return err + } + } else { + return fmt.Errorf("unknown inspect scope %q", options.Aspect) + } + return nil + } + } + } + return fmt.Errorf("step %q not found", options.Step) +} + +func inspectVars(s *step, options *PipelineInspectOptions) error { + switch s.Action { + case "Shell": + envVars, err := s.getEnvVars(options.Vars, false) + if err != nil { + return err + } + for _, e := range envVars { + parts := strings.SplitN(e, "=", 2) + fmt.Printf("%s ?= %s\n", parts[0], parts[1]) + } + return nil + default: + return fmt.Errorf("dumping step variables not implemented for action type %q", s.Action) + } +} diff --git a/tooling/templatize/pkg/pipeline/run.go b/tooling/templatize/pkg/pipeline/run.go index 650346aa7..6cc9df3fd 100644 --- a/tooling/templatize/pkg/pipeline/run.go +++ b/tooling/templatize/pkg/pipeline/run.go @@ -30,6 +30,7 @@ func NewPipelineFromFile(pipelineFilePath string, vars config.Variables) (*Pipel type PipelineRunOptions struct { DryRun bool + Step string Region string Vars config.Variables } @@ -64,6 +65,7 @@ func (p *Pipeline) Run(ctx context.Context, options *PipelineRunOptions) error { } func (rg *resourceGroup) run(ctx context.Context, options *PipelineRunOptions) error { + // prepare execution context subscriptionID, err := lookupSubscriptionID(ctx, rg.Subscription) if err != nil { return err @@ -77,6 +79,11 @@ func (rg *resourceGroup) run(ctx context.Context, options *PipelineRunOptions) e } for _, step := range rg.Steps { + if options.Step != "" && step.Name != options.Step { + // skip steps that don't match the specified step name + continue + } + // execute fmt.Println("\n---------------------") fmt.Println(step.description()) fmt.Print("\n") diff --git a/tooling/templatize/pkg/pipeline/shell.go b/tooling/templatize/pkg/pipeline/shell.go index c33bcae3c..a473ff17f 100644 --- a/tooling/templatize/pkg/pipeline/shell.go +++ b/tooling/templatize/pkg/pipeline/shell.go @@ -5,13 +5,19 @@ import ( "fmt" "os" "os/exec" + + "github.com/Azure/ARO-HCP/tooling/templatize/pkg/config" ) func (s *step) runShellStep(ctx context.Context, executionTarget *ExecutionTarget, options *PipelineRunOptions) error { // build ENV vars - envVars := os.Environ() + envVars, err := s.getEnvVars(options.Vars, true) + if err != nil { + return fmt.Errorf("failed to build env vars: %w", err) + } + + // prepare kubeconfig if executionTarget.AKSClusterName != "" { - // prepare kubeconfig kubeconfigFile, err := executionTarget.KubeConfig(ctx) if err != nil { return fmt.Errorf("failed to build kubeconfig for %s: %w", executionTarget.aksID(), err) @@ -24,18 +30,10 @@ func (s *step) runShellStep(ctx context.Context, executionTarget *ExecutionTarge envVars = append(envVars, fmt.Sprintf("KUBECONFIG=%s", kubeconfigFile)) } - // prepare declared env vars - for _, e := range s.Env { - value, found := options.Vars.GetByPath(e.ConfigRef) - if !found { - return fmt.Errorf("failed to lookup config reference %s for %s", e.ConfigRef, e.Name) - } - envVars = append(envVars, fmt.Sprintf("%s=%s", e.Name, value)) - } - // TODO handle dry-run // execute the command + fmt.Printf("Executing shell command: %s - %s\n", s.Command[0], s.Command[1:]) cmd := exec.CommandContext(ctx, s.Command[0], s.Command[1:]...) cmd.Env = append(cmd.Env, envVars...) output, err := cmd.CombinedOutput() @@ -48,3 +46,19 @@ func (s *step) runShellStep(ctx context.Context, executionTarget *ExecutionTarge return nil } + +func (s *step) getEnvVars(vars config.Variables, includeOSEnvVars bool) ([]string, error) { + envVars := make([]string, 0) + if includeOSEnvVars { + envVars = append(envVars, os.Environ()...) + } + envVars = append(envVars, "RUNS_IN_TEMPLATIZE=1") + for _, e := range s.Env { + value, found := vars.GetByPath(e.ConfigRef) + if !found { + return nil, fmt.Errorf("failed to lookup config reference %s for %s", e.ConfigRef, e.Name) + } + envVars = append(envVars, fmt.Sprintf("%s=%s", e.Name, value)) + } + return envVars, nil +}