Skip to content

Commit

Permalink
Merge pull request #389 from synfinatic/predict-in-binary
Browse files Browse the repository at this point in the history
Context sensitive prediction
  • Loading branch information
synfinatic authored May 11, 2022
2 parents 7f86c33 + 6d213f6 commit 08025db
Show file tree
Hide file tree
Showing 16 changed files with 929 additions and 99 deletions.
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
# AWS SSO CLI Changelog

## Unreleased

### New Features

* Auto-completion is now context sensitive to the `--sso`, `--account`, and
`--role` flags and filters results accordingly.

### Bugs

## [v1.9.1] - 2022-05-09

## Bugs

* Fix `config` command when user has no `UrlExecCommand` defined #385
* `console` no longer warns when a role is missing the Color or Icon tag
* `console` no longer warns when a role is missing the Color or Icon tag

## [v1.9.0] - 2022-05-08

Expand Down Expand Up @@ -353,7 +362,8 @@

Initial release

[Unreleased]: https://github.com/synfinatic/aws-sso-cli/compare/v1.9.0...main
[Unreleased]: https://github.com/synfinatic/aws-sso-cli/compare/v1.9.1...main
[v1.9.1]: https://github.com/synfinatic/aws-sso-cli/releases/tag/v1.9.1
[v1.9.0]: https://github.com/synfinatic/aws-sso-cli/releases/tag/v1.9.0
[v1.8.1]: https://github.com/synfinatic/aws-sso-cli/releases/tag/v1.8.1
[v1.8.0]: https://github.com/synfinatic/aws-sso-cli/releases/tag/v1.8.0
Expand Down
22 changes: 3 additions & 19 deletions cmd/list_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,13 @@ import (
"sort"
"strings"

"github.com/synfinatic/aws-sso-cli/internal/predictor"
"github.com/synfinatic/aws-sso-cli/internal/utils"
"github.com/synfinatic/aws-sso-cli/sso"
"github.com/synfinatic/aws-sso-cli/storage"
"github.com/synfinatic/gotable"
)

// keys match AWSRoleFlat header and value is the description
var allListFields = map[string]string{
"Id": "Column Index",
"Arn": "AWS Role Resource Name",
"AccountId": "AWS AccountID",
"AccountName": "Configured Account Name",
"AccountAlias": "AWS Account Alias",
"DefaultRegion": "Default AWS Region",
"EmailAddress": "Root Email for AWS account",
"ExpiresStr": "Time until STS creds expire",
"Expires": "Unix Epoch when STS creds expire",
"RoleName": "AWS Role Name",
"SSO": "AWS SSO Instance Name",
"Via": "Role Chain Via",
"Profile": "AWS_SSO_PROFILE / AWS_PROFILE",
}

