Skip to content

Commit 29610db

Browse files
committed
Made columns customizable when selecting ec2 instances
1 parent f77679d commit 29610db

File tree

6 files changed

+70
-17
lines changed

6 files changed

+70
-17
lines changed

README.md

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,32 @@ sso_start_url = https://d-0000000000.awsapps.com/start
141141

142142
The Knox config file is located at `~/.aws/knox/config.yaml`. Below are the configuration options available:
143143

144-
| Option | Default | Description |
145-
|-----------------------|---------|--------------------------------------------------------------------------------------------------------|
146-
| `default_connect_uid` | `0` | Default user ID for SSM sessions initiated with the `knox connect` command. |
147-
| `max_items_to_show` | `10` | Maximum number of items to display when listing profiles or options. |
148-
| `select_cached_first` | `false` | When selecting credentials, specifies whether to default to showing the cached role credentials first. |
149-
| `account_aliases` | `{}` | Account aliases for AWS accounts. Key is the account ID, and value is the account alias. |
144+
### `default_connect_uid`
145+
146+
Default value is `0` (root).
147+
148+
Default user ID for SSM sessions initiated with the `knox connect` command.
149+
150+
### `max_items_to_show`
151+
152+
Default value is `10`.
153+
154+
Maximum number of items to display when listing profiles or options.
155+
156+
### `select_cached_first`
157+
158+
Default value is `false`.
159+
160+
When selecting credentials, specifies whether to default to showing the cached role credentials first.
161+
162+
### `account_aliases`
163+
164+
Default value is `{}`.
165+
166+
Account aliases for AWS accounts. Key is the account ID, and value is the account alias.
167+
168+
### `instance_col_tags`
169+
170+
Default value is `["Instance Type", "Private IP", "Public IP", "Name"]`.
171+
172+
Specify "Instance Type", "Private IP", or "Public IP" to display when selecting an instance. All other values are extracted from tags.

