2
// goamz - Go packages to interact with the Amazon Web Services.
4
// https://wiki.ubuntu.com/goamz
6
// Copyright (c) 2011 Canonical Ltd.
30
// debug, when set to true causes AWS requests and responses to be
34
// apiVersion is the AWS API version used for all EC2 requests.
35
apiVersion = "2014-10-01"
38
// The EC2 type encapsulates operations with a specific EC2 region.
43
private byte // Reserve the right of using private data.
46
// New creates a new EC2.
47
func New(auth aws.Auth, region aws.Region, signer aws.Signer) *EC2 {
48
return &EC2{auth, region, signer, 0}
51
// ----------------------------------------------------------------------------
54
// Filter builds filtering parameters to be used in an EC2 query which supports
55
// filtering. For example:
57
// filter := NewFilter()
58
// filter.Add("architecture", "i386")
59
// filter.Add("launch-index", "0")
60
// resp, err := ec2.Instances(nil, filter)
66
// NewFilter creates a new Filter.
67
func NewFilter() *Filter {
68
return &Filter{make(map[string][]string)}
71
// Add appends a filtering parameter with the given name and value(s).
72
func (f *Filter) Add(name string, value ...string) {
73
f.m[name] = append(f.m[name], value...)
76
func (f *Filter) addParams(params map[string]string) {
78
a := make([]string, len(f.m))
84
sort.StringSlice(a).Sort()
86
prefix := "Filter." + strconv.Itoa(i+1)
87
params[prefix+".Name"] = k
88
for j, v := range f.m[k] {
89
params[prefix+".Value."+strconv.Itoa(j+1)] = v
95
// ----------------------------------------------------------------------------
96
// Request dispatching logic.
98
// Error encapsulates an error returned by EC2.
100
// See http://goo.gl/VZGuC for more details.
102
// HTTP status code (200, 403, ...)
104
// EC2 error code ("UnsupportedOperation", ...)
106
// The human-oriented error message
108
RequestId string `xml:"RequestID"`
111
func (err *Error) Error() string {
116
return fmt.Sprintf("%s (%s)", err.Message, err.Code)
119
// For now a single error inst is being exposed. In the future it may be useful
120
// to provide access to all of them, but rather than doing it as an array/slice,
121
// use a *next pointer, so that it's backward compatible and it continues to be
122
// easy to handle the first error, which is what most people will want.
123
type xmlErrors struct {
124
RequestId string `xml:"RequestID"`
125
Errors []Error `xml:"Errors>Error"`
128
var timeNow = time.Now
130
// resp = response structure that will get inflated by XML unmarshaling.
131
func (ec2 *EC2) query(params map[string]string, resp interface{}) error {
133
req, err := http.NewRequest("GET", ec2.Region.EC2Endpoint, nil)
138
// Add the params passed in to the query string
139
query := req.URL.Query()
140
for varName, varVal := range params {
141
query.Add(varName, varVal)
143
query.Add("Timestamp", timeNow().In(time.UTC).Format(time.RFC3339))
144
req.URL.RawQuery = query.Encode()
145
req.Header.Set("x-amz-date", time.Now().In(time.UTC).Format(aws.ISO8601BasicFormat))
147
if err := ec2.Sign(req, ec2.Auth); err != nil {
151
r, err := http.DefaultClient.Do(req)
159
dump, _ := httputil.DumpResponse(r, true)
160
log.Printf("response:\n%v\n}\n", string(dump))
162
if r.StatusCode != 200 {
165
return xml.NewDecoder(r.Body).Decode(resp)
168
// dumpRequest pretty-prints the AWS request the way the API docs
170
func dumpRequest(req *http.Request) {
171
queryParts := strings.Split(req.URL.RawQuery, "&")
176
reqURL := path + "?" + queryParts[0] + "\n\t&" + strings.Join(queryParts[1:], "\n\t&")
177
log.Printf("request: %s %s %s\n}\n", req.Method, reqURL, req.Proto)
180
func multimap(p map[string]string) url.Values {
181
q := make(url.Values, len(p))
182
for k, v := range p {
188
func buildError(r *http.Response) error {
189
errors := xmlErrors{}
190
xml.NewDecoder(r.Body).Decode(&errors)
192
if len(errors.Errors) > 0 {
193
err = errors.Errors[0]
195
err.RequestId = errors.RequestId
196
err.StatusCode = r.StatusCode
197
if err.Message == "" {
198
err.Message = r.Status
203
func makeParams(action string) map[string]string {
204
params := make(map[string]string)
205
params["Action"] = action
206
params["Version"] = apiVersion
210
func addParamsList(params map[string]string, label string, ids []string) {
211
for i, id := range ids {
212
params[label+"."+strconv.Itoa(i+1)] = id
216
// ----------------------------------------------------------------------------
217
// Instance management functions and types.
219
// RunNetworkInterface encapsulates options for a single network
220
// interface, specified when calling RunInstances.
222
// If Id is set, it must match an existing VPC network interface, and
223
// in this case only a single instance can be launched. If Id is not
224
// set, a new network interface will be created for each instance.
226
// The following fields are required when creating a new network
227
// interface (i.e. Id is empty): DeviceIndex, SubnetId, Description
228
// (only used if set), SecurityGroupIds.
230
// PrivateIPs can be used to add one or more private IP addresses to a
231
// network interface. Only one of the IP addresses can be set as
232
// primary. If none are given, EC2 selects a primary IP for each
233
// created interface from the subnet pool.
235
// When SecondaryPrivateIPCount is non-zero, EC2 allocates that number
236
// of IP addresses from within the subnet range and sets them as
237
// secondary IPs. The number of IP addresses that can be assigned to a
238
// network interface varies by instance type.
239
type RunNetworkInterface struct {
244
PrivateIPs []PrivateIP
245
SecurityGroupIds []string
246
DeleteOnTermination bool
247
SecondaryPrivateIPCount int
250
// The RunInstances type encapsulates options for the respective request in EC2.
252
// See http://goo.gl/Mcm3b for more details.
253
type RunInstances struct {
259
SecurityGroups []SecurityGroup
264
PlacementGroupName string
267
DisableAPITermination bool
268
ShutdownBehavior string
269
PrivateIPAddress string
270
IAMInstanceProfile string
271
BlockDeviceMappings []BlockDeviceMapping
272
NetworkInterfaces []RunNetworkInterface
276
// Response to a RunInstances request.
278
// See http://goo.gl/Mcm3b for more details.
279
type RunInstancesResp struct {
280
RequestId string `xml:"requestId"`
281
ReservationId string `xml:"reservationId"`
282
OwnerId string `xml:"ownerId"`
283
SecurityGroups []SecurityGroup `xml:"groupSet>item"`
284
Instances []Instance `xml:"instancesSet>item"`
287
// Instance encapsulates a running instance in EC2.
289
// See http://goo.gl/OCH8a for more details.
290
type Instance struct {
291
InstanceId string `xml:"instanceId"`
292
InstanceType string `xml:"instanceType"`
293
ImageId string `xml:"imageId"`
294
IAMInstanceProfile string `xml:"iamInstanceProfile>id"`
295
PrivateDNSName string `xml:"privateDnsName"`
296
DNSName string `xml:"dnsName"`
297
IPAddress string `xml:"ipAddress"`
298
PrivateIPAddress string `xml:"privateIpAddress"`
299
SubnetId string `xml:"subnetId"`
300
VPCId string `xml:"vpcId"`
301
SourceDestCheck bool `xml:"sourceDestCheck"`
302
KeyName string `xml:"keyName"`
303
AMILaunchIndex int `xml:"amiLaunchIndex"`
304
Hypervisor string `xml:"hypervisor"`
305
VirtType string `xml:"virtualizationType"`
306
Monitoring string `xml:"monitoring>state"`
307
AvailZone string `xml:"placement>availabilityZone"`
308
AssociatePublicIP bool `xml:"associatePublicIpAddress,omitempty"`
309
PlacementGroupName string `xml:"placement>groupName"`
310
EBSOptimized bool `xml:"ebsOptimized,omitempty"`
311
SRIOVNetSupport bool `xml:"sriovNetSupport,omitempty"`
312
State InstanceState `xml:"instanceState"`
313
Tags []Tag `xml:"tagSet>item"`
314
SecurityGroups []SecurityGroup `xml:"groupSet>item"`
315
NetworkInterfaces []NetworkInterface `xml:"networkInterfaceSet>item"`
316
BlockDeviceMappings []InstanceBlockDeviceMapping `xml:"blockDeviceMapping>item"`
317
RootDeviceType string `xml:"rootDeviceType"`
318
RootDeviceName string `xml:"rootDeviceName"`
321
// InstanceBlockDeviceMapping describes a block device mapping.
323
// See http://goo.gl/Ua0BIw for more details.
324
type InstanceBlockDeviceMapping struct {
325
DeviceName string `xml:"deviceName"`
326
AttachTime string `xml:"ebs>attachTime"`
327
DeleteOnTermination bool `xml:"ebs>deleteOnTermination"`
328
Status string `xml:"ebs>status"`
329
VolumeId string `xml:"ebs>volumeId"`
332
// RunInstances starts new instances in EC2.
333
// If options.MinCount and options.MaxCount are both zero, a single instance
334
// will be started; otherwise if options.MaxCount is zero, options.MinCount
335
// will be used instead.
337
// See http://goo.gl/Mcm3b for more details.
338
func (ec2 *EC2) RunInstances(options *RunInstances) (resp *RunInstancesResp, err error) {
339
params := makeParams("RunInstances")
340
params["ImageId"] = options.ImageId
341
params["InstanceType"] = options.InstanceType
343
if options.MinCount == 0 && options.MaxCount == 0 {
346
} else if options.MaxCount == 0 {
347
min = options.MinCount
350
min = options.MinCount
351
max = options.MaxCount
353
params["MinCount"] = strconv.Itoa(min)
354
params["MaxCount"] = strconv.Itoa(max)
356
for _, g := range options.SecurityGroups {
358
params["SecurityGroupId."+strconv.Itoa(i)] = g.Id
361
params["SecurityGroup."+strconv.Itoa(j)] = g.Name
365
prepareBlockDevices(params, options.BlockDeviceMappings)
366
prepareNetworkInterfaces(params, options.NetworkInterfaces)
367
token, err := clientToken()
371
params["ClientToken"] = token
373
if options.KeyName != "" {
374
params["KeyName"] = options.KeyName
376
if options.KernelId != "" {
377
params["KernelId"] = options.KernelId
379
if options.RamdiskId != "" {
380
params["RamdiskId"] = options.RamdiskId
382
if options.UserData != nil {
383
userData := make([]byte, base64.StdEncoding.EncodedLen(len(options.UserData)))
384
base64.StdEncoding.Encode(userData, options.UserData)
385
params["UserData"] = string(userData)
387
if options.AvailZone != "" {
388
params["Placement.AvailabilityZone"] = options.AvailZone
390
if options.PlacementGroupName != "" {
391
params["Placement.GroupName"] = options.PlacementGroupName
393
if options.Monitoring {
394
params["Monitoring.Enabled"] = "true"
396
if options.SubnetId != "" {
397
params["SubnetId"] = options.SubnetId
399
if options.DisableAPITermination {
400
params["DisableApiTermination"] = "true"
402
if options.ShutdownBehavior != "" {
403
params["InstanceInitiatedShutdownBehavior"] = options.ShutdownBehavior
405
if options.PrivateIPAddress != "" {
406
params["PrivateIpAddress"] = options.PrivateIPAddress
408
if options.IAMInstanceProfile != "" {
409
params["IamInstanceProfile.Name"] = options.IAMInstanceProfile
411
if options.EBSOptimized {
412
params["EbsOptimized"] = "true"
415
resp = &RunInstancesResp{}
416
err = ec2.query(params, resp)
423
func prepareBlockDevices(params map[string]string, blockDevs []BlockDeviceMapping) {
424
for i, b := range blockDevs {
425
n := strconv.Itoa(i + 1)
426
prefix := "BlockDeviceMapping." + n
427
if b.DeviceName != "" {
428
params[prefix+".DeviceName"] = b.DeviceName
430
if b.VirtualName != "" {
431
params[prefix+".VirtualName"] = b.VirtualName
433
if b.SnapshotId != "" {
434
params[prefix+".Ebs.SnapshotId"] = b.SnapshotId
436
if b.VolumeType != "" {
437
params[prefix+".Ebs.VolumeType"] = b.VolumeType
439
if b.VolumeSize > 0 {
440
params[prefix+".Ebs.VolumeSize"] = strconv.FormatInt(b.VolumeSize, 10)
443
params[prefix+".Ebs.Iops"] = strconv.FormatInt(b.IOPS, 10)
445
if b.DeleteOnTermination {
446
params[prefix+".Ebs.DeleteOnTermination"] = "true"
451
func prepareNetworkInterfaces(params map[string]string, nics []RunNetworkInterface) {
452
for i, ni := range nics {
453
// Unlike other lists, NetworkInterface and PrivateIpAddresses
454
// should start from 0, not 1, according to the examples
455
// requests in the API documentation here http://goo.gl/Mcm3b.
457
prefix := "NetworkInterface." + n
459
params[prefix+".NetworkInterfaceId"] = ni.Id
461
params[prefix+".DeviceIndex"] = strconv.Itoa(ni.DeviceIndex)
462
if ni.SubnetId != "" {
463
params[prefix+".SubnetId"] = ni.SubnetId
465
if ni.Description != "" {
466
params[prefix+".Description"] = ni.Description
468
for j, gid := range ni.SecurityGroupIds {
469
k := strconv.Itoa(j + 1)
470
params[prefix+".SecurityGroupId."+k] = gid
472
if ni.DeleteOnTermination {
473
params[prefix+".DeleteOnTermination"] = "true"
475
if ni.SecondaryPrivateIPCount > 0 {
476
val := strconv.Itoa(ni.SecondaryPrivateIPCount)
477
params[prefix+".SecondaryPrivateIpAddressCount"] = val
479
for j, ip := range ni.PrivateIPs {
481
subprefix := prefix + ".PrivateIpAddresses." + k
482
params[subprefix+".PrivateIpAddress"] = ip.Address
483
params[subprefix+".Primary"] = strconv.FormatBool(ip.IsPrimary)
488
func clientToken() (string, error) {
489
// Maximum EC2 client token size is 64 bytes.
490
// Each byte expands to two when hex encoded.
491
buf := make([]byte, 32)
492
_, err := rand.Read(buf)
496
return hex.EncodeToString(buf), nil
499
// Response to a TerminateInstances request.
501
// See http://goo.gl/3BKHj for more details.
502
type TerminateInstancesResp struct {
503
RequestId string `xml:"requestId"`
504
StateChanges []InstanceStateChange `xml:"instancesSet>item"`
507
// InstanceState encapsulates the state of an instance in EC2.
509
// See http://goo.gl/y3ZBq for more details.
510
type InstanceState struct {
511
Code int `xml:"code"` // Watch out, bits 15-8 have unpublished meaning.
512
Name string `xml:"name"`
515
// InstanceStateChange informs of the previous and current states
516
// for an instance when a state change is requested.
517
type InstanceStateChange struct {
518
InstanceId string `xml:"instanceId"`
519
CurrentState InstanceState `xml:"currentState"`
520
PreviousState InstanceState `xml:"previousState"`
523
// TerminateInstances requests the termination of instances when the given ids.
525
// See http://goo.gl/3BKHj for more details.
526
func (ec2 *EC2) TerminateInstances(instIds []string) (resp *TerminateInstancesResp, err error) {
527
params := makeParams("TerminateInstances")
528
addParamsList(params, "InstanceId", instIds)
529
resp = &TerminateInstancesResp{}
530
err = ec2.query(params, resp)
537
// Response to a DescribeInstances request.
539
// See http://goo.gl/mLbmw for more details.
540
type InstancesResp struct {
541
RequestId string `xml:"requestId"`
542
Reservations []Reservation `xml:"reservationSet>item"`
545
// Reservation represents details about a reservation in EC2.
547
// See http://goo.gl/0ItPT for more details.
548
type Reservation struct {
549
ReservationId string `xml:"reservationId"`
550
OwnerId string `xml:"ownerId"`
551
RequesterId string `xml:"requesterId"`
552
SecurityGroups []SecurityGroup `xml:"groupSet>item"`
553
Instances []Instance `xml:"instancesSet>item"`
556
// Instances returns details about instances in EC2. Both parameters
557
// are optional, and if provided will limit the instances returned to those
558
// matching the given instance ids or filtering rules.
560
// See http://goo.gl/4No7c for more details.
561
func (ec2 *EC2) Instances(instIds []string, filter *Filter) (resp *InstancesResp, err error) {
562
params := makeParams("DescribeInstances")
563
addParamsList(params, "InstanceId", instIds)
564
filter.addParams(params)
565
resp = &InstancesResp{}
566
err = ec2.query(params, resp)
573
// The ModifyInstanceAttribute type encapsulates options for the respective
576
// See http://goo.gl/cTxLa7 for more details.
577
type ModifyInstanceAttribute struct {
579
SourceDestCheck *bool
580
BlockDeviceMappings []InstanceBlockDeviceMapping
583
// ModifyInstanceAttribute modifies a single attribute of an instance in EC2.
585
// See http://goo.gl/cTxLa7 for more details.
586
func (ec2 *EC2) ModifyInstanceAttribute(req *ModifyInstanceAttribute, filter *Filter) (resp *SimpleResp, err error) {
587
params := makeParams("ModifyInstanceAttribute")
588
params["InstanceId"] = req.InstanceId
589
if req.SourceDestCheck != nil {
590
params["SourceDestCheck.Value"] = fmt.Sprint(*req.SourceDestCheck)
592
if req.BlockDeviceMappings != nil {
593
for i, b := range req.BlockDeviceMappings {
594
n := strconv.Itoa(i + 1)
595
prefix := "BlockDeviceMapping." + n
596
if b.DeviceName != "" {
597
params[prefix+".DeviceName"] = b.DeviceName
599
if b.VolumeId != "" {
600
params[prefix+".Ebs.VolumeId"] = b.VolumeId
602
params[prefix+".Ebs.DeleteOnTermination"] = fmt.Sprint(b.DeleteOnTermination)
605
filter.addParams(params)
607
err = ec2.query(params, resp)
614
// ----------------------------------------------------------------------------
615
// Image and snapshot management functions and types.
617
// Response to a DescribeImages request.
619
// See http://goo.gl/hLnyg for more details.
620
type ImagesResp struct {
621
RequestId string `xml:"requestId"`
622
Images []Image `xml:"imagesSet>item"`
625
// BlockDeviceMapping represents the association of a block device with an image.
627
// See http://goo.gl/wnDBf for more details.
628
type BlockDeviceMapping struct {
629
DeviceName string `xml:"deviceName"`
630
VirtualName string `xml:"virtualName"`
631
SnapshotId string `xml:"ebs>snapshotId"`
632
VolumeType string `xml:"ebs>volumeType"`
633
VolumeSize int64 `xml:"ebs>volumeSize"` // Size is given in GB
634
DeleteOnTermination bool `xml:"ebs>deleteOnTermination"`
636
// The number of I/O operations per second (IOPS) that the volume supports.
637
IOPS int64 `xml:"ebs>iops"`
640
// Image represents details about an image.
642
// See http://goo.gl/iSqJG for more details.
644
Id string `xml:"imageId"`
645
Name string `xml:"name"`
646
Description string `xml:"description"`
647
Type string `xml:"imageType"`
648
State string `xml:"imageState"`
649
Location string `xml:"imageLocation"`
650
Public bool `xml:"isPublic"`
651
Architecture string `xml:"architecture"`
652
Platform string `xml:"platform"`
653
ProductCodes []string `xml:"productCode>item>productCode"`
654
KernelId string `xml:"kernelId"`
655
RamdiskId string `xml:"ramdiskId"`
656
StateReason string `xml:"stateReason"`
657
OwnerId string `xml:"imageOwnerId"`
658
OwnerAlias string `xml:"imageOwnerAlias"`
659
RootDeviceType string `xml:"rootDeviceType"`
660
RootDeviceName string `xml:"rootDeviceName"`
661
VirtualizationType string `xml:"virtualizationType"`
662
Hypervisor string `xml:"hypervisor"`
663
SRIOVNetSupport bool `xml:"sriovNetSupport,omitempty"`
664
BlockDevices []BlockDeviceMapping `xml:"blockDeviceMapping>item"`
667
// Images returns details about available images.
668
// The ids and filter parameters, if provided, will limit the images returned.
669
// For example, to get all the private images associated with this account set
670
// the boolean filter "is-private" to true.
672
// Note: calling this function with nil ids and filter parameters will result in
673
// a very large number of images being returned.
675
// See http://goo.gl/SRBhW for more details.
676
func (ec2 *EC2) Images(ids []string, filter *Filter) (resp *ImagesResp, err error) {
677
params := makeParams("DescribeImages")
678
for i, id := range ids {
679
params["ImageId."+strconv.Itoa(i+1)] = id
681
filter.addParams(params)
684
err = ec2.query(params, resp)
691
// Response to a CreateSnapshot request.
693
// See http://goo.gl/ttcda for more details.
694
type CreateSnapshotResp struct {
695
RequestId string `xml:"requestId"`
699
// CreateSnapshot creates a volume snapshot and stores it in S3.
701
// See http://goo.gl/ttcda for more details.
702
func (ec2 *EC2) CreateSnapshot(volumeId, description string) (resp *CreateSnapshotResp, err error) {
703
params := makeParams("CreateSnapshot")
704
params["VolumeId"] = volumeId
705
params["Description"] = description
707
resp = &CreateSnapshotResp{}
708
err = ec2.query(params, resp)
715
// DeleteSnapshots deletes the volume snapshots with the given ids.
717
// Note: If you make periodic snapshots of a volume, the snapshots are
718
// incremental so that only the blocks on the device that have changed
719
// since your last snapshot are incrementally saved in the new snapshot.
720
// Even though snapshots are saved incrementally, the snapshot deletion
721
// process is designed so that you need to retain only the most recent
722
// snapshot in order to restore the volume.
724
// See http://goo.gl/vwU1y for more details.
725
func (ec2 *EC2) DeleteSnapshots(ids []string) (resp *SimpleResp, err error) {
726
params := makeParams("DeleteSnapshot")
727
for i, id := range ids {
728
params["SnapshotId."+strconv.Itoa(i+1)] = id
732
err = ec2.query(params, resp)
739
// Response to a DescribeSnapshots request.
741
// See http://goo.gl/nClDT for more details.
742
type SnapshotsResp struct {
743
RequestId string `xml:"requestId"`
744
Snapshots []Snapshot `xml:"snapshotSet>item"`
747
// Snapshot represents details about a volume snapshot.
749
// See http://goo.gl/nkovs for more details.
750
type Snapshot struct {
751
Id string `xml:"snapshotId"`
752
VolumeId string `xml:"volumeId"`
753
VolumeSize string `xml:"volumeSize"`
754
Status string `xml:"status"`
755
StartTime string `xml:"startTime"`
756
Description string `xml:"description"`
757
Progress string `xml:"progress"`
758
OwnerId string `xml:"ownerId"`
759
OwnerAlias string `xml:"ownerAlias"`
760
Tags []Tag `xml:"tagSet>item"`
763
// Snapshots returns details about volume snapshots available to the user.
764
// The ids and filter parameters, if provided, limit the snapshots returned.
766
// See http://goo.gl/ogJL4 for more details.
767
func (ec2 *EC2) Snapshots(ids []string, filter *Filter) (resp *SnapshotsResp, err error) {
768
params := makeParams("DescribeSnapshots")
769
for i, id := range ids {
770
params["SnapshotId."+strconv.Itoa(i+1)] = id
772
filter.addParams(params)
774
resp = &SnapshotsResp{}
775
err = ec2.query(params, resp)
782
// ----------------------------------------------------------------------------
783
// Security group management functions and types.
785
// SimpleResp represents a response to an EC2 request which on success will
786
// return no other information besides a request id.
787
type SimpleResp struct {
789
RequestId string `xml:"requestId"`
790
Return bool `xml:"return"`
793
// CreateSecurityGroupResp represents a response to a CreateSecurityGroup request.
794
type CreateSecurityGroupResp struct {
796
RequestId string `xml:"requestId"`
799
// CreateSecurityGroup creates a security group with the provided name
800
// and description. The vpcId argument can be empty to create a
801
// EC2-Classic group, instead of EC2-VPC one.
803
// See http://goo.gl/Eo7Yl for more details.
804
func (ec2 *EC2) CreateSecurityGroup(vpcId, name, description string) (resp *CreateSecurityGroupResp, err error) {
805
params := makeParams("CreateSecurityGroup")
806
params["GroupName"] = name
807
params["GroupDescription"] = description
809
params["VpcId"] = vpcId
812
resp = &CreateSecurityGroupResp{}
813
err = ec2.query(params, resp)
821
// SecurityGroupsResp represents a response to a DescribeSecurityGroups
824
// See http://goo.gl/k12Uy for more details.
825
type SecurityGroupsResp struct {
826
RequestId string `xml:"requestId"`
827
Groups []SecurityGroupInfo `xml:"securityGroupInfo>item"`
830
// SecurityGroup encapsulates details for a security group in EC2.
832
// See http://goo.gl/CIdyP for more details.
833
type SecurityGroupInfo struct {
835
VPCId string `xml:"vpcId"`
836
OwnerId string `xml:"ownerId"`
837
Description string `xml:"groupDescription"`
838
IPPerms []IPPerm `xml:"ipPermissions>item"`
841
// IPPerm represents an allowance within an EC2 security group.
843
// See http://goo.gl/4oTxv for more details.
845
Protocol string `xml:"ipProtocol"`
846
FromPort int `xml:"fromPort"`
847
ToPort int `xml:"toPort"`
848
SourceIPs []string `xml:"ipRanges>item>cidrIp"`
849
SourceGroups []UserSecurityGroup `xml:"groups>item"`
852
// UserSecurityGroup holds a security group and the owner
854
type UserSecurityGroup struct {
855
Id string `xml:"groupId"`
856
Name string `xml:"groupName,omitempty"`
857
OwnerId string `xml:"userId"`
860
// SecurityGroup represents an EC2 security group.
861
// If SecurityGroup is used as a parameter, then one of Id or Name
862
// may be empty. If both are set, then Id is used.
863
type SecurityGroup struct {
864
Id string `xml:"groupId"`
865
Name string `xml:"groupName"`
868
// SecurityGroupNames is a convenience function that
869
// returns a slice of security groups with the given names.
870
func SecurityGroupNames(names ...string) []SecurityGroup {
871
g := make([]SecurityGroup, len(names))
872
for i, name := range names {
873
g[i] = SecurityGroup{Name: name}
878
// SecurityGroupNames is a convenience function that
879
// returns a slice of security groups with the given ids.
880
func SecurityGroupIds(ids ...string) []SecurityGroup {
881
g := make([]SecurityGroup, len(ids))
882
for i, id := range ids {
883
g[i] = SecurityGroup{Id: id}
888
// SecurityGroups returns details about security groups in EC2. Both parameters
889
// are optional, and if provided will limit the security groups returned to those
890
// matching the given groups or filtering rules.
892
// See http://goo.gl/k12Uy for more details.
893
func (ec2 *EC2) SecurityGroups(groups []SecurityGroup, filter *Filter) (resp *SecurityGroupsResp, err error) {
894
params := makeParams("DescribeSecurityGroups")
896
for _, g := range groups {
898
params["GroupId."+strconv.Itoa(i)] = g.Id
901
params["GroupName."+strconv.Itoa(j)] = g.Name
905
filter.addParams(params)
907
resp = &SecurityGroupsResp{}
908
err = ec2.query(params, resp)
915
// DeleteSecurityGroup removes the given security group in EC2.
917
// See http://goo.gl/QJJDO for more details.
918
func (ec2 *EC2) DeleteSecurityGroup(group SecurityGroup) (resp *SimpleResp, err error) {
919
params := makeParams("DeleteSecurityGroup")
921
params["GroupId"] = group.Id
923
params["GroupName"] = group.Name
927
err = ec2.query(params, resp)
934
// AuthorizeSecurityGroup creates an allowance for clients matching the provided
935
// rules to access instances within the given security group.
937
// See http://goo.gl/u2sDJ for more details.
938
func (ec2 *EC2) AuthorizeSecurityGroup(group SecurityGroup, perms []IPPerm) (resp *SimpleResp, err error) {
939
return ec2.authOrRevoke("AuthorizeSecurityGroupIngress", group, perms)
942
// RevokeSecurityGroup revokes permissions from a group.
944
// See http://goo.gl/ZgdxA for more details.
945
func (ec2 *EC2) RevokeSecurityGroup(group SecurityGroup, perms []IPPerm) (resp *SimpleResp, err error) {
946
return ec2.authOrRevoke("RevokeSecurityGroupIngress", group, perms)
949
func (ec2 *EC2) authOrRevoke(op string, group SecurityGroup, perms []IPPerm) (resp *SimpleResp, err error) {
950
params := makeParams(op)
952
params["GroupId"] = group.Id
954
params["GroupName"] = group.Name
957
for i, perm := range perms {
958
prefix := "IpPermissions." + strconv.Itoa(i+1)
959
params[prefix+".IpProtocol"] = perm.Protocol
960
params[prefix+".FromPort"] = strconv.Itoa(perm.FromPort)
961
params[prefix+".ToPort"] = strconv.Itoa(perm.ToPort)
962
for j, ip := range perm.SourceIPs {
963
params[prefix+".IpRanges."+strconv.Itoa(j+1)+".CidrIp"] = ip
965
for j, g := range perm.SourceGroups {
966
subprefix := prefix + ".Groups." + strconv.Itoa(j+1)
968
params[subprefix+".UserId"] = g.OwnerId
971
params[subprefix+".GroupId"] = g.Id
973
params[subprefix+".GroupName"] = g.Name
979
err = ec2.query(params, resp)
986
// Tag represents key-value metadata used to classify and organize
989
// See http://goo.gl/bncl3 for more details
991
Key string `xml:"key"`
992
Value string `xml:"value"`
995
// CreateTags adds or overwrites one or more tags for the specified instance ids.
997
// See http://goo.gl/Vmkqc for more details
998
func (ec2 *EC2) CreateTags(instIds []string, tags []Tag) (resp *SimpleResp, err error) {
999
params := makeParams("CreateTags")
1000
addParamsList(params, "ResourceId", instIds)
1002
for j, tag := range tags {
1003
params["Tag."+strconv.Itoa(j+1)+".Key"] = tag.Key
1004
params["Tag."+strconv.Itoa(j+1)+".Value"] = tag.Value
1007
resp = &SimpleResp{}
1008
err = ec2.query(params, resp)
1015
// Response to a StartInstances request.
1017
// See http://goo.gl/awKeF for more details.
1018
type StartInstanceResp struct {
1019
RequestId string `xml:"requestId"`
1020
StateChanges []InstanceStateChange `xml:"instancesSet>item"`
1023
// Response to a StopInstances request.
1025
// See http://goo.gl/436dJ for more details.
1026
type StopInstanceResp struct {
1027
RequestId string `xml:"requestId"`
1028
StateChanges []InstanceStateChange `xml:"instancesSet>item"`
1031
// StartInstances starts an Amazon EBS-backed AMI that you've previously stopped.
1033
// See http://goo.gl/awKeF for more details.
1034
func (ec2 *EC2) StartInstances(ids ...string) (resp *StartInstanceResp, err error) {
1035
params := makeParams("StartInstances")
1036
addParamsList(params, "InstanceId", ids)
1037
resp = &StartInstanceResp{}
1038
err = ec2.query(params, resp)
1045
// StopInstances requests stopping one or more Amazon EBS-backed instances.
1047
// See http://goo.gl/436dJ for more details.
1048
func (ec2 *EC2) StopInstances(ids ...string) (resp *StopInstanceResp, err error) {
1049
params := makeParams("StopInstances")
1050
addParamsList(params, "InstanceId", ids)
1051
resp = &StopInstanceResp{}
1052
err = ec2.query(params, resp)
1059
// RebootInstance requests a reboot of one or more instances. This operation is asynchronous;
1060
// it only queues a request to reboot the specified instance(s). The operation will succeed
1061
// if the instances are valid and belong to you.
1063
// Requests to reboot terminated instances are ignored.
1065
// See http://goo.gl/baoUf for more details.
1066
func (ec2 *EC2) RebootInstances(ids ...string) (resp *SimpleResp, err error) {
1067
params := makeParams("RebootInstances")
1068
addParamsList(params, "InstanceId", ids)
1069
resp = &SimpleResp{}
1070
err = ec2.query(params, resp)
1077
// ----------------------------------------------------------------------------
1078
// Availability zone management functions and types.
1079
// See http://goo.gl/ylxT4R for more details.
1081
// AvailabilityZonesResp represents a response to a DescribeAvailabilityZones
1083
type AvailabilityZonesResp struct {
1084
RequestId string `xml:"requestId"`
1085
Zones []AvailabilityZoneInfo `xml:"availabilityZoneInfo>item"`
1088
// AvailabilityZoneInfo encapsulates details for an availability zone in EC2.
1089
type AvailabilityZoneInfo struct {
1091
State string `xml:"zoneState"`
1092
MessageSet []string `xml:"messageSet>item"`
1095
// AvailabilityZone represents an EC2 availability zone.
1096
type AvailabilityZone struct {
1097
Name string `xml:"zoneName"`
1098
Region string `xml:"regionName"`
1101
// AvailabilityZones returns details about availability zones in EC2.
1102
// The filter parameter is optional, and if provided will limit the
1103
// availability zones returned to those matching the given filtering
1106
// See http://goo.gl/ylxT4R for more details.
1107
func (ec2 *EC2) AvailabilityZones(filter *Filter) (resp *AvailabilityZonesResp, err error) {
1108
params := makeParams("DescribeAvailabilityZones")
1109
filter.addParams(params)
1110
resp = &AvailabilityZonesResp{}
1111
err = ec2.query(params, resp)
1118
// AccountAttribute holds information about an account attribute.
1120
// See http://goo.gl/hBc28j for more details.
1121
type AccountAttribute struct {
1122
Name string `xml:"attributeName"`
1123
Values []string `xml:"attributeValueSet>item>attributeValue"`
1126
// AccountAttributesResp is the response to an AccountAttributes request.
1128
// See http://goo.gl/hBc28j for more details.
1129
type AccountAttributesResp struct {
1130
RequestId string `xml:"requestId"`
1131
Attributes []AccountAttribute `xml:"accountAttributeSet>item"`
1134
// AccountAttributes returns the values of one or more account
1137
// See http://goo.gl/hBc28j for more details.
1138
func (ec2 *EC2) AccountAttributes(attrNames ...string) (*AccountAttributesResp, error) {
1139
params := makeParams("DescribeAccountAttributes")
1140
for i, attrName := range attrNames {
1141
params["AttributeName."+strconv.Itoa(i+1)] = attrName
1144
resp := &AccountAttributesResp{}
1145
if err := ec2.query(params, resp); err != nil {