type ListCmd struct {
ListFields bool `kong:"short='f',help='List available fields',xor='fields'"`
CSV bool `kong:"help='Generate CSV instead of a table',xor='fields'"`
Expand Down Expand Up @@ -196,15 +180,15 @@ func (cfn ConfigFieldNames) GetHeader(fieldName string) (string, error) {
// listAllFields generates a table with all the AWSRoleFlat fields we can print
func listAllFields() {
names := []string{}
for k := range allListFields {
for k := range predictor.AllListFields {
names = append(names, k)
}
sort.Strings(names)
ts := []gotable.TableStruct{}
for _, k := range names {
ts = append(ts, ConfigFieldNames{
Field: k,
Description: allListFields[k],
Description: predictor.AllListFields[k],
})
}

Expand Down
8 changes: 4 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/synfinatic/aws-sso-cli/awsconfig"
"github.com/synfinatic/aws-sso-cli/internal/helper"
"github.com/synfinatic/aws-sso-cli/internal/predictor"
"github.com/synfinatic/aws-sso-cli/internal/utils"
"github.com/synfinatic/aws-sso-cli/sso"
"github.com/synfinatic/aws-sso-cli/storage"
Expand Down Expand Up @@ -82,13 +83,11 @@ var DEFAULT_CONFIG map[string]interface{} = map[string]interface{}{
"ListFields": []string{"AccountId", "AccountAlias", "RoleName", "Profile", "ExpiresStr"},
"ConsoleDuration": 60,
"UrlAction": "open",
"UrlExecCommand": "",
"ConfigProfilesUrlAction": "open",
"LogLevel": "warn",
"DefaultSSO": "Default",
"FirefoxOpenUrlInContainer": false,
"AutoConfigCheck": false,
"ConfigProfilesUrlAction": "",
"ConfigUrlAction": "", // deprecated
"ProfileFormat": `{{ .AccountId }}:{{ .RoleName }}`,
"CacheRefresh": 24, // in hours
}
Expand Down Expand Up @@ -134,6 +133,7 @@ func main() {
utils.SetLogger(log)
awsconfig.SetLogger(log)
helper.SetLogger(log)
predictor.SetLogger(log)

if err := logLevelValidate(cli.LogLevel); err != nil {
log.Fatalf("%s", err.Error())
Expand Down Expand Up @@ -209,7 +209,7 @@ func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
vars,
)

p := NewPredictor(utils.GetHomePath(INSECURE_CACHE_FILE), utils.GetHomePath(CONFIG_FILE))
p := predictor.NewPredictor(utils.GetHomePath(INSECURE_CACHE_FILE), utils.GetHomePath(CONFIG_FILE))

kongplete.Complete(parser,
kongplete.WithPredictors(
Expand Down
25 changes: 3 additions & 22 deletions cmd/setup_prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strconv"

"github.com/manifoldco/promptui"
"github.com/synfinatic/aws-sso-cli/internal/predictor"
"github.com/synfinatic/aws-sso-cli/internal/utils"
)

Expand All @@ -35,26 +36,6 @@ const (
START_FQDN_FORMAT = "%s.awsapps.com"
)

// https://docs.aws.amazon.com/general/latest/gr/sso.html
var AvailableAwsSSORegions []string = []string{
"us-east-1",
"us-east-2",
"us-west-2",
"ap-south-1",
"ap-northeast-2",
"ap-southeast-1",
"ap-southeast-2",
"ap-northeast-1",
"ca-central-1",
"eu-central-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"eu-north-1",
"sa-east-1",
"us-gov-west-1",
}

type selectOptions struct {
Name string
Value string
Expand Down Expand Up @@ -184,7 +165,7 @@ func promptAwsSsoRegion(defaultValue string) string {
fmt.Printf("\n")

items := []selectOptions{}
for _, x := range AvailableAwsSSORegions {
for _, x := range predictor.AvailableAwsSSORegions {
items = append(items, selectOptions{
Value: x,
Name: x,
Expand Down Expand Up @@ -220,7 +201,7 @@ func promptDefaultRegion(defaultValue string) string {
Value: "",
},
}
for _, x := range AvailableAwsRegions {
for _, x := range predictor.AvailableAwsRegions {
items = append(items, selectOptions{
Value: x,
Name: x,
Expand Down
6 changes: 3 additions & 3 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ in your shell via [eval](#eval) or [exec](#exec).
### completions

Configures your appropriate shell configuration file to add auto-complete
functionality for commands, flags and options. Must restart your shell
for this to take effect.
and [shell helper](#shell-helper) functionality for commands, flags and
options. Must restart your shell for this to take effect.

For more information about this feature, please read [the quickstart](
quickstart.md#enabling-auto-completion-in-your-shell).
Expand Down Expand Up @@ -390,7 +390,7 @@ If you want to pass specific args to `aws-sso-profile` you can use the
`$AWS_SSO_HELPER_ARGS` environment variable. If nothing is set, then
`--level error` is used.

Currently the following shells are supported:
Currently the following shells are fully supported:

* `bash`
* [zsh - TBD](https://github.com/synfinatic/aws-sso-cli/issues/360)
Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ and the `$AWS_PROFILE` environment variable, AWS SSO CLI can support that as wel

#### Configuration

Run: `aws-sso config --open [open|clip|exec]`
Run: `aws-sso config`

This will add the following lines (example) to your `~/.aws/config` file:

Expand Down
103 changes: 103 additions & 0 deletions internal/predictor/comp_vars.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package predictor

/*
* AWS SSO CLI
* Copyright (c) 2021-2022 Aaron Turner <synfinatic at gmail dot com>
*
* This program is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or with the authors permission any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import (
"os"
"strconv"
"strings"
)

// getSSOFlag returns the value of -S/--sso from $COMP_LINE or empty string
func getSSOFlag() string {
compLine, ok := os.LookupEnv("COMP_LINE")
if !ok {
return ""
}

return flagValue(compLine, []string{"-S", "--sso"})
}

// getAccountIdFlag returns the value of -A/--account from $COMP_LINE or
// -1 for none
func getAccountIdFlag() int64 {
compLine, ok := os.LookupEnv("COMP_LINE")
if !ok {
return -1
}

aStr := flagValue(compLine, []string{"-A", "--account"})
if aStr == "" {
return -1
}
aid, _ := strconv.ParseInt(aStr, 10, 64)
return aid
}

// getRoleFlag returns the value of -R/--role from $COMP_LINE or empty string
func getRoleFlag() string {
compLine, ok := os.LookupEnv("COMP_LINE")
if !ok {
return ""
}

return flagValue(compLine, []string{"-R", "--role"})
}

func flagValue(line string, flags []string) string {
var flag string
i := 0

// remove double spaces
line = strings.ReplaceAll(line, " ", "")

// skip past our executable
i = strings.Index(line, " ")
if i < 0 {
return ""
}

line = line[i:]

for _, flag = range flags {
i = strings.Index(line, flag)
if i > 0 {
i += len(flag)
line = line[i:] // jump past our flag
break
}
}

// missing completely or need a space + at least 1 char
if i < 0 || len(line) < 2 {
return ""
}

line = line[1:] // eat the space

// find the next space
i = strings.Index(line, " ")
if i < 0 {
// let kongplete do the work
return ""
}

// return a result
return line[:i]
}
78 changes: 78 additions & 0 deletions internal/predictor/comp_vars_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package predictor

/*
* AWS SSO CLI
* Copyright (c) 2021-2022 Aaron Turner <synfinatic at gmail dot com>
*
* This program is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or with the authors permission any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetSSOFlag(t *testing.T) {
defer func() { os.Unsetenv("COMP_LINE") }()

os.Setenv("COMP_LINE", "aws-sso eval -S Default -R")
assert.Equal(t, "Default", getSSOFlag())

os.Setenv("COMP_LINE", "aws-sso eval --sso Default -R")
assert.Equal(t, "Default", getSSOFlag())

os.Setenv("COMP_LINE", "aws-sso eval --so Default -R")
assert.Equal(t, "", getSSOFlag())
}

func TestGetAccountIdFlag(t *testing.T) {
defer func() { os.Unsetenv("COMP_LINE") }()

os.Setenv("COMP_LINE", "aws-sso eval -A 5555 -R")
assert.Equal(t, int64(5555), getAccountIdFlag())

os.Setenv("COMP_LINE", "aws-sso eval --account 5555 -R")
assert.Equal(t, int64(5555), getAccountIdFlag())

os.Setenv("COMP_LINE", "aws-sso eval --account -5555 -R")
assert.Equal(t, int64(-5555), getAccountIdFlag())

os.Setenv("COMP_LINE", "aws-sso eval --accoun 5555 -R")
assert.Equal(t, int64(-1), getAccountIdFlag())
}

func TestGetRoleFlag(t *testing.T) {
defer func() { os.Unsetenv("COMP_LINE") }()

os.Setenv("COMP_LINE", "aws-sso eval -R Default -A")
assert.Equal(t, "Default", getRoleFlag())

os.Setenv("COMP_LINE", "aws-sso eval --role Default -A")
assert.Equal(t, "Default", getRoleFlag())

os.Setenv("COMP_LINE", "aws-sso eval --rol Default -A")
assert.Equal(t, "", getRoleFlag())
}

func TestFlagValue(t *testing.T) {
flags := []string{"-S", "--sso"}

assert.Equal(t, "", flagValue("", flags))
assert.Equal(t, "", flagValue("aws-sso eval -S", flags))
assert.Equal(t, "", flagValue("aws-sso eval -S D", flags))
assert.Equal(t, "", flagValue("aws-sso eval -S Default", flags))
assert.Equal(t, "Default", flagValue("aws-sso eval -S Default ", flags))
}
Loading

0 comments on commit 08025db

Please sign in to comment.