diff --git a/pkg/cfn/cfn.go b/pkg/cfn/cfn.go index e328f8a..a4db693 100644 --- a/pkg/cfn/cfn.go +++ b/pkg/cfn/cfn.go @@ -24,6 +24,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/google/uuid" ) const DefaultStackName = "simple-ec2" @@ -51,7 +52,8 @@ func (c Cfn) CreateStackAndGetResources(availabilityZones []*ec2.AvailabilityZon stackName *string, template string) (vpcId *string, subnetIds []string, instanceId *string, stackResources []*cloudformation.StackResource, err error) { if stackName == nil { - stackName = aws.String(DefaultStackName) + stackIdentifier := uuid.New() + stackName = aws.String(fmt.Sprintf("%s%s", DefaultStackName, stackIdentifier)) } zonesToUse := []*ec2.AvailabilityZone{} diff --git a/pkg/cfn/cfn_test.go b/pkg/cfn/cfn_test.go index 2e7bce0..6985295 100644 --- a/pkg/cfn/cfn_test.go +++ b/pkg/cfn/cfn_test.go @@ -92,7 +92,7 @@ func TestCreateStackAndGetResources_Success(t *testing.T) { StackEvents: mockedEvents, } - vpcId, subnetIds, instanceId, _, err := testCfn.CreateStackAndGetResources(testAzs, nil, "") + vpcId, subnetIds, instanceId, _, err := testCfn.CreateStackAndGetResources(testAzs, aws.String(cfn.DefaultStackName), "") th.Ok(t, err) th.Equals(t, testVpcId, *vpcId) th.Equals(t, testSubnetIds, subnetIds) @@ -106,7 +106,7 @@ func TestCreateStackAndGetResources_DescribeStackEventsPagesError(t *testing.T) DescribeStackEventsPagesError: errors.New("Test error"), } - _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, nil, "") + _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, aws.String(cfn.DefaultStackName), "") th.Nok(t, err) } @@ -118,7 +118,7 @@ func TestCreateStackAndGetResources_DescribeStackResourcesError(t *testing.T) { DescribeStackResourcesError: errors.New("Test error"), } - _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, nil, "") + _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, aws.String(cfn.DefaultStackName), "") th.Nok(t, err) } @@ -133,7 +133,7 @@ func TestCreateStackAndGetResources_NoSubnet(t *testing.T) { StackEvents: mockedEvents, } - _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, nil, "") + _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, aws.String(cfn.DefaultStackName), "") th.Nok(t, err) } @@ -152,7 +152,7 @@ func TestCreateStackAndGetResources_NoVpc(t *testing.T) { StackEvents: mockedEvents, } - _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, nil, "") + _, _, _, _, err := testCfn.CreateStackAndGetResources(testAzs, aws.String(cfn.DefaultStackName), "") th.Nok(t, err) } diff --git a/pkg/ec2helper/ec2helper.go b/pkg/ec2helper/ec2helper.go index 3df0aac..a6647a3 100644 --- a/pkg/ec2helper/ec2helper.go +++ b/pkg/ec2helper/ec2helper.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "os" "sort" + "strconv" "strings" "simple-ec2/pkg/cfn" @@ -1117,6 +1118,14 @@ func (h *EC2Helper) LaunchSpotInstance(simpleConfig *config.SimpleInfo, detailed if simpleConfig.LaunchTemplateId != "" { _, err = h.LaunchFleet(aws.String(simpleConfig.LaunchTemplateId)) } else { + // Create new stack, if specified. + if simpleConfig.NewVPC { + err := h.createNetworkConfiguration(simpleConfig, nil) + if err != nil { + return err + } + } + template, err := h.CreateLaunchTemplate(simpleConfig, detailedConfig) if err != nil { if aerr, ok := err.(awserr.Error); ok { @@ -1171,7 +1180,9 @@ func (h *EC2Helper) createNetworkConfiguration(simpleConfig *config.SimpleInfo, return errors.New("No subnet with the selected availability zone found") } - input.SubnetId = selectedSubnetId + if input != nil { + input.SubnetId = selectedSubnetId + } /* Get the security group. @@ -1208,7 +1219,9 @@ func (h *EC2Helper) createNetworkConfiguration(simpleConfig *config.SimpleInfo, return errors.New("No security group available for stack") } - input.SecurityGroupIds = aws.StringSlice(selectedSecurityGroupIds) + if input != nil { + input.SecurityGroupIds = aws.StringSlice(selectedSecurityGroupIds) + } // Update simpleConfig for config saving simpleConfig.NewVPC = false @@ -1284,6 +1297,15 @@ func ValidateTags(h *EC2Helper, userTags string) bool { return true } +// ValidateInteger checks if a given string is an integer +func ValidateInteger(h *EC2Helper, intString string) bool { + _, err := strconv.Atoi(intString) + if err != nil { + return false + } + return true +} + // Given an AWS platform string, tell if it's a Linux platform func IsLinux(platform string) bool { return platform == ec2.CapacityReservationInstancePlatformLinuxUnix || diff --git a/pkg/ec2helper/ec2helper_test.go b/pkg/ec2helper/ec2helper_test.go index 74d0f48..8f44dfc 100644 --- a/pkg/ec2helper/ec2helper_test.go +++ b/pkg/ec2helper/ec2helper_test.go @@ -1390,6 +1390,26 @@ func TestValidateTags_False(t *testing.T) { th.Equals(t, false, result) } +func TestValidateInteger_True(t *testing.T) { + testUserInput := "123" + result := ec2helper.ValidateInteger(testEC2, testUserInput) + th.Equals(t, true, result) +} + +func TestValidateInteger_False(t *testing.T) { + floatInput := "123.456" + floatResult := ec2helper.ValidateInteger(testEC2, floatInput) + th.Equals(t, false, floatResult) + + stringInput := "abcdefg" + stringResult := ec2helper.ValidateInteger(testEC2, stringInput) + th.Equals(t, false, stringResult) + + alphanumericInput := "123abc" + alphanumericResult := ec2helper.ValidateInteger(testEC2, alphanumericInput) + th.Equals(t, false, alphanumericResult) +} + func TestIsLinux_True(t *testing.T) { actualIsLinux := ec2helper.IsLinux(ec2.CapacityReservationInstancePlatformLinuxUnix) th.Equals(t, true, actualIsLinux)