Skip to content

Commit 7a056de

Browse files
author
Enda Phelan
committed
fix: replace service account "name" with "short description"
BREAKING CHANGE: The service account `long description` field is removed and the `name` has been re-labeled to `short description`
1 parent d42692c commit 7a056de

9 files changed

Lines changed: 69 additions & 109 deletions

File tree

pkg/cmd/serviceaccount/create/create.go

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77

88
"github.com/redhat-developer/app-services-cli/pkg/icon"
9+
"github.com/redhat-developer/app-services-cli/pkg/ioutil/spinner"
910

1011
"github.com/redhat-developer/app-services-cli/pkg/localize"
1112
"github.com/redhat-developer/app-services-cli/pkg/serviceaccount/validation"
@@ -33,11 +34,10 @@ type options struct {
3334
localizer localize.Localizer
3435
Context context.Context
3536

36-
fileFormat string
37-
overwrite bool
38-
name string
39-
description string
40-
filename string
37+
fileFormat string
38+
overwrite bool
39+
shortDescription string
40+
filename string
4141

4242
interactive bool
4343
}
@@ -60,9 +60,9 @@ func NewCreateCommand(f *factory.Factory) *cobra.Command {
6060
Example: opts.localizer.MustLocalize("serviceAccount.create.cmd.example"),
6161
Args: cobra.NoArgs,
6262
RunE: func(cmd *cobra.Command, _ []string) (err error) {
63-
if !opts.IO.CanPrompt() && opts.name == "" {
63+
if !opts.IO.CanPrompt() && opts.shortDescription == "" {
6464
return opts.localizer.MustLocalizeError("flag.error.requiredWhenNonInteractive", localize.NewEntry("Flag", "name"))
65-
} else if opts.name == "" && opts.description == "" {
65+
} else if opts.shortDescription == "" {
6666
opts.interactive = true
6767
}
6868

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

78-
if err = validator.ValidateName(opts.name); err != nil {
79-
return err
80-
}
81-
if err = validator.ValidateDescription(opts.description); err != nil {
78+
if err = validator.ValidateShortDescription(opts.shortDescription); err != nil {
8279
return err
8380
}
8481
}
@@ -93,8 +90,7 @@ func NewCreateCommand(f *factory.Factory) *cobra.Command {
9390
},
9491
}
9592

96-
cmd.Flags().StringVar(&opts.name, "name", "", opts.localizer.MustLocalize("serviceAccount.create.flag.name.description"))
97-
cmd.Flags().StringVar(&opts.description, "description", "", opts.localizer.MustLocalize("serviceAccount.create.flag.description.description"))
93+
cmd.Flags().StringVar(&opts.shortDescription, "short-description", "", opts.localizer.MustLocalize("serviceAccount.create.flag.shortDescription.description"))
9894
cmd.Flags().BoolVar(&opts.overwrite, "overwrite", false, opts.localizer.MustLocalize("serviceAccount.common.flag.overwrite.description"))
9995
cmd.Flags().StringVar(&opts.filename, "output-file", "", opts.localizer.MustLocalize("serviceAccount.common.flag.fileLocation.description"))
10096
cmd.Flags().StringVar(&opts.fileFormat, "file-format", "", opts.localizer.MustLocalize("serviceAccount.common.flag.fileFormat.description"))
@@ -110,6 +106,10 @@ func runCreate(opts *options) error {
110106
if err != nil {
111107
return err
112108
}
109+
cfg, err := opts.Config.Load()
110+
if err != nil {
111+
return err
112+
}
113113

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

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

135-
a := conn.API().ServiceAccount().CreateServiceAccount(opts.Context)
136-
a = a.ServiceAccountRequest(*serviceAccountPayload)
137-
serviceacct, _, err := a.Execute()
138-
if err != nil {
139-
return err
140-
}
138+
serviceacct, httpRes, err := conn.API().
139+
ServiceAccount().
140+
CreateServiceAccount(opts.Context).
141+
ServiceAccountRequest(serviceAccountPayload).
142+
Execute()
143+
spinner.Stop()
141144

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

144-
cfg, err := opts.Config.Load()
145149
if err != nil {
146150
return err
147151
}
148152

153+
opts.Logger.Info(icon.SuccessPrefix(), opts.localizer.MustLocalize("serviceAccount.create.log.info.createdSuccessfully", localize.NewEntry("ID", serviceacct.GetId())))
154+
149155
creds := &credentials.Credentials{
150156
ClientID: serviceacct.GetClientId(),
151157
ClientSecret: serviceacct.GetClientSecret(),
@@ -158,7 +164,7 @@ func runCreate(opts *options) error {
158164
return fmt.Errorf("%v: %w", opts.localizer.MustLocalize("serviceAccount.common.error.couldNotSaveCredentialsFile"), err)
159165
}
160166

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

163169
return nil
164170
}
@@ -176,11 +182,11 @@ func runInteractivePrompt(opts *options) (err error) {
176182
opts.Logger.Debug(opts.localizer.MustLocalize("common.log.debug.startingInteractivePrompt"))
177183

178184
promptName := &survey.Input{
179-
Message: opts.localizer.MustLocalize("serviceAccount.create.input.name.message"),
180-
Help: opts.localizer.MustLocalize("serviceAccount.create.input.name.help"),
185+
Message: opts.localizer.MustLocalize("serviceAccount.create.input.shortDescription.message"),
186+
Help: opts.localizer.MustLocalize("serviceAccount.create.input.shortDescription.help"),
181187
}
182188

183-
err = survey.AskOne(promptName, &opts.name, survey.WithValidator(survey.Required), survey.WithValidator(validator.ValidateName))
189+
err = survey.AskOne(promptName, &opts.shortDescription, survey.WithValidator(survey.Required), survey.WithValidator(validator.ValidateShortDescription))
184190
if err != nil {
185191
return err
186192
}
@@ -207,17 +213,5 @@ func runInteractivePrompt(opts *options) (err error) {
207213
return err
208214
}
209215

210-
promptDescription := &survey.Multiline{
211-
Message: opts.localizer.MustLocalize("serviceAccount.create.input.description.message"),
212-
Help: opts.localizer.MustLocalize("serviceAccount.create.flag.description.description"),
213-
}
214-
215-
err = survey.AskOne(promptDescription, &opts.description, survey.WithValidator(validator.ValidateDescription))
216-
if err != nil {
217-
return err
218-
}
219-
220-
opts.Logger.Info(opts.localizer.MustLocalize("serviceAccount.create.log.info.creating", localize.NewEntry("Name", opts.name)))
221-
222216
return nil
223217
}

pkg/cmd/serviceaccount/list/list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ type options struct {
3030
// populate the list of service accounts into a table row
3131
type svcAcctRow struct {
3232
ID string `json:"id" header:"ID"`
33-
Name string `json:"name" header:"Name"`
3433
ClientID string `json:"clientID" header:"Client ID"`
34+
Name string `json:"name" header:"Short Description"`
3535
Owner string `json:"owner" header:"Owner"`
3636
CreatedAt string `json:"createdAt" header:"Created At"`
3737
}

pkg/cmd/serviceaccount/resetcredentials/reset_credentials.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
kafkamgmtclient "github.com/redhat-developer/app-services-sdk-go/kafkamgmt/apiv1/client"
1010

1111
"github.com/redhat-developer/app-services-cli/pkg/connection"
12+
"github.com/redhat-developer/app-services-cli/pkg/icon"
1213
"github.com/redhat-developer/app-services-cli/pkg/localize"
1314

1415
"github.com/AlecAivazis/survey/v2"
@@ -153,10 +154,10 @@ func runResetCredentials(opts *options) (err error) {
153154

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

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

161162
cfg, err := opts.Config.Load()
162163
if err != nil {
@@ -175,7 +176,7 @@ func runResetCredentials(opts *options) (err error) {
175176
return err
176177
}
177178

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

180181
return nil
181182
}
@@ -189,7 +190,7 @@ func resetCredentials(name string, opts *options) (*kafkamgmtclient.ServiceAccou
189190
// check if the service account exists
190191
api := conn.API()
191192

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

194195
serviceacct, httpRes, err := api.ServiceAccount().ResetServiceAccountCreds(opts.Context, opts.id).Execute()
195196
if httpRes != nil {

pkg/icon/icon.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package icon
22

3-
import "runtime"
3+
import (
4+
"runtime"
5+
6+
"github.com/redhat-developer/app-services-cli/pkg/color"
7+
)
48

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

1923
// SuccessPrefix returns check mark emoji prefix
2024
func SuccessPrefix() string {
21-
return Emoji(CheckMark, "")
25+
return color.Success(Emoji(CheckMark, ""))
2226
}
2327

2428
// ErrorPrefix returns cross mark emoji prefix or default "Error:"

pkg/localize/locales/en/cmd/serviceaccount.en.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ one = 'Sets a custom file location to save the credentials'
7979
description = 'debug message'
8080
one = '--file-format flag is not set, prompting user to enter a value'
8181

82-
[serviceAccount.common.validation.name.error.required]
82+
[serviceAccount.common.validation.shortDescription.error.required]
8383
one = 'service account name is required'
8484

85-
[serviceAccount.common.validation.name.error.lengthError]
85+
[serviceAccount.common.validation.shortDescription.error.lengthError]
8686
one = 'service account name cannot exceed {{.MaxNameLen}} characters'
8787

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

9191
[serviceAccount.common.validation.description.error.invalidChars]

pkg/localize/locales/en/cmd/serviceaccount_create.en.toml

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,30 @@ $ rhoas service-account create --overwrite
3232
$ rhoas service-account create --output-file=./service-acct-credentials.json
3333
'''
3434

35-
[serviceAccount.create.flag.name.description]
36-
description = 'Description for --name flag'
37-
one = 'Name of the service account'
38-
39-
[serviceAccount.create.flag.description.description]
40-
description = 'Description for --description flag'
41-
one = "Description for the service account (only alphanumeric characters and '-', '.', ',' are valid)"
35+
[serviceAccount.create.flag.shortDescription.description]
36+
description = 'Description for --short-description flag'
37+
one = 'Short description of the service account'
4238

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

4743
[serviceAccount.create.log.info.creating]
48-
one = 'Creating service account "{{.Name}}"'
44+
one = 'Creating service account'
4945

5046
[serviceAccount.create.log.info.createdSuccessfully]
51-
one = 'Service account "{{.Name}}" created successfully with ID "{{.ID}}".'
47+
one = 'Service account created successfully with ID "{{.ID}}"'
5248

53-
[serviceAccount.create.input.name.message]
54-
description = 'title for the Name input'
55-
one = "Name:"
49+
[serviceAccount.create.input.shortDescription.message]
50+
one = "Short Description:"
5651

57-
[serviceAccount.create.input.name.help]
58-
description = 'help for the Name input'
59-
one = "Give your service account an easily identifiable name"
52+
[serviceAccount.create.input.shortDescription.help]
53+
one = "Provide a short description for your service account"
6054

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

6559
[serviceAccount.create.input.fileFormat.help]
6660
description = 'Help for credentials format input'
67-
one = 'File format in which to save the service account credentials:'
68-
69-
[serviceAccount.create.input.description.message]
70-
description = 'Message for service account description'
71-
one = 'Description [optional]:'
61+
one = 'File format in which to save the service account credentials:'

pkg/localize/locales/en/cmd/serviceaccount_reset_credentials.en.toml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ one = 'Skip confirmation to forcibly reset service account credentials'
3838
description = 'Error message when service account could not be created'
3939
one = 'could not create service account'
4040

41-
[serviceAccount.resetCredentials.log.info.createdSuccessfully]
42-
one = 'Service account "{{.Name}}" created successfully with ID "{{.ID}}".'
43-
4441
[serviceAccount.resetCredentials.input.id.message]
4542
one = "Service Account ID:"
4643

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

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

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

6966
[serviceAccount.resetCredentials.error.resetError]
70-
one = 'could not reset credentials for service account "{{.Name}}"'
67+
one = 'could not reset credentials for service account with ID "{{.ID}}"'
7168

7269
[serviceAccount.resetCredentials.log.info.resetSuccess]
73-
one = 'Credentials reset for service account "{{.Name}}"'
70+
one = 'Credentials reset for service account with ID "{{.ID}}"'
7471

7572
[serviceAccount.resetCredentials.log.debug.resettingCredentials]
76-
one = 'Resetting credentials for service account "{{.Name}}"'
73+
one = 'Resetting credentials for service account with ID "{{.ID}}"'

pkg/serviceaccount/validation/validation.go

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,63 +9,37 @@ import (
99

1010
const (
1111
// name validation rules
12-
legalNameChars = "^[a-z]([-a-z0-9]*[a-z0-9])?$"
12+
legalShortDescriptionChars = "^[a-z]([-a-z0-9]*[a-z0-9])?$"
1313
maxNameLength = 50
1414
minNameLength = 1
1515
legalUUID = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
16-
// description validation rules
17-
legalDescriptionChars = "^[a-zA-Z0-9.,\\-\\s]*$"
18-
maxDescriptionLength = 255
1916
)
2017

2118
// Validator is a type for validating service account configuration values
2219
type Validator struct {
2320
Localizer localize.Localizer
2421
}
2522

26-
func (v *Validator) ValidateName(val interface{}) error {
23+
// ValidateShortDescription validates the short description value
24+
func (v *Validator) ValidateShortDescription(val interface{}) error {
2725
name, ok := val.(string)
2826
if !ok {
2927
return commonerr.NewCastError(val, "string")
3028
}
3129

3230
if len(name) < minNameLength {
33-
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.name.error.required")
31+
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.shortDescription.error.required")
3432
} else if len(name) > maxNameLength {
35-
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.name.error.lengthError", localize.NewEntry("MaxNameLen", maxNameLength))
33+
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.shortDescription.error.lengthError", localize.NewEntry("MaxNameLen", maxNameLength))
3634
}
3735

38-
matched, _ := regexp.Match(legalNameChars, []byte(name))
36+
matched, _ := regexp.Match(legalShortDescriptionChars, []byte(name))
3937

4038
if matched {
4139
return nil
4240
}
4341

44-
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.name.error.invalidChars", localize.NewEntry("Name", name))
45-
}
46-
47-
// ValidateDescription validates the service account description text
48-
func (v *Validator) ValidateDescription(val interface{}) error {
49-
description, ok := val.(string)
50-
if !ok {
51-
return commonerr.NewCastError(val, "string")
52-
}
53-
54-
if description == "" {
55-
return nil
56-
}
57-
58-
if len(description) > maxDescriptionLength {
59-
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.description.error.lengthError", localize.NewEntry("MaxLen", maxDescriptionLength))
60-
}
61-
62-
matched, _ := regexp.Match(legalDescriptionChars, []byte(description))
63-
64-
if matched {
65-
return nil
66-
}
67-
68-
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.description.error.invalidChars")
42+
return v.Localizer.MustLocalizeError("serviceAccount.common.validation.shortDescription.error.invalidChars", localize.NewEntry("Name", name))
6943
}
7044

7145
// ValidateUUID validates if ID is a valid UUID

pkg/serviceaccount/validation/validation_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func TestValidateName(t *testing.T) {
7474
// nolint:scopelint
7575
for _, tt := range tests {
7676
t.Run(tt.name, func(t *testing.T) {
77-
if err := validator.ValidateName(tt.args.val); (err != nil) != tt.wantErr {
77+
if err := validator.ValidateShortDescription(tt.args.val); (err != nil) != tt.wantErr {
7878
t.Errorf("ValidateName() error = %v, wantErr %v", err, tt.wantErr)
7979
}
8080
})

0 commit comments

Comments
 (0)