-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Refactored fuzzyfinder previewer (#3)
Co-authored-by: Reus <Reus>
- Loading branch information
Showing
8 changed files
with
239 additions
and
62 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,173 @@ | ||
package ui | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/bigkevmcd/go-configparser" | ||
mapset "github.com/deckarep/golang-set" | ||
"github.com/ktr0731/go-fuzzyfinder" | ||
) | ||
|
||
func fuzzyPreviewer(credentialsPath string, rolesPath string) string { | ||
var selected string | ||
creds, err := configparser.NewConfigParserFromFile(credentialsPath) | ||
const ( | ||
VALID_TEXT = "Valid" | ||
EXPIRED_TEXT = "Expired" | ||
) | ||
|
||
type FuzzyPreviewer struct { | ||
entries *configparser.ConfigParser | ||
outputSections []string | ||
rolesMapping *map[string]string | ||
} | ||
|
||
func NewFuzzyPreviewer(credentialsPath string, rolesPath string) (*FuzzyPreviewer, error) { | ||
creds, err := configparser.NewConfigParserFromFile(credentialsPath) | ||
if err != nil { | ||
return nil, errors.New(fmt.Sprintf("Cannot parse file %s: %v", credentialsPath, err)) | ||
} | ||
roles, err := configparser.NewConfigParserFromFile(rolesPath) | ||
if err != nil { | ||
return nil, errors.New(fmt.Sprintf("Cannot parse file %s: %v", rolesPath, err)) | ||
} | ||
|
||
sections := creds.Sections() | ||
sections = append(sections, roles.Sections()...) | ||
sort.Strings(sections) | ||
_, err = fuzzyfinder.FindMulti( | ||
sections, | ||
func(i int) string { | ||
return sections[i] | ||
}, | ||
fuzzyfinder.WithPreviewWindow(func(i, w, h int) string { | ||
if i == -1 { | ||
return "" | ||
} | ||
selected = sections[i] | ||
s := fmt.Sprintf("[%s]\n", selected) | ||
|
||
// if is a profile (~/.aws/confg) | ||
var aux configparser.Dict | ||
var showedKeys configparser.Dict = make(configparser.Dict) | ||
if strings.HasPrefix(selected, "profile") { | ||
aux, err = roles.Items(selected) | ||
rolesMapping := map[string]string{} | ||
|
||
outputSections := []string{} | ||
extraSections := mapset.NewSet() | ||
entries := configparser.New() | ||
|
||
// Go though the sections of the credentials file (~/.aws/credentials) | ||
for _, sec := range creds.Sections() { | ||
err := entries.AddSection(sec) | ||
if err != nil { | ||
return nil, errors.New(fmt.Sprintf("Cannot add section %s: %v", sec, err)) | ||
} | ||
extraSections.Add(sec) | ||
items, err := creds.Items(sec) | ||
if err != nil { | ||
return nil, errors.New(fmt.Sprintf("Cannot get the %s entries from the credentials file (~/.aws/credentials): %v", sec, err)) | ||
} | ||
|
||
rolesMapping[sec] = sec | ||
for k, v := range items { | ||
entries.Set(sec, k, v) | ||
} | ||
} | ||
|
||
var outputName string | ||
var extraItems configparser.Dict | ||
|
||
// Go though the sections of the config file (~/.aws/config) | ||
for _, sec := range roles.Sections() { | ||
profileName := strings.TrimPrefix(sec, "profile ") | ||
_, err := roles.GetBool(sec, "sso_auto_populated") | ||
// If is not autopopulated | ||
if err != nil { | ||
if entries.HasSection(profileName) { | ||
extraItems, _ = entries.Items(profileName) | ||
err = entries.RemoveSection(profileName) | ||
if err != nil { | ||
return "" | ||
return nil, errors.New(fmt.Sprintf("Cannot erase section %s from configFile: %v", profileName, err)) | ||
} | ||
showedKeys["Account name"] = aux["sso_account_name"] | ||
showedKeys["Account ID"] = aux["sso_account_id"] | ||
showedKeys["Region"] = aux["region"] | ||
extraSections.Remove(profileName) | ||
} | ||
outputName = fmt.Sprintf("(profile) %s", profileName) | ||
} else { | ||
outputName = fmt.Sprintf("(SSO profile) %s", profileName) | ||
} | ||
|
||
rolesMapping[outputName] = sec | ||
|
||
outputSections = append(outputSections, outputName) | ||
entries.AddSection(sec) | ||
|
||
items, _ := roles.Items(sec) | ||
for k, v := range items { | ||
entries.Set(sec, k, v) | ||
} | ||
|
||
for k, v := range extraItems { | ||
entries.Set(sec, k, v) | ||
} | ||
} | ||
|
||
for sec := range extraSections.Iter() { | ||
outputSections = append(outputSections, sec.(string)) | ||
} | ||
return &FuzzyPreviewer{ | ||
rolesMapping: &rolesMapping, | ||
entries: entries, | ||
outputSections: outputSections, | ||
}, nil | ||
} | ||
|
||
func (fp *FuzzyPreviewer) generatePreviewAttrs(selected string) (*string, error) { | ||
s := fmt.Sprintf("[%s]\n", (*fp.rolesMapping)[selected]) | ||
items, _ := fp.entries.Items((*fp.rolesMapping)[selected]) | ||
keys := sort.StringSlice(items.Keys()) | ||
for _, k := range keys { | ||
v := items[k] | ||
switch k { | ||
case "aws_secret_access_key", "aws_session_token": | ||
continue | ||
case "expires_time": | ||
exp, err := strconv.Atoi(v) | ||
if err != nil { | ||
s += fmt.Sprintln(fmt.Sprintf("Cannot parse: %s", k)) | ||
} | ||
expiresAt := time.Unix(int64(exp), 0) | ||
s += fmt.Sprintln(fmt.Sprintf("Expires Time: %s", expiresAt.String())) | ||
var expiredTxt string | ||
if expiresAt.Before(time.Now()) { | ||
expiredTxt = EXPIRED_TEXT | ||
} else { | ||
aux, err = creds.Items(selected) | ||
if err != nil { | ||
return "" | ||
} | ||
showedKeys["AWS access key id"] = aux["aws_access_key_id"] | ||
iss, err := strconv.Atoi(aux["issued_time"]) | ||
if err != nil { | ||
return "" | ||
} | ||
exp, err := strconv.Atoi(aux["expires_time"]) | ||
if err != nil { | ||
return "" | ||
} | ||
expiredAt := time.Unix(int64(exp), 0) | ||
showedKeys["Issued at"] = time.Unix(int64(iss), 0).String() | ||
showedKeys["Expires at"] = expiredAt.String() | ||
if expiredAt.Before(time.Now()) { | ||
showedKeys["Status"] = "Expiradas" | ||
} else { | ||
showedKeys["Status"] = "Válidas" | ||
} | ||
expiredTxt = VALID_TEXT | ||
} | ||
s += fmt.Sprintln(fmt.Sprintf("Status: %s", expiredTxt)) | ||
break | ||
case "issued_time": | ||
iss, err := strconv.Atoi(v) | ||
if err != nil { | ||
s += fmt.Sprintln(fmt.Sprintf("Cannot parse %s", k)) | ||
} | ||
issuedAt := time.Unix(int64(iss), 0) | ||
s += fmt.Sprintln(fmt.Sprintf("Issued Time: %s", issuedAt.String())) | ||
break | ||
default: | ||
k = strings.Title(strings.ReplaceAll(k, "_", " ")) | ||
s += fmt.Sprintln(fmt.Sprintf("%s: %s", k, v)) | ||
} | ||
} | ||
return &s, nil | ||
} | ||
|
||
for _, key := range showedKeys.Keys() { | ||
s += fmt.Sprintf("%s: %s\n", key, showedKeys[key]) | ||
func (fp *FuzzyPreviewer) Preview() (*string, error) { | ||
var selected string | ||
_, err := fuzzyfinder.FindMulti( | ||
fp.outputSections, | ||
func(i int) string { | ||
return fp.outputSections[i] | ||
}, | ||
fuzzyfinder.WithPreviewWindow(func(i, w, h int) string { | ||
if i == -1 { | ||
return "" | ||
} | ||
selected = fp.outputSections[i] | ||
s, err := fp.generatePreviewAttrs(selected) | ||
if err != nil { | ||
return fmt.Sprintf("Cannot parse attributes from %s", selected) | ||
} | ||
return s | ||
return *s | ||
})) | ||
|
||
parts := strings.Split(selected, " ") | ||
var role string | ||
if len(parts) == 1 { | ||
role = parts[0] | ||
} else { | ||
role = parts[1] | ||
if err != nil { | ||
return nil, err | ||
} | ||
return role | ||
|
||
result := strings.TrimPrefix((*fp.rolesMapping)[selected], "profile ") | ||
return &result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
[profile tmp:Account 5:Role 2] | ||
region = us-east-1 | ||
|
||
[profile Account 1:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 5 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 2:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 2 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 3:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 3 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 4:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 4 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 5:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 5 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 5:Role 2] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 5 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 2 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 5:Role 3] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 5 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 3 | ||
region = us-east-1 | ||
sso_auto_populated = true | ||
|
||
[profile Account 6:Role 1] | ||
sso_start_url = https://myApp.awsapps.com/start | ||
sso_region = us-east-1 | ||
sso_account_name = Account 6 | ||
sso_account_id = XXXXXXXXXXXX | ||
sso_role_name = Role 1 | ||
region = us-east-1 | ||
sso_auto_populated = true |