From f433b207e72d529a99e9143ff2d86e5d6bb897b8 Mon Sep 17 00:00:00 2001 From: Wojciech Trocki Date: Mon, 25 Apr 2022 17:21:56 +0100 Subject: [PATCH] feat: support secret output for generate config --- docs/commands/rhoas_generate-config.md | 5 +- go.sum | 2 - pkg/cmd/generate/build-configs.go | 10 ++-- pkg/cmd/generate/configurations.go | 21 +++++--- pkg/cmd/generate/generate-config.go | 3 +- pkg/cmd/generate/templates.go | 50 ++++++++++++++++--- .../registry/registrycmdutil/registry_util.go | 18 ++++--- .../locales/en/cmd/generate_config.en.toml | 5 ++ 8 files changed, 84 insertions(+), 30 deletions(-) diff --git a/docs/commands/rhoas_generate-config.md b/docs/commands/rhoas_generate-config.md index ee49da7d7..b61e41444 100644 --- a/docs/commands/rhoas_generate-config.md +++ b/docs/commands/rhoas_generate-config.md @@ -21,8 +21,9 @@ $ rhoas generate-config --type json ### Options ``` - --name string Name of the context - --type string Type of configuration file to be generated + --name string Name of the context + --output-file string Sets a custom file location to save the credentials + --type string Type of configuration file to be generated ``` ### Options inherited from parent commands diff --git a/go.sum b/go.sum index 1aa3a0ce9..e9195e4e3 100644 --- a/go.sum +++ b/go.sum @@ -635,8 +635,6 @@ github.com/redhat-developer/app-services-sdk-go v0.10.0 h1:zI0X5FR0NOj6IwBWk3y1T github.com/redhat-developer/app-services-sdk-go v0.10.0/go.mod h1:enn8Zz6IT0HZYzS6LSttiME2apwnvfVWZnGRS81A4rk= github.com/redhat-developer/app-services-sdk-go/accountmgmt v0.1.0 h1:MOljVN8AKTM72Yed8ioAwhdW0KdWEhBZjjam3lY2lyY= github.com/redhat-developer/app-services-sdk-go/accountmgmt v0.1.0/go.mod h1:0LX7ZCEmMKAbncO05/zRYsV0K5wsds7AGPpOFC7KWGo= -github.com/redhat-developer/app-services-sdk-go/connectormgmt v0.4.1 h1:BuzYhAhO/jHi1R3eOpVoH7tSLvrlWR2s6lb/3m3pqZY= -github.com/redhat-developer/app-services-sdk-go/connectormgmt v0.4.1/go.mod h1:nQK2LFPPaTR+R6dZKBqSpaLCHBOWWDIewhzFZcfUfrg= github.com/redhat-developer/app-services-sdk-go/connectormgmt v0.5.0 h1:cf+K96kW8o6v6JSzaGpQI5amEzSJuGrd5on3V+SmKhg= github.com/redhat-developer/app-services-sdk-go/connectormgmt v0.5.0/go.mod h1:JAedrXf/qLHd7lpOS+bOFh8nrOpp2j0sg4/VG/1um6c= github.com/redhat-developer/app-services-sdk-go/kafkainstance v0.6.0 h1:ExEHQaihnPNxN2nKXB0q5nrmSv4p8b3Idzt7TChxv+Q= diff --git a/pkg/cmd/generate/build-configs.go b/pkg/cmd/generate/build-configs.go index fd58f265e..680aa002c 100644 --- a/pkg/cmd/generate/build-configs.go +++ b/pkg/cmd/generate/build-configs.go @@ -20,6 +20,9 @@ type configValues struct { ClientID string ClientSecret string TokenURL string + + // Optional + Name string } func createServiceAccount(opts *options, shortDescription string) (*kafkamgmtclient.ServiceAccount, error) { @@ -92,8 +95,8 @@ func BuildConfiguration(svcConfig *servicecontext.ServiceConfig, opts *options) if !serviceAvailable { return opts.localizer.MustLocalizeError("generate.log.info.noSevices") } - - serviceAccount, err := createServiceAccount(opts, fmt.Sprintf("%s-%v", opts.name, time.Now().Unix())) + configInstanceName := fmt.Sprintf("%s-%v", opts.name, time.Now().Unix()) + serviceAccount, err := createServiceAccount(opts, configInstanceName) if err != nil { return err } @@ -106,8 +109,9 @@ func BuildConfiguration(svcConfig *servicecontext.ServiceConfig, opts *options) configurations.ClientID = serviceAccount.GetClientId() configurations.ClientSecret = serviceAccount.GetClientSecret() configurations.TokenURL = cfg.MasAuthURL + "/protocol/openid-connect/token" + configurations.Name = configInstanceName - if err = WriteConfig(opts.configType, configurations); err != nil { + if err = WriteConfig(opts.configType, opts.fileName, configurations); err != nil { return err } diff --git a/pkg/cmd/generate/configurations.go b/pkg/cmd/generate/configurations.go index c0fcd45cf..fddaf6535 100644 --- a/pkg/cmd/generate/configurations.go +++ b/pkg/cmd/generate/configurations.go @@ -13,19 +13,21 @@ const ( envFormat = "env" jsonFormat = "json" propertiesFormat = "properties" + secretFormat = "secret" ) -var configurationTypes = []string{envFormat, jsonFormat, propertiesFormat} +var configurationTypes = []string{envFormat, jsonFormat, propertiesFormat, secretFormat} var ( - envConfig = template.Must(template.New(envFormat).Parse(templateEnv)) - jsonConfig = template.Must(template.New(jsonFormat).Parse(templateJSON)) - propertiesConfig = template.Must(template.New(propertiesFormat).Parse(templateProperties)) + envConfig = template.Must(template.New(envFormat).Parse(templateEnv)) + jsonConfig = template.Must(template.New(jsonFormat).Parse(templateJSON)) + propertiesConfig = template.Must(template.New(propertiesFormat).Parse(templateProperties)) + secretTemplateConfig = template.Must(template.New(secretFormat).Parse(templateSecret)) ) // WriteConfig saves the configurations to a file // in the specified output format -func WriteConfig(configType string, config *configValues) error { +func WriteConfig(configType string, filePath string, config *configValues) error { var fileBody bytes.Buffer fileTemplate := getFileFormat(configType) @@ -35,7 +37,9 @@ func WriteConfig(configType string, config *configValues) error { } fileData := []byte(fileBody.String()) - filePath := getDefaultPath(configType) + if filePath == "" { + filePath = getDefaultPath(configType) + } return ioutil.WriteFile(filePath, fileData, 0o600) } @@ -49,6 +53,8 @@ func getDefaultPath(configType string) (filePath string) { filePath = "rhoas.properties" case jsonFormat: filePath = "rhoas.json" + case secretFormat: + filePath = "rhoas-services-secret.yaml" } pwd, err := os.Getwd() @@ -62,7 +68,6 @@ func getDefaultPath(configType string) (filePath string) { } func getFileFormat(configType string) (template *template.Template) { - switch configType { case envFormat: template = envConfig @@ -70,6 +75,8 @@ func getFileFormat(configType string) (template *template.Template) { template = propertiesConfig case jsonFormat: template = jsonConfig + case secretFormat: + template = secretTemplateConfig } return template diff --git a/pkg/cmd/generate/generate-config.go b/pkg/cmd/generate/generate-config.go index 9250c5f1f..1054e42ec 100644 --- a/pkg/cmd/generate/generate-config.go +++ b/pkg/cmd/generate/generate-config.go @@ -25,6 +25,7 @@ type options struct { ServiceContext servicecontext.IContext name string + fileName string configType string } @@ -47,7 +48,6 @@ func NewGenerateCommand(f *factory.Factory) *cobra.Command { Example: f.Localizer.MustLocalize("generate.cmd.example"), Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - // check that a valid type is provided validType := flagutil.IsValidInput(opts.configType, configurationTypes...) if !validType { @@ -61,6 +61,7 @@ func NewGenerateCommand(f *factory.Factory) *cobra.Command { flags := contextcmdutil.NewFlagSet(cmd, f) flags.AddContextName(&opts.name) flags.StringVar(&opts.configType, "type", "", opts.localizer.MustLocalize("generate.flag.type")) + cmd.Flags().StringVar(&opts.fileName, "output-file", "", opts.localizer.MustLocalize("generate.common.flag.fileLocation.description")) _ = cmd.MarkFlagRequired("type") flagutil.EnableStaticFlagCompletion(cmd, "type", configurationTypes) diff --git a/pkg/cmd/generate/templates.go b/pkg/cmd/generate/templates.go index 5ac6b40d8..f05340b6f 100644 --- a/pkg/cmd/generate/templates.go +++ b/pkg/cmd/generate/templates.go @@ -2,14 +2,21 @@ package generate import ( "github.com/MakeNowJust/heredoc" + "github.com/redhat-developer/app-services-cli/pkg/cmd/registry/registrycmdutil" ) var ( templateEnv = heredoc.Doc(` - ## Generated by rhoas generate-config - {{if .KafkaHost}}KAFKA_HOST={{.KafkaHost}} - {{end}}{{if .RegistryURL}}SERVICE_REGISTRY_URL={{.RegistryURL}} - {{end}}RHOAS_CLIENT_ID={{.ClientID}} + ## Generated by rhoas cli + {{if .KafkaHost}}## Kafka Configuration + KAFKA_HOST={{.KafkaHost}} + {{end}}{{if .RegistryURL}}## Service Registry Configuration + SERVICE_REGISTRY_URL={{.RegistryURL}} + SERVICE_REGISTRY_CORE_PATH=` + registrycmdutil.REGISTRY_CORE_PATH + ` + SERVICE_REGISTRY_COMPAT_PATH=` + registrycmdutil.REGISTRY_COMPAT_PATH + ` + {{end}} + ## Authentication Configuration + RHOAS_CLIENT_ID={{.ClientID}} RHOAS_CLIENT_SECRET={{.ClientSecret}} RHOAS_OAUTH_TOKEN_URL={{.TokenURL}} `) @@ -18,6 +25,8 @@ var ( { {{if .KafkaHost}}"kafkaHost":"{{.KafkaHost}}", {{end}}{{if .RegistryURL}}"serviceRegistryUrl":"{{.RegistryURL}}", + "serviceRegistryCorePath":"` + registrycmdutil.REGISTRY_CORE_PATH + `", + "serviceRegistryCompatPath":"` + registrycmdutil.REGISTRY_COMPAT_PATH + `", {{end}}"rhoasClientID":"{{.ClientID}}", "rhoasClientSecret":"{{.ClientSecret}}", "rhoasOauthTokenUrl":"{{.TokenURL}}" @@ -25,11 +34,36 @@ var ( `) templateProperties = heredoc.Doc(` - ## Generated by rhoas generate-config - {{if .KafkaHost}}kafkaHost={{.KafkaHost}} - {{end}}{{if .RegistryURL}}serviceRegistryUrl={{.RegistryURL}} - {{end}}rhoasClientID={{.ClientID}} + ## Generated by rhoas cli + {{if .KafkaHost}}## Kafka Configuration + kafkaHost={{.KafkaHost}} + {{end}}{{if .RegistryURL}} ## Service Registry Configuration + serviceRegistryUrl={{.RegistryURL}} + serviceRegistryCorePath=` + registrycmdutil.REGISTRY_CORE_PATH + ` + serviceRegistryCompatPath=` + registrycmdutil.REGISTRY_COMPAT_PATH + ` + {{end}} + ## Authentication Configuration + rhoasClientID={{.ClientID}} rhoasClientSecret={{.ClientSecret}} rhoasOauthTokenUrl={{.TokenURL}} `) + + templateSecret = heredoc.Doc(` + apiVersion: v1 + kind: Secret + metadata: + name: {{.Name}} + type: Opaque + stringData: + {{if .KafkaHost}}## Kafka Configuration + KAFKA_HOST: {{.KafkaHost}}{{end}} + {{if .RegistryURL}}## Service Registry Configuration + SERVICE_REGISTRY_URL: {{.RegistryURL}} + SERVICE_REGISTRY_CORE_PATH: ` + registrycmdutil.REGISTRY_CORE_PATH + ` + SERVICE_REGISTRY_COMPAT_PATH: ` + registrycmdutil.REGISTRY_COMPAT_PATH + ` + {{end}} + ## Authentication Configuration + RHOAS_CLIENT_ID: {{.ClientID}} + RHOAS_CLIENT_SECRET: {{.ClientSecret}} + RHOAS_OAUTH_TOKEN_URL: {{.TokenURL}}`) ) diff --git a/pkg/cmd/registry/registrycmdutil/registry_util.go b/pkg/cmd/registry/registrycmdutil/registry_util.go index 510abca14..4b137c0f9 100644 --- a/pkg/cmd/registry/registrycmdutil/registry_util.go +++ b/pkg/cmd/registry/registrycmdutil/registry_util.go @@ -9,12 +9,17 @@ import ( var validNameRegexp = regexp.MustCompile(`^[a-z]([-a-z0-9]*[a-z0-9])?$`) -type compatibilityEndpoints struct { +// CompatibilityEndpoints - Service Registry API paths for various clients +type CompatibilityEndpoints struct { CoreRegistry string `json:"coreRegistryAPI"` SchemaRegistry string `json:"schemaRegistryCompatAPI"` CncfSchemaRegistry string `json:"cncfSchemaRegistryAPI"` } +const REGISTRY_CORE_PATH = "/apis/registry/v2" +const REGISTRY_COMPAT_PATH = "/apis/ccompat/v6" +const REGISTRY_CNCF_PATH = "/apis/cncf/v0" + // ValidateName validates the proposed name of a Kafka instance func ValidateName(val interface{}) error { name, ok := val.(string) @@ -37,12 +42,11 @@ func ValidateName(val interface{}) error { } // GetCompatibilityEndpoints returns the compatible API endpoints -func GetCompatibilityEndpoints(url string) *compatibilityEndpoints { - - endpoints := &compatibilityEndpoints{ - CoreRegistry: url + "/apis/registry/v2", - SchemaRegistry: url + "/apis/ccompat/v6", - CncfSchemaRegistry: url + "/apis/cncf/v0", +func GetCompatibilityEndpoints(url string) *CompatibilityEndpoints { + endpoints := &CompatibilityEndpoints{ + CoreRegistry: url + REGISTRY_CORE_PATH, + SchemaRegistry: url + REGISTRY_COMPAT_PATH, + CncfSchemaRegistry: url + REGISTRY_CNCF_PATH, } return endpoints diff --git a/pkg/core/localize/locales/en/cmd/generate_config.en.toml b/pkg/core/localize/locales/en/cmd/generate_config.en.toml index 6075cb466..5de22bf1b 100644 --- a/pkg/core/localize/locales/en/cmd/generate_config.en.toml +++ b/pkg/core/localize/locales/en/cmd/generate_config.en.toml @@ -13,6 +13,11 @@ $ rhoas generate-config --type json [generate.flag.type] one='Type of configuration file to be generated' +[generate.common.flag.fileLocation.description] +description = 'Description for --output-file flag' +one = 'Sets a custom file location to save the credentials' + + [generate.log.info.noSevices] one='No services available to generate configurations'