Skip to content

Commit 5cb9183

Browse files
committed
More sorting and list field fixes
- Sorting by Profile was busted because we were loading ProfileFormat after sorting - Fix bug where we did not detect invalid field names for `list` - Generally clean up logic/code - Don't do SSO workflow for CSV since we don't report SSO Token expire time in CSV output - ListFields now deprecates AccountIdStr for AccountIdPad Fixes: #503, #506
1 parent 75e7dd5 commit 5cb9183

File tree

7 files changed

+66
-30
lines changed

7 files changed

+66
-30
lines changed

CHANGELOG.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
### Bugs
66

7+
* Fix `list --sort` bugs #506
78
* Fix `process --profile` flag not working
8-
* Fix `AccountId` still not zero padding in `list` output
9+
* Fix `AccountId` still not zero padding in `list` output #503
10+
* Invalid fields passed to `list` command are now detected instead of an empty column
11+
912

1013
### Changes
1114

@@ -20,7 +23,9 @@
2023
### Deprecated
2124

2225
* `AccountIdStr` function for `ProfileFormat`. Use the `.AccountIdPad` variable instead.
23-
* `ExpiresStr` is now deprecated. Use `Expires` instead.
26+
* `AccountIdStr` field is replaced by `AccountIdPad` in `list` command and `ListFields` in config.yaml
27+
* `ARN` field is replaced by `Arn` in `list` command and `ListFields` in config.yaml
28+
* `ExpiresStr` field is replaced by `Expires` in `list` command and `ListFields` in config.yaml
2429

2530
## [v1.10.0] - 2023-07-30
2631

cmd/aws-sso/list_cmd.go

+29-17
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ func (cc *ListCmd) Run(ctx *RunContext) error {
8686
fields = ctx.Cli.List.Fields
8787
}
8888

89+
for _, f := range fields {
90+
if !predictor.SupportedListField(f) {
91+
return fmt.Errorf("Unsupported field: '%s'", f)
92+
}
93+
}
94+
8995
return printRoles(ctx, fields, ctx.Cli.List.CSV, prefixSearch, ctx.Cli.List.Sort, ctx.Cli.List.Reverse)
9096
}
9197

