Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/commands/rhoas_service-account.adoc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions docs/commands/rhoas_service-account_create.adoc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 33 additions & 39 deletions pkg/cmd/serviceaccount/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/redhat-developer/app-services-cli/pkg/color"
"github.com/redhat-developer/app-services-cli/pkg/icon"
"github.com/redhat-developer/app-services-cli/pkg/ioutil/spinner"

"github.com/redhat-developer/app-services-cli/pkg/localize"
"github.com/redhat-developer/app-services-cli/pkg/serviceaccount/validation"
Expand Down Expand Up @@ -34,11 +35,10 @@ type options struct {
localizer localize.Localizer
Context context.Context

fileFormat string
overwrite bool
name string
description string
filename string
fileFormat string
overwrite bool
shortDescription string
filename string

interactive bool
}
Expand All @@ -61,9 +61,9 @@ func NewCreateCommand(f *factory.Factory) *cobra.Command {
Example: opts.localizer.MustLocalize("serviceAccount.create.cmd.example"),
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, _ []string) (err error) {
if !opts.IO.CanPrompt() && opts.name == "" {
return opts.localizer.MustLocalizeError("flag.error.requiredWhenNonInteractive", localize.NewEntry("Flag", "name"))
} else if opts.name == "" && opts.description == "" {
if !opts.IO.CanPrompt() && opts.shortDescription == "" {
return opts.localizer.MustLocalizeError("flag.error.requiredWhenNonInteractive", localize.NewEntry("Flag", "short-description"))
} else if opts.shortDescription == "" {
opts.interactive = true
}

Expand All @@ -76,10 +76,7 @@ func NewCreateCommand(f *factory.Factory) *cobra.Command {
return opts.localizer.MustLocalizeError("flag.error.requiredWhenNonInteractive", localize.NewEntry("Flag", "file-format"))
}

if err = validator.ValidateName(opts.name); err != nil {
return err
}
if err = validator.ValidateDescription(opts.description); err != nil {
if err = validator.ValidateShortDescription(opts.shortDescription); err != nil {
return err
}
}
Expand All @@ -94,8 +91,7 @@ func NewCreateCommand(f *factory.Factory) *cobra.Command {
},
}

cmd.Flags().StringVar(&opts.name, "name", "", opts.localizer.MustLocalize("serviceAccount.create.flag.name.description"))
cmd.Flags().StringVar(&opts.description, "description", "", opts.localizer.MustLocalize("serviceAccount.create.flag.description.description"))
cmd.Flags().StringVar(&opts.shortDescription, "short-description", "", opts.localizer.MustLocalize("serviceAccount.create.flag.shortDescription.description"))
cmd.Flags().BoolVar(&opts.overwrite, "overwrite", false, opts.localizer.MustLocalize("serviceAccount.common.flag.overwrite.description"))
cmd.Flags().StringVar(&opts.filename, "output-file", "", opts.localizer.MustLocalize("serviceAccount.common.flag.fileLocation.description"))
cmd.Flags().StringVar(&opts.fileFormat, "file-format", "", opts.localizer.MustLocalize("serviceAccount.common.flag.fileFormat.description"))
Expand All @@ -111,6 +107,10 @@ func runCreate(opts *options) error {
if err != nil {
return err
}
cfg, err := opts.Config.Load()
if err != nil {
return err
}

if opts.interactive {
// run the create command interactively
Expand All @@ -130,23 +130,29 @@ func runCreate(opts *options) error {
return opts.localizer.MustLocalizeError("serviceAccount.common.error.credentialsFileAlreadyExists", localize.NewEntry("FilePath", opts.filename))
}

spinner := spinner.New(opts.IO.ErrOut, opts.localizer)
spinner.SetSuffix(opts.localizer.MustLocalize("serviceAccount.create.log.info.creating"))
spinner.Start()
// create the service account
serviceAccountPayload := &kafkamgmtclient.ServiceAccountRequest{Name: opts.name, Description: &opts.description}
serviceAccountPayload := kafkamgmtclient.ServiceAccountRequest{Name: opts.shortDescription}

a := conn.API().ServiceAccount().CreateServiceAccount(opts.Context)
a = a.ServiceAccountRequest(*serviceAccountPayload)
serviceacct, _, err := a.Execute()
if err != nil {
return err
}
serviceacct, httpRes, err := conn.API().
ServiceAccount().
CreateServiceAccount(opts.Context).
ServiceAccountRequest(serviceAccountPayload).
Execute()
spinner.Stop()

opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.create.log.info.createdSuccessfully", localize.NewEntry("ID", serviceacct.GetId()), localize.NewEntry("Name", serviceacct.GetName())))
if httpRes != nil {
defer httpRes.Body.Close()
}

cfg, err := opts.Config.Load()
if err != nil {
return err
}

opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.create.log.info.createdSuccessfully", localize.NewEntry("ID", serviceacct.GetId())))

creds := &credentials.Credentials{
ClientID: serviceacct.GetClientId(),
ClientSecret: serviceacct.GetClientSecret(),
Expand All @@ -159,7 +165,7 @@ func runCreate(opts *options) error {
return fmt.Errorf("%v: %w", opts.localizer.MustLocalize("serviceAccount.common.error.couldNotSaveCredentialsFile"), err)
}

opts.Logger.Info(opts.localizer.MustLocalize("serviceAccount.common.log.info.credentialsSaved", localize.NewEntry("FilePath", color.CodeSnippet(opts.filename))))
opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.common.log.info.credentialsSaved", localize.NewEntry("FilePath", color.CodeSnippet(opts.filename))))

return nil
}
Expand All @@ -177,11 +183,11 @@ func runInteractivePrompt(opts *options) (err error) {
opts.Logger.Debug(opts.localizer.MustLocalize("common.log.debug.startingInteractivePrompt"))

promptName := &survey.Input{
Message: opts.localizer.MustLocalize("serviceAccount.create.input.name.message"),
Help: opts.localizer.MustLocalize("serviceAccount.create.input.name.help"),
Message: opts.localizer.MustLocalize("serviceAccount.create.input.shortDescription.message"),
Help: opts.localizer.MustLocalize("serviceAccount.create.input.shortDescription.help"),
}

err = survey.AskOne(promptName, &opts.name, survey.WithValidator(survey.Required), survey.WithValidator(validator.ValidateName))
err = survey.AskOne(promptName, &opts.shortDescription, survey.WithValidator(survey.Required), survey.WithValidator(validator.ValidateShortDescription))
if err != nil {
return err
}
Expand All @@ -208,17 +214,5 @@ func runInteractivePrompt(opts *options) (err error) {
return err
}

promptDescription := &survey.Multiline{
Message: opts.localizer.MustLocalize("serviceAccount.create.input.description.message"),
Help: opts.localizer.MustLocalize("serviceAccount.create.flag.description.description"),
}

err = survey.AskOne(promptDescription, &opts.description, survey.WithValidator(validator.ValidateDescription))
if err != nil {
return err
}

opts.Logger.Info(opts.localizer.MustLocalize("serviceAccount.create.log.info.creating", localize.NewEntry("Name", opts.name)))

return nil
}
2 changes: 1 addition & 1 deletion pkg/cmd/serviceaccount/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ type options struct {
// populate the list of service accounts into a table row
type svcAcctRow struct {
ID string `json:"id" header:"ID"`
Name string `json:"name" header:"Name"`
ClientID string `json:"clientID" header:"Client ID"`
Name string `json:"name" header:"Short Description"`
Owner string `json:"owner" header:"Owner"`
CreatedAt string `json:"createdAt" header:"Created At"`
}
Expand Down
17 changes: 8 additions & 9 deletions pkg/cmd/serviceaccount/resetcredentials/reset_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/redhat-developer/app-services-cli/pkg/color"
"github.com/redhat-developer/app-services-cli/pkg/connection"
"github.com/redhat-developer/app-services-cli/pkg/icon"
"github.com/redhat-developer/app-services-cli/pkg/localize"

"github.com/AlecAivazis/survey/v2"
Expand Down Expand Up @@ -109,16 +110,14 @@ func runResetCredentials(opts *options) (err error) {

api := conn.API()

serviceacct, httpRes, err := api.ServiceAccount().GetServiceAccountById(opts.Context, opts.id).Execute()
_, httpRes, err := api.ServiceAccount().GetServiceAccountById(opts.Context, opts.id).Execute()
if httpRes != nil {
defer httpRes.Body.Close()
}

if err != nil {
return err
}
serviceAcctName := serviceacct.GetName()

if opts.interactive {
err = runInteractivePrompt(opts)
if err != nil {
Expand Down Expand Up @@ -152,12 +151,12 @@ func runResetCredentials(opts *options) (err error) {
}
}

updatedServiceAccount, err := resetCredentials(serviceAcctName, opts)
updatedServiceAccount, err := resetCredentials(opts)
if err != nil {
return fmt.Errorf("%v: %w", opts.localizer.MustLocalize("serviceAccount.resetCredentials.error.resetError", localize.NewEntry("Name", updatedServiceAccount.GetName())), err)
return fmt.Errorf("%v: %w", opts.localizer.MustLocalize("serviceAccount.resetCredentials.error.resetError", localize.NewEntry("ID", opts.id)), err)
}

opts.Logger.Info(opts.localizer.MustLocalize("serviceAccount.resetCredentials.log.info.resetSuccess", localize.NewEntry("Name", updatedServiceAccount.GetName())))
opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.resetCredentials.log.info.resetSuccess", localize.NewEntry("ID", updatedServiceAccount.GetId())))

cfg, err := opts.Config.Load()
if err != nil {
Expand All @@ -176,12 +175,12 @@ func runResetCredentials(opts *options) (err error) {
return err
}

opts.Logger.Info(opts.localizer.MustLocalize("serviceAccount.common.log.info.credentialsSaved", localize.NewEntry("FilePath", opts.filename)))
opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.common.log.info.credentialsSaved", localize.NewEntry("FilePath", opts.filename)))

return nil
}

func resetCredentials(name string, opts *options) (*kafkamgmtclient.ServiceAccount, error) {
func resetCredentials(opts *options) (*kafkamgmtclient.ServiceAccount, error) {
conn, err := opts.Connection(connection.DefaultConfigSkipMasAuth)
if err != nil {
return nil, err
Expand All @@ -190,7 +189,7 @@ func resetCredentials(name string, opts *options) (*kafkamgmtclient.ServiceAccou
// check if the service account exists
api := conn.API()

opts.Logger.Debug(opts.localizer.MustLocalize("serviceAccount.resetCredentials.log.debug.resettingCredentials", localize.NewEntry("Name", name)))
opts.Logger.Debug(opts.localizer.MustLocalize("serviceAccount.resetCredentials.log.debug.resettingCredentials", localize.NewEntry("ID", opts.id)))

serviceacct, httpRes, err := api.ServiceAccount().ResetServiceAccountCreds(opts.Context, opts.id).Execute()
if httpRes != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/editor/linux.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// nolint
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

golangci-lint run cmd/... pkg/... internal/...
pkg/editor/linux.go:1: File is not `gofmt`-ed with `-s` (gofmt)
// +build !windows
make: *** [Makefile:64: lint] Error 1

I was suddenly getting this lint error for some reason.


// +build !windows

package editor
Expand Down
8 changes: 6 additions & 2 deletions pkg/icon/icon.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package icon

import "runtime"
import (
"runtime"

"github.com/redhat-developer/app-services-cli/pkg/color"
)

const (
CrossMark = "\u274c"
Expand All @@ -18,7 +22,7 @@ func Emoji(emoji string, fallback string) string {

// SuccessPrefix returns check mark emoji prefix
func SuccessPrefix() string {
return Emoji(CheckMark, "")
return color.Success(Emoji(CheckMark, ""))
}

// ErrorPrefix returns cross mark emoji prefix or default "Error:"
Expand Down
20 changes: 7 additions & 13 deletions pkg/localize/locales/en/cmd/serviceaccount.en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ one = 'Use these commands to create, list, describe, delete and update service a
[serviceAccount.cmd.example]
one = '''
## Create a service account
rhoas service-account create myserviceaccount
rhoas service-account create

## List all service accounts
rhoas service-account list
Expand Down Expand Up @@ -79,20 +79,14 @@ one = 'Sets a custom file location to save the credentials'
description = 'debug message'
one = '--file-format flag is not set, prompting user to enter a value'

[serviceAccount.common.validation.name.error.required]
one = 'service account name is required'
[serviceAccount.common.validation.shortDescription.error.required]
one = 'short description is required'

[serviceAccount.common.validation.name.error.lengthError]
one = 'service account name cannot exceed {{.MaxNameLen}} characters'
[serviceAccount.common.validation.shortDescription.error.lengthError]
one = 'service account description cannot exceed {{.MaxNameLen}} characters'

[serviceAccount.common.validation.name.error.invalidChars]
one = 'invalid service account name "{{.Name}}"; only lowercase letters (a-z), numbers, and "-" are accepted'

[serviceAccount.common.validation.description.error.invalidChars]
one = 'invalid service account description: only alphanumeric characters and "-", ".", "," are accepted'

[serviceAccount.common.validation.description.error.lengthError]
one = 'service account description cannot exceed {{.MaxLen}} characters'
[serviceAccount.common.validation.shortDescription.error.invalidChars]
one = 'invalid service account description: only lowercase letters (a-z), numbers, and "-" are accepted'

[serviceAccount.common.validation.id.error.invalidID]
one = '"{{.ID}}" is not a valid UUID'
30 changes: 10 additions & 20 deletions pkg/localize/locales/en/cmd/serviceaccount_create.en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,30 @@ $ rhoas service-account create --overwrite
$ rhoas service-account create --output-file=./service-acct-credentials.json
'''

[serviceAccount.create.flag.name.description]
description = 'Description for --name flag'
one = 'Name of the service account'

[serviceAccount.create.flag.description.description]
description = 'Description for --description flag'
one = "Description for the service account (only alphanumeric characters and '-', '.', ',' are valid)"
[serviceAccount.create.flag.shortDescription.description]
description = 'Description for --short-description flag'
one = 'Short description of the service account'

[serviceAccount.create.error.couldNotCreate]
description = 'Error message when service account could not be created'
one = 'could not create service account'

[serviceAccount.create.log.info.creating]
one = 'Creating service account "{{.Name}}"'
one = 'Creating service account'

[serviceAccount.create.log.info.createdSuccessfully]
one = 'Service account "{{.Name}}" created successfully with ID "{{.ID}}".'
one = 'Service account created successfully with ID "{{.ID}}"'

[serviceAccount.create.input.name.message]
description = 'title for the Name input'
one = "Name:"
[serviceAccount.create.input.shortDescription.message]
one = "Short Description:"

[serviceAccount.create.input.name.help]
description = 'help for the Name input'
one = "Give your service account an easily identifiable name"
[serviceAccount.create.input.shortDescription.help]
one = "Provide a short description for your service account"

[serviceAccount.create.input.fileFormat.message]
description = 'Title for credentials format input'
one = 'Credentials file format:'

[serviceAccount.create.input.fileFormat.help]
description = 'Help for credentials format input'
one = 'File format in which to save the service account credentials:'

[serviceAccount.create.input.description.message]
description = 'Message for service account description'
one = 'Description [optional]:'
one = 'File format in which to save the service account credentials:'
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ one = 'Skip confirmation to forcibly reset service account credentials'
description = 'Error message when service account could not be created'
one = 'could not create service account'

[serviceAccount.resetCredentials.log.info.createdSuccessfully]
one = 'Service account "{{.Name}}" created successfully with ID "{{.ID}}".'

[serviceAccount.resetCredentials.input.id.message]
one = "Service Account ID:"

Expand All @@ -61,16 +58,16 @@ description = 'Help for credentials format input'
one = 'File format in which to save the service account credentials:'

[serviceAccount.resetCredentials.input.confirmReset.message]
one = 'Are you sure you want to reset the credentials for service account "{{.ID}}"?'
one = 'Are you sure you want to reset the credentials for service account with ID "{{.ID}}"?'

[serviceAccount.resetCredentials.log.debug.cancelledReset]
one = 'You have chosen not to reset the service account credentials.'

[serviceAccount.resetCredentials.error.resetError]
one = 'could not reset credentials for service account "{{.Name}}"'
one = 'could not reset credentials for service account with ID "{{.ID}}"'

[serviceAccount.resetCredentials.log.info.resetSuccess]
one = 'Credentials reset for service account "{{.Name}}"'
one = 'Credentials reset for service account with ID "{{.ID}}"'

[serviceAccount.resetCredentials.log.debug.resettingCredentials]
one = 'Resetting credentials for service account "{{.Name}}"'
one = 'Resetting credentials for service account with ID "{{.ID}}"'
Loading