Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions cmd/exportStepConfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package cmd

import (
"os"

"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/ghodss/yaml"
"github.com/spf13/cobra"
)

var exportStepConfigOptions struct {
stepName string
stepMetadata string
outputFile string
}

// ExportStepConfigCommand is the entry command for exporting the step configuration
func ExportStepConfigCommand() *cobra.Command {
var exportStepConfigCmd = &cobra.Command{
Use: "exportStepConfig",
Short: "For internal use by Piper team only. Do NOT use this command in production pipelines.",
PreRun: func(cmd *cobra.Command, _ []string) {
path, _ := os.Getwd()
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
log.RegisterHook(fatalHook)
initStageName(false)
log.SetVerbose(GeneralConfig.Verbose)
GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
},
Run: func(cmd *cobra.Command, _ []string) {
metadata, err := config.ResolveMetadata(GeneralConfig.GitHubAccessTokens, GeneralConfig.MetaDataResolver, exportStepConfigOptions.stepMetadata, "")
if err != nil {
log.Entry().WithError(err).Fatal("Failed to resolve metadata")
return
}

var result map[string]interface{}
err = PrepareConfig(cmd, &metadata, exportStepConfigOptions.stepName, nil, config.OpenPiperFile, &result)
if err != nil {
log.Entry().WithError(err).Fatal("Failed to prepare configuration")
return
}

yamlData, err := yaml.Marshal(result)
if err != nil {
log.Entry().WithError(err).Fatal("Failed to marshal result to YAML")
return
}
err = os.WriteFile(exportStepConfigOptions.outputFile, yamlData, 0644)
if err != nil {
log.Entry().WithError(err).Fatal("Failed to write YAML to file")
return
}
log.Entry().Infof("Configuration exported to %s\n", exportStepConfigOptions.outputFile)
},
}
addExportStepConfigFlags(exportStepConfigCmd)
return exportStepConfigCmd
}

func addExportStepConfigFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&exportStepConfigOptions.stepName, "stepName", "", "Name of the step being checked")
cmd.Flags().StringVar(&exportStepConfigOptions.stepMetadata, "metadataFile", "", "Step metadata, passed as path to yaml")
cmd.Flags().StringVar(&exportStepConfigOptions.outputFile, "outputFilePath", "", "Defines a file path. If set, the output will be written to the defined file")
_ = cmd.MarkFlagRequired("stepName")
_ = cmd.MarkFlagRequired("metadataFile")
_ = cmd.MarkFlagRequired("outputFilePath")
}
26 changes: 22 additions & 4 deletions cmd/piper.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ func Execute() {
rootCmd.AddCommand(AbapLandscapePortalUpdateAddOnProductCommand())
rootCmd.AddCommand(ImagePushToRegistryCommand())

// this command is only for coexistence and compatibility while migrating steps to the new architecture
// Should never be used in productive pipelines!
rootCmd.AddCommand(ExportStepConfigCommand())

addRootFlags(rootCmd)

if err := rootCmd.Execute(); err != nil {
Expand Down Expand Up @@ -347,7 +351,7 @@ func initStageName(outputToLog bool) {
}

// PrepareConfig reads step configuration from various sources and merges it (defaults, config file, flags, ...)
func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName string, options interface{}, openFile func(s string, t map[string]string) (io.ReadCloser, error)) error {
func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName string, options interface{}, openFile func(s string, t map[string]string) (io.ReadCloser, error), outputResult ...interface{}) error {
log.SetFormatter(GeneralConfig.LogFormat)

initStageName(true)
Expand Down Expand Up @@ -434,10 +438,24 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
}
}

stepConfig.Config = checkTypes(stepConfig.Config, options)
confJSON, _ := json.Marshal(stepConfig.Config)
_ = json.Unmarshal(confJSON, &options)
if len(outputResult) == 1 {
// This branch is only used by the exportStepConfig command.
// No other step should use this!
// This is required temporarily for compatibility during migration to the new architecture.

// The main reason for this separate branch is that checkTypes() below expects
// a struct in &options and will panic otherwise. We cannot pass a struct here
// because the required fields are not known at compile time, since exportStepConfig
// can be called for any step.

// And yeah, this workaround is ugly, I know.
reflect.ValueOf(outputResult[0]).Elem().Set(reflect.ValueOf(stepConfig.Config)) // copy stepConfig.Config into outputResult[0]
} else {
// For all other steps, check and convert types, then unmarshal config into options (as before)
stepConfig.Config = checkTypes(stepConfig.Config, options)
confJSON, _ := json.Marshal(stepConfig.Config)
_ = json.Unmarshal(confJSON, &options)
}
config.MarkFlagsWithValue(cmd, stepConfig)

retrieveHookConfig(stepConfig.HookConfig, &GeneralConfig.HookConfig)
Expand Down
Loading