From 3e797dc516e634b3eb67e679e549f69a5d5b94e8 Mon Sep 17 00:00:00 2001 From: Rafael Grigorian Date: Fri, 3 Jun 2022 13:19:10 -0500 Subject: [PATCH] Fixed #95 --- cmd/jrctl/main.go | 7 +- internal/aws-autoscale-detect.go | 109 +++++++++++++++++++------------ internal/aws-autoscale-ingest.go | 54 ++++++++++----- 3 files changed, 107 insertions(+), 63 deletions(-) diff --git a/cmd/jrctl/main.go b/cmd/jrctl/main.go index 8490729..5bad3df 100644 --- a/cmd/jrctl/main.go +++ b/cmd/jrctl/main.go @@ -2,13 +2,8 @@ package main import ( "github.com/jetrails/jrctl/internal" - "github.com/jetrails/jrctl/pkg/env" ) func main() { internal.RootCmd.Execute() -} - -func init() { - env.EnvPrefix = "JR_" -} +} \ No newline at end of file diff --git a/internal/aws-autoscale-detect.go b/internal/aws-autoscale-detect.go index 2100441..c9f8b1a 100644 --- a/internal/aws-autoscale-detect.go +++ b/internal/aws-autoscale-detect.go @@ -2,6 +2,7 @@ package internal import ( "context" + "errors" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" @@ -15,6 +16,12 @@ import ( "github.com/spf13/cobra" ) +var ( + ErrAwsImdsCredsMissing = errors.New("failed to extract credentials from IMDS service") + ErrAwsAutoScalingGroupNotFound = errors.New("failed to find autoscaling group with that name") + ErrAwsInstanceDetails = errors.New("failed to query instance details") +) + func GetAWSConfig() (aws.Config, error) { return config.LoadDefaultConfig( context.TODO(), @@ -34,6 +41,47 @@ func GetInstanceIdentityDocument(cfg aws.Config) *imds.InstanceIdentityDocument return nil } +func GetAutoScalingGroupInstances(cfg aws.Config, asgName string) ([]types.Instance, error) { + entries := []types.Instance{} + autoscalingClient := autoscaling.NewFromConfig(cfg) + ec2Client := ec2.NewFromConfig(cfg) + + asgs, err := autoscalingClient.DescribeAutoScalingGroups( + context.TODO(), + &autoscaling.DescribeAutoScalingGroupsInput{AutoScalingGroupNames: []string{asgName}}, + ) + + if err != nil { + return entries, ErrAwsAutoScalingGroupNotFound + } + + for _, asg := range asgs.AutoScalingGroups { + instanceIds := []string{} + for _, instance := range asg.Instances { + instanceIds = append(instanceIds, aws.ToString(instance.InstanceId)) + } + infos, err := ec2Client.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{ + InstanceIds: instanceIds, + Filters: []types.Filter{ + { + Name: aws.String("instance-state-name"), + Values: []string{"running"}, + }, + }, + }) + if err != nil { + return []types.Instance{}, ErrAwsInstanceDetails + } + for _, reservation := range infos.Reservations { + for _, instance := range reservation.Instances { + entries = append(entries, instance) + } + } + } + + return entries, nil +} + var awsAutoscaleDetectCmd = &cobra.Command{ Use: "autoscale-detect AUTOSCALING_GROUP_NAME", Short: "Query aws for instances in autoscaling group", @@ -64,51 +112,30 @@ var awsAutoscaleDetectCmd = &cobra.Command{ cfg, err := GetAWSConfig() if err != nil { - output.ExitWithMessage(3, "\nfailed to extract credentials from IMDS service\n") + output.ExitWithMessage(3, "\n"+ErrAwsImdsCredsMissing.Error()+"\n") } - autoscalingClient := autoscaling.NewFromConfig(cfg) - ec2Client := ec2.NewFromConfig(cfg) - - asgs, err := autoscalingClient.DescribeAutoScalingGroups( - context.TODO(), - &autoscaling.DescribeAutoScalingGroupsInput{AutoScalingGroupNames: []string{asgName}}, - ) - if err != nil { - output.ExitWithMessage(3, "\nfailed to extract credentials from IMDS service\n") - } - - for _, asg := range asgs.AutoScalingGroups { - instanceIds := []string{} - for _, instance := range asg.Instances { - instanceIds = append(instanceIds, aws.ToString(instance.InstanceId)) + if instances, err := GetAutoScalingGroupInstances(cfg, asgName); err == nil { + for _, instance := range instances { + tbl.AddQuietEntry(aws.ToString(instance.PrivateIpAddress)) + tbl.AddRow(Columns{ + aws.ToString(instance.InstanceId), + aws.ToString(instance.ImageId), + "Running", + aws.ToString(instance.PrivateIpAddress), + aws.ToString(instance.PublicIpAddress), + instance.LaunchTime.String(), + }) } - infos, err := ec2Client.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{ - InstanceIds: instanceIds, - Filters: []types.Filter{ - { - Name: aws.String("instance-state-name"), - Values: []string{"running"}, - }, - }, - }) - if err != nil { - output.ExitWithMessage(4, "\nfailed to query instance details\n") - } - for _, reservation := range infos.Reservations { - for _, instance := range reservation.Instances { - tbl.AddQuietEntry(aws.ToString(instance.PrivateIpAddress)) - tbl.AddRow(Columns{ - aws.ToString(instance.InstanceId), - aws.ToString(instance.ImageId), - "Running", - aws.ToString(instance.PrivateIpAddress), - aws.ToString(instance.PublicIpAddress), - instance.LaunchTime.String(), - }) - } + } else { + switch err { + case ErrAwsAutoScalingGroupNotFound: + output.ExitWithMessage(4, "\n"+err.Error()+"\n") + case ErrAwsInstanceDetails: + output.ExitWithMessage(5, "\n"+err.Error()+"\n") + default: + output.ExitWithMessage(6, "\nunknown error\n") } - } output.Print() diff --git a/internal/aws-autoscale-ingest.go b/internal/aws-autoscale-ingest.go index 2340b1d..b0e0463 100644 --- a/internal/aws-autoscale-ingest.go +++ b/internal/aws-autoscale-ingest.go @@ -1,12 +1,11 @@ package internal import ( - "errors" "fmt" "strings" + "github.com/aws/aws-sdk-go-v2/aws" "github.com/jetrails/jrctl/pkg/array" - "github.com/jetrails/jrctl/pkg/input" . "github.com/jetrails/jrctl/pkg/output" "github.com/jetrails/jrctl/pkg/text" "github.com/jetrails/jrctl/sdk/config" @@ -29,35 +28,58 @@ func NormalizeEndpoints(endpoints []string) []string { } var awsAutoscaleIngestCmd = &cobra.Command{ - Use: "autoscale-ingest", - Short: "Display databases in deployment", - Example: text.Examples([]string{}), - Args: cobra.ExactArgs(0), - PreRunE: func(cmd *cobra.Command, args []string) error { - if !input.HasDataInPipe() { - return errors.New("must pipe endpoints to stdin") - } - return nil - }, + Use: "autoscale-ingest AUTOSCALING_GROUP_NAME", + Short: "Display databases in deployment", + Example: text.Examples([]string{ + "jrctl aws autoscale-ingest example-asg", + "jrctl aws autoscale-ingest example-asg -t www", + "jrctl aws autoscale-ingest example-asg -q", + }), + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { quiet, _ := cmd.Flags().GetBool("quiet") tag, _ := cmd.Flags().GetString("type") - endpoints := NormalizeEndpoints(strings.Fields(input.GetPipeData())) tags := []string{tag} + asgName := args[0] output := NewOutput(quiet, tags) + privateIps := []string{} + cfg, err := GetAWSConfig() + if err != nil { + output.ExitWithMessage(3, "\n"+ErrAwsImdsCredsMissing.Error()+"\n") + } + if instances, err := GetAutoScalingGroupInstances(cfg, asgName); err == nil { + for _, instance := range instances { + privateIps = append(privateIps, aws.ToString(instance.PrivateIpAddress)) + } + } else { + switch err { + case ErrAwsAutoScalingGroupNotFound: + output.ExitWithMessage(4, "\n"+err.Error()+"\n") + case ErrAwsInstanceDetails: + output.ExitWithMessage(5, "\n"+err.Error()+"\n") + default: + output.ExitWithMessage(6, "\nunknown error\n") + } + } + endpoints := NormalizeEndpoints(privateIps) if len(endpoints) < 1 { - output.ExitWithMessage(3, "\nmust pass at least one endpoint\n") + output.ExitWithMessage(7, "\nmust pass at least one endpoint\n") } contexts := config.GetContexts(tags) servers := []config.Entry{} viper.UnmarshalKey("servers", &servers) + if len(contexts) < 1 { + output.PrintTags() + output.ExitWithMessage(8, "\nno servers found with given type selector\n") + } + if !config.ContextsHaveSameToken(contexts) { output.PrintTags() - output.ExitWithMessage(4, "\nfound differing tokens, autoscale requires same tokens\n") + output.ExitWithMessage(9, "\nfound differing tokens, autoscale requires same tokens\n") } tbl := output.CreateTable(Columns{ @@ -114,6 +136,6 @@ func init() { OnlyRunOnAWS(awsAutoscaleIngestCmd) awsCmd.AddCommand(awsAutoscaleIngestCmd) awsAutoscaleIngestCmd.Flags().SortFlags = true - awsAutoscaleIngestCmd.Flags().BoolP("quiet", "q", false, "output only errors") + awsAutoscaleIngestCmd.Flags().BoolP("quiet", "q", false, "display no output") awsAutoscaleIngestCmd.Flags().StringP("type", "t", "www", "filter servers using type selectors, only one selector allowed") }