1/* Copyright 2017 WALLIX 2 3Licensed under the Apache License, Version 2.0 (the "License"); 4you may not use this file except in compliance with the License. 5You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9Unless required by applicable law or agreed to in writing, software 10distributed under the License is distributed on an "AS IS" BASIS, 11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12See the License for the specific language governing permissions and 13limitations under the License. 14*/ 15package awsspec 16 17import ( 18 "fmt" 19 "time" 20 21 "github.com/wallix/awless/cloud" 22 "github.com/wallix/awless/template/env" 23 "github.com/wallix/awless/template/params" 24 25 awssdk "github.com/aws/aws-sdk-go/aws" 26 "github.com/aws/aws-sdk-go/aws/awserr" 27 "github.com/aws/aws-sdk-go/service/ec2" 28 "github.com/aws/aws-sdk-go/service/ec2/ec2iface" 29 "github.com/wallix/awless/logger" 30) 31 32type CreateVolume struct { 33 _ string `action:"create" entity:"volume" awsAPI:"ec2" awsCall:"CreateVolume" awsInput:"ec2.CreateVolumeInput" awsOutput:"ec2.Volume" awsDryRun:""` 34 logger *logger.Logger 35 graph cloud.GraphAPI 36 api ec2iface.EC2API 37 Availabilityzone *string `awsName:"AvailabilityZone" awsType:"awsstr" templateName:"availabilityzone"` 38 Size *int64 `awsName:"Size" awsType:"awsint64" templateName:"size"` 39} 40 41func (cmd *CreateVolume) ParamsSpec() params.Spec { 42 return params.NewSpec(params.AllOf(params.Key("availabilityzone"), params.Key("size"))) 43} 44 45func (cmd *CreateVolume) ExtractResult(i interface{}) string { 46 return awssdk.StringValue(i.(*ec2.Volume).VolumeId) 47} 48 49type CheckVolume struct { 50 _ string `action:"check" entity:"volume" awsAPI:"ec2"` 51 logger *logger.Logger 52 graph cloud.GraphAPI 53 api ec2iface.EC2API 54 Id *string `templateName:"id"` 55 State *string `templateName:"state"` 56 Timeout *int64 `templateName:"timeout"` 57} 58 59func (cmd *CheckVolume) ParamsSpec() params.Spec { 60 return params.NewSpec( 61 params.AllOf(params.Key("id"), params.Key("state"), params.Key("timeout")), 62 params.Validators{ 63 "state": params.IsInEnumIgnoreCase("available", "in-use", notFoundState), 64 }, 65 ) 66} 67 68func (cmd *CheckVolume) ManualRun(renv env.Running) (interface{}, error) { 69 input := &ec2.DescribeVolumesInput{VolumeIds: []*string{cmd.Id}} 70 71 c := &checker{ 72 description: fmt.Sprintf("volume %s", StringValue(cmd.Id)), 73 timeout: time.Duration(Int64AsIntValue(cmd.Timeout)) * time.Second, 74 frequency: 5 * time.Second, 75 fetchFunc: func() (string, error) { 76 output, err := cmd.api.DescribeVolumes(input) 77 if err != nil { 78 if awserr, ok := err.(awserr.Error); ok { 79 if awserr.Code() == "VolumeNotFound" { 80 return notFoundState, nil 81 } 82 } else { 83 return "", err 84 } 85 } else { 86 for _, vol := range output.Volumes { 87 if StringValue(vol.VolumeId) == StringValue(cmd.Id) { 88 return StringValue(vol.State), nil 89 } 90 } 91 } 92 return notFoundState, nil 93 }, 94 expect: StringValue(cmd.State), 95 logger: cmd.logger, 96 } 97 return nil, c.check() 98} 99 100type DeleteVolume struct { 101 _ string `action:"delete" entity:"volume" awsAPI:"ec2" awsCall:"DeleteVolume" awsInput:"ec2.DeleteVolumeInput" awsOutput:"ec2.DeleteVolumeOutput" awsDryRun:""` 102 logger *logger.Logger 103 graph cloud.GraphAPI 104 api ec2iface.EC2API 105 Id *string `awsName:"VolumeId" awsType:"awsstr" templateName:"id"` 106} 107 108func (cmd *DeleteVolume) ParamsSpec() params.Spec { 109 return params.NewSpec(params.AllOf(params.Key("id"))) 110} 111 112type AttachVolume struct { 113 _ string `action:"attach" entity:"volume" awsAPI:"ec2" awsCall:"AttachVolume" awsInput:"ec2.AttachVolumeInput" awsOutput:"ec2.VolumeAttachment" awsDryRun:""` 114 logger *logger.Logger 115 graph cloud.GraphAPI 116 api ec2iface.EC2API 117 Device *string `awsName:"Device" awsType:"awsstr" templateName:"device"` 118 Id *string `awsName:"VolumeId" awsType:"awsstr" templateName:"id"` 119 Instance *string `awsName:"InstanceId" awsType:"awsstr" templateName:"instance"` 120} 121 122func (cmd *AttachVolume) ParamsSpec() params.Spec { 123 return params.NewSpec(params.AllOf(params.Key("device"), params.Key("id"), params.Key("instance"))) 124} 125func (cmd *AttachVolume) ExtractResult(i interface{}) string { 126 return awssdk.StringValue(i.(*ec2.VolumeAttachment).VolumeId) 127} 128 129type DetachVolume struct { 130 _ string `action:"detach" entity:"volume" awsAPI:"ec2" awsCall:"DetachVolume" awsInput:"ec2.DetachVolumeInput" awsOutput:"ec2.VolumeAttachment" awsDryRun:""` 131 logger *logger.Logger 132 graph cloud.GraphAPI 133 api ec2iface.EC2API 134 Device *string `awsName:"Device" awsType:"awsstr" templateName:"device"` 135 Id *string `awsName:"VolumeId" awsType:"awsstr" templateName:"id"` 136 Instance *string `awsName:"InstanceId" awsType:"awsstr" templateName:"instance"` 137 Force *bool `awsName:"Force" awsType:"awsbool" templateName:"force"` 138} 139 140func (cmd *DetachVolume) ParamsSpec() params.Spec { 141 return params.NewSpec(params.AllOf(params.Key("device"), params.Key("id"), params.Key("instance"), 142 params.Opt("force"), 143 )) 144} 145 146func (cmd *DetachVolume) ExtractResult(i interface{}) string { 147 return awssdk.StringValue(i.(*ec2.VolumeAttachment).VolumeId) 148} 149