diff --git a/omssh.go b/omssh.go index 0252535..8e16d31 100644 --- a/omssh.go +++ b/omssh.go @@ -22,7 +22,10 @@ const ( defUser = "ubuntu" ) -var defCredentialsPath string +var ( + defCredentialsPath string + defUsers = []string{"ubuntu", "ec2-user"} +) func init() { credentialsPath := os.Getenv("AWS_SHARED_CREDENTIALS_FILE") @@ -67,7 +70,7 @@ func Pre(c *cli.Context) { user := defUser if c.Bool("user") { - u, e := awsapi.FinderUsername() + u, e := awsapi.FinderUsername(defUsers) if e != nil { log.Fatal(e) return diff --git a/pkg/awsapi/ec2.go b/pkg/awsapi/ec2.go index 6eb062f..2432333 100644 --- a/pkg/awsapi/ec2.go +++ b/pkg/awsapi/ec2.go @@ -2,7 +2,6 @@ package awsapi import ( "fmt" - "log" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -10,8 +9,8 @@ import ( fuzzyfinder "github.com/ktr0731/go-fuzzyfinder" ) -// EC2Info : required ec2 instance information -type EC2Info struct { +// EC2Instance : required ec2 instance information +type EC2Instance struct { InstanceID string PublicIPAddress string PrivateIPAddress string @@ -21,7 +20,7 @@ type EC2Info struct { } // DescribeRunningEC2Instances : get list of running ec2 instances -func DescribeRunningEC2Instances(svc ec2iface.EC2API) ([]EC2Info, error) { +func DescribeRunningEC2Instances(svc ec2iface.EC2API) ([]EC2Instance, error) { // condition: running instance only input := &ec2.DescribeInstancesInput{ Filters: []*ec2.Filter{ @@ -39,7 +38,7 @@ func DescribeRunningEC2Instances(svc ec2iface.EC2API) ([]EC2Info, error) { return nil, err } - e := []EC2Info{} + e := []EC2Instance{} for _, r := range res.Reservations { for _, i := range r.Instances { @@ -63,7 +62,7 @@ func DescribeRunningEC2Instances(svc ec2iface.EC2API) ([]EC2Info, error) { privateIPAddress = *i.PrivateIpAddress } - e = append(e, EC2Info{ + e = append(e, EC2Instance{ InstanceID: *i.InstanceId, InstanceType: *i.InstanceType, PublicIPAddress: publicIPAddress, @@ -78,7 +77,7 @@ func DescribeRunningEC2Instances(svc ec2iface.EC2API) ([]EC2Info, error) { } // FinderEC2Instance : find information of ec2 instance through fuzzyfinder -func FinderEC2Instance(ec2List []EC2Info) (ec2Info EC2Info, err error) { +func FinderEC2Instance(ec2List []EC2Instance) (EC2Instance EC2Instance, err error) { idx, err := fuzzyfinder.FindMulti( ec2List, func(i int) string { @@ -104,23 +103,18 @@ func FinderEC2Instance(ec2List []EC2Info) (ec2Info EC2Info, err error) { ) if err != nil { - log.Fatal(err) - return ec2Info, err + return EC2Instance, err } for _, i := range idx { - ec2Info = ec2List[i] + EC2Instance = ec2List[i] } - return ec2Info, nil + return EC2Instance, nil } // FinderUsername : find ssh username through fuzzyfinder -func FinderUsername() (user string, err error) { - users := []string{ - "ubuntu", - "ec2-user", - } +func FinderUsername(users []string) (user string, err error) { idx, err := fuzzyfinder.FindMulti( users, func(i int) string { @@ -135,7 +129,6 @@ func FinderUsername() (user string, err error) { ) if err != nil { - log.Fatal(err) return user, err } diff --git a/pkg/awsapi/ec2_test.go b/pkg/awsapi/ec2_test.go index 497b250..06e4a26 100644 --- a/pkg/awsapi/ec2_test.go +++ b/pkg/awsapi/ec2_test.go @@ -1,11 +1,7 @@ package awsapi import ( - "fmt" - "io/ioutil" - "path/filepath" - "runtime" - "strings" + "errors" "testing" "github.com/aws/aws-sdk-go/aws" @@ -18,18 +14,22 @@ import ( ) var ( - testEC2Instances = []EC2Info{ - { + testEC2Instances = []EC2Instance{ + EC2Instance{ InstanceID: "i-aaaaaa", PublicIPAddress: "12.34.56.01", + PrivateIPAddress: "192.168.10.1", InstanceType: "t3.micro", AvailabilityZone: "ap-northeast-1a", + InstanceName: "hoge", }, - { + EC2Instance{ InstanceID: "i-bbbbbb", PublicIPAddress: "12.34.56.02", + PrivateIPAddress: "192.168.10.2", InstanceType: "t3.small", AvailabilityZone: "ap-northeast-1c", + InstanceName: "moge", }, } ) @@ -44,57 +44,92 @@ func (m *mockEC2Client) DescribeInstances(input *ec2.DescribeInstancesInput) (*e { Instances: []*ec2.Instance{ { - InstanceId: aws.String("i-aaaaaa"), - InstanceType: aws.String("t3.micro"), - PublicIpAddress: aws.String("12.34.56.01"), + InstanceId: aws.String("i-aaaaaa"), + InstanceType: aws.String("t3.micro"), + PublicIpAddress: aws.String("12.34.56.01"), + PrivateIpAddress: aws.String("192.168.10.1"), Placement: &ec2.Placement{ AvailabilityZone: aws.String("ap-northeast-1a"), }, + Tags: []*ec2.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("hoge"), + }, + }, }, }, }, { Instances: []*ec2.Instance{ { - InstanceId: aws.String("i-bbbbbb"), - InstanceType: aws.String("t3.small"), - PublicIpAddress: aws.String("12.34.56.02"), + InstanceId: aws.String("i-bbbbbb"), + InstanceType: aws.String("t3.small"), + PublicIpAddress: aws.String("12.34.56.02"), + PrivateIpAddress: aws.String("192.168.10.2"), Placement: &ec2.Placement{ AvailabilityZone: aws.String("ap-northeast-1c"), }, + Tags: []*ec2.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("moge"), + }, + }, }, }, }, { Instances: []*ec2.Instance{ { - InstanceId: aws.String("i-cccccc"), - InstanceType: aws.String("t3.medium"), + InstanceId: aws.String("i-cccccc"), + InstanceType: aws.String("t3.medium"), + PrivateIpAddress: aws.String("192.168.10.3"), Placement: &ec2.Placement{ AvailabilityZone: aws.String("ap-northeast-1c"), }, + Tags: []*ec2.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("foo"), + }, + }, }, }, }, { Instances: []*ec2.Instance{ { - InstanceId: aws.String("i-dddddd"), - InstanceType: aws.String("t3.large"), + InstanceId: aws.String("i-dddddd"), + InstanceType: aws.String("t3.large"), + PrivateIpAddress: aws.String("192.168.10.4"), Placement: &ec2.Placement{ AvailabilityZone: aws.String("ap-northeast-1c"), }, + Tags: []*ec2.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("baz"), + }, + }, }, }, }, { Instances: []*ec2.Instance{ { - InstanceId: aws.String("i-eeeeee"), - InstanceType: aws.String("t3.xlarge"), + InstanceId: aws.String("i-eeeeee"), + InstanceType: aws.String("t3.xlarge"), + PrivateIpAddress: aws.String("192.168.10.5"), Placement: &ec2.Placement{ AvailabilityZone: aws.String("ap-northeast-1c"), }, + Tags: []*ec2.Tag{ + { + Key: aws.String("Name"), + Value: aws.String("bar"), + }, + }, }, }, }, @@ -102,6 +137,16 @@ func (m *mockEC2Client) DescribeInstances(input *ec2.DescribeInstancesInput) (*e }, nil } +type mockEC2ClientFaild struct { + ec2iface.EC2API +} + +func (m *mockEC2ClientFaild) DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) { + return &ec2.DescribeInstancesOutput{ + Reservations: []*ec2.Reservation{}, + }, errors.New("Not Found") +} + func TestDescribeRunningEC2Instances(t *testing.T) { mockSvc := &mockEC2Client{} runningEC2Instances, err := DescribeRunningEC2Instances(mockSvc) @@ -114,7 +159,19 @@ func TestDescribeRunningEC2Instances(t *testing.T) { } } -func finderEC2Testing(t *testing.T, types string, expectedEC2 EC2Info) { +func TestDescribeNotFoundRunningEC2Instances(t *testing.T) { + mockEC2ClientFaild := &mockEC2ClientFaild{} + runningEC2Instances, err := DescribeRunningEC2Instances(mockEC2ClientFaild) + if err == nil { + t.Error(err) + } + + if diff := cmp.Diff([]EC2Instance(nil), runningEC2Instances); diff != "" { + t.Errorf("wrong result: \n%s", diff) + } +} + +func finderEC2Testing(t *testing.T, types string, tests []EC2Instance, expectedEC2 EC2Instance) { term := fuzzyfinder.UseMockedTerminal() term.SetSize(60, 10) @@ -122,34 +179,82 @@ func finderEC2Testing(t *testing.T, types string, expectedEC2 EC2Info) { utility.TermboxKeys(types), termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEnter})...) - actualEC2, err := FinderEC2Instance(testEC2Instances) + actualEC2, err := FinderEC2Instance(tests) if err != nil { t.Error("cannot get profile") } if diff := cmp.Diff(expectedEC2, actualEC2); diff != "" { t.Errorf("wrong result: \n%s", diff) } +} - actual := term.GetResult() +func TestFinderEC2Instance(t *testing.T) { + term := fuzzyfinder.UseMockedTerminal() + term.SetSize(60, 10) - g := fmt.Sprintf("finder_ec2_%s_ui.golden", types) - fname := filepath.Join("..", "..", "testdata", g) - // ioutil.WriteFile(fname, []byte(actual), 0644) - b, err := ioutil.ReadFile(fname) - if err != nil { - t.Fatalf("failed to load a golden file: %s", err) - } - expected := string(b) - if runtime.GOOS == "windows" { - expected = strings.Replace(expected, "\r\n", "\n", -1) - } + for _, testcase := range []struct { + name string + call func(t *testing.T) + }{ + { + "type i-a on terminal", + func(t *testing.T) { + finderEC2Testing( + t, + "i-a", + testEC2Instances, + EC2Instance{ + InstanceID: "i-aaaaaa", + PublicIPAddress: "12.34.56.01", + PrivateIPAddress: "192.168.10.1", + InstanceType: "t3.micro", + AvailabilityZone: "ap-northeast-1a", + InstanceName: "hoge", + }, + ) + }, + }, + { + "type i-b on terminal", + func(t *testing.T) { + finderEC2Testing(t, + "i-b", + testEC2Instances, + EC2Instance{ + InstanceID: "i-bbbbbb", + PublicIPAddress: "12.34.56.02", + PrivateIPAddress: "192.168.10.2", + InstanceType: "t3.small", + AvailabilityZone: "ap-northeast-1c", + InstanceName: "moge", + }, + ) + }, + }, + { + "type foo - Not found Instance name on terminal", + func(t *testing.T) { + types := "foo" + term := fuzzyfinder.UseMockedTerminal() + term.SetSize(60, 10) - if diff := cmp.Diff(expected, actual); diff != "" { - t.Errorf("wrong result: \n%s", diff) + term.SetEvents(append( + utility.TermboxKeys(types), + termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEnter})...) + + actual, err := FinderEC2Instance(testEC2Instances) + if err == nil { + t.Errorf("wrong result: err is not nil\n %s", err) + } + t.Logf("actual: %#v", actual) + }, + }, + } { + t.Run(testcase.name, testcase.call) } } -func TestFinderEC2Instance(t *testing.T) { +func TestFinderUsername(t *testing.T) { term := fuzzyfinder.UseMockedTerminal() term.SetSize(60, 10) @@ -158,27 +263,60 @@ func TestFinderEC2Instance(t *testing.T) { call func(t *testing.T) }{ { - "type i-a on terminal", + "type ubuntu on terminal", func(t *testing.T) { - expected := EC2Info{ - InstanceID: "i-aaaaaa", - PublicIPAddress: "12.34.56.01", - InstanceType: "t3.micro", - AvailabilityZone: "ap-northeast-1a", + username := "ubuntu" + expected := username + term.SetEvents(append( + utility.TermboxKeys(username), + termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEnter})...) + + usernames := []string{"ubuntu", "ec2-user"} + actual, err := FinderUsername(usernames) + if err != nil { + t.Error(err) + } + if diff := cmp.Diff(expected, actual); diff != "" { + t.Errorf("wrong result: \n%s", diff) } - finderEC2Testing(t, "i-a", expected) }, }, { - "type i-b on terminal", + "type ec2-user on terminal", + func(t *testing.T) { + username := "ec2-user" + expected := username + term.SetEvents(append( + utility.TermboxKeys(username), + termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEnter})...) + + usernames := []string{"ubuntu", "ec2-user"} + actual, err := FinderUsername(usernames) + if err != nil { + t.Error(err) + } + if diff := cmp.Diff(expected, actual); diff != "" { + t.Errorf("wrong result: \n%s", diff) + } + }, + }, + { + "type hoge on terminal", func(t *testing.T) { - expected := EC2Info{ - InstanceID: "i-bbbbbb", - PublicIPAddress: "12.34.56.02", - InstanceType: "t3.small", - AvailabilityZone: "ap-northeast-1c", + username := "hoge" + expected := "" + term.SetEvents(append( + utility.TermboxKeys(username), + termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEnter})...) + + usernames := []string{"ubuntu", "ec2-user"} + actual, err := FinderUsername(usernames) + if err == nil { + t.Errorf("wrong result: err is not nil\n %s", err) + } + if diff := cmp.Diff(expected, actual); diff != "" { + t.Errorf("wrong result: \n%s", diff) } - finderEC2Testing(t, "i-b", expected) }, }, } {