internal/connect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ var connectCmd = &cobra.Command{
8383
}
8484
if instanceId == "" {
8585
if currentSelector == "instance" {
86-
if instanceId, action, err = tui.SelectInstance(role, region, searchTerm); err != nil {
86+
if instanceId, action, err = tui.SelectInstance(role, region, searchTerm, instanceColTags); err != nil {
8787
ExitWithError(19, "failed to pick an instance", err)
8888
} else if action == "back" {
8989
goBack()

internal/root.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ var (
2525
instanceId string
2626
region string
2727
accountAliases map[string]string
28+
instanceColTags []string
2829
)
2930

3031
const (
@@ -176,12 +177,14 @@ func setupConfigFile() {
176177
viper.SetDefault("select_cached_first", false)
177178
viper.SetDefault("max_items_to_show", 10)
178179
viper.SetDefault("account_aliases", map[string]string{})
180+
viper.SetDefault("instance_col_tags", []string{"Instance Type", "Private IP", "Public IP", "Name"})
179181
viper.SafeWriteConfig()
180182
viper.ReadInConfig()
181183
tui.MaxItemsToShow = viper.GetInt("max_items_to_show")
182184
selectCachedFirst = viper.GetBool("select_cached_first")
183185
connectUid = viper.GetUint32("default_connect_uid")
184186
accountAliases = viper.GetStringMapString("account_aliases")
187+
instanceColTags = viper.GetStringSlice("instance_col_tags")
185188
}
186189

187190
func init() {

internal/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ var syncCmd = &cobra.Command{
232232
}
233233
if instanceId == "" {
234234
if currentSelector == "instance" {
235-
if instanceId, action, err = tui.SelectInstance(role, region, searchTerm); err != nil {
235+
if instanceId, action, err = tui.SelectInstance(role, region, searchTerm, instanceColTags); err != nil {
236236
ExitWithError(19, "failed to pick an instance", err)
237237
} else if action == "back" {
238238
goBack()

sdk/credentials/session.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ type Instances []Instance
2929

3030
type Instance struct {
3131
Id string
32-
Name string
3332
InstanceType string
3433
PrivateIpAddress string
3534
PublicIpAddress string
35+
Tags map[string]string
3636
}
3737

3838
func (r *Role) StartSession(instanceId string, defaultUid uint32) (*ssm.StartSessionOutput, error) {
@@ -141,7 +141,6 @@ func (r *Role) GetManagedInstances(region string) (Instances, error) {
141141
}
142142
for _, info := range page.Reservations {
143143
for _, instance := range info.Instances {
144-
name := "-"
145144
privateId := "-"
146145
publicId := "-"
147146
if instance.PrivateIpAddress != nil {
@@ -150,17 +149,18 @@ func (r *Role) GetManagedInstances(region string) (Instances, error) {
150149
if instance.PublicIpAddress != nil {
151150
publicId = aws.ToString(instance.PublicIpAddress)
152151
}
152+
tags := map[string]string{}
153153
for _, tag := range instance.Tags {
154-
if aws.ToString(tag.Key) == "Name" {
155-
name = aws.ToString(tag.Value)
156-
}
154+
key := aws.ToString(tag.Key)
155+
value := aws.ToString(tag.Value)
156+
tags[key] = value
157157
}
158158
instance := Instance{
159159
Id: aws.ToString(instance.InstanceId),
160-
Name: name,
161160
InstanceType: string(instance.InstanceType),
162161
PrivateIpAddress: privateId,
163162
PublicIpAddress: publicId,
163+
Tags: tags,
164164
}
165165
instances = append(instances, instance)
166166
}

sdk/tui/tui.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,20 +149,47 @@ func SelectRole(roles credentials.Roles) (string, string, error) {
149149
return selection.Value.(string), "", nil
150150
}
151151

152-
func SelectInstance(role *credentials.Role, region, initialFilter string) (string, string, error) {
152+
func cutOff(s string, n int) string {
153+
if len(s) > n {
154+
return s[:n-1] + "…"
155+
}
156+
return s
157+
}
158+
159+
func SelectInstance(role *credentials.Role, region, initialFilter string, instanceColTags []string) (string, string, error) {
153160
instances, err := role.GetManagedInstances(region)
154161
if err != nil {
155162
return "", "", err
156163
}
164+
cols := []string{"Instance ID"}
165+
for _, tag := range instanceColTags {
166+
cols = append(cols, tag)
167+
}
157168
p := picker.NewPicker()
158169
p.WithMaxHeight(MaxItemsToShow)
159170
p.WithEmptyMessage("No Instances Found")
160171
p.WithTitle(fmt.Sprintf("Pick EC2 Instance (%s)", region))
161-
p.WithHeaders("Instance ID", "Instance Type", "Private IP", "Public IP", "Name")
172+
p.WithHeaders(cols...)
162173
p.AddAction(keys.Esc, "esc", "go back")
163174
p.AddAction(keys.F1, "f1", "pick region")
164175
for _, instance := range instances {
165-
p.AddOption(instance.Id, instance.Id, instance.InstanceType, instance.PrivateIpAddress, instance.PublicIpAddress, instance.Name)
176+
values := []string{instance.Id}
177+
for _, tag := range instanceColTags {
178+
value := "-"
179+
switch tag {
180+
case "Instance Type":
181+
value = instance.InstanceType
182+
case "Private IP":
183+
value = instance.PrivateIpAddress
184+
case "Public IP":
185+
value = instance.PublicIpAddress
186+
default:
187+
value = instance.Tags[tag]
188+
}
189+
value = cutOff(value, 36)
190+
values = append(values, value)
191+
}
192+
p.AddOption(instance.Id, values...)
166193
}
167194
selection, firedKeyCode := p.Pick(initialFilter)
168195
if firedKeyCode != nil && *firedKeyCode == keys.Esc {

0 commit comments

Comments
 (0)