Skip to content

Commit

Permalink
- Change GetSession() signature
Browse files Browse the repository at this point in the history
- Make profile and region selectable
  • Loading branch information
RamanaReddy0M committed Feb 9, 2023
1 parent b30a7fd commit 175419d
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 91 deletions.
9 changes: 2 additions & 7 deletions cmd/localstackpopulator.go
Expand Up @@ -15,12 +15,7 @@ var lspop = &cobra.Command{
Short: ``,
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
cfg, err := config.Get()
if err != nil {
log.Fatal("err: ", err)
}

sess, err := config.GetSession(profile, region, cfg.AwsConfig)
sess, err := config.GetSession(profile, region)
if err != nil {
log.Fatal("err: ", err)
}
Expand All @@ -41,7 +36,7 @@ var lspop = &cobra.Command{

for i := 0; i < 4; i++ {
gofakeit.Seed(0)
sess, err := config.GetSession(profile, regions[gofakeit.Number(0, len(regions)-1)], cfg.AwsConfig)
sess, err := config.GetSession(profile, regions[gofakeit.Number(0, len(regions)-1)])
if err != nil {
log.Fatal("err: ", err)
}
Expand Down
64 changes: 52 additions & 12 deletions cmd/root.go
Expand Up @@ -5,8 +5,9 @@ import (
"fmt"
"os"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/one2nc/cloud-lens/internal"
"github.com/one2nc/cloud-lens/internal/aws"
"github.com/one2nc/cloud-lens/internal/color"
"github.com/one2nc/cloud-lens/internal/config"
"github.com/one2nc/cloud-lens/internal/view"
"github.com/rs/zerolog"
Expand All @@ -17,7 +18,7 @@ import (
var rootCmd = &cobra.Command{
Use: `cloudlens`,
Short: `cli for aws services`,
Long: `cli for aws services[s3, ec2]`,
Long: `cli for aws services[s3, ec2, security-groups, iam]`,
Run: run,
}

Expand Down Expand Up @@ -50,24 +51,63 @@ func run(cmd *cobra.Command, args []string) {
}()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: file})

//get config
// cfg, err := config.Get()
if err != nil {
panic(fmt.Sprintf("app get config failed -- %v", err))
}
sess, err := config.GetSession(profile, region, *aws.NewConfig())
profiles := readAndValidateProfile()
regions := readAndValidateRegion()
sess, err := config.GetSession(profiles[0], regions[0])
if err != nil {
panic(fmt.Sprintf("aws session init failed -- %v", err))
}

ctx := context.WithValue(context.Background(), internal.KeySession, sess)

app := view.NewApp()
//init app
if err := app.Init(profile, region, ctx); err != nil {
if err := app.Init(profiles, regions, ctx); err != nil {
panic(fmt.Sprintf("app init failed -- %v", err))
}
if err := app.Run(); err != nil {
panic(fmt.Sprintf("app run failed %v", err))
}
}

func readAndValidateProfile() []string {
profiles, err := config.GetProfiles()
if err != nil {
panic(fmt.Sprintf("failed to read profiles -- %v", err))
}
profiles, isSwapped := config.SwapFirstIndexWithValue(profiles, profile)
if !isSwapped {
loop:
for {
var input string
fmt.Printf("Profile '%v' not found, would you like to pick one from profiles[%v,..] ["+color.Colorize("y", color.Cyan)+"/"+color.Colorize("n", color.Red)+"]: ", color.Colorize(profile, color.Red), profiles[0])
fmt.Scanln(&input)
switch input {
case "y", "Y", "yes", "YES":
break loop
case "n", "N", "no", "NO":
fmt.Printf("Profile '%v' not found, exiting..", profile)
os.Exit(0)
}
}
}
return profiles
}

func readAndValidateRegion() []string {
regions := aws.GetAllRegions()
regions, isSwapped := config.SwapFirstIndexWithValue(regions, region)
if !isSwapped {
loop:
for {
var input string
fmt.Printf("Region '%v' not found, would you like to pick one from regions[%v,..] ["+color.Colorize("y", color.Cyan)+"/"+color.Colorize("n", color.Red)+"]: ", color.Colorize(region, color.Red), regions[0])
fmt.Scanln(&input)
switch input {
case "y", "Y", "yes", "YES":
break loop
case "n", "N", "no", "NO":
fmt.Printf("Region '%v' not found, exiting..", region)
os.Exit(0)
}
}
}
return regions
}
11 changes: 2 additions & 9 deletions internal/aws/ec2.go
Expand Up @@ -28,21 +28,14 @@ func (e ByLaunchTime) Less(i, j int) bool {
return e[i].Instance.LaunchTime.Before(*e[j].Instance.LaunchTime)
}

func GetAllRegions() []string {
return []string{
"us-east-1", "us-east-2", "us-west-1", "us-west-2", "af-south-1", "ap-east-1",
"ap-southeast-3", "ap-south-1", "ap-northeast-3", "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-south-1", "eu-west-3", "eu-north-1",
"me-south-1", "me-central-1", "sa-east-1", "us-gov-east-1", "us-gov-west-1"}
}


func GetInstances(sess session.Session) ([]EC2Resp, error) {
var ec2Info []EC2Resp
ec2Serv := *ec2.New(&sess)
result, err := ec2Serv.DescribeInstances(nil)
if err != nil {
fmt.Println("Error fetching instances:", err)
//fmt.Println("Error fetching instances:", err)
return nil, err
}
// Iterate through the instances and print their ID and state
Expand Down
10 changes: 10 additions & 0 deletions internal/aws/helpers.go
@@ -0,0 +1,10 @@
package aws

func GetAllRegions() []string {
return []string{
"us-east-1", "us-east-2", "us-west-1", "us-west-2", "af-south-1", "ap-east-1",
"ap-southeast-3", "ap-south-1", "ap-northeast-3", "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-south-1", "eu-west-3", "eu-north-1",
"me-south-1", "me-central-1", "sa-east-1", "us-gov-east-1", "us-gov-west-1"}
}
15 changes: 15 additions & 0 deletions internal/color/color.go
Expand Up @@ -10,6 +10,21 @@ const colorFmt = "\x1b[%dm%s\x1b[0m"
// Paint describes a terminal color.
type Paint int

// Defines basic ANSI colors.
const (
Black Paint = iota + 30 // 30
Red // 31
Green // 32
Yellow // 33
Blue // 34
Magenta // 35
Cyan // 36
LightGray // 37
DarkGray = 90

Bold = 1
)

// Colorize returns an ASCII colored string based on given color.
func Colorize(s string, c Paint) string {

Expand Down
42 changes: 23 additions & 19 deletions internal/config/config.go
Expand Up @@ -2,6 +2,7 @@ package config

import (
"context"
"errors"
"fmt"
"io/ioutil"
"os"
Expand All @@ -13,6 +14,7 @@ import (
awsV2 "github.com/aws/aws-sdk-go-v2/aws"
awsV2Config "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -50,7 +52,7 @@ func CloudlensHome() string {
return xdgCLHome
}

// Load K9s configuration from file.
// Load cloudlens configuration from file.
func (c *Config) Load(path string) error {
f, err := os.ReadFile(path)
if err != nil {
Expand Down Expand Up @@ -89,13 +91,11 @@ func (c *Config) SaveFile(path string) error {

var config Config

func GetSession(profile, region string, awsCfg awsV2.Config) (*session.Session, error) {
//crds, _ := awsCfg.Credentials.Retrieve(context.TODO())
func GetSession(profile, region string) (*session.Session, error) {
sess, err := session.NewSessionWithOptions(session.Options{Config: aws.Config{
//TODO: remove hardcoded enpoint
Endpoint: aws.String("http://localhost:4566"),
Region: aws.String(region),
//Credentials: credentials.NewStaticCredentials(crds.AccessKeyID, crds.SecretAccessKey, ""),
Endpoint: aws.String("http://localhost:4566"),
Region: aws.String(region),
S3ForcePathStyle: aws.Bool(true),
},
Profile: profile})
Expand All @@ -109,29 +109,28 @@ func GetSession(profile, region string, awsCfg awsV2.Config) (*session.Session,
func Get() (Config, error) {
emptyCfg := Config{}
if reflect.DeepEqual(emptyCfg, config) {
// Load the Shared AWS Configuration (~/.aws/config)
awsLocalCfg, err := awsV2Config.LoadDefaultConfig(context.TODO())
profiles, err := GetProfiles()
if err != nil {
return emptyCfg, err
}
config.AwsConfig = awsLocalCfg
creds, err := awsLocalCfg.Credentials.Retrieve(context.TODO())
if err != nil {
return emptyCfg, err
}
config.Profiles, err = GetProfiles(strings.Split(creds.Source, " ")[1])
if err != nil {
return emptyCfg, err
config.Profiles = profiles
if LookupForValue(config.Profiles, "default") {
// Load the Shared AWS Configuration (~/.aws/config)
awsLocalCfg, err := awsV2Config.LoadDefaultConfig(context.TODO())
if err != nil {
return emptyCfg, err
}
config.AwsConfig = awsLocalCfg
}
}
return config, nil
}

func GetProfiles(filepath string) ([]string, error) {
profiles := []string{}
func GetProfiles() (profiles []string, err error) {
filepath := defaults.SharedCredentialsFilename()
fileContent, err := ioutil.ReadFile(filepath)
if err != nil {
return nil, err
return profiles, err
}
lines := strings.Split(string(fileContent), "\n")
for _, line := range lines {
Expand All @@ -140,5 +139,10 @@ func GetProfiles(filepath string) ([]string, error) {
profiles = append(profiles, profile)
}
}
if len(profiles) < 1 {
err = errors.New("NO PROFILES FOUND")
return nil, err
}

return profiles, nil
}
27 changes: 27 additions & 0 deletions internal/config/helpers.go
Expand Up @@ -3,6 +3,7 @@ package config
import (
"os"
"path/filepath"
"strings"

"github.com/rs/zerolog/log"
)
Expand All @@ -14,6 +15,10 @@ const (
DefaultFileMod os.FileMode = 0600
)

type (
IsSwapHappen bool
)

// EnsurePath ensures a directory exist from the given path.
func EnsurePath(path string, mod os.FileMode) {
dir := filepath.Dir(path)
Expand All @@ -28,3 +33,25 @@ func EnsureFullPath(path string, mod os.FileMode) {
}
}
}

func LookupForValue(profiles []string, value string) bool {
for _, got := range profiles {
if strings.EqualFold(got, value) {
return true
}
}
return false
}

// SwapFirstIndexWithValue return swapped array if match found. If match not found returns same array and says match not found.
func SwapFirstIndexWithValue(array []string, value string) ([]string, IsSwapHappen) {
var isSwapped IsSwapHappen
for i, got := range array {
if strings.EqualFold(got, value) {
array[0], array[i] = array[i], array[0]
isSwapped = true
break
}
}
return array, isSwapped
}
16 changes: 9 additions & 7 deletions internal/keys.go
Expand Up @@ -5,11 +5,13 @@ type ContextKey string

// A collection of context keys.
const (
KeyFactory ContextKey = "factory"
KeyApp ContextKey = "app"
KeySession ContextKey = "session"
BucketName ContextKey = "bucket_name"
ObjectName ContextKey = "object_name"
FolderName ContextKey = "folder_name"
KeyAliases ContextKey = "aliases"
KeyFactory ContextKey = "factory"
KeyApp ContextKey = "app"
KeyActiveProfile ContextKey = "active-profile"
KeyActiveRegion ContextKey = "active-region"
KeySession ContextKey = "session"
BucketName ContextKey = "bucket_name"
ObjectName ContextKey = "object_name"
FolderName ContextKey = "folder_name"
KeyAliases ContextKey = "aliases"
)
37 changes: 37 additions & 0 deletions internal/ui/dropdown.go
@@ -0,0 +1,37 @@
package ui

import (
"github.com/derailed/tview"
"github.com/gdamore/tcell/v2"
)

type DropDown struct {
*tview.DropDown
label string
options []string
}

func NewDropDown(label string, options []string) *DropDown {
d := DropDown{
DropDown: tview.NewDropDown(),
label: label,
options: options,
}
d.build()
return &d
}

func (d *DropDown) SetSelectedFn(selectedFn DropdownSelectedFn) {
d.SetSelectedFunc(func(text string, index int) {
selectedFn(text, index)
})
}

func (d *DropDown) build() {
d.SetLabel(d.label)
d.SetLabelColor(tcell.ColorOrange)
d.SetOptions(d.options, func(text string, index int) {})
d.SetCurrentOption(0)
d.SetBorderPadding(0, 0, 0, 0)
//profileDropdown.SetBorder(true)
}

0 comments on commit 175419d

Please sign in to comment.