@@ -118,29 +124,39 @@ func printRoles(ctx *RunContext, fields []string, csv bool, prefixSearch []strin
118124
idx := 0
119125

120126
allRoles := roles.GetAllRoles()
127+
for _, roleFlat := range allRoles {
128+
// this doesn't happen in GetAllRoles()
129+
p, err := roleFlat.ProfileName(ctx.Settings)
130+
if err == nil {
131+
roleFlat.Profile = p
132+
}
133+
}
121134

122135
var sortError error
123136
sort.SliceStable(allRoles, func(i, j int) bool {
124137
a, err := allRoles[i].GetSortableField(sortby)
125138
if err != nil {
126-
sortError = fmt.Errorf("Invalid --sort value: %s", sortby)
139+
sortError = fmt.Errorf("Invalid --sort: %s", err.Error())
127140
return false
128141
}
129142
b, _ := allRoles[j].GetSortableField(sortby)
130143

131-
if a.Type == sso.Sval {
144+
switch a.Type {
145+
case sso.Sval:
132146
if !reverse {
133147
return a.Sval < b.Sval
134148
} else {
135149
return a.Sval > b.Sval
136150
}
137-
} else if a.Type == sso.Ival {
151+
152+
case sso.Ival:
138153
if !reverse {
139154
return a.Ival < b.Ival
140155
} else {
141156
return a.Ival > b.Ival
142157
}
143-
} else {
158+
159+
default:
144160
sortError = fmt.Errorf("Unable to sort by field: %s", sortby)
145161
return false
146162
}
@@ -163,27 +179,22 @@ func printRoles(ctx *RunContext, fields []string, csv bool, prefixSearch []strin
163179
}
164180
}
165181

166-
p, err := roleFlat.ProfileName(ctx.Settings)
167-
if err == nil {
168-
roleFlat.Profile = p
169-
}
170-
171182
roleFlat.Id = idx
172183
idx += 1
173184
tr = append(tr, *roleFlat)
174185
}
175186

176-
// Determine when our AWS SSO session expires
177-
// list doesn't call doAuth() so we have to initialize our global *AwsSSO manually
178-
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
179-
if err != nil {
180-
log.Fatalf("%s", err.Error())
181-
}
182-
AwsSSO = sso.NewAWSSSO(s, &ctx.Store)
183-
184187
if csv {
185188
err = gotable.GenerateCSV(tr, fields)
186189
} else {
190+
// Determine when our AWS SSO session expires
191+
// list doesn't call doAuth() so we have to initialize our global *AwsSSO manually
192+
s, err := ctx.Settings.GetSelectedSSO(ctx.Cli.SSO)
193+
if err != nil {
194+
log.Fatalf("%s", err.Error())
195+
}
196+
AwsSSO = sso.NewAWSSSO(s, &ctx.Store)
197+
187198
expires := ""
188199
ctr := storage.CreateTokenResponse{}
189200
if err := ctx.Store.GetCreateTokenResponse(AwsSSO.StoreKey(), &ctr); err != nil {
@@ -199,6 +210,7 @@ func printRoles(ctx *RunContext, fields []string, csv bool, prefixSearch []strin
199210

200211
err = gotable.GenerateTable(tr, fields)
201212
}
213+
202214
if err == nil {
203215
fmt.Printf("\n")
204216
}

internal/predictor/predictor.go

+11
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,14 @@ func getSSOValue() string {
197197
}
198198
return sso
199199
}
200+
201+
func SupportedListField(name string) bool {
202+
ret := false
203+
for k := range AllListFields {
204+
if k == name {
205+
ret = true
206+
break
207+
}
208+
}
209+
return ret
210+
}

internal/predictor/predictor_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ func TestCompletions(t *testing.T) {
7171
assert.NotNil(t, c)
7272
assert.Equal(t, 3, len(c.Predict(args)))
7373
}
74+
75+
func TestSupportedListField(t *testing.T) {
76+
assert.True(t, SupportedListField("AccountIdPad"))
77+
assert.False(t, SupportedListField("Account"))
78+
}

sso/roles.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ func (r *Roles) GetRole(accountId int64, roleName string) (*AWSRoleFlat, error)
159159
flat.Expires = exp
160160
}
161161
} else {
162+
flat.ExpiresEpoch = 0
162163
flat.Expires = "Expired"
163164
}
164165

@@ -517,18 +518,13 @@ type FlatField struct {
517518

518519
// GetSortableField returns a FlatField for the given field. We do some mapping across
519520
// fields so that this can be used for sorting.
520-
func (r *AWSRoleFlat) GetSortableField(columnName string) (FlatField, error) {
521-
var fieldName string
521+
func (r *AWSRoleFlat) GetSortableField(fieldName string) (FlatField, error) {
522522
ret := FlatField{}
523523

524-
// Map cases where the `header` != field name in the struct
525-
switch columnName {
524+
switch fieldName {
526525
case "Tags":
527526
// Tags is a valid field, but we can't sort by it
528527
return ret, fmt.Errorf("Unable to sort by `Tags`")
529-
530-
default:
531-
fieldName = columnName
532528
}
533529

534530
v := reflect.ValueOf(r)

sso/settings.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,17 @@ func (s *Settings) applyDeprecations() bool {
241241
}
242242

243243
// ExpiresStr => Expires in v1.11.0
244+
// AccountIdStr => AccountIdPad v1.11.0
245+
// ARN => Arn v1.11.0
244246
if len(s.ListFields) > 0 {
245247
for i, v := range s.ListFields {
246-
if v == "ExpiresStr" {
248+
switch v {
249+
case "ExpiresStr":
247250
s.ListFields[i] = "Expires"
251+
case "AccountIdStr":
252+
s.ListFields[i] = "AccountIdPad"
253+
case "ARN":
254+
s.ListFields[i] = "Arn"
248255
}
249256
}
250257
}

sso/settings_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ func TestCreatedAt(t *testing.T) {
332332

333333
func TestApplyDeprecations(t *testing.T) {
334334
s := &Settings{
335-
ListFields: []string{"Foo", "Bar", "ExpiresStr"},
335+
ListFields: []string{"Foo", "Bar", "ExpiresStr", "AccountIdStr", "ARN"},
336336
ProfileFormat: "{{ AccountIdStr .AccountId }}:{{ .RoleName }}",
337337
FirefoxOpenUrlInContainer: true,
338338
ConfigProfilesUrlAction: url.ConfigProfilesUndef,
@@ -350,8 +350,8 @@ func TestApplyDeprecations(t *testing.T) {
350350
assert.Equal(t, url.OpenUrlContainer, s.UrlAction)
351351
assert.Equal(t, false, s.FirefoxOpenUrlInContainer)
352352

353-
// ExpiresStr => Expires
354-
assert.Equal(t, []string{"Foo", "Bar", "Expires"}, s.ListFields)
353+
// ExpiresStr => Expires, etc
354+
assert.Equal(t, []string{"Foo", "Bar", "Expires", "AccountIdPad", "Arn"}, s.ListFields)
355355

356356
// AccountIdStr .AccountId => .AccountIdPad
357357
assert.Equal(t, "{{ .AccountIdPad }}:{{ .RoleName }}", s.ProfileFormat)

0 commit comments

Comments
 (0)