package ecs import ( "context" errorsNew "errors" "fmt" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" "github.com/hashicorp/packer/common/uuid" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) type stepConfigAlicloudVPC struct { VpcId string CidrBlock string //192.168.0.0/16 or 172.16.0.0/16 (default) VpcName string isCreate bool } var createVpcRetryErrors = []string{ "TOKEN_PROCESSING", } var deleteVpcRetryErrors = []string{ "DependencyViolation.Instance", "DependencyViolation.RouteEntry", "DependencyViolation.VSwitch", "DependencyViolation.SecurityGroup", "Forbbiden", "TaskConflict", } func (s *stepConfigAlicloudVPC) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*Config) client := state.Get("client").(*ClientWrapper) ui := state.Get("ui").(packer.Ui) if len(s.VpcId) != 0 { describeVpcsRequest := ecs.CreateDescribeVpcsRequest() describeVpcsRequest.VpcId = s.VpcId describeVpcsRequest.RegionId = config.AlicloudRegion vpcsResponse, err := client.DescribeVpcs(describeVpcsRequest) if err != nil { return halt(state, err, "Failed querying vpcs") } vpcs := vpcsResponse.Vpcs.Vpc if len(vpcs) > 0 { state.Put("vpcid", vpcs[0].VpcId) s.isCreate = false return multistep.ActionContinue } message := fmt.Sprintf("The specified vpc {%s} doesn't exist.", s.VpcId) return halt(state, errorsNew.New(message), "") } ui.Say("Creating vpc...") createVpcRequest := s.buildCreateVpcRequest(state) createVpcResponse, err := client.WaitForExpected(&WaitForExpectArgs{ RequestFunc: func() (responses.AcsResponse, error) { return client.CreateVpc(createVpcRequest) }, EvalFunc: client.EvalCouldRetryResponse(createVpcRetryErrors, EvalRetryErrorType), }) if err != nil { return halt(state, err, "Failed creating vpc") } vpcId := createVpcResponse.(*ecs.CreateVpcResponse).VpcId _, err = client.WaitForExpected(&WaitForExpectArgs{ RequestFunc: func() (responses.AcsResponse, error) { request := ecs.CreateDescribeVpcsRequest() request.RegionId = config.AlicloudRegion request.VpcId = vpcId return client.DescribeVpcs(request) }, EvalFunc: func(response responses.AcsResponse, err error) WaitForExpectEvalResult { if err != nil { return WaitForExpectToRetry } vpcsResponse := response.(*ecs.DescribeVpcsResponse) vpcs := vpcsResponse.Vpcs.Vpc if len(vpcs) > 0 { for _, vpc := range vpcs { if vpc.Status == VpcStatusAvailable { return WaitForExpectSuccess } } } return WaitForExpectToRetry }, RetryTimes: shortRetryTimes, }) if err != nil { return halt(state, err, "Failed waiting for vpc to become available") } ui.Message(fmt.Sprintf("Created vpc: %s", vpcId)) state.Put("vpcid", vpcId) s.isCreate = true s.VpcId = vpcId return multistep.ActionContinue } func (s *stepConfigAlicloudVPC) Cleanup(state multistep.StateBag) { if !s.isCreate { return } cleanUpMessage(state, "VPC") client := state.Get("client").(*ClientWrapper) ui := state.Get("ui").(packer.Ui) _, err := client.WaitForExpected(&WaitForExpectArgs{ RequestFunc: func() (responses.AcsResponse, error) { request := ecs.CreateDeleteVpcRequest() request.VpcId = s.VpcId return client.DeleteVpc(request) }, EvalFunc: client.EvalCouldRetryResponse(deleteVpcRetryErrors, EvalRetryErrorType), RetryTimes: shortRetryTimes, }) if err != nil { ui.Error(fmt.Sprintf("Error deleting vpc, it may still be around: %s", err)) } } func (s *stepConfigAlicloudVPC) buildCreateVpcRequest(state multistep.StateBag) *ecs.CreateVpcRequest { config := state.Get("config").(*Config) request := ecs.CreateCreateVpcRequest() request.ClientToken = uuid.TimeOrderedUUID() request.RegionId = config.AlicloudRegion request.CidrBlock = s.CidrBlock request.VpcName = s.VpcName return request }