Этот коммит содержится в:
Christopher Speller
2017-03-13 16:43:00 -04:00
коммит произвёл GitHub
родитель 3b081bda08
Коммит 24496cd0b2
140 изменённых файлов: 2 добавлений и 38156 удалений

Просмотреть файл

@@ -3554,201 +3554,6 @@ the property of their respective owners.
---
This product contains a modified portion of 'goamz', which enables Go programs to interact with Amazon Web Services.
* HOMEPAGE:
* https://github.com/goamz/goamz
* LICENSE:
This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
---
This product contains a modified portion of 'pdfjs-dist', is a Portable Document Format (PDF) library that is built with HTML5 built by mozilla.
* HOMEPAGE:

9
glide.lock сгенерированный
Просмотреть файл

@@ -1,5 +1,5 @@
hash: 978c0474f3432a26942e213ca1ba8e957fa5a34ee4652d736dae152fbd6d5384
updated: 2017-03-13T11:12:52.056509274-04:00
hash: cd23f3578895da94079e79ec355cca1eb64867c5b58f02fc5ec00dd88576d575
updated: 2017-03-13T15:29:09.097298322-04:00
imports:
- name: github.com/alecthomas/log4go
version: e5dc62318d9bd58682f1dceb53a4b24e8253682f
@@ -21,11 +21,6 @@ imports:
version: 8168ee085ee43257585e50c6441aadf54ecb2c9f
- name: github.com/go-sql-driver/mysql
version: a0583e0143b1624142adab07e0e97fe106d99561
- name: github.com/goamz/goamz
version: c35091c30f44b7f151ec9028b895465a191d1ea7
subpackages:
- aws
- s3
- name: github.com/golang/freetype
version: d9be45aaf7452cc30c0ceb1b1bf7efe1d17b7c87
subpackages:

Просмотреть файл

@@ -11,10 +11,6 @@ import:
version: v2.5.0
- package: github.com/go-sql-driver/mysql
version: v1.3
- package: github.com/goamz/goamz
subpackages:
- aws
- s3
- package: github.com/golang/freetype
- package: github.com/gorilla/handlers
version: v1.2

1
vendor/github.com/goamz/goamz/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -1 +0,0 @@
*.swp

1
vendor/github.com/goamz/goamz/.lbox сгенерированный поставляемый
Просмотреть файл

@@ -1 +0,0 @@
propose -for=lp:goamz -cr

32
vendor/github.com/goamz/goamz/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,32 +0,0 @@
language: go
go:
- 1.1
- 1.2
- 1.3
- 1.4
- tip
before_script:
- FIXED=$(go fmt ./... | wc -l); if [ $FIXED -gt 0 ]; then echo "gofmt - $FIXED file(s) not formatted correctly, please run gofmt to fix this." && exit 1; fi
script:
- go test -v ./autoscaling/
- go test -v ./aws/
- go test -v ./cloudformation/
- go test -v ./cloudfront/
- go test -v ./cloudwatch/
- go test -v ./dynamodb/
- go test -v ./ec2/
- go test -v ./ecs/
- go test -v ./elb/
- go test -v ./iam/
- go test -v ./rds/
- go test -v ./route53/
- go test -v ./s3/
- go test -v ./sqs/
- go test -v ./sts/
- go test -v ./exp/mturk/
- go test -v ./exp/sdb/
# - go test -v ./exp/ses/
# - go test -v ./exp/sns/

5
vendor/github.com/goamz/goamz/CHANGES.md сгенерированный поставляемый
Просмотреть файл

@@ -1,5 +0,0 @@
# Changes in this fork
* Added CNNorth Region
* Change SignV2 to SignV4
* V4Signer.canonicalQueryString empty value must append "="

185
vendor/github.com/goamz/goamz/LICENSE сгенерированный поставляемый
Просмотреть файл

@@ -1,185 +0,0 @@
This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

64
vendor/github.com/goamz/goamz/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,64 +0,0 @@
# goamz - An Amazon Library for Go
[![Build Status](http://travis-ci.org/goamz/goamz.png?branch=master)](https://travis-ci.org/goamz/goamz)
The _goamz_ package enables Go programs to interact with Amazon Web Services.
This is a fork of the version [developed within Canonical](https://wiki.ubuntu.com/goamz) with additional functionality and services from [a number of contributors](https://github.com/goamz/goamz/contributors)!
The API of AWS is very comprehensive, though, and goamz doesn't even scratch the surface of it. That said, it's fairly well tested, and is the foundation in which further calls can easily be integrated. We'll continue extending the API as necessary - Pull Requests are _very_ welcome!
The following packages are available at the moment:
```
github.com/goamz/goamz/autoscaling
github.com/goamz/goamz/aws
github.com/goamz/goamz/cloudformation
github.com/goamz/goamz/cloudfront
github.com/goamz/goamz/cloudwatch
github.com/goamz/goamz/dynamodb
github.com/goamz/goamz/ecs
github.com/goamz/goamz/ec2
github.com/goamz/goamz/elb
github.com/goamz/goamz/iam
github.com/goamz/goamz/rds
github.com/goamz/goamz/route53
github.com/goamz/goamz/s3
github.com/goamz/goamz/sqs
github.com/goamz/goamz/sts
github.com/goamz/goamz/exp/mturk
github.com/goamz/goamz/exp/sdb
github.com/goamz/goamz/exp/sns
```
Packages under `exp/` are still in an experimental or unfinished/unpolished state.
## API documentation
The API documentation is currently available at:
[http://godoc.org/github.com/goamz/goamz](http://godoc.org/github.com/goamz/goamz)
## How to build and install goamz
Just use `go get` with any of the available packages. For example:
* `$ go get github.com/goamz/goamz/ec2`
* `$ go get github.com/goamz/goamz/s3`
## Running tests
To run tests, first install gocheck with:
`$ go get gopkg.in/check.v1`
Then run go test as usual:
`$ go test github.com/goamz/goamz/...`
_Note:_ running all tests with the command `go test ./...` will currently fail as tests do not tear down their HTTP listeners.
If you want to run integration tests (costs money), set up the EC2 environment variables as usual, and run:
$ gotest -i

1768
vendor/github.com/goamz/goamz/autoscaling/autoscaling.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1180
vendor/github.com/goamz/goamz/autoscaling/autoscaling_test.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

627
vendor/github.com/goamz/goamz/autoscaling/responses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,627 +0,0 @@
package autoscaling
var AttachInstancesResponse = `
<AttachInstancesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</AttachInstancesResponse>
`
var BasicGroupResponse = `
<DescribeAutoScalingGroupsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeAutoScalingGroupsResult>
<AutoScalingGroups/>
</DescribeAutoScalingGroupsResult>
<ResponseMetadata>
<RequestId>08c3bedc-8421-11e3-9bb5-bfa219b29cce</RequestId>
</ResponseMetadata>
</DescribeAutoScalingGroupsResponse>
`
var CreateAutoScalingGroupResponse = `
<CreateAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</CreateAutoScalingGroupResponse>
`
var CreateLaunchConfigurationResponse = `
<CreateLaunchConfigurationResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>7c6e177f-f082-11e1-ac58-3714bEXAMPLE</RequestId>
</ResponseMetadata>
</CreateLaunchConfigurationResponse>
`
var CreateOrUpdateTagsResponse = `
<CreateOrUpdateTagsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>b0203919-bf1b-11e2-8a01-13263EXAMPLE</RequestId>
</ResponseMetadata>
</CreateOrUpdateTagsResponse>
`
var DeleteAutoScalingGroupResponse = `
<DeleteAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>70a76d42-9665-11e2-9fdf-211deEXAMPLE</RequestId>
</ResponseMetadata>
</DeleteAutoScalingGroupResponse>
`
var DeleteAutoScalingGroupErrorResponse = `
<ErrorResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<Error>
<Type>Sender</Type>
<Code>ResourceInUse</Code>
<Message>You cannot delete an AutoScalingGroup while there are instances or pending Spot instance request(s) still in the group.</Message>
</Error>
<RequestId>70a76d42-9665-11e2-9fdf-211deEXAMPLE</RequestId>
</ErrorResponse>
`
var DeleteLaunchConfigurationResponse = `
<DeleteLaunchConfigurationResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>7347261f-97df-11e2-8756-35eEXAMPLE</RequestId>
</ResponseMetadata>
</DeleteLaunchConfigurationResponse>
`
var DeleteLaunchConfigurationInUseResponse = `
<ErrorResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<Error>
<Type>Sender</Type>
<Code>ResourceInUse</Code>
<Message>Cannot delete launch configuration my-test-lc because it is attached to AutoScalingGroup test</Message>
</Error>
<RequestId>7347261f-97df-11e2-8756-35eEXAMPLE</RequestId>
</ErrorResponse>
`
var DeleteScheduledActionResponse = `
<DeleteScheduledActionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>0f38bb02-8421-11e3-9bb5-bfa219b29cce</RequestId>
</ResponseMetadata>
</DeleteScheduledActionResponse>
`
var DeleteTagsResponse = `
<CreateOrUpdateTagsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>b0203919-bf1b-11e2-8a01-13263EXAMPLE</RequestId>
</ResponseMetadata>
</CreateOrUpdateTagsResponse>
`
var DescribeAccountLimitsResponse = `
<DescribeAccountLimitsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeAccountLimitsResult>
<MaxNumberOfLaunchConfigurations>100</MaxNumberOfLaunchConfigurations>
<MaxNumberOfAutoScalingGroups>20</MaxNumberOfAutoScalingGroups>
</DescribeAccountLimitsResult>
<ResponseMetadata>
<RequestId>a32bd184-519d-11e3-a8a4-c1c467cbcc3b</RequestId>
</ResponseMetadata>
</DescribeAccountLimitsResponse>
`
var DescribeAdjustmentTypesResponse = `
<DescribeAdjustmentTypesResponse xmlns="http://autoscaling.amazonaws.com/doc/201-01-01/">
<DescribeAdjustmentTypesResult>
<AdjustmentTypes>
<member>
<AdjustmentType>ChangeInCapacity</AdjustmentType>
</member>
<member>
<AdjustmentType>ExactCapacity</AdjustmentType>
</member>
<member>
<AdjustmentType>PercentChangeInCapacity</AdjustmentType>
</member>
</AdjustmentTypes>
</DescribeAdjustmentTypesResult>
<ResponseMetadata>
<RequestId>cc5f0337-b694-11e2-afc0-6544dEXAMPLE</RequestId>
</ResponseMetadata>
</DescribeAdjustmentTypesResponse>
`
var DescribeAutoScalingGroupsResponse = `
<DescribeAutoScalingGroupsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeAutoScalingGroupsResult>
<AutoScalingGroups>
<member>
<Tags>
<member>
<ResourceId>my-test-asg-lbs</ResourceId>
<PropagateAtLaunch>true</PropagateAtLaunch>
<Value>bar</Value>
<Key>foo</Key>
<ResourceType>auto-scaling-group</ResourceType>
</member>
<member>
<ResourceId>my-test-asg-lbs</ResourceId>
<PropagateAtLaunch>true</PropagateAtLaunch>
<Value>qux</Value>
<Key>baz</Key>
<ResourceType>auto-scaling-group</ResourceType>
</member>
</Tags>
<SuspendedProcesses/>
<AutoScalingGroupName>my-test-asg-lbs</AutoScalingGroupName>
<HealthCheckType>ELB</HealthCheckType>
<CreatedTime>2013-05-06T17:47:15.107Z</CreatedTime>
<EnabledMetrics/>
<LaunchConfigurationName>my-test-lc</LaunchConfigurationName>
<Instances>
<member>
<HealthStatus>Healthy</HealthStatus>
<AvailabilityZone>us-east-1b</AvailabilityZone>
<InstanceId>i-zb1f313</InstanceId>
<LaunchConfigurationName>my-test-lc</LaunchConfigurationName>
<LifecycleState>InService</LifecycleState>
</member>
<member>
<HealthStatus>Healthy</HealthStatus>
<AvailabilityZone>us-east-1a</AvailabilityZone>
<InstanceId>i-90123adv</InstanceId>
<LaunchConfigurationName>my-test-lc</LaunchConfigurationName>
<LifecycleState>InService</LifecycleState>
</member>
</Instances>
<DesiredCapacity>2</DesiredCapacity>
<AvailabilityZones>
<member>us-east-1b</member>
<member>us-east-1a</member>
</AvailabilityZones>
<LoadBalancerNames>
<member>my-test-asg-loadbalancer</member>
</LoadBalancerNames>
<MinSize>2</MinSize>
<VPCZoneIdentifier>subnet-32131da1,subnet-1312dad2</VPCZoneIdentifier>
<HealthCheckGracePeriod>120</HealthCheckGracePeriod>
<DefaultCooldown>300</DefaultCooldown>
<AutoScalingGroupARN>arn:aws:autoscaling:us-east-1:803981987763:autoScalingGroup:ca861182-c8f9-4ca7-b1eb-cd35505f5ebb:autoScalingGroupName/my-test-asg-lbs</AutoScalingGroupARN>
<TerminationPolicies>
<member>Default</member>
</TerminationPolicies>
<MaxSize>10</MaxSize>
</member>
</AutoScalingGroups>
</DescribeAutoScalingGroupsResult>
<ResponseMetadata>
<RequestId>0f02a07d-b677-11e2-9eb0-dd50EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeAutoScalingGroupsResponse>
`
var DescribeAutoScalingInstancesResponse = `
<DescribeAutoScalingInstancesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeAutoScalingInstancesResult>
<AutoScalingInstances>
<member>
<HealthStatus>Healthy</HealthStatus>
<AutoScalingGroupName>my-test-asg</AutoScalingGroupName>
<AvailabilityZone>us-east-1a</AvailabilityZone>
<InstanceId>i-78e0d40b</InstanceId>
<LaunchConfigurationName>my-test-lc</LaunchConfigurationName>
<LifecycleState>InService</LifecycleState>
</member>
</AutoScalingInstances>
</DescribeAutoScalingInstancesResult>
<ResponseMetadata>
<RequestId>df992dc3-b72f-11e2-81e1-750aa6EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeAutoScalingInstancesResponse>
`
var DescribeLaunchConfigurationsResponse = `
<DescribeLaunchConfigurationsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeLaunchConfigurationsResult>
<LaunchConfigurations>
<member>
<AssociatePublicIpAddress>true</AssociatePublicIpAddress>
<SecurityGroups/>
<CreatedTime>2013-01-21T23:04:42.200Z</CreatedTime>
<KernelId/>
<LaunchConfigurationName>my-test-lc</LaunchConfigurationName>
<UserData/>
<InstanceType>m1.small</InstanceType>
<LaunchConfigurationARN>arn:aws:autoscaling:us-east-1:803981987763:launchConfiguration:9dbbbf87-6141-428a-a409-0752edbe6cad:launchConfigurationName/my-test-lc</LaunchConfigurationARN>
<BlockDeviceMappings>
<member>
<VirtualName>ephemeral0</VirtualName>
<DeviceName>/dev/sdb</DeviceName>
</member>
<member>
<Ebs>
<SnapshotId>snap-XXXXYYY</SnapshotId>
<VolumeSize>100</VolumeSize>
<Iops>50</Iops>
<VolumeType>io1</VolumeType>
<DeleteOnTermination>true</DeleteOnTermination>
</Ebs>
<DeviceName>/dev/sdf</DeviceName>
</member>
</BlockDeviceMappings>
<ImageId>ami-514ac838</ImageId>
<KeyName/>
<RamdiskId/>
<InstanceMonitoring>
<Enabled>true</Enabled>
</InstanceMonitoring>
<EbsOptimized>false</EbsOptimized>
</member>
</LaunchConfigurations>
</DescribeLaunchConfigurationsResult>
<ResponseMetadata>
<RequestId>d05a22f8-b690-11e2-bf8e-2113fEXAMPLE</RequestId>
</ResponseMetadata>
</DescribeLaunchConfigurationsResponse>
`
var DescribeMetricCollectionTypesResponse = `
<DescribeMetricCollectionTypesResponse xmlns="http://autoscaling.amazonaws.co
oc/2011-01-01/">
<DescribeMetricCollectionTypesResult>
<Metrics>
<member>
<Metric>GroupMinSize</Metric>
</member>
<member>
<Metric>GroupMaxSize</Metric>
</member>
<member>
<Metric>GroupDesiredCapacity</Metric>
</member>
<member>
<Metric>GroupInServiceInstances</Metric>
</member>
<member>
<Metric>GroupPendingInstances</Metric>
</member>
<member>
<Metric>GroupTerminatingInstances</Metric>
</member>
<member>
<Metric>GroupTotalInstances</Metric>
</member>
</Metrics>
<Granularities>
<member>
<Granularity>1Minute</Granularity>
</member>
</Granularities>
</DescribeMetricCollectionTypesResult>
<ResponseMetadata>
<RequestId>07f3fea2-bf3c-11e2-9b6f-f3cdbb80c073</RequestId>
</ResponseMetadata>
</DescribeMetricCollectionTypesResponse>
`
var DescribeNotificationConfigurationsResponse = `
<DescribeNotificationConfigurationsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeNotificationConfigurationsResult>
<NotificationConfigurations>
<member>
<AutoScalingGroupName>my-test-asg</AutoScalingGroupName>
<NotificationType>autoscaling: EC2_INSTANCE_LAUNCH</NotificationType>
<TopicARN>vajdoafj231j41231/topic</TopicARN>
</member>
</NotificationConfigurations>
</DescribeNotificationConfigurationsResult>
<ResponseMetadata>
<RequestId>07f3fea2-bf3c-11e2-9b6f-f3cdbb80c073</RequestId>
</ResponseMetadata>
</DescribeNotificationConfigurationsResponse>
`
var DescribePoliciesResponse = `
<DescribePoliciesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribePoliciesResult>
<NextToken>3ef417fe-9202-12-8ddd-d13e1313413</NextToken>
<ScalingPolicies>
<member>
<PolicyARN>arn:aws:autoscaling:us-east-1:803981987763:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/my-test-asg:policyName/MyScaleDownPolicy</PolicyARN>
<AdjustmentType>ChangeInCapacity</AdjustmentType>
<ScalingAdjustment>-1</ScalingAdjustment>
<PolicyName>MyScaleDownPolicy</PolicyName>
<AutoScalingGroupName>my-test-asg</AutoScalingGroupName>
<Cooldown>60</Cooldown>
<Alarms>
<member>
<AlarmName>TestQueue</AlarmName>
<AlarmARN>arn:aws:cloudwatch:us-east-1:803981987763:alarm:TestQueue</AlarmARN>
</member>
</Alarms>
</member>
<member>
<PolicyARN>arn:aws:autoscaling:us-east-1:803981987763:scalingPolicy:c55a5cdd-9be0-435b-b60b-a8dd313159f5:autoScalingGroupName/my-test-asg:policyName/MyScaleUpPolicy</PolicyARN>
<AdjustmentType>ChangeInCapacity</AdjustmentType>
<ScalingAdjustment>1</ScalingAdjustment>
<PolicyName>MyScaleUpPolicy</PolicyName>
<AutoScalingGroupName>my-test-asg</AutoScalingGroupName>
<Cooldown>60</Cooldown>
<Alarms>
<member>
<AlarmName>TestQueue</AlarmName>
<AlarmARN>arn:aws:cloudwatch:us-east-1:803981987763:alarm:TestQueue</AlarmARN>
</member>
</Alarms>
</member>
</ScalingPolicies>
</DescribePoliciesResult>
<ResponseMetadata>
<RequestId>ec3bffad-b739-11e2-b38d-15fbEXAMPLE</RequestId>
</ResponseMetadata>
</DescribePoliciesResponse>
`
var DescribeScalingActivitiesResponse = `
<DescribeScalingActivitiesResponse xmlns="http://ec2.amazonaws.com/doc/2011-01-01/">
<DescribeScalingActivitiesResult>
<NextToken>3ef417fe-9202-12-8ddd-d13e1313413</NextToken>
<Activities>
<member>
<StatusCode>Failed</StatusCode>
<Progress>0</Progress>
<ActivityId>063308ae-aa22-4a9b-94f4-9faeEXAMPLE</ActivityId>
<StartTime>2012-04-12T17:32:07.882Z</StartTime>
<AutoScalingGroupName>my-test-asg</AutoScalingGroupName>
<Cause>At 2012-04-12T17:31:30Z a user request created an AutoScalingGroup changing the desired capacity from 0 to 1. At 2012-04-12T17:32:07Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1.</Cause>
<Details>{}</Details>
<Description>Launching a new EC2 instance. Status Reason: The image id 'ami-4edb0327' does not exist. Launching EC2 instance failed.</Description>
<EndTime>2012-04-12T17:32:08Z</EndTime>
<StatusMessage>The image id 'ami-4edb0327' does not exist. Launching EC2 instance failed.</StatusMessage>
</member>
</Activities>
</DescribeScalingActivitiesResult>
<ResponseMetadata>
<RequestId>7a641adc-84c5-11e1-a8a5-217ebEXAMPLE</RequestId>
</ResponseMetadata>
</DescribeScalingActivitiesResponse>
`
var DescribeScalingProcessTypesResponse = `
<DescribeScalingProcessTypesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeScalingProcessTypesResult>
<Processes>
<member>
<ProcessName>AZRebalance</ProcessName>
</member>
<member>
<ProcessName>AddToLoadBalancer</ProcessName>
</member>
<member>
<ProcessName>AlarmNotification</ProcessName>
</member>
<member>
<ProcessName>HealthCheck</ProcessName>
</member>
<member>
<ProcessName>Launch</ProcessName>
</member>
<member>
<ProcessName>ReplaceUnhealthy</ProcessName>
</member>
<member>
<ProcessName>ScheduledActions</ProcessName>
</member>
<member>
<ProcessName>Terminate</ProcessName>
</member>
</Processes>
</DescribeScalingProcessTypesResult>
<ResponseMetadata>
<RequestId>27f2eacc-b73f-11e2-ad99-c7aba3a9c963</RequestId>
</ResponseMetadata>
</DescribeScalingProcessTypesResponse>
`
var DescribeScheduledActionsResponse = `
<DescribeScheduledActionsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeScheduledActionsResult>
<ScheduledUpdateGroupActions>
<member>
<ScheduledActionName>SATest1</ScheduledActionName>
<StartTime>2014-06-01T00:30:00Z</StartTime>
<Time>2014-06-01T00:30:00Z</Time>
<ScheduledActionARN>arn:aws:autoscaling:us-west-2:193024542802:scheduledUpdateGroupAction:61f68b2c-bde3-4316-9a81-eb95dc246509:autoScalingGroupName/ASGTest1:scheduledActionName/SATest1</ScheduledActionARN>
<AutoScalingGroupName>ASGTest1</AutoScalingGroupName>
<Recurrence>30 0 1 1,6,12 *</Recurrence>
<MaxSize>4</MaxSize>
</member>
</ScheduledUpdateGroupActions>
</DescribeScheduledActionsResult>
<ResponseMetadata>
<RequestId>0eb4217f-8421-11e3-9233-7100ef811766</RequestId>
</ResponseMetadata>
</DescribeScheduledActionsResponse>
`
var DescribeTerminationPolicyTypesResponse = `
<DescribeTerminationPolicyTypesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeTerminationPolicyTypesResult>
<TerminationPolicyTypes>
<member>ClosestToNextInstanceHour</member>
<member>Default</member>
<member>NewestInstance</member>
<member>OldestInstance</member>
<member>OldestLaunchConfiguration</member>
</TerminationPolicyTypes>
</DescribeTerminationPolicyTypesResult>
<ResponseMetadata>
<RequestId>d9a05827-b735-11e2-a40c-c79a5EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeTerminationPolicyTypesResponse>
`
var DescribeTagsResponse = `
<DescribeTagsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DescribeTagsResult>
<Tags>
<member>
<ResourceId>my-test-asg</ResourceId>
<PropagateAtLaunch>true</PropagateAtLaunch>
<Value>1.0</Value>
<Key>version</Key>
<ResourceType>auto-scaling-group</ResourceType>
</member>
</Tags>
</DescribeTagsResult>
<ResponseMetadata>
<RequestId>086265fd-bf3e-11e2-85fc-fbb1EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeTagsResponse>
`
var DetachInstancesResponse = `
<DetachInstancesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<DetachInstancesResult>
<Activities>
<member>
<ActivityId>e54ff599-bf05-4076-8b95-a0f090ed90bb</ActivityId>
<Progress>50</Progress>
<StatusCode>InProgress</StatusCode>
<StartTime>2014-06-14T00:07:30.280Z</StartTime>
<Cause>At 2014-06-14T00:07:30Z instance i-5f2e8a0d was detached in response to a user request, shrinking the capacity from 4 to 3.</Cause>
<AutoScalingGroupName>my-asg</AutoScalingGroupName>
<Details>{"Availability Zone":"us-east-1a"}</Details>
<Description>Detaching EC2 instance: i-5f2e8a0d</Description>
</member>
</Activities>
</DetachInstancesResult>
<ResponseMetadata>
<RequestId>e04f3b11-f357-11e3-a434-7f10009d5849</RequestId>
</ResponseMetadata>
</DetachInstancesResponse>
`
var DisableMetricsCollectionResponse = `
<DisableMetricsCollectionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DisableMetricsCollectionResponse>
`
var EnableMetricsCollectionResponse = `
<EnableMetricsCollectionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</EnableMetricsCollectionResponse>
`
var EnterStandbyResponse = `
<EnterStandbyResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<EnterStandbyResult>
<Activities>
<member>
<ActivityId>462b4bc3-ad3b-4e67-a58d-96cd00f02f9e</ActivityId>
<Progress>50</Progress>
<StatusCode>InProgress</StatusCode>
<StartTime>2014-06-13T22:35:50.884Z</StartTime>
<Cause>At 2014-06-13T22:35:50Z instance i-5b73d709 was moved to standby in response to a user request, shrinking the capacity from 4 to 3.</Cause>
<AutoScalingGroupName>my-asg</AutoScalingGroupName>
<Details>{"Availability Zone":"us-east-1a"}</Details>
<Description>Moving EC2 instance to Standby: i-5b73d709</Description>
</member>
</Activities>
</EnterStandbyResult>
<ResponseMetadata>
<RequestId>126f2f31-f34b-11e3-bc51-b35178f0274f</RequestId>
</ResponseMetadata>
</EnterStandbyResponse>
`
var ExecutePolicyResponse = `
<EnableMetricsCollectionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</EnableMetricsCollectionResponse>
`
var ExitStandbyResponse = `
<ExitStandbyResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ExitStandbyResult>
<Activities>
<member>
<ActivityId>dca4efcf-eea6-4844-8064-cab1fecd1aa2</ActivityId>
<Progress>30</Progress>
<StatusCode>PreInService</StatusCode>
<StartTime>2014-06-13T22:43:53.523Z</StartTime>
<Cause>At 2014-06-13T22:43:53Z instance i-5b73d709 was moved out of standby in response to a user request, increasing the capacity from 3 to 4.</Cause>
<AutoScalingGroupName>my-asg</AutoScalingGroupName>
<Details>{"Availability Zone":"us-east-1a"}</Details>
<Description>Moving EC2 instance out of Standby: i-5b73d709</Description>
</member>
</Activities>
</ExitStandbyResult>
<ResponseMetadata>
<RequestId>321a11c8-f34c-11e3-a434-7f10009d5849</RequestId>
</ResponseMetadata>
</ExitStandbyResponse>
`
var PutLifecycleHookResponse = `
<PutLifecycleHookResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<PutLifecycleHookResult/>
<ResponseMetadata>
<RequestId>1952f458-f645-11e3-bc51-b35178f0274f</RequestId>
</ResponseMetadata>
</PutLifecycleHookResponse>
`
var PutNotificationConfigurationResponse = `
<EnableMetricsCollectionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</EnableMetricsCollectionResponse>
`
var PutScalingPolicyResponse = `
<PutScalingPolicyResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<PutScalingPolicyResult>
<PolicyARN>arn:aws:autoscaling:us-east-1:803981987763:scalingPolicy:b0dcf5e8-02e6-4e31-9719-0675d0dc31ae:autoScalingGroupName/my-test-asg:policyName/my-scaleout-policy</PolicyARN>
</PutScalingPolicyResult>
<ResponseMetadata>
<RequestId>3cfc6fef-c08b-11e2-a697-2922EXAMPLE</RequestId>
</ResponseMetadata>
</PutScalingPolicyResponse>
`
var PutScheduledUpdateGroupActionResponse = `
<PutScheduledUpdateGroupActionResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>3bc8c9bc-6a62-11e2-8a51-4b8a1EXAMPLE</RequestId>
</ResponseMetadata>
</PutScheduledUpdateGroupActionResponse>
`
var ResumeProcessesResponse = `
<ResumeProcessesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</ResumeProcessesResponse>
`
var SetDesiredCapacityResponse = `
<SetDesiredCapacityResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>9fb7e2db-6998-11e2-a985-57c82EXAMPLE</RequestId>
</ResponseMetadata>
</SetDesiredCapacityResponse>
`
var SetInstanceHealthResponse = `
<SetInstanceHealthResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>9fb7e2db-6998-11e2-a985-57c82EXAMPLE</RequestId>
</ResponseMetadata>
</SetInstanceHealthResponse>
`
var SuspendProcessesResponse = `
<SuspendProcessesResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</SuspendProcessesResponse>
`
var TerminateInstanceInAutoScalingGroupResponse = `
<TerminateInstanceInAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<TerminateInstanceInAutoScalingGroupResult>
<Activity>
<StatusCode>InProgress</StatusCode>
<ActivityId>cczc44a87-7d04-dsa15-31-d27c219864c5</ActivityId>
<Progress>0</Progress>
<StartTime>2014-01-26T14:08:30.560Z</StartTime>
<Cause>At 2014-01-26T14:08:30Z instance i-br234123 was taken out of service in response to a user request.</Cause>
<Details>{&quot;Availability Zone&quot;:&quot;us-east-1b&quot;}</Details>
<Description>Terminating EC2 instance: i-br234123</Description>
</Activity>
</TerminateInstanceInAutoScalingGroupResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</TerminateInstanceInAutoScalingGroupResponse>
`
var UpdateAutoScalingGroupResponse = `
<UpdateAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</UpdateAutoScalingGroupResponse>
`

74
vendor/github.com/goamz/goamz/aws/attempt.go сгенерированный поставляемый
Просмотреть файл

@@ -1,74 +0,0 @@
package aws
import (
"time"
)
// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully. This is an internal type used by the
// implementation of other goamz packages.
type AttemptStrategy struct {
Total time.Duration // total duration of attempt.
Delay time.Duration // interval between each try in the burst.
Min int // minimum number of retries; overrides Total
}
type Attempt struct {
strategy AttemptStrategy
last time.Time
end time.Time
force bool
count int
}
// Start begins a new sequence of attempts for the given strategy.
func (s AttemptStrategy) Start() *Attempt {
now := time.Now()
return &Attempt{
strategy: s,
last: now,
end: now.Add(s.Total),
force: true,
}
}
// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
now := time.Now()
sleep := a.nextSleep(now)
if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
return false
}
a.force = false
if sleep > 0 && a.count > 0 {
time.Sleep(sleep)
now = time.Now()
}
a.count++
a.last = now
return true
}
func (a *Attempt) nextSleep(now time.Time) time.Duration {
sleep := a.strategy.Delay - now.Sub(a.last)
if sleep < 0 {
return 0
}
return sleep
}
// HasNext returns whether another attempt will be made if the current
// one fails. If it returns true, the following call to Next is
// guaranteed to return true.
func (a *Attempt) HasNext() bool {
if a.force || a.strategy.Min > a.count {
return true
}
now := time.Now()
if now.Add(a.nextSleep(now)).Before(a.end) {
a.force = true
return true
}
return false
}

58
vendor/github.com/goamz/goamz/aws/attempt_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,58 +0,0 @@
package aws_test
import (
"time"
"github.com/goamz/goamz/aws"
. "gopkg.in/check.v1"
)
func (S) TestAttemptTiming(c *C) {
testAttempt := aws.AttemptStrategy{
Total: 0.25e9,
Delay: 0.1e9,
}
want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9}
got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing
t0 := time.Now()
for a := testAttempt.Start(); a.Next(); {
got = append(got, time.Now().Sub(t0))
}
got = append(got, time.Now().Sub(t0))
c.Assert(got, HasLen, len(want))
const margin = 0.01e9
for i, got := range want {
lo := want[i] - margin
hi := want[i] + margin
if got < lo || got > hi {
c.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds())
}
}
}
func (S) TestAttemptNextHasNext(c *C) {
a := aws.AttemptStrategy{}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, false)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{Total: 2e8}.Start()
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, true)
time.Sleep(2e8)
c.Assert(a.HasNext(), Equals, true)
c.Assert(a.Next(), Equals, true)
c.Assert(a.Next(), Equals, false)
a = aws.AttemptStrategy{Total: 1e8, Min: 2}.Start()
time.Sleep(1e8)
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, true)
c.Assert(a.Next(), Equals, true)
c.Assert(a.HasNext(), Equals, false)
c.Assert(a.Next(), Equals, false)
}

435
vendor/github.com/goamz/goamz/aws/aws.go сгенерированный поставляемый
Просмотреть файл

@@ -1,435 +0,0 @@
//
// goamz - Go packages to interact with the Amazon Web Services.
//
// https://wiki.ubuntu.com/goamz
//
// Copyright (c) 2011 Canonical Ltd.
//
// Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>
//
package aws
import (
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"time"
"github.com/vaughan0/go-ini"
)
// Defines the valid signers
const (
V2Signature = iota
V4Signature = iota
Route53Signature = iota
)
// Defines the service endpoint and correct Signer implementation to use
// to sign requests for this endpoint
type ServiceInfo struct {
Endpoint string
Signer uint
}
// Region defines the URLs where AWS services may be accessed.
//
// See http://goo.gl/d8BP1 for more details.
type Region struct {
Name string // the canonical name of this region.
EC2Endpoint string
S3Endpoint string
S3BucketEndpoint string // Not needed by AWS S3. Use ${bucket} for bucket name.
S3LocationConstraint bool // true if this region requires a LocationConstraint declaration.
S3LowercaseBucket bool // true if the region requires bucket names to be lower case.
SDBEndpoint string
SESEndpoint string
SNSEndpoint string
SQSEndpoint string
IAMEndpoint string
ELBEndpoint string
DynamoDBEndpoint string
CloudWatchServicepoint ServiceInfo
AutoScalingEndpoint string
RDSEndpoint ServiceInfo
STSEndpoint string
CloudFormationEndpoint string
ECSEndpoint string
DynamoDBStreamsEndpoint string
}
var Regions = map[string]Region{
APNortheast.Name: APNortheast,
APNortheast2.Name: APNortheast2,
APSoutheast.Name: APSoutheast,
APSoutheast2.Name: APSoutheast2,
EUCentral.Name: EUCentral,
EUWest.Name: EUWest,
USEast.Name: USEast,
USEast2.Name: USEast2,
USWest.Name: USWest,
USWest2.Name: USWest2,
USGovWest.Name: USGovWest,
SAEast.Name: SAEast,
CNNorth.Name: CNNorth,
}
// Designates a signer interface suitable for signing AWS requests, params
// should be appropriately encoded for the request before signing.
//
// A signer should be initialized with Auth and the appropriate endpoint.
type Signer interface {
Sign(method, path string, params map[string]string)
}
// An AWS Service interface with the API to query the AWS service
//
// Supplied as an easy way to mock out service calls during testing.
type AWSService interface {
// Queries the AWS service at a given method/path with the params and
// returns an http.Response and error
Query(method, path string, params map[string]string) (*http.Response, error)
// Builds an error given an XML payload in the http.Response, can be used
// to process an error if the status code is not 200 for example.
BuildError(r *http.Response) error
}
// Implements a Server Query/Post API to easily query AWS services and build
// errors when desired
type Service struct {
service ServiceInfo
signer Signer
}
// Create a base set of params for an action
func MakeParams(action string) map[string]string {
params := make(map[string]string)
params["Action"] = action
return params
}
// Create a new AWS server to handle making requests
func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
var signer Signer
switch service.Signer {
case V2Signature:
signer, err = NewV2Signer(auth, service)
// case V4Signature:
// signer, err = NewV4Signer(auth, service, Regions["eu-west-1"])
default:
err = fmt.Errorf("Unsupported signer for service")
}
if err != nil {
return
}
s = &Service{service: service, signer: signer}
return
}
func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) {
params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
u, err := url.Parse(s.service.Endpoint)
if err != nil {
return nil, err
}
u.Path = path
s.signer.Sign(method, path, params)
if method == "GET" {
u.RawQuery = multimap(params).Encode()
resp, err = http.Get(u.String())
} else if method == "POST" {
resp, err = http.PostForm(u.String(), multimap(params))
}
return
}
func (s *Service) BuildError(r *http.Response) error {
errors := ErrorResponse{}
xml.NewDecoder(r.Body).Decode(&errors)
var err Error
err = errors.Errors
err.RequestId = errors.RequestId
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
type ErrorResponse struct {
Errors Error `xml:"Error"`
RequestId string // A unique ID for tracking the request
}
type Error struct {
StatusCode int
Type string
Code string
Message string
RequestId string
}
func (err *Error) Error() string {
return fmt.Sprintf("Type: %s, Code: %s, Message: %s",
err.Type, err.Code, err.Message,
)
}
type Auth struct {
AccessKey, SecretKey string
token string
expiration time.Time
}
func (a *Auth) Token() string {
if a.token == "" {
return ""
}
if time.Since(a.expiration) >= -30*time.Second { //in an ideal world this should be zero assuming the instance is synching it's clock
*a, _ = GetAuth("", "", "", time.Time{})
}
return a.token
}
func (a *Auth) Expiration() time.Time {
return a.expiration
}
// To be used with other APIs that return auth credentials such as STS
func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth {
return &Auth{
AccessKey: accessKey,
SecretKey: secretKey,
token: token,
expiration: expiration,
}
}
// ResponseMetadata
type ResponseMetadata struct {
RequestId string // A unique ID for tracking the request
}
type BaseResponse struct {
ResponseMetadata ResponseMetadata
}
var unreserved = make([]bool, 128)
var hex = "0123456789ABCDEF"
func init() {
// RFC3986
u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
for _, c := range u {
unreserved[c] = true
}
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
type credentials struct {
Code string
LastUpdated string
Type string
AccessKeyId string
SecretAccessKey string
Token string
Expiration string
}
// GetMetaData retrieves instance metadata about the current machine.
//
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html for more details.
func GetMetaData(path string) (contents []byte, err error) {
url := "http://169.254.169.254/latest/meta-data/" + path
resp, err := RetryingClient.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return []byte(body), err
}
func getInstanceCredentials() (cred credentials, err error) {
credentialPath := "iam/security-credentials/"
// Get the instance role
role, err := GetMetaData(credentialPath)
if err != nil {
return
}
// Get the instance role credentials
credentialJSON, err := GetMetaData(credentialPath + string(role))
if err != nil {
return
}
err = json.Unmarshal([]byte(credentialJSON), &cred)
return
}
// GetAuth creates an Auth based on either passed in credentials,
// environment information or instance based role credentials.
func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error) {
// First try passed in credentials
if accessKey != "" && secretKey != "" {
return Auth{accessKey, secretKey, token, expiration}, nil
}
// Next try to get auth from the shared credentials file
auth, err = SharedAuth()
if err == nil {
// Found auth, return
return
}
// Next try to get auth from the environment
auth, err = EnvAuth()
if err == nil {
// Found auth, return
return
}
// Next try getting auth from the instance role
cred, err := getInstanceCredentials()
if err == nil {
// Found auth, return
auth.AccessKey = cred.AccessKeyId
auth.SecretKey = cred.SecretAccessKey
auth.token = cred.Token
exptdate, err := time.Parse("2006-01-02T15:04:05Z", cred.Expiration)
if err != nil {
err = fmt.Errorf("Error Parseing expiration date: cred.Expiration :%s , error: %s \n", cred.Expiration, err)
}
auth.expiration = exptdate
return auth, err
}
err = errors.New("No valid AWS authentication found")
return auth, err
}
// EnvAuth creates an Auth based on environment information.
// The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment
// variables are used.
// AWS_SESSION_TOKEN is used if present.
func EnvAuth() (auth Auth, err error) {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
if auth.AccessKey == "" {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY")
}
auth.SecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
if auth.SecretKey == "" {
auth.SecretKey = os.Getenv("AWS_SECRET_KEY")
}
if auth.AccessKey == "" {
err = errors.New("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
}
if auth.SecretKey == "" {
err = errors.New("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
}
auth.token = os.Getenv("AWS_SESSION_TOKEN")
return
}
// SharedAuth creates an Auth based on shared credentials stored in
// $HOME/.aws/credentials. The AWS_PROFILE environment variables is used to
// select the profile.
func SharedAuth() (auth Auth, err error) {
var profileName = os.Getenv("AWS_PROFILE")
if profileName == "" {
profileName = "default"
}
var credentialsFile = os.Getenv("AWS_CREDENTIAL_FILE")
if credentialsFile == "" {
var homeDir = os.Getenv("HOME")
if homeDir == "" {
err = errors.New("Could not get HOME")
return
}
credentialsFile = homeDir + "/.aws/credentials"
}
file, err := ini.LoadFile(credentialsFile)
if err != nil {
err = errors.New("Couldn't parse AWS credentials file")
return
}
var profile = file[profileName]
if profile == nil {
err = errors.New("Couldn't find profile in AWS credentials file")
return
}
auth.AccessKey = profile["aws_access_key_id"]
auth.SecretKey = profile["aws_secret_access_key"]
auth.token = profile["aws_session_token"]
if auth.AccessKey == "" {
err = errors.New("AWS_ACCESS_KEY_ID not found in environment in credentials file")
}
if auth.SecretKey == "" {
err = errors.New("AWS_SECRET_ACCESS_KEY not found in credentials file")
}
return
}
// Encode takes a string and URI-encodes it in a way suitable
// to be used in AWS signatures.
func Encode(s string) string {
encode := false
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
encode = true
break
}
}
if !encode {
return s
}
e := make([]byte, len(s)*3)
ei := 0
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
e[ei] = '%'
e[ei+1] = hex[c>>4]
e[ei+2] = hex[c&0xF]
ei += 3
} else {
e[ei] = c
ei += 1
}
}
return string(e[:ei])
}

211
vendor/github.com/goamz/goamz/aws/aws_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,211 +0,0 @@
package aws_test
import (
"io/ioutil"
"os"
"strings"
"testing"
"time"
"github.com/goamz/goamz/aws"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
environ []string
}
func (s *S) SetUpSuite(c *C) {
s.environ = os.Environ()
}
func (s *S) TearDownTest(c *C) {
os.Clearenv()
for _, kv := range s.environ {
l := strings.SplitN(kv, "=", 2)
os.Setenv(l[0], l[1])
}
}
func (s *S) TestSharedAuthNoHome(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
_, err := aws.SharedAuth()
c.Assert(err, ErrorMatches, "Could not get HOME")
}
func (s *S) TestSharedAuthNoCredentialsFile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
os.Setenv("HOME", "/tmp")
_, err := aws.SharedAuth()
c.Assert(err, ErrorMatches, "Couldn't parse AWS credentials file")
}
func (s *S) TestSharedAuthNoProfileInFile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "foo")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\n"), 0644)
os.Setenv("HOME", d)
_, err = aws.SharedAuth()
c.Assert(err, ErrorMatches, "Couldn't find profile in AWS credentials file")
}
func (s *S) TestSharedAuthNoKeysInProfile(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "bar")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\nawsaccesskeyid = AK.."), 0644)
os.Setenv("HOME", d)
_, err = aws.SharedAuth()
c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY not found in credentials file")
}
func (s *S) TestSharedAuthDefaultCredentials(c *C) {
os.Clearenv()
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[default]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644)
os.Setenv("HOME", d)
auth, err := aws.SharedAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestSharedAuth(c *C) {
os.Clearenv()
os.Setenv("AWS_PROFILE", "bar")
d, err := ioutil.TempDir("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(d)
err = os.Mkdir(d+"/.aws", 0755)
if err != nil {
panic(err)
}
ioutil.WriteFile(d+"/.aws/credentials", []byte("[bar]\naws_access_key_id = access\naws_secret_access_key = secret\n"), 0644)
os.Setenv("HOME", d)
auth, err := aws.SharedAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthNoSecret(c *C) {
os.Clearenv()
_, err := aws.EnvAuth()
c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
}
func (s *S) TestEnvAuthNoAccess(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "foo")
_, err := aws.EnvAuth()
c.Assert(err, ErrorMatches, "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
}
func (s *S) TestEnvAuth(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY_ID", "access")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthAlt(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY", "access")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEnvAuthToken(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY", "access")
os.Setenv("AWS_SESSION_TOKEN", "token")
auth, err := aws.EnvAuth()
c.Assert(err, IsNil)
c.Assert(auth.SecretKey, Equals, "secret")
c.Assert(auth.AccessKey, Equals, "access")
c.Assert(auth.Token(), Equals, "token")
}
func (s *S) TestGetAuthStatic(c *C) {
exptdate := time.Now().Add(time.Hour)
auth, err := aws.GetAuth("access", "secret", "token", exptdate)
c.Assert(err, IsNil)
c.Assert(auth.AccessKey, Equals, "access")
c.Assert(auth.SecretKey, Equals, "secret")
c.Assert(auth.Token(), Equals, "token")
c.Assert(auth.Expiration(), Equals, exptdate)
}
func (s *S) TestGetAuthEnv(c *C) {
os.Clearenv()
os.Setenv("AWS_SECRET_ACCESS_KEY", "secret")
os.Setenv("AWS_ACCESS_KEY_ID", "access")
auth, err := aws.GetAuth("", "", "", time.Time{})
c.Assert(err, IsNil)
c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"})
}
func (s *S) TestEncode(c *C) {
c.Assert(aws.Encode("foo"), Equals, "foo")
c.Assert(aws.Encode("/"), Equals, "%2F")
}
func (s *S) TestRegionsAreNamed(c *C) {
for n, r := range aws.Regions {
c.Assert(n, Equals, r.Name)
}
}

124
vendor/github.com/goamz/goamz/aws/client.go сгенерированный поставляемый
Просмотреть файл

@@ -1,124 +0,0 @@
package aws
import (
"math"
"net"
"net/http"
"time"
)
type RetryableFunc func(*http.Request, *http.Response, error) bool
type WaitFunc func(try int)
type DeadlineFunc func() time.Time
type ResilientTransport struct {
// Timeout is the maximum amount of time a dial will wait for
// a connect to complete.
//
// The default is no timeout.
//
// With or without a timeout, the operating system may impose
// its own earlier timeout. For instance, TCP timeouts are
// often around 3 minutes.
DialTimeout time.Duration
// MaxTries, if non-zero, specifies the number of times we will retry on
// failure. Retries are only attempted for temporary network errors or known
// safe failures.
MaxTries int
Deadline DeadlineFunc
ShouldRetry RetryableFunc
Wait WaitFunc
transport *http.Transport
}
// Convenience method for creating an http client
func NewClient(rt *ResilientTransport) *http.Client {
rt.transport = &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, rt.DialTimeout)
if err != nil {
return nil, err
}
c.SetDeadline(rt.Deadline())
return c, nil
},
Proxy: http.ProxyFromEnvironment,
}
// TODO: Would be nice is ResilientTransport allowed clients to initialize
// with http.Transport attributes.
return &http.Client{
Transport: rt,
}
}
var retryingTransport = &ResilientTransport{
Deadline: func() time.Time {
return time.Now().Add(5 * time.Second)
},
DialTimeout: 10 * time.Second,
MaxTries: 3,
ShouldRetry: awsRetry,
Wait: ExpBackoff,
}
// Exported default client
var RetryingClient = NewClient(retryingTransport)
func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return t.tries(req)
}
// Retry a request a maximum of t.MaxTries times.
// We'll only retry if the proper criteria are met.
// If a wait function is specified, wait that amount of time
// In between requests.
func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) {
for try := 0; try < t.MaxTries; try += 1 {
res, err = t.transport.RoundTrip(req)
if !t.ShouldRetry(req, res, err) {
break
}
if res != nil {
res.Body.Close()
}
if t.Wait != nil {
t.Wait(try)
}
}
return
}
func ExpBackoff(try int) {
time.Sleep(100 * time.Millisecond *
time.Duration(math.Exp2(float64(try))))
}
func LinearBackoff(try int) {
time.Sleep(time.Duration(try*100) * time.Millisecond)
}
// Decide if we should retry a request.
// In general, the criteria for retrying a request is described here
// http://docs.aws.amazon.com/general/latest/gr/api-retries.html
func awsRetry(req *http.Request, res *http.Response, err error) bool {
retry := false
// Retry if there's a temporary network error.
if neterr, ok := err.(net.Error); ok {
if neterr.Temporary() {
retry = true
}
}
// Retry if we get a 5xx series error.
if res != nil {
if res.StatusCode >= 500 && res.StatusCode < 600 {
retry = true
}
}
return retry
}

121
vendor/github.com/goamz/goamz/aws/client_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,121 +0,0 @@
package aws_test
import (
"fmt"
"github.com/goamz/goamz/aws"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
// Retrieve the response from handler using aws.RetryingClient
func serveAndGet(handler http.HandlerFunc) (body string, err error) {
ts := httptest.NewServer(handler)
defer ts.Close()
resp, err := aws.RetryingClient.Get(ts.URL)
if err != nil {
return
}
if resp.StatusCode != 200 {
return "", fmt.Errorf("Bad status code: %d", resp.StatusCode)
}
greeting, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return
}
return strings.TrimSpace(string(greeting)), nil
}
func TestClient_expected(t *testing.T) {
body := "foo bar"
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, body)
})
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.")
}
}
func TestClient_delay(t *testing.T) {
body := "baz"
wait := 4
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
if wait < 0 {
// If we dipped to zero delay and still failed.
t.Fatal("Never succeeded.")
}
wait -= 1
time.Sleep(time.Second * time.Duration(wait))
fmt.Fprintln(w, body)
})
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.", resp)
}
}
func TestClient_no4xxRetry(t *testing.T) {
tries := 0
// Fail once before succeeding.
_, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
tries += 1
http.Error(w, "error", 404)
})
if err == nil {
t.Fatal("should have error")
}
if tries != 1 {
t.Fatalf("should only try once: %d", tries)
}
}
func TestClient_retries(t *testing.T) {
body := "biz"
failed := false
// Fail once before succeeding.
resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
if !failed {
http.Error(w, "error", 500)
failed = true
} else {
fmt.Fprintln(w, body)
}
})
if failed != true {
t.Error("We didn't retry!")
}
if err != nil {
t.Fatal(err)
}
if resp != body {
t.Fatal("Body not as expected.")
}
}
func TestClient_fails(t *testing.T) {
tries := 0
// Fail 3 times and return the last error.
_, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) {
tries += 1
http.Error(w, "error", 500)
})
if err == nil {
t.Fatal(err)
}
if tries != 3 {
t.Fatal("Didn't retry enough")
}
}

29
vendor/github.com/goamz/goamz/aws/export_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,29 +0,0 @@
package aws
import (
"net/http"
"time"
)
// V4Signer:
// Exporting methods for testing
func (s *V4Signer) RequestTime(req *http.Request) time.Time {
return s.requestTime(req)
}
func (s *V4Signer) CanonicalRequest(req *http.Request) string {
return s.canonicalRequest(req)
}
func (s *V4Signer) StringToSign(t time.Time, creq string) string {
return s.stringToSign(t, creq)
}
func (s *V4Signer) Signature(t time.Time, sts string) string {
return s.signature(t, sts)
}
func (s *V4Signer) Authorization(header http.Header, t time.Time, signature string) string {
return s.authorization(header, t, signature)
}

300
vendor/github.com/goamz/goamz/aws/regions.go сгенерированный поставляемый
Просмотреть файл

@@ -1,300 +0,0 @@
package aws
var USGovWest = Region{
"us-gov-west-1",
"https://ec2.us-gov-west-1.amazonaws.com",
"https://s3-fips-us-gov-west-1.amazonaws.com",
"",
true,
true,
"",
"",
"https://sns.us-gov-west-1.amazonaws.com",
"https://sqs.us-gov-west-1.amazonaws.com",
"https://iam.us-gov.amazonaws.com",
"https://elasticloadbalancing.us-gov-west-1.amazonaws.com",
"https://dynamodb.us-gov-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature},
"https://autoscaling.us-gov-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.us-gov-west-1.amazonaws.com",
"https://ecs.us-gov-west-1.amazonaws.com",
"https://streams.dynamodb.us-gov-west-1.amazonaws.com",
}
var USEast = Region{
"us-east-1",
"https://ec2.us-east-1.amazonaws.com",
"https://s3.amazonaws.com",
"",
false,
false,
"https://sdb.amazonaws.com",
"https://email.us-east-1.amazonaws.com",
"https://sns.us-east-1.amazonaws.com",
"https://sqs.us-east-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-east-1.amazonaws.com",
"https://dynamodb.us-east-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature},
"https://autoscaling.us-east-1.amazonaws.com",
ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.us-east-1.amazonaws.com",
"https://ecs.us-east-1.amazonaws.com",
"https://streams.dynamodb.us-east-1.amazonaws.com",
}
var USEast2 = Region{
"us-east-2",
"https://ec2.us-east-2.amazonaws.com",
"https://s3.amazonaws.com",
"",
true,
true,
"",
"",
"https://sns.us-east-2.amazonaws.com",
"https://sqs.us-east-2.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-east-2.amazonaws.com",
"https://dynamodb.us-east-2.amazonaws.com",
ServiceInfo{"https://monitoring.us-east-2.amazonaws.com", V2Signature},
"https://autoscaling.us-east-1.amazonaws.com",
ServiceInfo{"https://rds.us-east-2.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.us-east-2.amazonaws.com",
"https://ecs.us-east-2.amazonaws.com",
"https://streams.dynamodb.us-east-2.amazonaws.com",
}
var USWest = Region{
"us-west-1",
"https://ec2.us-west-1.amazonaws.com",
"https://s3-us-west-1.amazonaws.com",
"",
true,
true,
"https://sdb.us-west-1.amazonaws.com",
"",
"https://sns.us-west-1.amazonaws.com",
"https://sqs.us-west-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-west-1.amazonaws.com",
"https://dynamodb.us-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature},
"https://autoscaling.us-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.us-west-1.amazonaws.com",
"https://ecs.us-west-1.amazonaws.com",
"https://streams.dynamodb.us-west-1.amazonaws.com",
}
var USWest2 = Region{
"us-west-2",
"https://ec2.us-west-2.amazonaws.com",
"https://s3-us-west-2.amazonaws.com",
"",
true,
true,
"https://sdb.us-west-2.amazonaws.com",
"https://email.us-west-2.amazonaws.com",
"https://sns.us-west-2.amazonaws.com",
"https://sqs.us-west-2.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-west-2.amazonaws.com",
"https://dynamodb.us-west-2.amazonaws.com",
ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature},
"https://autoscaling.us-west-2.amazonaws.com",
ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.us-west-2.amazonaws.com",
"https://ecs.us-west-2.amazonaws.com",
"https://streams.dynamodb.us-west-2.amazonaws.com",
}
var EUWest = Region{
"eu-west-1",
"https://ec2.eu-west-1.amazonaws.com",
"https://s3-eu-west-1.amazonaws.com",
"",
true,
true,
"https://sdb.eu-west-1.amazonaws.com",
"https://email.eu-west-1.amazonaws.com",
"https://sns.eu-west-1.amazonaws.com",
"https://sqs.eu-west-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.eu-west-1.amazonaws.com",
"https://dynamodb.eu-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature},
"https://autoscaling.eu-west-1.amazonaws.com",
ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.eu-west-1.amazonaws.com",
"https://ecs.eu-west-1.amazonaws.com",
"https://streams.dynamodb.eu-west-1.amazonaws.com",
}
var EUCentral = Region{
"eu-central-1",
"https://ec2.eu-central-1.amazonaws.com",
"https://s3-eu-central-1.amazonaws.com",
"",
true,
true,
"https://sdb.eu-central-1.amazonaws.com",
"https://email.eu-central-1.amazonaws.com",
"https://sns.eu-central-1.amazonaws.com",
"https://sqs.eu-central-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.eu-central-1.amazonaws.com",
"https://dynamodb.eu-central-1.amazonaws.com",
ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature},
"https://autoscaling.eu-central-1.amazonaws.com",
ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.eu-central-1.amazonaws.com",
"https://ecs.eu-central-1.amazonaws.com",
"https://streams.dynamodb.eu-central-1.amazonaws.com",
}
var APSoutheast = Region{
"ap-southeast-1",
"https://ec2.ap-southeast-1.amazonaws.com",
"https://s3-ap-southeast-1.amazonaws.com",
"",
true,
true,
"https://sdb.ap-southeast-1.amazonaws.com",
"",
"https://sns.ap-southeast-1.amazonaws.com",
"https://sqs.ap-southeast-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-southeast-1.amazonaws.com",
"https://dynamodb.ap-southeast-1.amazonaws.com",
ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature},
"https://autoscaling.ap-southeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.ap-southeast-1.amazonaws.com",
"https://ecs.ap-southeast-1.amazonaws.com",
"https://streams.dynamodb.ap-southeast-1.amazonaws.com",
}
var APSoutheast2 = Region{
"ap-southeast-2",
"https://ec2.ap-southeast-2.amazonaws.com",
"https://s3-ap-southeast-2.amazonaws.com",
"",
true,
true,
"https://sdb.ap-southeast-2.amazonaws.com",
"",
"https://sns.ap-southeast-2.amazonaws.com",
"https://sqs.ap-southeast-2.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-southeast-2.amazonaws.com",
"https://dynamodb.ap-southeast-2.amazonaws.com",
ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature},
"https://autoscaling.ap-southeast-2.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.ap-southeast-2.amazonaws.com",
"https://ecs.ap-southeast-2.amazonaws.com",
"https://streams.dynamodb.ap-southeast-2.amazonaws.com",
}
var APNortheast = Region{
"ap-northeast-1",
"https://ec2.ap-northeast-1.amazonaws.com",
"https://s3-ap-northeast-1.amazonaws.com",
"",
true,
true,
"https://sdb.ap-northeast-1.amazonaws.com",
"",
"https://sns.ap-northeast-1.amazonaws.com",
"https://sqs.ap-northeast-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-northeast-1.amazonaws.com",
"https://dynamodb.ap-northeast-1.amazonaws.com",
ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature},
"https://autoscaling.ap-northeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.ap-northeast-1.amazonaws.com",
"https://ecs.ap-northeast-1.amazonaws.com",
"https://streams.dynamodb.ap-northeast-1.amazonaws.com",
}
var APNortheast2 = Region{
"ap-northeast-2",
"https://ec2.ap-northeast-2.amazonaws.com",
"https://s3-ap-northeast-2.amazonaws.com",
"",
true,
true,
"https://sdb.ap-northeast-2.amazonaws.com",
"",
"https://sns.ap-northeast-2.amazonaws.com",
"https://sqs.ap-northeast-2.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-northeast-2.amazonaws.com",
"https://dynamodb.ap-northeast-2.amazonaws.com",
ServiceInfo{"https://monitoring.ap-northeast-2.amazonaws.com", V2Signature},
"https://autoscaling.ap-northeast-2.amazonaws.com",
ServiceInfo{"https://rds.ap-northeast-2.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.ap-northeast-2.amazonaws.com",
"https://ecs.ap-northeast-2.amazonaws.com",
"https://streams.dynamodb.ap-northeast-2.amazonaws.com",
}
var SAEast = Region{
"sa-east-1",
"https://ec2.sa-east-1.amazonaws.com",
"https://s3-sa-east-1.amazonaws.com",
"",
true,
true,
"https://sdb.sa-east-1.amazonaws.com",
"",
"https://sns.sa-east-1.amazonaws.com",
"https://sqs.sa-east-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.sa-east-1.amazonaws.com",
"https://dynamodb.sa-east-1.amazonaws.com",
ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature},
"https://autoscaling.sa-east-1.amazonaws.com",
ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature},
"https://sts.amazonaws.com",
"https://cloudformation.sa-east-1.amazonaws.com",
"https://ecs.sa-east-1.amazonaws.com",
"https://streams.dynamodb.sa-east-1.amazonaws.com",
}
var CNNorth = Region{
"cn-north-1",
"https://ec2.cn-north-1.amazonaws.com.cn",
"https://s3.cn-north-1.amazonaws.com.cn",
"",
true,
true,
"https://sdb.cn-north-1.amazonaws.com.cn",
"",
"https://sns.cn-north-1.amazonaws.com.cn",
"https://sqs.cn-north-1.amazonaws.com.cn",
"https://iam.cn-north-1.amazonaws.com.cn",
"https://elasticloadbalancing.cn-north-1.amazonaws.com.cn",
"https://dynamodb.cn-north-1.amazonaws.com.cn",
ServiceInfo{"https://monitoring.cn-north-1.amazonaws.com.cn", V4Signature},
"https://autoscaling.cn-north-1.amazonaws.com.cn",
ServiceInfo{"https://rds.cn-north-1.amazonaws.com.cn", V4Signature},
"https://sts.cn-north-1.amazonaws.com.cn",
"https://cloudformation.cn-north-1.amazonaws.com.cn",
"https://ecs.cn-north-1.amazonaws.com.cn",
"https://streams.dynamodb.cn-north-1.amazonaws.com.cn",
}

357
vendor/github.com/goamz/goamz/aws/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,357 +0,0 @@
package aws
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path"
"sort"
"strings"
"time"
)
type V2Signer struct {
auth Auth
service ServiceInfo
host string
}
var b64 = base64.StdEncoding
func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) {
u, err := url.Parse(service.Endpoint)
if err != nil {
return nil, err
}
return &V2Signer{auth: auth, service: service, host: u.Host}, nil
}
func (s *V2Signer) Sign(method, path string, params map[string]string) {
params["AWSAccessKeyId"] = s.auth.AccessKey
params["SignatureVersion"] = "2"
params["SignatureMethod"] = "HmacSHA256"
if s.auth.Token() != "" {
params["SecurityToken"] = s.auth.Token()
}
// AWS specifies that the parameters in a signed request must
// be provided in the natural order of the keys. This is distinct
// from the natural order of the encoded value of key=value.
// Percent and Equals affect the sorting order.
var keys, sarray []string
for k, _ := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
sarray = append(sarray, Encode(k)+"="+Encode(params[k]))
}
joined := strings.Join(sarray, "&")
payload := method + "\n" + s.host + "\n" + path + "\n" + joined
hash := hmac.New(sha256.New, []byte(s.auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}
// Common date formats for signing requests
const (
ISO8601BasicFormat = "20060102T150405Z"
ISO8601BasicFormatShort = "20060102"
)
type Route53Signer struct {
auth Auth
}
func NewRoute53Signer(auth Auth) *Route53Signer {
return &Route53Signer{auth: auth}
}
// getCurrentDate fetches the date stamp from the aws servers to
// ensure the auth headers are within 5 minutes of the server time
func (s *Route53Signer) getCurrentDate() string {
response, err := http.Get("https://route53.amazonaws.com/date")
if err != nil {
fmt.Print("Unable to get date from amazon: ", err)
return ""
}
response.Body.Close()
return response.Header.Get("Date")
}
// Creates the authorize signature based on the date stamp and secret key
func (s *Route53Signer) getHeaderAuthorize(message string) string {
hmacSha256 := hmac.New(sha256.New, []byte(s.auth.SecretKey))
hmacSha256.Write([]byte(message))
cryptedString := hmacSha256.Sum(nil)
return base64.StdEncoding.EncodeToString(cryptedString)
}
// Adds all the required headers for AWS Route53 API to the request
// including the authorization
func (s *Route53Signer) Sign(req *http.Request) {
date := s.getCurrentDate()
authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=%s,Signature=%s",
s.auth.AccessKey, "HmacSHA256", s.getHeaderAuthorize(date))
req.Header.Set("Host", req.Host)
req.Header.Set("X-Amzn-Authorization", authHeader)
req.Header.Set("X-Amz-Date", date)
req.Header.Set("Content-Type", "application/xml")
}
/*
The V4Signer encapsulates all of the functionality to sign a request with the AWS
Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
*/
type V4Signer struct {
auth Auth
serviceName string
region Region
}
/*
Return a new instance of a V4Signer capable of signing AWS requests.
*/
func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer {
return &V4Signer{auth: auth, serviceName: serviceName, region: region}
}
/*
Sign a request according to the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
The signed request will include an "x-amz-date" header with a current timestamp if a valid "x-amz-date"
or "date" header was not available in the original request. In addition, AWS Signature Version 4 requires
the "host" header to be a signed header, therefor the Sign method will manually set a "host" header from
the request.Host.
The signed request will include a new "Authorization" header indicating that the request has been signed.
Any changes to the request after signing the request will invalidate the signature.
*/
func (s *V4Signer) Sign(req *http.Request) {
req.Header.Set("host", req.Host) // host header must be included as a signed header
t := s.requestTime(req) // Get requst time
creq := s.canonicalRequest(req) // Build canonical request
sts := s.stringToSign(t, creq) // Build string to sign
signature := s.signature(t, sts) // Calculate the AWS Signature Version 4
auth := s.authorization(req.Header, t, signature) // Create Authorization header value
req.Header.Set("Authorization", auth) // Add Authorization header to request
return
}
/*
requestTime method will parse the time from the request "x-amz-date" or "date" headers.
If the "x-amz-date" header is present, that will take priority over the "date" header.
If neither header is defined or we are unable to parse either header as a valid date
then we will create a new "x-amz-date" header with the current time.
*/
func (s *V4Signer) requestTime(req *http.Request) time.Time {
// Get "x-amz-date" header
date := req.Header.Get("x-amz-date")
// Attempt to parse as ISO8601BasicFormat
t, err := time.Parse(ISO8601BasicFormat, date)
if err == nil {
return t
}
// Attempt to parse as http.TimeFormat
t, err = time.Parse(http.TimeFormat, date)
if err == nil {
req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
return t
}
// Get "date" header
date = req.Header.Get("date")
// Attempt to parse as http.TimeFormat
t, err = time.Parse(http.TimeFormat, date)
if err == nil {
return t
}
// Create a current time header to be used
t = time.Now().UTC()
req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
return t
}
/*
canonicalRequest method creates the canonical request according to Task 1 of the AWS Signature Version 4 Signing Process. (http://goo.gl/eUUZ3S)
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HexEncode(Hash(Payload))
*/
func (s *V4Signer) canonicalRequest(req *http.Request) string {
c := new(bytes.Buffer)
fmt.Fprintf(c, "%s\n", req.Method)
fmt.Fprintf(c, "%s\n", s.canonicalURI(req.URL))
fmt.Fprintf(c, "%s\n", s.canonicalQueryString(req.URL))
fmt.Fprintf(c, "%s\n\n", s.canonicalHeaders(req.Header))
fmt.Fprintf(c, "%s\n", s.signedHeaders(req.Header))
fmt.Fprintf(c, "%s", s.payloadHash(req))
return c.String()
}
func (s *V4Signer) canonicalURI(u *url.URL) string {
canonicalPath := u.RequestURI()
if u.RawQuery != "" {
canonicalPath = canonicalPath[:len(canonicalPath)-len(u.RawQuery)-1]
}
slash := strings.HasSuffix(canonicalPath, "/")
canonicalPath = path.Clean(canonicalPath)
if canonicalPath != "/" && slash {
canonicalPath += "/"
}
return canonicalPath
}
func (s *V4Signer) canonicalQueryString(u *url.URL) string {
var a []string
for k, vs := range u.Query() {
k = Encode(k)
for _, v := range vs {
if v == "" {
a = append(a, k+"=")
} else {
v = Encode(v)
a = append(a, k+"="+v)
}
}
}
sort.Strings(a)
return strings.Join(a, "&")
}
func (s *V4Signer) canonicalHeaders(h http.Header) string {
i, a := 0, make([]string, len(h))
for k, v := range h {
for j, w := range v {
v[j] = strings.Trim(w, " ")
}
sort.Strings(v)
a[i] = strings.ToLower(k) + ":" + strings.Join(v, ",")
i++
}
sort.Strings(a)
return strings.Join(a, "\n")
}
func (s *V4Signer) signedHeaders(h http.Header) string {
i, a := 0, make([]string, len(h))
for k, _ := range h {
a[i] = strings.ToLower(k)
i++
}
sort.Strings(a)
return strings.Join(a, ";")
}
func (s *V4Signer) payloadHash(req *http.Request) string {
var b []byte
if req.Body == nil {
b = []byte("")
} else {
var err error
b, err = ioutil.ReadAll(req.Body)
if err != nil {
// TODO: I REALLY DON'T LIKE THIS PANIC!!!!
panic(err)
}
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
return s.hash(string(b))
}
/*
stringToSign method creates the string to sign accorting to Task 2 of the AWS Signature Version 4 Signing Process. (http://goo.gl/es1PAu)
StringToSign =
Algorithm + '\n' +
RequestDate + '\n' +
CredentialScope + '\n' +
HexEncode(Hash(CanonicalRequest))
*/
func (s *V4Signer) stringToSign(t time.Time, creq string) string {
w := new(bytes.Buffer)
fmt.Fprint(w, "AWS4-HMAC-SHA256\n")
fmt.Fprintf(w, "%s\n", t.Format(ISO8601BasicFormat))
fmt.Fprintf(w, "%s\n", s.credentialScope(t))
fmt.Fprintf(w, "%s", s.hash(creq))
return w.String()
}
func (s *V4Signer) credentialScope(t time.Time) string {
return fmt.Sprintf("%s/%s/%s/aws4_request", t.Format(ISO8601BasicFormatShort), s.region.Name, s.serviceName)
}
/*
signature method calculates the AWS Signature Version 4 according to Task 3 of the AWS Signature Version 4 Signing Process. (http://goo.gl/j0Yqe1)
signature = HexEncode(HMAC(derived-signing-key, string-to-sign))
*/
func (s *V4Signer) signature(t time.Time, sts string) string {
h := s.hmac(s.derivedKey(t), []byte(sts))
return fmt.Sprintf("%x", h)
}
/*
derivedKey method derives a signing key to be used for signing a request.
kSecret = Your AWS Secret Access Key
kDate = HMAC("AWS4" + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, "aws4_request")
*/
func (s *V4Signer) derivedKey(t time.Time) []byte {
h := s.hmac([]byte("AWS4"+s.auth.SecretKey), []byte(t.Format(ISO8601BasicFormatShort)))
h = s.hmac(h, []byte(s.region.Name))
h = s.hmac(h, []byte(s.serviceName))
h = s.hmac(h, []byte("aws4_request"))
return h
}
/*
authorization method generates the authorization header value.
*/
func (s *V4Signer) authorization(header http.Header, t time.Time, signature string) string {
w := new(bytes.Buffer)
fmt.Fprint(w, "AWS4-HMAC-SHA256 ")
fmt.Fprintf(w, "Credential=%s/%s, ", s.auth.AccessKey, s.credentialScope(t))
fmt.Fprintf(w, "SignedHeaders=%s, ", s.signedHeaders(header))
fmt.Fprintf(w, "Signature=%s", signature)
return w.String()
}
// hash method calculates the sha256 hash for a given string
func (s *V4Signer) hash(in string) string {
h := sha256.New()
fmt.Fprintf(h, "%s", in)
return fmt.Sprintf("%x", h.Sum(nil))
}
// hmac method calculates the sha256 hmac for a given slice of bytes
func (s *V4Signer) hmac(key, data []byte) []byte {
h := hmac.New(sha256.New, key)
h.Write(data)
return h.Sum(nil)
}

540
vendor/github.com/goamz/goamz/aws/sign_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,540 +0,0 @@
package aws_test
import (
"fmt"
"net/http"
"strings"
"time"
"github.com/goamz/goamz/aws"
. "gopkg.in/check.v1"
)
var _ = Suite(&V4SignerSuite{})
type V4SignerSuite struct {
auth aws.Auth
region aws.Region
cases []V4SignerSuiteCase
}
type V4SignerSuiteCase struct {
label string
request V4SignerSuiteCaseRequest
canonicalRequest string
stringToSign string
signature string
authorization string
}
type V4SignerSuiteCaseRequest struct {
method string
host string
url string
headers []string
body string
}
func (s *V4SignerSuite) SetUpSuite(c *C) {
s.auth = aws.Auth{AccessKey: "AKIDEXAMPLE", SecretKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"}
s.region = aws.USEast
// Test cases from the Signature Version 4 Test Suite (http://goo.gl/nguvs0)
s.cases = append(s.cases,
// get-header-key-duplicate
V4SignerSuiteCase{
label: "get-header-key-duplicate",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar", "zoo:foobar", "zoo:zoobar"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:foobar,zoobar,zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3c52f0eaae2b61329c0a332e3fa15842a37bc5812cf4d80eb64784308850e313",
signature: "54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=54afcaaf45b331f81cd2edb974f7b824ff4dd594cbbaa945ed636b48477368ed",
},
// get-header-value-order
V4SignerSuiteCase{
label: "get-header-value-order",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p:z", "p:a", "p:p", "p:a"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:a,a,p,z\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n94c0389fefe0988cbbedc8606f0ca0b485b48da010d09fc844b45b697c8924fe",
signature: "d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=d2973954263943b11624a11d1c963ca81fb274169c7868b2858c04f083199e3d",
},
// get-header-value-trim
V4SignerSuiteCase{
label: "get-header-value-trim",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "p: phfft "},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\np:phfft\n\ndate;host;p\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndddd1902add08da1ac94782b05f9278c08dc7468db178a84f8950d93b30b1f35",
signature: "debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;p, Signature=debf546796015d6f6ded8626f5ce98597c33b47b9164cf6b17b4642036fcb592",
},
// get-relative-relative
V4SignerSuiteCase{
label: "get-relative-relative",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/foo/bar/../..",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// get-relative
V4SignerSuiteCase{
label: "get-relative",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/foo/..",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// get-slash-dot-slash
V4SignerSuiteCase{
label: "get-slash-dot-slash",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/./",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// get-slash-pointless-dot
V4SignerSuiteCase{
label: "get-slash-pointless-dot",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/./foo",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n8021a97572ee460f87ca67f4e8c0db763216d84715f5424a843a5312a3321e2d",
signature: "910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=910e4d6c9abafaf87898e1eb4c929135782ea25bb0279703146455745391e63a",
},
// get-slash
V4SignerSuiteCase{
label: "get-slash",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "//",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// get-slashes
V4SignerSuiteCase{
label: "get-slashes",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "//foo//",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/foo/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6bb4476ee8745730c9cb79f33a0c70baa6d8af29c0077fa12e4e8f1dd17e7098",
signature: "b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b00392262853cfe3201e47ccf945601079e9b8a7f51ee4c3d9ee4f187aa9bf19",
},
// get-space
V4SignerSuiteCase{
label: "get-space",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/%20/foo",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/%20/foo\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n69c45fb9fe3fd76442b5086e50b2e9fec8298358da957b293ef26e506fdfb54b",
signature: "f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f309cfbd10197a230c42dd17dbf5cca8a0722564cb40a872d25623cfa758e374",
},
// get-unreserved
V4SignerSuiteCase{
label: "get-unreserved",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ndf63ee3247c0356c696a3b21f8d8490b01fa9cd5bc6550ef5ef5f4636b7b8901",
signature: "830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=830cc36d03f0f84e6ee4953fbe701c1c8b71a0372c63af9255aa364dd183281e",
},
// get-utf8
V4SignerSuiteCase{
label: "get-utf8",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/%E1%88%B4",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/%E1%88%B4\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n27ba31df5dbc6e063d8f87d62eb07143f7f271c5330a917840586ac1c85b6f6b",
signature: "8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=8d6634c189aa8c75c2e51e106b6b5121bed103fdb351f7d7d4381c738823af74",
},
// get-vanilla-empty-query-key
V4SignerSuiteCase{
label: "get-vanilla-empty-query-key",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?foo=bar",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n0846c2945b0832deb7a463c66af5c4f8bd54ec28c438e67a214445b157c9ddf8",
signature: "56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=56c054473fd260c13e4e7393eb203662195f5d4a1fada5314b8b52b23f985e9f",
},
// get-vanilla-space-query-parameters
V4SignerSuiteCase{
label: "get-vanilla-space-query-parameters",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?foo foo=bar bar",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\nfoo%20foo=bar%20bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n6a81658ae0a0a4f73aa72ca7d3b01c9cb0c5d4099f7a5ee897f5a571bfe6f7ff",
signature: "c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=c8556bc676129d0806ea8fe6ef182dc095666f4c1582c3d9751d47e4306037c9",
},
// get-vanilla-query-order-key-case
V4SignerSuiteCase{
label: "get-vanilla-query-order-key-case",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?foo=Zoo&foo=aha",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\nfoo=Zoo&foo=aha\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ne25f777ba161a0f1baf778a87faf057187cf5987f17953320e3ca399feb5f00d",
signature: "be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=be7148d34ebccdc6423b19085378aa0bee970bdc61d144bd1a8c48c33079ab09",
},
// get-vanilla-query-order-key
V4SignerSuiteCase{
label: "get-vanilla-query-order-key",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?a=foo&b=foo",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\na=foo&b=foo\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n2f23d14fe13caebf6dfda346285c6d9c14f49eaca8f5ec55c627dd7404f7a727",
signature: "0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=0dc122f3b28b831ab48ba65cb47300de53fbe91b577fe113edac383730254a3b",
},
// get-vanilla-query-order-value
V4SignerSuiteCase{
label: "get-vanilla-query-order-value",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?foo=b&foo=a",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\nfoo=a&foo=b\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n33dffc220e89131f8f6157a35c40903daa658608d9129ff9489e5cf5bbd9b11b",
signature: "feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=feb926e49e382bec75c9d7dcb2a1b6dc8aa50ca43c25d2bc51143768c0875acc",
},
// get-vanilla-query-unreserved
V4SignerSuiteCase{
label: "get-vanilla-query-unreserved",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=-._~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nd2578f3156d4c9d180713d1ff20601d8a3eed0dd35447d24603d7d67414bd6b5",
signature: "f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=f1498ddb4d6dae767d97c466fb92f1b59a2c71ca29ac954692663f9db03426fb",
},
// get-vanilla-query
V4SignerSuiteCase{
label: "get-vanilla-query",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// get-vanilla-ut8-query
V4SignerSuiteCase{
label: "get-vanilla-ut8-query",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/?ሴ=bar",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n%E1%88%B4=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nde5065ff39c131e6c2e2bd19cd9345a794bf3b561eab20b8d97b2093fc2a979e",
signature: "6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=6fb359e9a05394cc7074e0feb42573a2601abc0c869a953e8c5c12e4e01f1a8c",
},
// get-vanilla
V4SignerSuiteCase{
label: "get-vanilla",
request: V4SignerSuiteCaseRequest{
method: "GET",
host: "host.foo.com",
url: "/",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "GET\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n366b91fb121d72a00f46bbe8d395f53a102b06dfb7e79636515208ed3fa606b1",
signature: "b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b27ccfbfa7df52a200ff74193ca6e32d4b48b8856fab7ebf1c595d0670a7e470",
},
// post-header-key-case
V4SignerSuiteCase{
label: "post-header-key-case",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4",
signature: "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
},
// post-header-key-sort
V4SignerSuiteCase{
label: "post-header-key-sort",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "ZOO:zoobar"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:zoobar\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n34e1bddeb99e76ee01d63b5e28656111e210529efeec6cdfd46a48e4c734545d",
signature: "b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=b7a95a52518abbca0964a999a880429ab734f35ebbf1235bd79a5de87756dc4a",
},
// post-header-value-case
V4SignerSuiteCase{
label: "post-header-value-case",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"DATE:Mon, 09 Sep 2011 23:36:00 GMT", "zoo:ZOOBAR"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\nzoo:ZOOBAR\n\ndate;host;zoo\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n3aae6d8274b8c03e2cc96fc7d6bda4b9bd7a0a184309344470b2c96953e124aa",
signature: "273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host;zoo, Signature=273313af9d0c265c531e11db70bbd653f3ba074c1009239e8559d3987039cad7",
},
// post-vanilla-empty-query-value
V4SignerSuiteCase{
label: "post-vanilla-empty-query-value",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/?foo=bar",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e",
signature: "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
},
// post-vanilla-query
V4SignerSuiteCase{
label: "post-vanilla-query",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/?foo=bar",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "POST\n/\nfoo=bar\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\ncd4f39132d8e60bb388831d734230460872b564871c47f5de62e62d1a68dbe1e",
signature: "b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=b6e3b79003ce0743a491606ba1035a804593b0efb1e20a11cba83f8c25a57a92",
},
// post-vanilla
V4SignerSuiteCase{
label: "post-vanilla",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"Date:Mon, 09 Sep 2011 23:36:00 GMT"},
},
canonicalRequest: "POST\n/\n\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ndate;host\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n05da62cee468d24ae84faff3c39f1b85540de60243c1bcaace39c0a2acc7b2c4",
signature: "22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=date;host, Signature=22902d79e148b64e7571c3565769328423fe276eae4b26f83afceda9e767f726",
},
// post-x-www-form-urlencoded-parameters
V4SignerSuiteCase{
label: "post-x-www-form-urlencoded-parameters",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"Content-Type:application/x-www-form-urlencoded; charset=utf8", "Date:Mon, 09 Sep 2011 23:36:00 GMT"},
body: "foo=bar",
},
canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded; charset=utf8\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\nc4115f9e54b5cecf192b1eaa23b8e88ed8dc5391bd4fde7b3fff3d9c9fe0af1f",
signature: "b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=b105eb10c6d318d2294de9d49dd8b031b55e3c3fe139f2e637da70511e9e7b71",
},
// post-x-www-form-urlencoded
V4SignerSuiteCase{
label: "post-x-www-form-urlencoded",
request: V4SignerSuiteCaseRequest{
method: "POST",
host: "host.foo.com",
url: "/",
headers: []string{"Content-Type:application/x-www-form-urlencoded", "Date:Mon, 09 Sep 2011 23:36:00 GMT"},
body: "foo=bar",
},
canonicalRequest: "POST\n/\n\ncontent-type:application/x-www-form-urlencoded\ndate:Mon, 09 Sep 2011 23:36:00 GMT\nhost:host.foo.com\n\ncontent-type;date;host\n3ba8907e7a252327488df390ed517c45b96dead033600219bdca7107d1d3f88a",
stringToSign: "AWS4-HMAC-SHA256\n20110909T233600Z\n20110909/us-east-1/host/aws4_request\n4c5c6e4b52fb5fb947a8733982a8a5a61b14f04345cbfe6e739236c76dd48f74",
signature: "5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc",
authorization: "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20110909/us-east-1/host/aws4_request, SignedHeaders=content-type;date;host, Signature=5a15b22cf462f047318703b92e6f4f38884e4a7ab7b1d6426ca46a8bd1c26cbc",
},
)
}
func (s *V4SignerSuite) TestCases(c *C) {
signer := aws.NewV4Signer(s.auth, "host", s.region)
for _, testCase := range s.cases {
req, err := http.NewRequest(testCase.request.method, "http://"+testCase.request.host+testCase.request.url, strings.NewReader(testCase.request.body))
c.Assert(err, IsNil, Commentf("Testcase: %s", testCase.label))
for _, v := range testCase.request.headers {
h := strings.SplitN(v, ":", 2)
req.Header.Add(h[0], h[1])
}
req.Header.Set("host", req.Host)
t := signer.RequestTime(req)
canonicalRequest := signer.CanonicalRequest(req)
c.Check(canonicalRequest, Equals, testCase.canonicalRequest, Commentf("Testcase: %s", testCase.label))
stringToSign := signer.StringToSign(t, canonicalRequest)
c.Check(stringToSign, Equals, testCase.stringToSign, Commentf("Testcase: %s", testCase.label))
signature := signer.Signature(t, stringToSign)
c.Check(signature, Equals, testCase.signature, Commentf("Testcase: %s", testCase.label))
authorization := signer.Authorization(req.Header, t, signature)
c.Check(authorization, Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label))
signer.Sign(req)
c.Check(req.Header.Get("Authorization"), Equals, testCase.authorization, Commentf("Testcase: %s", testCase.label))
}
}
func ExampleV4Signer() {
// Get auth from env vars
auth, err := aws.EnvAuth()
if err != nil {
fmt.Println(err)
}
// Create a signer with the auth, name of the service, and aws region
signer := aws.NewV4Signer(auth, "dynamodb", aws.USEast)
// Create a request
req, err := http.NewRequest("POST", aws.USEast.DynamoDBEndpoint, strings.NewReader("sample_request"))
if err != nil {
fmt.Println(err)
}
// Date or x-amz-date header is required to sign a request
req.Header.Add("Date", time.Now().UTC().Format(http.TimeFormat))
// Sign the request
signer.Sign(req)
// Issue signed request
http.DefaultClient.Do(req)
}

837
vendor/github.com/goamz/goamz/cloudformation/cloudformation.go сгенерированный поставляемый
Просмотреть файл

@@ -1,837 +0,0 @@
//
// cloudformation: This package provides types and functions to interact with the AWS CloudFormation API
//
// Depends on https://github.com/goamz/goamz
//
package cloudformation
import (
"encoding/xml"
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"strings"
"time"
"github.com/goamz/goamz/aws"
)
// The CloudFormation type encapsulates operations within a specific EC2 region.
type CloudFormation struct {
aws.Auth
aws.Region
}
// New creates a new CloudFormation Client.
func New(auth aws.Auth, region aws.Region) *CloudFormation {
return &CloudFormation{auth, region}
}
const debug = false
// ----------------------------------------------------------------------------
// Request dispatching logic.
// Error encapsulates an error returned by the AWS CloudFormation API.
//
// See http://goo.gl/zDZbuQ for more details.
type Error struct {
// HTTP status code (200, 403, ...)
StatusCode int
// Error type
Type string `xml:"Type"`
// CloudFormation error code
Code string `xml:"Code"`
// The human-oriented error message
Message string `xml:"Message"`
RequestId string `xml:"RequestID"`
}
func (err *Error) Error() string {
if err.Code == "" {
return err.Message
}
return fmt.Sprintf("%s (%s)", err.Message, err.Code)
}
type xmlErrors struct {
RequestId string `xml:"RequestId"`
Errors []Error `xml:"Error"`
}
func (c *CloudFormation) query(params map[string]string, resp interface{}) error {
params["Version"] = "2010-05-15"
data := strings.NewReader(multimap(params).Encode())
hreq, err := http.NewRequest("POST", c.Region.CloudFormationEndpoint+"/", data)
if err != nil {
return err
}
hreq.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
token := c.Auth.Token()
if token != "" {
hreq.Header.Set("X-Amz-Security-Token", token)
}
signer := aws.NewV4Signer(c.Auth, "cloudformation", c.Region)
signer.Sign(hreq)
if debug {
log.Printf("%v -> {\n", hreq)
}
r, err := http.DefaultClient.Do(hreq)
if err != nil {
log.Printf("Error calling Amazon")
return err
}
defer r.Body.Close()
if debug {
dump, _ := httputil.DumpResponse(r, true)
log.Printf("response:\n")
log.Printf("%v\n}\n", string(dump))
}
if r.StatusCode != 200 {
return buildError(r)
}
err = xml.NewDecoder(r.Body).Decode(resp)
return err
}
func buildError(r *http.Response) error {
var (
err Error
errors xmlErrors
)
xml.NewDecoder(r.Body).Decode(&errors)
if len(errors.Errors) > 0 {
err = errors.Errors[0]
}
err.RequestId = errors.RequestId
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
func makeParams(action string) map[string]string {
params := make(map[string]string)
params["Action"] = action
return params
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
// addParamsList adds params in the form of param.member.N to the params map
func addParamsList(params map[string]string, label string, ids []string) {
for i, id := range ids {
params[label+"."+strconv.Itoa(i+1)] = id
}
}
// -----------------------------------------------------------------------
// API Supported Types and Methods
// SimpleResp is the basic response from most actions.
type SimpleResp struct {
XMLName xml.Name
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// CancelUpdateStack cancels an update on the specified stack.
// If the call completes successfully, the stack will roll back the update and revert
// to the previous stack configuration.
//
// See http://goo.gl/ZE6fOa for more details
func (c *CloudFormation) CancelUpdateStack(stackName string) (resp *SimpleResp, err error) {
params := makeParams("CancelUpdateStack")
params["StackName"] = stackName
resp = new(SimpleResp)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Parameter encapsulates the cloudstack paramter data type
//
// See http://goo.gl/2rg9eG for more details
type Parameter struct {
ParameterKey string `xml:"ParameterKey"`
ParameterValue string `xml:"ParameterValue"`
UsePreviousValue bool `xml:"UsePreviousValue"`
}
type Tag struct {
Key string `xml:"Key"`
Value string `xml:"Value"`
}
// CreateStackParams wraps CreateStack request options
//
// See http://goo.gl/yDZYuV for more information
type CreateStackParams struct {
Capabilities []string
DisableRollback bool
NotificationARNs []string
OnFailure string
Parameters []Parameter
StackName string
StackPolicyBody string
StackPolicyURL string
Tags []Tag
TemplateBody string
TemplateURL string
TimeoutInMinutes int
}
// CreateStackResponse wraps a CreateStack call response
//
// See http://goo.gl/yDZYuV for more details
type CreateStackResponse struct {
StackId string `xml:"CreateStackResult>StackId"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// CreateStack creates a stack as specified in the template. After the call completes successfully,
// the stack creation starts.
//
// Required params: StackName
//
// See http://goo.gl/yDZYuV for more details
func (c *CloudFormation) CreateStack(options *CreateStackParams) (
resp *CreateStackResponse, err error) {
params := makeParams("CreateStack")
params["StackName"] = options.StackName
if options.DisableRollback {
params["DisableRollback"] = strconv.FormatBool(options.DisableRollback)
}
if options.OnFailure != "" {
params["OnFailure"] = options.OnFailure
}
if options.StackPolicyBody != "" {
params["StackPolicyBody"] = options.StackPolicyBody
}
if options.StackPolicyURL != "" {
params["StackPolicyURL"] = options.StackPolicyURL
}
if options.TemplateBody != "" {
params["TemplateBody"] = options.TemplateBody
}
if options.TemplateURL != "" {
params["TemplateURL"] = options.TemplateURL
}
if options.TimeoutInMinutes != 0 {
params["TimeoutInMinutes"] = strconv.Itoa(options.TimeoutInMinutes)
}
if len(options.Capabilities) > 0 {
addParamsList(params, "Capabilities.member", options.Capabilities)
}
if len(options.NotificationARNs) > 0 {
addParamsList(params, "NotificationARNs.member", options.NotificationARNs)
}
// Add any parameters
for i, t := range options.Parameters {
key := "Parameters.member.%d.%s"
index := i + 1
params[fmt.Sprintf(key, index, "ParameterKey")] = t.ParameterKey
params[fmt.Sprintf(key, index, "ParameterValue")] = t.ParameterValue
params[fmt.Sprintf(key, index, "UsePreviousValue")] = strconv.FormatBool(t.UsePreviousValue)
}
// Add any tags
for i, t := range options.Tags {
key := "Tags.member.%d.%s"
index := i + 1
params[fmt.Sprintf(key, index, "Key")] = t.Key
params[fmt.Sprintf(key, index, "Value")] = t.Value
}
resp = new(CreateStackResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// DeleteStack deletes a specified stack.
// Once the call completes successfully, stack deletion starts.
//
// See http://goo.gl/CVMpxC for more details
func (c *CloudFormation) DeleteStack(stackName string) (resp *SimpleResp, err error) {
params := makeParams("DeleteStack")
params["StackName"] = stackName
resp = new(SimpleResp)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// StackEvent encapsulates the StackEvent data type
//
// See http://goo.gl/EHwiMf for more details
type StackEvent struct {
EventId string `xml:"EventId"`
LogicalResourceId string `xml:"LogicalResourceId"`
PhysicalResourceId string `xml:"PhysicalResourceId"`
ResourceProperties string `xml:"ResourceProperties"`
ResourceStatus string `xml:"ResourceStatus"`
ResourceStatusReason string `xml:"ResourceStatusReason"`
ResourceType string `xml:"ResourceType"`
StackId string `xml:"StackId"`
StackName string `xml:"StackName"`
Timestamp time.Time `xml:"Timestamp"`
}
// DescribeStackEventsResponse wraps a response returned by DescribeStackEvents request
//
// See http://goo.gl/zqj4Bz for more details
type DescribeStackEventsResponse struct {
NextToken string `xml:"DescribeStackEventsResult>NextToken"`
StackEvents []StackEvent `xml:"DescribeStackEventsResult>StackEvents>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// DescribeStackEvents returns all stack related events for a specified stack.
//
// See http://goo.gl/zqj4Bz for more details
func (c *CloudFormation) DescribeStackEvents(stackName string, nextToken string) (
resp *DescribeStackEventsResponse, err error) {
params := makeParams("DescribeStackEvents")
if stackName != "" {
params["StackName"] = stackName
}
if nextToken != "" {
params["NextToken"] = nextToken
}
resp = new(DescribeStackEventsResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// StackResourceDetail encapsulates the StackResourceDetail data type
//
// See http://goo.gl/flce6I for more details
type StackResourceDetail struct {
Description string `xml:"Description"`
LastUpdatedTimestamp time.Time `xml:"LastUpdatedTimestamp"`
LogicalResourceId string `xml:"LogicalResourceId"`
Metadata string `xml:"Metadata"`
PhysicalResourceId string `xml:"PhysicalResourceId"`
ResourceStatus string `xml:"ResourceStatus"`
ResourceStatusReason string `xml:"ResourceStatusReason"`
ResourceType string `xml:"ResourceType"`
StackId string `xml:"StackId"`
StackName string `xml:"StackName"`
}
// DescribeStackResourceResponse wraps a response returned by DescribeStackResource request
//
// See http://goo.gl/6pfPFs for more details
type DescribeStackResourceResponse struct {
StackResourceDetail StackResourceDetail `xml:"DescribeStackResourceResult>StackResourceDetail"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// DescribeStackResource returns a description of the specified resource in the specified stack.
// For deleted stacks, DescribeStackResource returns resource information
// for up to 90 days after the stack has been deleted.
//
// Required params: stackName, logicalResourceId
//
// See http://goo.gl/6pfPFs for more details
func (c *CloudFormation) DescribeStackResource(stackName string, logicalResourceId string) (
resp *DescribeStackResourceResponse, err error) {
params := makeParams("DescribeStackResource")
params["StackName"] = stackName
params["LogicalResourceId"] = logicalResourceId
resp = new(DescribeStackResourceResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// StackResource encapsulates the StackResource data type
//
// See http://goo.gl/j4eli5 for more details
type StackResource struct {
Description string `xml:"Description"`
LogicalResourceId string `xml:"LogicalResourceId"`
PhysicalResourceId string `xml:"PhysicalResourceId"`
ResourceStatus string `xml:"ResourceStatus"`
ResourceStatusReason string `xml:"ResourceStatusReason"`
ResourceType string `xml:"ResourceType"`
StackId string `xml:"StackId"`
StackName string `xml:"StackName"`
Timestamp time.Time `xml:"Timestamp"`
}
// DescribeStackResourcesResponse wraps a response returned by DescribeStackResources request
//
// See http://goo.gl/YnY5rs for more details
type DescribeStackResourcesResponse struct {
StackResources []StackResource `xml:"DescribeStackResourcesResult>StackResources>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// DescribeStackResources returns AWS resource descriptions for running and deleted stacks.
// If stackName is specified, all the associated resources that are part of the stack are returned.
// If physicalResourceId is specified, the associated resources of the stack that the resource
// belongs to are returned.
//
// Only the first 100 resources will be returned. If your stack has more resources than this,
// you should use ListStackResources instead.
//
// See http://goo.gl/YnY5rs for more details
func (c *CloudFormation) DescribeStackResources(stackName, physicalResourceId, logicalResourceId string) (
resp *DescribeStackResourcesResponse, err error) {
params := makeParams("DescribeStackResources")
if stackName != "" {
params["StackName"] = stackName
}
if physicalResourceId != "" {
params["PhysicalResourceId"] = physicalResourceId
}
if logicalResourceId != "" {
params["LogicalResourceId"] = logicalResourceId
}
resp = new(DescribeStackResourcesResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Output encapsulates the Output AWS data type
//
// See http://goo.gl/UOn7q6 for more information
type Output struct {
Description string `xml:"Description"`
OutputKey string `xml:"OutputKey"`
OutputValue string `xml:"OutputValue"`
}
// Stack encapsulates the Stack AWS data type
//
// See http://goo.gl/yDZYuV for more information
type Stack struct {
Capabilities []string `xml:"Capabilities>member"`
CreationTime time.Time `xml:"CreationTime"`
Description string `xml:"Description"`
DisableRollback bool `xml:"DisableRollback"`
LastUpdatedTime time.Time `xml:"LastUpdatedTime"`
NotificationARNs []string `xml:"NotificationARNs>member"`
Outputs []Output `xml:"Outputs>member"`
Parameters []Parameter `xml:"Parameters>member"`
StackId string `xml:"StackId"`
StackName string `xml:"StackName"`
StackStatus string `xml:"StackStatus"`
StackStatusReason string `xml:"StackStatusReason"`
Tags []Tag `xml:"Tags>member"`
TimeoutInMinutes int `xml:"TimeoutInMinutes"`
}
// DescribeStacksResponse wraps a response returned by DescribeStacks request
//
// See http://goo.gl/UOLsXD for more information
type DescribeStacksResponse struct {
NextToken string `xml:"DescribeStacksResult>NextToken"`
Stacks []Stack `xml:"DescribeStacksResult>Stacks>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// DescribeStacks returns the description for the specified stack;
// If no stack name was specified, then it returns the description for all the stacks created.
//
// See http://goo.gl/UOLsXD for more information
func (c *CloudFormation) DescribeStacks(stackName string, nextToken string) (
resp *DescribeStacksResponse, err error) {
params := makeParams("DescribeStacks")
if stackName != "" {
params["StackName"] = stackName
}
if nextToken != "" {
params["NextToken"] = nextToken
}
resp = new(DescribeStacksResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// EstimateTemplateCostResponse wraps a response returned by EstimateTemplateCost request
//
// See http://goo.gl/PD9hle for more information
type EstimateTemplateCostResponse struct {
Url string `xml:"EstimateTemplateCostResult>Url"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// EstimateTemplateCost returns the estimated monthly cost of a template.
// The return value is an AWS Simple Monthly Calculator URL with a query string that describes
// the resources required to run the template.
//
// See http://goo.gl/PD9hle for more information
func (c *CloudFormation) EstimateTemplateCost(parameters []Parameter, templateBody, templateUrl string) (
resp *EstimateTemplateCostResponse, err error) {
params := makeParams("EstimateTemplateCost")
if templateBody != "" {
params["TemplateBody"] = templateBody
}
if templateUrl != "" {
params["TemplateURL"] = templateUrl
}
// Add any parameters
for i, t := range parameters {
key := "Parameters.member.%d.%s"
index := i + 1
params[fmt.Sprintf(key, index, "ParameterKey")] = t.ParameterKey
params[fmt.Sprintf(key, index, "ParameterValue")] = t.ParameterValue
params[fmt.Sprintf(key, index, "UsePreviousValue")] = strconv.FormatBool(t.UsePreviousValue)
}
resp = new(EstimateTemplateCostResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// GetStackPolicyResponse wraps a response returned by GetStackPolicy request
//
// See http://goo.gl/iZFSgy for more information
type GetStackPolicyResponse struct {
StackPolicyBody string `xml:"GetStackPolicyResult>StackPolicyBody"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// GetStackPolicy returns the stack policy for a specified stack. If a stack doesn't have a policy,
// a null value is returned.
//
// See http://goo.gl/iZFSgy for more information
func (c *CloudFormation) GetStackPolicy(stackName string) (
resp *GetStackPolicyResponse, err error) {
params := makeParams("GetStackPolicy")
params["StackName"] = stackName
resp = new(GetStackPolicyResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// GetTemplateResponse wraps a response returned by GetTemplate request
//
// See http://goo.gl/GU59CB for more information
type GetTemplateResponse struct {
TemplateBody string `xml:"GetTemplateResult>TemplateBody"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// GetTemplate returns the template body for a specified stack.
// You can get the template for running or deleted stacks
//
// Required Params: StackName - The name or the unique identifier associated with the stack,
// which are not always interchangeable:
// Running stacks: You can specify either the stack's name or its unique stack ID.
// Deleted stacks: You must specify the unique stack ID.
//
// See http://goo.gl/GU59CB for more information
func (c *CloudFormation) GetTemplate(stackName string) (
resp *GetTemplateResponse, err error) {
params := makeParams("GetTemplate")
params["StackName"] = stackName
resp = new(GetTemplateResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// StackResourceSummary encapsulates the StackResourceSummary data type
//
// See http://goo.gl/Af0vcm for more details
type StackResourceSummary struct {
LastUpdatedTimestamp time.Time `xml:"LastUpdatedTimestamp"`
LogicalResourceId string `xml:"LogicalResourceId"`
PhysicalResourceId string `xml:"PhysicalResourceId"`
ResourceStatus string `xml:"ResourceStatus"`
ResourceStatusReason string `xml:"ResourceStatusReason"`
ResourceType string `xml:"ResourceType"`
}
// ListStackResourcesResponse wraps a response returned by ListStackResources request
//
// See http://goo.gl/JUCgLf for more details
type ListStackResourcesResponse struct {
NextToken string `xml:"ListStackResourcesResult>NextToken"`
StackResourceSummaries []StackResourceSummary `xml:"ListStackResourcesResult>StackResourceSummaries>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// ListStackResources returns descriptions of all resources of the specified stack.
// For deleted stacks, ListStackResources returns resource information for up to 90 days
// after the stack has been deleted.
//
// Required Params: stackName - the name or the unique identifier associated with the stack,
// which are not always interchangeable:
// Running stacks: You can specify either the stack's name or its unique stack ID.
// Deleted stacks: You must specify the unique stack ID.
//
// See http://goo.gl/JUCgLf for more details
func (c *CloudFormation) ListStackResources(stackName, nextToken string) (
resp *ListStackResourcesResponse, err error) {
params := makeParams("ListStackResources")
params["StackName"] = stackName
if nextToken != "" {
params["NextToken"] = nextToken
}
resp = new(ListStackResourcesResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// StackSummary encapsulates the StackSummary data type
//
// See http://goo.gl/35j3wf for more details
type StackSummary struct {
CreationTime time.Time `xml:"CreationTime"`
DeletionTime time.Time `xml:"DeletionTime"`
LastUpdatedTime time.Time `xml:"LastUpdatedTime"`
StackId string `xml:"StackId"`
StackName string `xml:"StackName"`
StackStatus string `xml:"StackStatus"`
StackStatusReason string `xml:"StackStatusReason"`
TemplateDescription string `xml:"TemplateDescription"`
}
// ListStacksResponse wraps a response returned by ListStacks request
//
// See http://goo.gl/UWi6nm for more details
type ListStacksResponse struct {
NextToken string `xml:"ListStacksResult>NextToken"`
StackSummaries []StackSummary `xml:"ListStacksResult>StackSummaries>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// ListStacks Returns the summary information for stacks whose status matches the specified StackStatusFilter.
// Summary information for stacks that have been deleted is kept for 90 days after the stack is deleted.
// If no StackStatusFilter is specified, summary information for all stacks is returned
// (including existing stacks and stacks that have been deleted).
//
// See http://goo.gl/UWi6nm for more details
func (c *CloudFormation) ListStacks(stackStatusFilters []string, nextToken string) (
resp *ListStacksResponse, err error) {
params := makeParams("ListStacks")
if nextToken != "" {
params["NextToken"] = nextToken
}
if len(stackStatusFilters) > 0 {
addParamsList(params, "StackStatusFilter.member", stackStatusFilters)
}
resp = new(ListStacksResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// SetStackPolicy sets a stack policy for a specified stack.
//
// Required Params: stackName
//
// See http://goo.gl/iY9ohu for more information
func (c *CloudFormation) SetStackPolicy(stackName, stackPolicyBody, stackPolicyUrl string) (
resp *SimpleResp, err error) {
params := makeParams("SetStackPolicy")
params["StackName"] = stackName
if stackPolicyBody != "" {
params["StackPolicyBody"] = stackPolicyBody
}
if stackPolicyUrl != "" {
params["StackPolicyURL"] = stackPolicyUrl
}
resp = new(SimpleResp)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// UpdateStackParams wraps UpdateStack request options
//
// See http://goo.gl/LvkhZq for more information
type UpdateStackParams struct {
Capabilities []string
NotificationARNs []string
Parameters []Parameter
StackName string
StackPolicyBody string
StackPolicyDuringUpdateBody string
StackPolicyDuringUpdateURL string
StackPolicyURL string
TemplateBody string
TemplateURL string
UsePreviousTemplate bool
}
// UpdateStackResponse wraps the UpdateStack call response
//
// See http://goo.gl/LvkhZq for more information
type UpdateStackResponse struct {
StackId string `xml:"UpdateStackResult>StackId"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// UpdateStack updates a stack as specified in the template.
// After the call completes successfully, the stack update starts.
// You can check the status of the stack via the DescribeStacks action.
//
// Required Params: options.StackName
//
// See http://goo.gl/LvkhZq for more information
func (c *CloudFormation) UpdateStack(options *UpdateStackParams) (
resp *UpdateStackResponse, err error) {
params := makeParams("UpdateStack")
params["StackName"] = options.StackName
if options.StackPolicyBody != "" {
params["StackPolicyBody"] = options.StackPolicyBody
}
if options.StackPolicyDuringUpdateBody != "" {
params["StackPolicyDuringUpdateBody"] = options.StackPolicyDuringUpdateBody
}
if options.StackPolicyDuringUpdateURL != "" {
params["StackPolicyDuringUpdateURL"] = options.StackPolicyDuringUpdateURL
}
if options.StackPolicyURL != "" {
params["StackPolicyURL"] = options.StackPolicyURL
}
if options.TemplateBody != "" {
params["TemplateBody"] = options.TemplateBody
}
if options.TemplateURL != "" {
params["TemplateURL"] = options.TemplateURL
}
if options.UsePreviousTemplate {
params["UsePreviousTemplate"] = strconv.FormatBool(options.UsePreviousTemplate)
}
if len(options.Capabilities) > 0 {
addParamsList(params, "Capabilities.member", options.Capabilities)
}
if len(options.NotificationARNs) > 0 {
addParamsList(params, "NotificationARNs.member", options.NotificationARNs)
}
// Add any parameters
for i, t := range options.Parameters {
key := "Parameters.member.%d.%s"
index := i + 1
params[fmt.Sprintf(key, index, "ParameterKey")] = t.ParameterKey
params[fmt.Sprintf(key, index, "ParameterValue")] = t.ParameterValue
params[fmt.Sprintf(key, index, "UsePreviousValue")] = strconv.FormatBool(t.UsePreviousValue)
}
resp = new(UpdateStackResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// TemplateParameter encapsulates the AWS TemplateParameter data type
//
// See http://goo.gl/OBhNzk for more information
type TemplateParameter struct {
DefaultValue string `xml:"DefaultValue"`
Description string `xml:Description"`
NoEcho bool `xml:NoEcho"`
ParameterKey string `xml:ParameterKey"`
}
// ValidateTemplateResponse wraps the ValidateTemplate call response
//
// See http://goo.gl/OBhNzk for more information
type ValidateTemplateResponse struct {
Capabilities []string `xml:"ValidateTemplateResult>Capabilities>member"`
CapabilitiesReason string `xml:"ValidateTemplateResult>CapabilitiesReason"`
Description string `xml:"ValidateTemplateResult>Description"`
Parameters []TemplateParameter `xml:"ValidateTemplateResult>Parameters>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// ValidateTemplate validates a specified template.
//
// See http://goo.gl/OBhNzk for more information
func (c *CloudFormation) ValidateTemplate(templateBody, templateUrl string) (
resp *ValidateTemplateResponse, err error) {
params := makeParams("ValidateTemplate")
if templateBody != "" {
params["TemplateBody"] = templateBody
}
if templateUrl != "" {
params["TemplateURL"] = templateUrl
}
resp = new(ValidateTemplateResponse)
if err := c.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}

653
vendor/github.com/goamz/goamz/cloudformation/cloudformation_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,653 +0,0 @@
package cloudformation_test
import (
"testing"
"time"
. "gopkg.in/check.v1"
"github.com/goamz/goamz/aws"
cf "github.com/goamz/goamz/cloudformation"
"github.com/goamz/goamz/testutil"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
cf *cf.CloudFormation
}
var testServer = testutil.NewHTTPServer()
var mockTest bool
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.cf = cf.New(auth, aws.Region{CloudFormationEndpoint: testServer.URL})
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func (s *S) TestCancelUpdateStack(c *C) {
testServer.Response(200, nil, CancelUpdateStackResponse)
resp, err := s.cf.CancelUpdateStack("foo")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "CancelUpdateStack")
c.Assert(values.Get("StackName"), Equals, "foo")
// Response test
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestCreateStack(c *C) {
testServer.Response(200, nil, CreateStackResponse)
stackParams := &cf.CreateStackParams{
NotificationARNs: []string{"arn:aws:sns:us-east-1:1234567890:my-topic"},
Parameters: []cf.Parameter{
{
ParameterKey: "AvailabilityZone",
ParameterValue: "us-east-1a",
},
},
StackName: "MyStack",
TemplateBody: "[Template Document]",
}
resp, err := s.cf.CreateStack(stackParams)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "CreateStack")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NotificationARNs.member.1"), Equals, "arn:aws:sns:us-east-1:1234567890:my-topic")
c.Assert(values.Get("TemplateBody"), Equals, "[Template Document]")
c.Assert(values.Get("Parameters.member.1.ParameterKey"), Equals, "AvailabilityZone")
c.Assert(values.Get("Parameters.member.1.ParameterValue"), Equals, "us-east-1a")
// Response test
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
c.Assert(resp.StackId, Equals, "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83")
}
func (s *S) TestCreateStackWithInvalidParams(c *C) {
testServer.Response(400, nil, CreateStackWithInvalidParamsResponse)
//testServer.Response(200, nil, DeleteAutoScalingGroupResponse)
cfTemplate := `
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Sample template",
"Parameters" : {
"KeyName" : {
"Description" : "key pair",
"Type" : "String"
}
},
"Resources" : {
"Ec2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"KeyName" : { "Ref" : "KeyName" },
"ImageId" : "ami-7f418316",
"UserData" : { "Fn::Base64" : "80" }
}
}
},
"Outputs" : {
"InstanceId" : {
"Description" : "InstanceId of the newly created EC2 instance",
"Value" : { "Ref" : "Ec2Instance" }
}
}`
stackParams := &cf.CreateStackParams{
Capabilities: []string{"CAPABILITY_IAM"},
DisableRollback: true,
NotificationARNs: []string{
"arn:aws:sns:us-east-1:1234567890:my-topic",
"arn:aws:sns:us-east-1:1234567890:my-topic2",
},
OnFailure: "ROLLBACK",
Parameters: []cf.Parameter{
{
ParameterKey: "AvailabilityZone",
ParameterValue: "us-east-1a",
},
},
StackName: "MyStack",
StackPolicyBody: "{PolicyBody}",
StackPolicyURL: "http://stack-policy-url",
Tags: []cf.Tag{
{
Key: "TagKey",
Value: "TagValue",
},
},
TemplateBody: cfTemplate,
TemplateURL: "http://url",
TimeoutInMinutes: 20,
}
resp, err := s.cf.CreateStack(stackParams)
c.Assert(err, NotNil)
c.Assert(resp, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "CreateStack")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NotificationARNs.member.1"), Equals, "arn:aws:sns:us-east-1:1234567890:my-topic")
c.Assert(values.Get("NotificationARNs.member.2"), Equals, "arn:aws:sns:us-east-1:1234567890:my-topic2")
c.Assert(values.Get("Capabilities.member.1"), Equals, "CAPABILITY_IAM")
c.Assert(values.Get("TemplateBody"), Equals, cfTemplate)
c.Assert(values.Get("TemplateURL"), Equals, "http://url")
c.Assert(values.Get("StackPolicyBody"), Equals, "{PolicyBody}")
c.Assert(values.Get("StackPolicyURL"), Equals, "http://stack-policy-url")
c.Assert(values.Get("OnFailure"), Equals, "ROLLBACK")
c.Assert(values.Get("DisableRollback"), Equals, "true")
c.Assert(values.Get("Tags.member.1.Key"), Equals, "TagKey")
c.Assert(values.Get("Tags.member.1.Value"), Equals, "TagValue")
c.Assert(values.Get("Parameters.member.1.ParameterKey"), Equals, "AvailabilityZone")
c.Assert(values.Get("Parameters.member.1.ParameterValue"), Equals, "us-east-1a")
c.Assert(values.Get("TimeoutInMinutes"), Equals, "20")
// Response test
c.Assert(err.(*cf.Error).RequestId, Equals, "70a76d42-9665-11e2-9fdf-211deEXAMPLE")
c.Assert(err.(*cf.Error).Message, Equals, "Either Template URL or Template Body must be specified.")
c.Assert(err.(*cf.Error).Type, Equals, "Sender")
c.Assert(err.(*cf.Error).Code, Equals, "ValidationError")
c.Assert(err.(*cf.Error).StatusCode, Equals, 400)
}
func (s *S) TestDeleteStack(c *C) {
testServer.Response(200, nil, DeleteStackResponse)
resp, err := s.cf.DeleteStack("foo")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "DeleteStack")
c.Assert(values.Get("StackName"), Equals, "foo")
// Response test
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestDescribeStackEvents(c *C) {
testServer.Response(200, nil, DescribeStackEventsResponse)
resp, err := s.cf.DescribeStackEvents("MyStack", "")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
t1, _ := time.Parse(time.RFC3339, "2010-07-27T22:26:28Z")
t2, _ := time.Parse(time.RFC3339, "2010-07-27T22:27:28Z")
t3, _ := time.Parse(time.RFC3339, "2010-07-27T22:28:28Z")
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "DescribeStackEvents")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NextToken"), Equals, "")
// Response test
expected := &cf.DescribeStackEventsResponse{
StackEvents: []cf.StackEvent{
{
EventId: "Event-1-Id",
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MyStack",
PhysicalResourceId: "MyStack_One",
ResourceType: "AWS::CloudFormation::Stack",
Timestamp: t1,
ResourceStatus: "CREATE_IN_PROGRESS",
ResourceStatusReason: "User initiated",
},
{
EventId: "Event-2-Id",
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MyDBInstance",
PhysicalResourceId: "MyStack_DB1",
ResourceType: "AWS::SecurityGroup",
Timestamp: t2,
ResourceStatus: "CREATE_IN_PROGRESS",
ResourceProperties: "{\"GroupDescription\":...}",
},
{
EventId: "Event-3-Id",
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MySG1",
PhysicalResourceId: "MyStack_SG1",
ResourceType: "AWS::SecurityGroup",
Timestamp: t3,
ResourceStatus: "CREATE_COMPLETE",
},
},
NextToken: "",
RequestId: "4af14eec-350e-11e4-b260-EXAMPLE",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestDescribeStackResource(c *C) {
testServer.Response(200, nil, DescribeStackResourceResponse)
resp, err := s.cf.DescribeStackResource("MyStack", "MyDBInstance")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "DescribeStackResource")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("LogicalResourceId"), Equals, "MyDBInstance")
t, _ := time.Parse(time.RFC3339, "2011-07-07T22:27:28Z")
// Response test
expected := &cf.DescribeStackResourceResponse{
StackResourceDetail: cf.StackResourceDetail{
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MyDBInstance",
PhysicalResourceId: "MyStack_DB1",
ResourceType: "AWS::RDS::DBInstance",
LastUpdatedTimestamp: t,
ResourceStatus: "CREATE_COMPLETE",
},
RequestId: "4af14eec-350e-11e4-b260-EXAMPLE",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestDescribeStackResources(c *C) {
testServer.Response(200, nil, DescribeStackResourcesResponse)
resp, err := s.cf.DescribeStackResources("MyStack", "", "")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
t1, _ := time.Parse(time.RFC3339, "2010-07-27T22:27:28Z")
t2, _ := time.Parse(time.RFC3339, "2010-07-27T22:28:28Z")
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "DescribeStackResources")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("PhysicalResourceId"), Equals, "")
c.Assert(values.Get("LogicalResourceId"), Equals, "")
// Response test
expected := &cf.DescribeStackResourcesResponse{
StackResources: []cf.StackResource{
{
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MyDBInstance",
PhysicalResourceId: "MyStack_DB1",
ResourceType: "AWS::DBInstance",
Timestamp: t1,
ResourceStatus: "CREATE_COMPLETE",
},
{
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
LogicalResourceId: "MyAutoScalingGroup",
PhysicalResourceId: "MyStack_ASG1",
ResourceType: "AWS::AutoScalingGroup",
Timestamp: t2,
ResourceStatus: "CREATE_IN_PROGRESS",
},
},
RequestId: "4af14eec-350e-11e4-b260-EXAMPLE",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestDescribeStacks(c *C) {
testServer.Response(200, nil, DescribeStacksResponse)
resp, err := s.cf.DescribeStacks("MyStack", "")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
t, _ := time.Parse(time.RFC3339, "2010-07-27T22:28:28Z")
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "DescribeStacks")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NextToken"), Equals, "")
// Response test
expected := &cf.DescribeStacksResponse{
Stacks: []cf.Stack{
{
StackId: "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83",
StackName: "MyStack",
Description: "My Description",
Capabilities: []string{"CAPABILITY_IAM"},
NotificationARNs: []string{"arn:aws:sns:region-name:account-name:topic-name"},
Parameters: []cf.Parameter{
{
ParameterKey: "MyKey",
ParameterValue: "MyValue",
},
},
Tags: []cf.Tag{
{
Key: "MyTagKey",
Value: "MyTagValue",
},
},
CreationTime: t,
StackStatus: "CREATE_COMPLETE",
DisableRollback: false,
Outputs: []cf.Output{
{
Description: "ServerUrl",
OutputKey: "StartPage",
OutputValue: "http://my-load-balancer.amazonaws.com:80/index.html",
},
},
},
},
NextToken: "",
RequestId: "4af14eec-350e-11e4-b260-EXAMPLE",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestEstimateTemplateCost(c *C) {
testServer.Response(200, nil, EstimateTemplateCostResponse)
resp, err := s.cf.EstimateTemplateCost(nil, "", "https://s3.amazonaws.com/cloudformation-samples-us-east-1/Drupal_Simple.template")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "EstimateTemplateCost")
c.Assert(values.Get("TemplateBody"), Equals, "")
c.Assert(values.Get("TemplateURL"), Equals, "https://s3.amazonaws.com/cloudformation-samples-us-east-1/Drupal_Simple.template")
// Response test
c.Assert(resp.Url, Equals, "http://calculator.s3.amazonaws.com/calc5.html?key=cf-2e351785-e821-450c-9d58-625e1e1ebfb6")
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestGetStackPolicy(c *C) {
testServer.Response(200, nil, GetStackPolicyResponse)
resp, err := s.cf.GetStackPolicy("MyStack")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "GetStackPolicy")
c.Assert(values.Get("StackName"), Equals, "MyStack")
// Response test
policy := `{
"Statement" : [
{
"Effect" : "Deny",
"Action" : "Update:*",
"Principal" : "*",
"Resource" : "LogicalResourceId/ProductionDatabase"
},
{
"Effect" : "Allow",
"Action" : "Update:*",
"Principal" : "*",
"Resource" : "*"
}
]
}`
c.Assert(resp.StackPolicyBody, Equals, policy)
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestGetTemplate(c *C) {
testServer.Response(200, nil, GetTemplateResponse)
resp, err := s.cf.GetTemplate("MyStack")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "GetTemplate")
c.Assert(values.Get("StackName"), Equals, "MyStack")
// Response test
templateBody := `{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Simple example",
"Resources" : {
"MySQS" : {
"Type" : "AWS::SQS::Queue",
"Properties" : {
}
}
}
}`
c.Assert(resp.TemplateBody, Equals, templateBody)
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestListStackResources(c *C) {
testServer.Response(200, nil, ListStackResourcesResponse)
resp, err := s.cf.ListStackResources("MyStack", "4dad1-32131da-d-31")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "ListStackResources")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NextToken"), Equals, "4dad1-32131da-d-31")
// Response test
t1, _ := time.Parse(time.RFC3339, "2011-06-21T20:15:58Z")
t2, _ := time.Parse(time.RFC3339, "2011-06-21T20:25:57Z")
t3, _ := time.Parse(time.RFC3339, "2011-06-21T20:26:12Z")
t4, _ := time.Parse(time.RFC3339, "2011-06-21T20:28:48Z")
t5, _ := time.Parse(time.RFC3339, "2011-06-21T20:29:06Z")
t6, _ := time.Parse(time.RFC3339, "2011-06-21T20:29:23Z")
expected := &cf.ListStackResourcesResponse{
StackResourceSummaries: []cf.StackResourceSummary{
{
LogicalResourceId: "DBSecurityGroup",
PhysicalResourceId: "gmarcteststack-dbsecuritygroup-1s5m0ez5lkk6w",
ResourceType: "AWS::RDS::DBSecurityGroup",
LastUpdatedTimestamp: t1,
ResourceStatus: "CREATE_COMPLETE",
},
{
LogicalResourceId: "SampleDB",
PhysicalResourceId: "MyStack-sampledb-ycwhk1v830lx",
ResourceType: "AWS::RDS::DBInstance",
LastUpdatedTimestamp: t2,
ResourceStatus: "CREATE_COMPLETE",
},
{
LogicalResourceId: "SampleApplication",
PhysicalResourceId: "MyStack-SampleApplication-1MKNASYR3RBQL",
ResourceType: "AWS::ElasticBeanstalk::Application",
LastUpdatedTimestamp: t3,
ResourceStatus: "CREATE_COMPLETE",
},
{
LogicalResourceId: "SampleEnvironment",
PhysicalResourceId: "myst-Samp-1AGU6ERZX6M3Q",
ResourceType: "AWS::ElasticBeanstalk::Environment",
LastUpdatedTimestamp: t4,
ResourceStatus: "CREATE_COMPLETE",
},
{
LogicalResourceId: "AlarmTopic",
PhysicalResourceId: "arn:aws:sns:us-east-1:803981987763:MyStack-AlarmTopic-SW4IQELG7RPJ",
ResourceType: "AWS::SNS::Topic",
LastUpdatedTimestamp: t5,
ResourceStatus: "CREATE_COMPLETE",
},
{
LogicalResourceId: "CPUAlarmHigh",
PhysicalResourceId: "MyStack-CPUAlarmHigh-POBWQPDJA81F",
ResourceType: "AWS::CloudWatch::Alarm",
LastUpdatedTimestamp: t6,
ResourceStatus: "CREATE_COMPLETE",
},
},
NextToken: "",
RequestId: "2d06e36c-ac1d-11e0-a958-f9382b6eb86b",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestListStacks(c *C) {
testServer.Response(200, nil, ListStacksResponse)
resp, err := s.cf.ListStacks([]string{"CREATE_IN_PROGRESS", "DELETE_COMPLETE"}, "4dad1-32131da-d-31")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "ListStacks")
c.Assert(values.Get("StackStatusFilter.member.1"), Equals, "CREATE_IN_PROGRESS")
c.Assert(values.Get("StackStatusFilter.member.2"), Equals, "DELETE_COMPLETE")
c.Assert(values.Get("NextToken"), Equals, "4dad1-32131da-d-31")
// Response test
c1, _ := time.Parse(time.RFC3339, "2011-05-23T15:47:44Z")
c2, _ := time.Parse(time.RFC3339, "2011-03-05T19:57:58Z")
d2, _ := time.Parse(time.RFC3339, "2011-03-10T16:20:51Z")
expected := &cf.ListStacksResponse{
StackSummaries: []cf.StackSummary{
{
StackId: "arn:aws:cloudformation:us-east-1:1234567:stack/TestCreate1/aaaaa",
StackName: "vpc1",
StackStatus: "CREATE_IN_PROGRESS",
CreationTime: c1,
TemplateDescription: "Creates one EC2 instance and a load balancer.",
},
{
StackId: "arn:aws:cloudformation:us-east-1:1234567:stack/TestDelete2/bbbbb",
StackName: "WP1",
StackStatus: "DELETE_COMPLETE",
CreationTime: c2,
DeletionTime: d2,
TemplateDescription: "A simple basic Cloudformation Template.",
},
},
NextToken: "",
RequestId: "2d06e36c-ac1d-11e0-a958-f9382b6eb86b",
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestSetStackPolicy(c *C) {
testServer.Response(200, nil, SetStackPolicyResponse)
resp, err := s.cf.SetStackPolicy("MyStack", "[Stack Policy Document]", "")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "SetStackPolicy")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("StackPolicyBody"), Equals, "[Stack Policy Document]")
c.Assert(values.Get("StackPolicyUrl"), Equals, "")
// Response test
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
}
func (s *S) TestUpdateStack(c *C) {
testServer.Response(200, nil, UpdateStackResponse)
stackParams := &cf.UpdateStackParams{
Capabilities: []string{"CAPABILITY_IAM"},
NotificationARNs: []string{"arn:aws:sns:us-east-1:1234567890:my-topic"},
StackPolicyBody: "{PolicyBody}",
StackPolicyDuringUpdateBody: "{PolicyDuringUpdateBody}",
Parameters: []cf.Parameter{
{
ParameterKey: "AvailabilityZone",
ParameterValue: "us-east-1a",
},
},
UsePreviousTemplate: true,
StackName: "MyStack",
TemplateBody: "[Template Document]",
}
resp, err := s.cf.UpdateStack(stackParams)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "UpdateStack")
c.Assert(values.Get("StackName"), Equals, "MyStack")
c.Assert(values.Get("NotificationARNs.member.1"), Equals, "arn:aws:sns:us-east-1:1234567890:my-topic")
c.Assert(values.Get("TemplateBody"), Equals, "[Template Document]")
c.Assert(values.Get("Parameters.member.1.ParameterKey"), Equals, "AvailabilityZone")
c.Assert(values.Get("Parameters.member.1.ParameterValue"), Equals, "us-east-1a")
c.Assert(values.Get("Capabilities.member.1"), Equals, "CAPABILITY_IAM")
c.Assert(values.Get("StackPolicyBody"), Equals, "{PolicyBody}")
c.Assert(values.Get("StackPolicyDuringUpdateBody"), Equals, "{PolicyDuringUpdateBody}")
c.Assert(values.Get("UsePreviousTemplate"), Equals, "true")
// Response test
c.Assert(resp.RequestId, Equals, "4af14eec-350e-11e4-b260-EXAMPLE")
c.Assert(resp.StackId, Equals, "arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83")
}
func (s *S) TestValidateTemplate(c *C) {
testServer.Response(200, nil, ValidateTemplateResponse)
resp, err := s.cf.ValidateTemplate("", "http://myTemplateRepository/TemplateOne.template")
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
// Post request test
c.Assert(values.Get("Version"), Equals, "2010-05-15")
c.Assert(values.Get("Action"), Equals, "ValidateTemplate")
c.Assert(values.Get("TemplateURL"), Equals, "http://myTemplateRepository/TemplateOne.template")
c.Assert(values.Get("TemplateBody"), Equals, "")
// Response test
expected := &cf.ValidateTemplateResponse{
Description: "Test",
Capabilities: []string{"CAPABILITY_IAM"},
Parameters: []cf.TemplateParameter{
{
NoEcho: false,
ParameterKey: "InstanceType",
Description: "Type of instance to launch",
DefaultValue: "m1.small",
},
{
NoEcho: false,
ParameterKey: "WebServerPort",
Description: "The TCP port for the Web Server",
DefaultValue: "8888",
},
{
NoEcho: false,
ParameterKey: "KeyName",
Description: "Name of an existing EC2 KeyPair to enable SSH access into the server",
},
},
RequestId: "0be7b6e8-e4a0-11e0-a5bd-9f8d5a7dbc91",
}
c.Assert(resp, DeepEquals, expected)
}

371
vendor/github.com/goamz/goamz/cloudformation/responses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,371 +0,0 @@
package cloudformation_test
var CancelUpdateStackResponse = `
<CancelUpdateStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<CancelUpdateStackResult/>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</CancelUpdateStackResponse>
`
var CreateStackResponse = `
<CreateStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<CreateStackResult>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
</CreateStackResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</CreateStackResponse>
`
var CreateStackWithInvalidParamsResponse = `
<ErrorResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<Error>
<Type>Sender</Type>
<Code>ValidationError</Code>
<Message>Either Template URL or Template Body must be specified.</Message>
</Error>
<RequestId>70a76d42-9665-11e2-9fdf-211deEXAMPLE</RequestId>
</ErrorResponse>
`
var DeleteStackResponse = `
<DeleteStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<DeleteStackResult/>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</DeleteStackResponse>
`
var DescribeStackEventsResponse = `
<DescribeStackEventsResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<DescribeStackEventsResult>
<StackEvents>
<member>
<EventId>Event-1-Id</EventId>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MyStack</LogicalResourceId>
<PhysicalResourceId>MyStack_One</PhysicalResourceId>
<ResourceType>AWS::CloudFormation::Stack</ResourceType>
<Timestamp>2010-07-27T22:26:28Z</Timestamp>
<ResourceStatus>CREATE_IN_PROGRESS</ResourceStatus>
<ResourceStatusReason>User initiated</ResourceStatusReason>
</member>
<member>
<EventId>Event-2-Id</EventId>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MyDBInstance</LogicalResourceId>
<PhysicalResourceId>MyStack_DB1</PhysicalResourceId>
<ResourceType>AWS::SecurityGroup</ResourceType>
<Timestamp>2010-07-27T22:27:28Z</Timestamp>
<ResourceStatus>CREATE_IN_PROGRESS</ResourceStatus>
<ResourceProperties>{"GroupDescription":...}</ResourceProperties>
</member>
<member>
<EventId>Event-3-Id</EventId>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MySG1</LogicalResourceId>
<PhysicalResourceId>MyStack_SG1</PhysicalResourceId>
<ResourceType>AWS::SecurityGroup</ResourceType>
<Timestamp>2010-07-27T22:28:28Z</Timestamp>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
</member>
</StackEvents>
<NextToken/>
</DescribeStackEventsResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeStackEventsResponse>
`
var DescribeStackResourceResponse = `
<DescribeStackResourceResponse>
<DescribeStackResourceResult>
<StackResourceDetail>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MyDBInstance</LogicalResourceId>
<PhysicalResourceId>MyStack_DB1</PhysicalResourceId>
<ResourceType>AWS::RDS::DBInstance</ResourceType>
<LastUpdatedTimestamp>2011-07-07T22:27:28Z</LastUpdatedTimestamp>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
</StackResourceDetail>
</DescribeStackResourceResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeStackResourceResponse>
`
var DescribeStackResourcesResponse = `
<DescribeStackResourcesResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<DescribeStackResourcesResult>
<StackResources>
<member>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MyDBInstance</LogicalResourceId>
<PhysicalResourceId>MyStack_DB1</PhysicalResourceId>
<ResourceType>AWS::DBInstance</ResourceType>
<Timestamp>2010-07-27T22:27:28Z</Timestamp>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
</member>
<member>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackName>MyStack</StackName>
<LogicalResourceId>MyAutoScalingGroup</LogicalResourceId>
<PhysicalResourceId>MyStack_ASG1</PhysicalResourceId>
<ResourceType>AWS::AutoScalingGroup</ResourceType>
<Timestamp>2010-07-27T22:28:28Z</Timestamp>
<ResourceStatus>CREATE_IN_PROGRESS</ResourceStatus>
</member>
</StackResources>
</DescribeStackResourcesResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeStackResourcesResponse>
`
var DescribeStacksResponse = `
<DescribeStacksResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<DescribeStacksResult>
<Stacks>
<member>
<StackName>MyStack</StackName>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
<StackStatusReason/>
<Description>My Description</Description>
<Capabilities>
<member>CAPABILITY_IAM</member>
</Capabilities>
<NotificationARNs>
<member>arn:aws:sns:region-name:account-name:topic-name</member>
</NotificationARNs>
<Parameters>
<member>
<ParameterValue>MyValue</ParameterValue>
<ParameterKey>MyKey</ParameterKey>
</member>
</Parameters>
<Tags>
<member>
<Key>MyTagKey</Key>
<Value>MyTagValue</Value>
</member>
</Tags>
<CreationTime>2010-07-27T22:28:28Z</CreationTime>
<StackStatus>CREATE_COMPLETE</StackStatus>
<DisableRollback>false</DisableRollback>
<Outputs>
<member>
<Description>ServerUrl</Description>
<OutputKey>StartPage</OutputKey>
<OutputValue>http://my-load-balancer.amazonaws.com:80/index.html</OutputValue>
</member>
</Outputs>
</member>
</Stacks>
<NextToken/>
</DescribeStacksResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeStacksResponse>
`
var EstimateTemplateCostResponse = `
<EstimateTemplateCostResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<EstimateTemplateCostResult>
<Url>http://calculator.s3.amazonaws.com/calc5.html?key=cf-2e351785-e821-450c-9d58-625e1e1ebfb6</Url>
</EstimateTemplateCostResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</EstimateTemplateCostResponse>
`
var GetStackPolicyResponse = `
<GetStackPolicyResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<GetStackPolicyResult>
<StackPolicyBody>{
"Statement" : [
{
"Effect" : "Deny",
"Action" : "Update:*",
"Principal" : "*",
"Resource" : "LogicalResourceId/ProductionDatabase"
},
{
"Effect" : "Allow",
"Action" : "Update:*",
"Principal" : "*",
"Resource" : "*"
}
]
}</StackPolicyBody>
</GetStackPolicyResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</GetStackPolicyResponse>
`
var GetTemplateResponse = `
<GetTemplateResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<GetTemplateResult>
<TemplateBody>{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Simple example",
"Resources" : {
"MySQS" : {
"Type" : "AWS::SQS::Queue",
"Properties" : {
}
}
}
}</TemplateBody>
</GetTemplateResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</GetTemplateResponse>
`
var ListStackResourcesResponse = `
<ListStackResourcesResponse>
<ListStackResourcesResult>
<StackResourceSummaries>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>DBSecurityGroup</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:15:58Z</LastUpdatedTimestamp>
<PhysicalResourceId>gmarcteststack-dbsecuritygroup-1s5m0ez5lkk6w</PhysicalResourceId>
<ResourceType>AWS::RDS::DBSecurityGroup</ResourceType>
</member>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>SampleDB</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:25:57Z</LastUpdatedTimestamp>
<PhysicalResourceId>MyStack-sampledb-ycwhk1v830lx</PhysicalResourceId>
<ResourceType>AWS::RDS::DBInstance</ResourceType>
</member>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>SampleApplication</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:26:12Z</LastUpdatedTimestamp>
<PhysicalResourceId>MyStack-SampleApplication-1MKNASYR3RBQL</PhysicalResourceId>
<ResourceType>AWS::ElasticBeanstalk::Application</ResourceType>
</member>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>SampleEnvironment</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:28:48Z</LastUpdatedTimestamp>
<PhysicalResourceId>myst-Samp-1AGU6ERZX6M3Q</PhysicalResourceId>
<ResourceType>AWS::ElasticBeanstalk::Environment</ResourceType>
</member>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>AlarmTopic</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:29:06Z</LastUpdatedTimestamp>
<PhysicalResourceId>arn:aws:sns:us-east-1:803981987763:MyStack-AlarmTopic-SW4IQELG7RPJ</PhysicalResourceId>
<ResourceType>AWS::SNS::Topic</ResourceType>
</member>
<member>
<ResourceStatus>CREATE_COMPLETE</ResourceStatus>
<LogicalResourceId>CPUAlarmHigh</LogicalResourceId>
<LastUpdatedTimestamp>2011-06-21T20:29:23Z</LastUpdatedTimestamp>
<PhysicalResourceId>MyStack-CPUAlarmHigh-POBWQPDJA81F</PhysicalResourceId>
<ResourceType>AWS::CloudWatch::Alarm</ResourceType>
</member>
</StackResourceSummaries>
</ListStackResourcesResult>
<ResponseMetadata>
<RequestId>2d06e36c-ac1d-11e0-a958-f9382b6eb86b</RequestId>
</ResponseMetadata>
</ListStackResourcesResponse>
`
var ListStacksResponse = `
<ListStacksResponse>
<ListStacksResult>
<StackSummaries>
<member>
<StackId>arn:aws:cloudformation:us-east-1:1234567:stack/TestCreate1/aaaaa</StackId>
<StackStatus>CREATE_IN_PROGRESS</StackStatus>
<StackName>vpc1</StackName>
<CreationTime>2011-05-23T15:47:44Z</CreationTime>
<TemplateDescription>Creates one EC2 instance and a load balancer.</TemplateDescription>
</member>
<member>
<StackId>arn:aws:cloudformation:us-east-1:1234567:stack/TestDelete2/bbbbb</StackId>
<StackStatus>DELETE_COMPLETE</StackStatus>
<DeletionTime>2011-03-10T16:20:51Z</DeletionTime>
<StackName>WP1</StackName>
<CreationTime>2011-03-05T19:57:58Z</CreationTime>
<TemplateDescription>A simple basic Cloudformation Template.</TemplateDescription>
</member>
</StackSummaries>
</ListStacksResult>
<ResponseMetadata>
<RequestId>2d06e36c-ac1d-11e0-a958-f9382b6eb86b</RequestId>
</ResponseMetadata>
</ListStacksResponse>
`
var SetStackPolicyResponse = `
<SetStackPolicyResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<SetStackPolicyResponse/>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</SetStackPolicyResponse>
`
var UpdateStackResponse = `
<UpdateStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<UpdateStackResult>
<StackId>arn:aws:cloudformation:us-east-1:123456789:stack/MyStack/aaf549a0-a413-11df-adb3-5081b3858e83</StackId>
</UpdateStackResult>
<ResponseMetadata>
<RequestId>4af14eec-350e-11e4-b260-EXAMPLE</RequestId>
</ResponseMetadata>
</UpdateStackResponse>
`
var ValidateTemplateResponse = `
<ValidateTemplateResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<ValidateTemplateResult>
<Description>Test</Description>
<Capabilities>
<member>CAPABILITY_IAM</member>
</Capabilities>
<Parameters>
<member>
<NoEcho>false</NoEcho>
<ParameterKey>InstanceType</ParameterKey>
<Description>Type of instance to launch</Description>
<DefaultValue>m1.small</DefaultValue>
</member>
<member>
<NoEcho>false</NoEcho>
<ParameterKey>WebServerPort</ParameterKey>
<Description>The TCP port for the Web Server</Description>
<DefaultValue>8888</DefaultValue>
</member>
<member>
<NoEcho>false</NoEcho>
<ParameterKey>KeyName</ParameterKey>
<Description>Name of an existing EC2 KeyPair to enable SSH access into the server</Description>
</member>
</Parameters>
</ValidateTemplateResult>
<ResponseMetadata>
<RequestId>0be7b6e8-e4a0-11e0-a5bd-9f8d5a7dbc91</RequestId>
</ResponseMetadata>
</ValidateTemplateResponse>
`

135
vendor/github.com/goamz/goamz/cloudfront/cloudfront.go сгенерированный поставляемый
Просмотреть файл

@@ -1,135 +0,0 @@
package cloudfront
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strconv"
"strings"
"time"
)
type CloudFront struct {
BaseURL string
keyPairId string
key *rsa.PrivateKey
}
var base64Replacer = strings.NewReplacer("=", "_", "+", "-", "/", "~")
func New(baseurl string, key *rsa.PrivateKey, keyPairId string) *CloudFront {
return &CloudFront{
BaseURL: baseurl,
keyPairId: keyPairId,
key: key,
}
}
type epochTime struct {
EpochTime int64 `json:"AWS:EpochTime"`
}
type condition struct {
DateLessThan epochTime
}
type statement struct {
Resource string
Condition condition
}
type policy struct {
Statement []statement
}
func buildPolicy(resource string, expireTime time.Time) ([]byte, error) {
p := &policy{
Statement: []statement{
statement{
Resource: resource,
Condition: condition{
DateLessThan: epochTime{
EpochTime: expireTime.Truncate(time.Millisecond).Unix(),
},
},
},
},
}
return json.Marshal(p)
}
func (cf *CloudFront) generateSignature(policy []byte) (string, error) {
hash := sha1.New()
if _, err := hash.Write(policy); err != nil {
return "", err
}
hashed := hash.Sum(nil)
signed, err := rsa.SignPKCS1v15(rand.Reader, cf.key, crypto.SHA1, hashed)
if err != nil {
return "", err
}
encoded := base64Replacer.Replace(base64.StdEncoding.EncodeToString(signed))
return encoded, nil
}
// Creates a signed url using RSAwithSHA1 as specified by
// http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html#private-content-canned-policy-creating-signature
func (cf *CloudFront) CannedSignedURL(path, queryString string, expires time.Time) (string, error) {
resource := cf.BaseURL + path
if queryString != "" {
resource = path + "?" + queryString
}
policy, err := buildPolicy(resource, expires)
if err != nil {
return "", err
}
signature, err := cf.generateSignature(policy)
if err != nil {
return "", err
}
// TOOD: Do this once
uri, err := url.Parse(cf.BaseURL)
if err != nil {
return "", err
}
uri.RawQuery = queryString
if queryString != "" {
uri.RawQuery += "&"
}
expireTime := expires.Truncate(time.Millisecond).Unix()
uri.Path = path
uri.RawQuery += fmt.Sprintf("Expires=%d&Signature=%s&Key-Pair-Id=%s", expireTime, signature, cf.keyPairId)
return uri.String(), nil
}
func (cloudfront *CloudFront) SignedURL(path, querystrings string, expires time.Time) string {
policy := `{"Statement":[{"Resource":"` + path + "?" + querystrings + `,"Condition":{"DateLessThan":{"AWS:EpochTime":` + strconv.FormatInt(expires.Truncate(time.Millisecond).Unix(), 10) + `}}}]}`
hash := sha1.New()
hash.Write([]byte(policy))
b := hash.Sum(nil)
he := base64.StdEncoding.EncodeToString(b)
policySha1 := he
url := cloudfront.BaseURL + path + "?" + querystrings + "&Expires=" + strconv.FormatInt(expires.Unix(), 10) + "&Signature=" + policySha1 + "&Key-Pair-Id=" + cloudfront.keyPairId
return url
}

52
vendor/github.com/goamz/goamz/cloudfront/cloudfront_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,52 +0,0 @@
package cloudfront
import (
"crypto/x509"
"encoding/pem"
"io/ioutil"
"net/url"
"testing"
"time"
)
func TestSignedCannedURL(t *testing.T) {
rawKey, err := ioutil.ReadFile("testdata/key.pem")
if err != nil {
t.Fatal(err)
}
pemKey, _ := pem.Decode(rawKey)
privateKey, err := x509.ParsePKCS1PrivateKey(pemKey.Bytes)
if err != nil {
t.Fatal(err)
}
cf := &CloudFront{
key: privateKey,
keyPairId: "test-key-pair-1231245",
BaseURL: "https://cloudfront.com",
}
expireTime, err := time.Parse(time.RFC3339, "2014-03-28T14:00:21Z")
if err != nil {
t.Fatal(err)
}
query := make(url.Values)
query.Add("test", "value")
uri, err := cf.CannedSignedURL("test", "test=value", expireTime)
if err != nil {
t.Fatal(err)
}
parsed, err := url.Parse(uri)
if err != nil {
t.Fatal(err)
}
signature := parsed.Query().Get("Signature")
if signature == "" {
t.Fatal("Encoded signature is empty")
}
}

15
vendor/github.com/goamz/goamz/cloudfront/testdata/key.pem сгенерированный поставляемый
Просмотреть файл

@@ -1,15 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC0yMzp9DkPAE99DhsEaGkqougLvtmDKri4bZj0fFjmGmjyyjz9
hlrsr87LHVWzH/7igK7040HG1UqypX3ijtJa9+6BKHwBBctboU3y4GfwFwVAOumY
9UytFpyPlgUFrffZLQAywKkT24OgcfEj0G5kiQn760wFnmSUtOuITo708QIDAQAB
AoGAJUA6+PoZx72Io3wElSPuh5qJteHdb+mdpmLu4XG936wRc/W4G4VTtvGC6tdg
kUhGfOWHJ26sXwwUGDuBdO146m0DkBTuIooy97afpL6hXgL5v4ELHbbuFJcf4Geg
/UAuexvRT1HenYFQ/iXM0LlqI33i8cFRc1A+j0Gseo07gAECQQDYFCn7OUokX+Q8
M2Cwhu7JT1obmP2HwsBtXl0CDDxtOQkuYJP/UqvtdYPz/kRn3yQjoynaCTHYrFz/
H8oN1nNhAkEA1i9TEpo7RbanIyT4vbc1/5xfjE7Pj0lnGku0QXFp/S+8YxbqhjrQ
4Qp7TTXIPPqvQhhEpAGGspM460K3F6h7kQJBANJCbMeFa9wRY2ohJIkiA+HoUWph
aPNeUxkZpa+EcJhn08NJPzpIG/ypSYl3duEMhYIYF3WPVO3ea2/mYxsr/oECQFj5
td/fdEoEk7AU1sQxDNyPwF2QC8dxbcRNuKcLD0Wfg/oB9hEm88jYytoLQpCabx3c
6P7cp3EdmaKZx2erlRECQDYTSK2tS0+VoXSV9JbU08Pbu53j3Zhmp4l0csP+l7EU
U+rRQzKho4X9vpR/VpRGXbw8tTIhojNpHh5ofryVfgk=
-----END RSA PRIVATE KEY-----

6
vendor/github.com/goamz/goamz/cloudfront/testdata/key.pub сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0yMzp9DkPAE99DhsEaGkqougL
vtmDKri4bZj0fFjmGmjyyjz9hlrsr87LHVWzH/7igK7040HG1UqypX3ijtJa9+6B
KHwBBctboU3y4GfwFwVAOumY9UytFpyPlgUFrffZLQAywKkT24OgcfEj0G5kiQn7
60wFnmSUtOuITo708QIDAQAB
-----END PUBLIC KEY-----

7
vendor/github.com/goamz/goamz/cloudwatch/ChangeLog сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +0,0 @@
2013-10-21 Carlos Salguero <cfsalguero@gmail.com>
* Removed Namespace from the constructor as not all AWS API method needs it
and methods like ListMetrics you could need to call the method without a
Namespace to list all available metrics
* Added ListMetrics method

109
vendor/github.com/goamz/goamz/cloudwatch/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,109 +0,0 @@
#GoLang AWS Cloudwatch
## Installation
Please refer to the project's main page at [https://github.com/goamz/goamz](https://github.com/goamz/goamz) for instructions about how to install.
## Available methods
<table>
<tr>
<td>GetMetricStatistics</td>
<td>Gets statistics for the specified metric.</td>
</tr>
<tr>
<td>ListMetrics</td>
<td>Returns a list of valid metrics stored for the AWS account.</td>
</tr>
<tr>
<td>PutMetricData</td>
<td>Publishes metric data points to Amazon CloudWatch.</td>
</tr>
<tr>
<td>PutMetricAlarm</td>
<td>Creates or updates an alarm and associates it with the specified Amazon CloudWatch metric.</td>
</tr>
</table>
[Please refer to AWS Cloudwatch's documentation for more info](http://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_Operations.html)
##Examples
####Get Metric Statistics
```
import (
"fmt"
"time"
"os"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/cloudwatch"
)
func test_get_metric_statistics() {
region := aws.Regions["a_region"]
namespace:= "AWS/ELB"
dimension := &cloudwatch.Dimension{
Name: "LoadBalancerName",
Value: "your_value",
}
metricName := "RequestCount"
now := time.Now()
prev := now.Add(time.Duration(600)*time.Second*-1) // 600 secs = 10 minutes
auth, err := aws.GetAuth("your_AccessKeyId", "your_SecretAccessKey", "", now)
if err != nil {
fmt.Printf("Error: %+v\n", err)
os.Exit(1)
}
cw, err := cloudwatch.NewCloudWatch(auth, region.CloudWatchServicepoint)
request := &cloudwatch.GetMetricStatisticsRequest {
Dimensions: []cloudwatch.Dimension{*dimension},
EndTime: now,
StartTime: prev,
MetricName: metricName,
Unit: "Count", // Not mandatory
Period: 60,
Statistics: []string{"Sum"},
Namespace: namespace,
}
response, err := cw.GetMetricStatistics(request)
if err == nil {
fmt.Printf("%+v\n", response)
} else {
fmt.Printf("Error: %+v\n", err)
}
}
```
####List Metrics
```
import (
"fmt"
"time"
"os"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/cloudwatch"
)
func test_list_metrics() {
region := aws.Regions["us-east-1"] // Any region here
now := time.Now()
auth, err := aws.GetAuth("an AccessKeyId", "a SecretAccessKey", "", now)
if err != nil {
fmt.Printf("Error: %+v\n", err)
os.Exit(1)
}
cw, err := cloudwatch.NewCloudWatch(auth, region.CloudWatchServicepoint)
request := &cloudwatch.ListMetricsRequest{Namespace: "AWS/EC2"}
response, err := cw.ListMetrics(request)
if err == nil {
fmt.Printf("%+v\n", response)
} else {
fmt.Printf("Error: %+v\n", err)
}
}
```

404
vendor/github.com/goamz/goamz/cloudwatch/cloudwatch.go сгенерированный поставляемый
Просмотреть файл

@@ -1,404 +0,0 @@
/***** BEGIN LICENSE BLOCK *****
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# The Initial Developer of the Original Code is the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2012
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Ben Bangert (bbangert@mozilla.com)
# Logan Owen (lsowen@s1network.com)
#
# ***** END LICENSE BLOCK *****/
package cloudwatch
import (
"encoding/xml"
"errors"
"fmt"
"github.com/feyeleanor/sets"
"github.com/goamz/goamz/aws"
"strconv"
"time"
)
// The CloudWatch type encapsulates all the CloudWatch operations in a region.
type CloudWatch struct {
Service aws.AWSService
}
type Dimension struct {
Name string
Value string
}
type StatisticSet struct {
Maximum float64
Minimum float64
SampleCount float64
Sum float64
}
type MetricDatum struct {
Dimensions []Dimension
MetricName string
StatisticValues *StatisticSet
Timestamp time.Time
Unit string
Value float64
}
type Datapoint struct {
Average float64
Maximum float64
Minimum float64
SampleCount float64
Sum float64
Timestamp time.Time
Unit string
}
type GetMetricStatisticsRequest struct {
Dimensions []Dimension
EndTime time.Time
StartTime time.Time
MetricName string
Unit string
Period int
Statistics []string
Namespace string
}
type GetMetricStatisticsResult struct {
Datapoints []Datapoint `xml:"Datapoints>member"`
NextToken string `xml:"NextToken"`
}
type GetMetricStatisticsResponse struct {
GetMetricStatisticsResult GetMetricStatisticsResult
ResponseMetadata aws.ResponseMetadata
}
type Metric struct {
Dimensions []Dimension `xml:"Dimensions>member"`
MetricName string
Namespace string
}
type ListMetricsResult struct {
Metrics []Metric `xml:"Metrics>member"`
NextToken string
}
type ListMetricsResponse struct {
ListMetricsResult ListMetricsResult
ResponseMetadata aws.ResponseMetadata
}
type ListMetricsRequest struct {
Dimensions []Dimension
MetricName string
Namespace string
NextToken string
}
type AlarmAction struct {
ARN string
}
type MetricAlarm struct {
AlarmActions []AlarmAction
AlarmDescription string
AlarmName string
ComparisonOperator string
Dimensions []Dimension
EvaluationPeriods int
InsufficientDataActions []AlarmAction
MetricName string
Namespace string
OkActions []AlarmAction
Period int
Statistic string
Threshold float64
Unit string
}
var attempts = aws.AttemptStrategy{
Min: 5,
Total: 5 * time.Second,
Delay: 200 * time.Millisecond,
}
var validUnits = sets.SSet(
"Seconds",
"Microseconds",
"Milliseconds",
"Bytes",
"Kilobytes",
"Megabytes",
"Gigabytes",
"Terabytes",
"Bits",
"Kilobits",
"Megabits",
"Gigabits",
"Terabits",
"Percent",
"Count",
"Bytes/Second",
"Kilobytes/Second",
"Megabytes/Second",
"Gigabytes/Second",
"Terabytes/Second",
"Bits/Second",
"Kilobits/Second",
"Megabits/Second",
"Gigabits/Second",
"Terabits/Second",
"Count/Second",
)
var validMetricStatistics = sets.SSet(
"Average",
"Sum",
"SampleCount",
"Maximum",
"Minimum",
)
var validComparisonOperators = sets.SSet(
"LessThanThreshold",
"LessThanOrEqualToThreshold",
"GreaterThanThreshold",
"GreaterThanOrEqualToThreshold",
)
// Create a new CloudWatch object for a given namespace
func NewCloudWatch(auth aws.Auth, region aws.ServiceInfo) (*CloudWatch, error) {
service, err := aws.NewService(auth, region)
if err != nil {
return nil, err
}
return &CloudWatch{
Service: service,
}, nil
}
func (c *CloudWatch) query(method, path string, params map[string]string, resp interface{}) error {
// Add basic Cloudwatch param
params["Version"] = "2010-08-01"
r, err := c.Service.Query(method, path, params)
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode != 200 {
return c.Service.BuildError(r)
}
err = xml.NewDecoder(r.Body).Decode(resp)
return err
}
// Get statistics for specified metric
//
// If the arguments are invalid or the server returns an error, the error will
// be set and the other values undefined.
func (c *CloudWatch) GetMetricStatistics(req *GetMetricStatisticsRequest) (result *GetMetricStatisticsResponse, err error) {
statisticsSet := sets.SSet(req.Statistics...)
// Kick out argument errors
switch {
case req.EndTime.IsZero():
err = errors.New("No endTime specified")
case req.StartTime.IsZero():
err = errors.New("No startTime specified")
case req.MetricName == "":
err = errors.New("No metricName specified")
case req.Namespace == "":
err = errors.New("No Namespace specified")
case req.Period < 60 || req.Period%60 != 0:
err = errors.New("Period not 60 seconds or a multiple of 60 seconds")
case len(req.Statistics) < 1:
err = errors.New("No statistics supplied")
case validMetricStatistics.Union(statisticsSet).Len() != validMetricStatistics.Len():
err = errors.New("Invalid statistic values supplied")
case req.Unit != "" && !validUnits.Member(req.Unit):
err = errors.New("Unit is not a valid value")
}
if err != nil {
return
}
// Serialize all the params
params := aws.MakeParams("GetMetricStatistics")
params["EndTime"] = req.EndTime.UTC().Format(time.RFC3339)
params["StartTime"] = req.StartTime.UTC().Format(time.RFC3339)
params["MetricName"] = req.MetricName
params["Namespace"] = req.Namespace
params["Period"] = strconv.Itoa(req.Period)
if req.Unit != "" {
params["Unit"] = req.Unit
}
// Serialize the lists of data
for i, d := range req.Dimensions {
prefix := "Dimensions.member." + strconv.Itoa(i+1)
params[prefix+".Name"] = d.Name
params[prefix+".Value"] = d.Value
}
for i, d := range req.Statistics {
prefix := "Statistics.member." + strconv.Itoa(i+1)
params[prefix] = d
}
result = new(GetMetricStatisticsResponse)
err = c.query("GET", "/", params, result)
return
}
// Returns a list of valid metrics stored for the AWS account owner.
// Returned metrics can be used with GetMetricStatistics to obtain statistical data for a given metric.
func (c *CloudWatch) ListMetrics(req *ListMetricsRequest) (result *ListMetricsResponse, err error) {
// Serialize all the params
params := aws.MakeParams("ListMetrics")
if req.Namespace != "" {
params["Namespace"] = req.Namespace
}
if len(req.Dimensions) > 0 {
for i, d := range req.Dimensions {
prefix := "Dimensions.member." + strconv.Itoa(i+1)
params[prefix+".Name"] = d.Name
params[prefix+".Value"] = d.Value
}
}
result = new(ListMetricsResponse)
err = c.query("GET", "/", params, &result)
metrics := result.ListMetricsResult.Metrics
if result.ListMetricsResult.NextToken != "" {
params = aws.MakeParams("ListMetrics")
params["NextToken"] = result.ListMetricsResult.NextToken
for result.ListMetricsResult.NextToken != "" && err == nil {
result = new(ListMetricsResponse)
err = c.query("GET", "/", params, &result)
if err == nil {
newslice := make([]Metric, len(metrics)+len(result.ListMetricsResult.Metrics))
copy(newslice, metrics)
copy(newslice[len(metrics):], result.ListMetricsResult.Metrics)
metrics = newslice
}
}
result.ListMetricsResult.Metrics = metrics
}
return
}
func (c *CloudWatch) PutMetricData(metrics []MetricDatum) (result *aws.BaseResponse, err error) {
return c.PutMetricDataNamespace(metrics, "")
}
func (c *CloudWatch) PutMetricDataNamespace(metrics []MetricDatum, namespace string) (result *aws.BaseResponse, err error) {
// Serialize the params
params := aws.MakeParams("PutMetricData")
if namespace != "" {
params["Namespace"] = namespace
}
for i, metric := range metrics {
prefix := "MetricData.member." + strconv.Itoa(i+1)
if metric.MetricName == "" {
err = fmt.Errorf("No metric name supplied for metric: %d", i)
return
}
params[prefix+".MetricName"] = metric.MetricName
if metric.Unit != "" {
params[prefix+".Unit"] = metric.Unit
}
params[prefix+".Value"] = strconv.FormatFloat(metric.Value, 'E', 10, 64)
if !metric.Timestamp.IsZero() {
params[prefix+".Timestamp"] = metric.Timestamp.UTC().Format(time.RFC3339)
}
for j, dim := range metric.Dimensions {
dimprefix := prefix + ".Dimensions.member." + strconv.Itoa(j+1)
params[dimprefix+".Name"] = dim.Name
params[dimprefix+".Value"] = dim.Value
}
if metric.StatisticValues != nil {
statprefix := prefix + ".StatisticValues"
params[statprefix+".Maximum"] = strconv.FormatFloat(metric.StatisticValues.Maximum, 'E', 10, 64)
params[statprefix+".Minimum"] = strconv.FormatFloat(metric.StatisticValues.Minimum, 'E', 10, 64)
params[statprefix+".SampleCount"] = strconv.FormatFloat(metric.StatisticValues.SampleCount, 'E', 10, 64)
params[statprefix+".Sum"] = strconv.FormatFloat(metric.StatisticValues.Sum, 'E', 10, 64)
}
}
result = new(aws.BaseResponse)
err = c.query("POST", "/", params, result)
return
}
func (c *CloudWatch) PutMetricAlarm(alarm *MetricAlarm) (result *aws.BaseResponse, err error) {
// Serialize the params
params := aws.MakeParams("PutMetricAlarm")
switch {
case alarm.AlarmName == "":
err = errors.New("No AlarmName supplied")
case !validComparisonOperators.Member(alarm.ComparisonOperator):
err = errors.New("ComparisonOperator is not valid")
case alarm.EvaluationPeriods == 0:
err = errors.New("No number of EvaluationPeriods specified")
case alarm.MetricName == "":
err = errors.New("No MetricName specified")
case alarm.Namespace == "":
err = errors.New("No Namespace specified")
case alarm.Period == 0:
err = errors.New("No Period over which statistic should apply was specified")
case !validMetricStatistics.Member(alarm.Statistic):
err = errors.New("Invalid statistic value supplied")
case alarm.Threshold == 0:
err = errors.New("No Threshold value specified")
case alarm.Unit != "" && !validUnits.Member(alarm.Unit):
err = errors.New("Unit is not a valid value")
}
if err != nil {
return
}
for i, action := range alarm.AlarmActions {
params["AlarmActions.member."+strconv.Itoa(i+1)] = action.ARN
}
for i, action := range alarm.InsufficientDataActions {
params["InsufficientDataActions.member."+strconv.Itoa(i+1)] = action.ARN
}
for i, action := range alarm.OkActions {
params["OKActions.member."+strconv.Itoa(i+1)] = action.ARN
}
if alarm.AlarmDescription != "" {
params["AlarmDescription"] = alarm.AlarmDescription
}
params["AlarmDescription"] = alarm.AlarmDescription
params["AlarmName"] = alarm.AlarmName
params["ComparisonOperator"] = alarm.ComparisonOperator
for i, dim := range alarm.Dimensions {
dimprefix := "Dimensions.member." + strconv.Itoa(i+1)
params[dimprefix+".Name"] = dim.Name
params[dimprefix+".Value"] = dim.Value
}
params["EvaluationPeriods"] = strconv.Itoa(alarm.EvaluationPeriods)
params["MetricName"] = alarm.MetricName
params["Namespace"] = alarm.Namespace
params["Period"] = strconv.Itoa(alarm.Period)
params["Statistic"] = alarm.Statistic
params["Threshold"] = strconv.FormatFloat(alarm.Threshold, 'E', 10, 64)
if alarm.Unit != "" {
params["Unit"] = alarm.Unit
}
result = new(aws.BaseResponse)
err = c.query("POST", "/", params, result)
return
}

132
vendor/github.com/goamz/goamz/cloudwatch/cloudwatch_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,132 +0,0 @@
package cloudwatch_test
import (
"testing"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/cloudwatch"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
type S struct {
cw *cloudwatch.CloudWatch
}
var _ = Suite(&S{})
var testServer = testutil.NewHTTPServer()
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.cw, _ = cloudwatch.NewCloudWatch(auth, aws.ServiceInfo{testServer.URL, aws.V2Signature})
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func getTestAlarm() *cloudwatch.MetricAlarm {
alarm := new(cloudwatch.MetricAlarm)
alarm.AlarmName = "TestAlarm"
alarm.MetricName = "TestMetric"
alarm.Namespace = "TestNamespace"
alarm.ComparisonOperator = "LessThanThreshold"
alarm.Threshold = 1
alarm.EvaluationPeriods = 5
alarm.Period = 60
alarm.Statistic = "Sum"
return alarm
}
func (s *S) TestPutAlarm(c *C) {
testServer.Response(200, nil, "<RequestId>123</RequestId>")
alarm := getTestAlarm()
_, err := s.cw.PutMetricAlarm(alarm)
c.Assert(err, IsNil)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "POST")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Form["Action"], DeepEquals, []string{"PutMetricAlarm"})
c.Assert(req.Form["AlarmName"], DeepEquals, []string{"TestAlarm"})
c.Assert(req.Form["ComparisonOperator"], DeepEquals, []string{"LessThanThreshold"})
c.Assert(req.Form["EvaluationPeriods"], DeepEquals, []string{"5"})
c.Assert(req.Form["Threshold"], DeepEquals, []string{"1.0000000000E+00"})
c.Assert(req.Form["Period"], DeepEquals, []string{"60"})
c.Assert(req.Form["Statistic"], DeepEquals, []string{"Sum"})
}
func (s *S) TestPutAlarmWithAction(c *C) {
testServer.Response(200, nil, "<RequestId>123</RequestId>")
alarm := getTestAlarm()
alarm.AlarmActions = []cloudwatch.AlarmAction{
cloudwatch.AlarmAction{
ARN: "123",
},
}
alarm.OkActions = []cloudwatch.AlarmAction{
cloudwatch.AlarmAction{
ARN: "456",
},
}
alarm.InsufficientDataActions = []cloudwatch.AlarmAction{
cloudwatch.AlarmAction{
ARN: "789",
},
}
_, err := s.cw.PutMetricAlarm(alarm)
c.Assert(err, IsNil)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "POST")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Form["Action"], DeepEquals, []string{"PutMetricAlarm"})
c.Assert(req.Form["AlarmActions.member.1"], DeepEquals, []string{"123"})
c.Assert(req.Form["OKActions.member.1"], DeepEquals, []string{"456"})
c.Assert(req.Form["InsufficientDataActions.member.1"], DeepEquals, []string{"789"})
c.Assert(req.Form["AlarmName"], DeepEquals, []string{"TestAlarm"})
c.Assert(req.Form["ComparisonOperator"], DeepEquals, []string{"LessThanThreshold"})
c.Assert(req.Form["EvaluationPeriods"], DeepEquals, []string{"5"})
c.Assert(req.Form["Threshold"], DeepEquals, []string{"1.0000000000E+00"})
c.Assert(req.Form["Period"], DeepEquals, []string{"60"})
c.Assert(req.Form["Statistic"], DeepEquals, []string{"Sum"})
}
func (s *S) TestPutAlarmInvalidComapirsonOperator(c *C) {
testServer.Response(200, nil, "<RequestId>123</RequestId>")
alarm := getTestAlarm()
alarm.ComparisonOperator = "LessThan"
_, err := s.cw.PutMetricAlarm(alarm)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "ComparisonOperator is not valid")
}
func (s *S) TestPutAlarmInvalidStatistic(c *C) {
testServer.Response(200, nil, "<RequestId>123</RequestId>")
alarm := getTestAlarm()
alarm.Statistic = "Count"
_, err := s.cw.PutMetricAlarm(alarm)
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "Invalid statistic value supplied")
}

1
vendor/github.com/goamz/goamz/dynamodb/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -1 +0,0 @@
dynamodb_local*

13
vendor/github.com/goamz/goamz/dynamodb/Makefile сгенерированный поставляемый
Просмотреть файл

@@ -1,13 +0,0 @@
DYNAMODB_LOCAL_VERSION = 2013-12-12
launch: DynamoDBLocal.jar
cd dynamodb_local_$(DYNAMODB_LOCAL_VERSION) && java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar
DynamoDBLocal.jar: dynamodb_local_$(DYNAMODB_LOCAL_VERSION).tar.gz
[ -d dynamodb_local_$(DYNAMODB_LOCAL_VERSION) ] || tar -zxf dynamodb_local_$(DYNAMODB_LOCAL_VERSION).tar.gz
dynamodb_local_$(DYNAMODB_LOCAL_VERSION).tar.gz:
curl -O https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_$(DYNAMODB_LOCAL_VERSION).tar.gz
clean:
rm -rf dynamodb_local_$(DYNAMODB_LOCAL_VERSION)*

27
vendor/github.com/goamz/goamz/dynamodb/README.md сгенерированный поставляемый
Просмотреть файл

@@ -1,27 +0,0 @@
# Running integration tests
## against DynamoDB local
To download and launch DynamoDB local:
```sh
$ make
```
To test:
```sh
$ go test -v -amazon
```
## against real DynamoDB server on us-east
_WARNING_: Some dangerous operations such as `DeleteTable` will be performed during the tests. Please be careful.
To test:
```sh
$ go test -v -amazon -local=false
```
_Note_: Running tests against real DynamoDB will take several minutes.

185
vendor/github.com/goamz/goamz/dynamodb/attribute.go сгенерированный поставляемый
Просмотреть файл

@@ -1,185 +0,0 @@
package dynamodb
import (
"strconv"
)
const (
TYPE_STRING = "S"
TYPE_NUMBER = "N"
TYPE_BINARY = "B"
TYPE_STRING_SET = "SS"
TYPE_NUMBER_SET = "NS"
TYPE_BINARY_SET = "BS"
COMPARISON_EQUAL = "EQ"
COMPARISON_NOT_EQUAL = "NE"
COMPARISON_LESS_THAN_OR_EQUAL = "LE"
COMPARISON_LESS_THAN = "LT"
COMPARISON_GREATER_THAN_OR_EQUAL = "GE"
COMPARISON_GREATER_THAN = "GT"
COMPARISON_ATTRIBUTE_EXISTS = "NOT_NULL"
COMPARISON_ATTRIBUTE_DOES_NOT_EXIST = "NULL"
COMPARISON_CONTAINS = "CONTAINS"
COMPARISON_DOES_NOT_CONTAIN = "NOT_CONTAINS"
COMPARISON_BEGINS_WITH = "BEGINS_WITH"
COMPARISON_IN = "IN"
COMPARISON_BETWEEN = "BETWEEN"
)
type Key struct {
HashKey string
RangeKey string
}
type PrimaryKey struct {
KeyAttribute *Attribute
RangeAttribute *Attribute
}
type Attribute struct {
Type string
Name string
Value string
SetValues []string
Exists string // exists on dynamodb? Values: "true", "false", or ""
}
type AttributeComparison struct {
AttributeName string
ComparisonOperator string
AttributeValueList []Attribute // contains attributes with only types and names (value ignored)
}
func NewEqualInt64AttributeComparison(attributeName string, equalToValue int64) *AttributeComparison {
numeric := NewNumericAttribute(attributeName, strconv.FormatInt(equalToValue, 10))
return &AttributeComparison{attributeName,
COMPARISON_EQUAL,
[]Attribute{*numeric},
}
}
func NewEqualStringAttributeComparison(attributeName string, equalToValue string) *AttributeComparison {
str := NewStringAttribute(attributeName, equalToValue)
return &AttributeComparison{attributeName,
COMPARISON_EQUAL,
[]Attribute{*str},
}
}
func NewStringAttributeComparison(attributeName string, comparisonOperator string, value string) *AttributeComparison {
valueToCompare := NewStringAttribute(attributeName, value)
return &AttributeComparison{attributeName,
comparisonOperator,
[]Attribute{*valueToCompare},
}
}
func NewNumericAttributeComparison(attributeName string, comparisonOperator string, value int64) *AttributeComparison {
valueToCompare := NewNumericAttribute(attributeName, strconv.FormatInt(value, 10))
return &AttributeComparison{attributeName,
comparisonOperator,
[]Attribute{*valueToCompare},
}
}
func NewBinaryAttributeComparison(attributeName string, comparisonOperator string, value bool) *AttributeComparison {
valueToCompare := NewBinaryAttribute(attributeName, strconv.FormatBool(value))
return &AttributeComparison{attributeName,
comparisonOperator,
[]Attribute{*valueToCompare},
}
}
func NewStringAttribute(name string, value string) *Attribute {
return &Attribute{
Type: TYPE_STRING,
Name: name,
Value: value,
}
}
func NewNumericAttribute(name string, value string) *Attribute {
return &Attribute{
Type: TYPE_NUMBER,
Name: name,
Value: value,
}
}
func NewBinaryAttribute(name string, value string) *Attribute {
return &Attribute{
Type: TYPE_BINARY,
Name: name,
Value: value,
}
}
func NewStringSetAttribute(name string, values []string) *Attribute {
return &Attribute{
Type: TYPE_STRING_SET,
Name: name,
SetValues: values,
}
}
func NewNumericSetAttribute(name string, values []string) *Attribute {
return &Attribute{
Type: TYPE_NUMBER_SET,
Name: name,
SetValues: values,
}
}
func NewBinarySetAttribute(name string, values []string) *Attribute {
return &Attribute{
Type: TYPE_BINARY_SET,
Name: name,
SetValues: values,
}
}
func (a *Attribute) SetType() bool {
switch a.Type {
case TYPE_BINARY_SET, TYPE_NUMBER_SET, TYPE_STRING_SET:
return true
}
return false
}
func (a *Attribute) SetExists(exists bool) *Attribute {
if exists {
a.Exists = "true"
} else {
a.Exists = "false"
}
return a
}
func (k *PrimaryKey) HasRange() bool {
return k.RangeAttribute != nil
}
// Useful when you may have many goroutines using a primary key, so they don't fuxor up your values.
func (k *PrimaryKey) Clone(h string, r string) []Attribute {
pk := &Attribute{
Type: k.KeyAttribute.Type,
Name: k.KeyAttribute.Name,
Value: h,
}
result := []Attribute{*pk}
if k.HasRange() {
rk := &Attribute{
Type: k.RangeAttribute.Type,
Name: k.RangeAttribute.Name,
Value: r,
}
result = append(result, *rk)
}
return result
}

11
vendor/github.com/goamz/goamz/dynamodb/const.go сгенерированный поставляемый
Просмотреть файл

@@ -1,11 +0,0 @@
package dynamodb
type ReturnValues string
const (
NONE ReturnValues = "NONE"
ALL_OLD ReturnValues = "ALL_HOLD"
UPDATED_OLD ReturnValues = "UPDATED_OLD"
ALL_NEW ReturnValues = "ALL_NEW"
UPDATED_NEW ReturnValues = "UPDATED_NEW"
)

142
vendor/github.com/goamz/goamz/dynamodb/dynamodb.go сгенерированный поставляемый
Просмотреть файл

@@ -1,142 +0,0 @@
package dynamodb
import simplejson "github.com/bitly/go-simplejson"
import (
"errors"
"github.com/goamz/goamz/aws"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
)
type Server struct {
Auth aws.Auth
Region aws.Region
}
/*
type Query struct {
Query string
}
*/
/*
func NewQuery(queryParts []string) *Query {
return &Query{
"{" + strings.Join(queryParts, ",") + "}",
}
}
*/
const (
// DynamoDBAPIPrefix is the versioned prefix for DynamoDB API commands.
DynamoDBAPIPrefix = "DynamoDB_20120810."
// DynamoDBStreamsAPIPrefix is the versioned prefix for DynamoDB Streams API commands.
DynamoDBStreamsAPIPrefix = "DynamoDBStreams_20120810."
)
// Specific error constants
var ErrNotFound = errors.New("Item not found")
// Error represents an error in an operation with Dynamodb (following goamz/s3)
type Error struct {
StatusCode int // HTTP status code (200, 403, ...)
Status string
Code string // Dynamodb error code ("MalformedQueryString", ...)
Message string // The human-oriented error message
}
func (e *Error) Error() string {
return e.Code + ": " + e.Message
}
func buildError(r *http.Response, jsonBody []byte) error {
ddbError := Error{
StatusCode: r.StatusCode,
Status: r.Status,
}
// TODO return error if Unmarshal fails?
json, err := simplejson.NewJson(jsonBody)
if err != nil {
log.Printf("Failed to parse body as JSON")
return err
}
ddbError.Message = json.Get("message").MustString()
// Of the form: com.amazon.coral.validate#ValidationException
// We only want the last part
codeStr := json.Get("__type").MustString()
hashIndex := strings.Index(codeStr, "#")
if hashIndex > 0 {
codeStr = codeStr[hashIndex+1:]
}
ddbError.Code = codeStr
return &ddbError
}
func (s *Server) queryServer(target string, query *Query) ([]byte, error) {
data := strings.NewReader(query.String())
var endpoint string
if isStreamsTarget(target) {
endpoint = s.Region.DynamoDBStreamsEndpoint
} else {
endpoint = s.Region.DynamoDBEndpoint
}
hreq, err := http.NewRequest("POST", endpoint+"/", data)
if err != nil {
return nil, err
}
hreq.Header.Set("Content-Type", "application/x-amz-json-1.0")
hreq.Header.Set("X-Amz-Date", time.Now().UTC().Format(aws.ISO8601BasicFormat))
hreq.Header.Set("X-Amz-Target", target)
token := s.Auth.Token()
if token != "" {
hreq.Header.Set("X-Amz-Security-Token", token)
}
signer := aws.NewV4Signer(s.Auth, "dynamodb", s.Region)
signer.Sign(hreq)
resp, err := http.DefaultClient.Do(hreq)
if err != nil {
log.Printf("Error calling Amazon")
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("Could not read response body")
return nil, err
}
// http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html
// "A response code of 200 indicates the operation was successful."
if resp.StatusCode != 200 {
ddbErr := buildError(resp, body)
return nil, ddbErr
}
return body, nil
}
func target(name string) string {
return DynamoDBAPIPrefix + name
}
func streamsTarget(name string) string {
return DynamoDBStreamsAPIPrefix + name
}
func isStreamsTarget(target string) bool {
return strings.HasPrefix(target, DynamoDBStreamsAPIPrefix)
}

166
vendor/github.com/goamz/goamz/dynamodb/dynamodb_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,166 +0,0 @@
package dynamodb_test
import (
"flag"
"testing"
"time"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
const TIMEOUT = 3 * time.Minute
var amazon = flag.Bool("amazon", false, "Enable tests against dynamodb")
var local = flag.Bool("local", true, "Use DynamoDB local on 8080 instead of real server on us-east.")
var dynamodb_region aws.Region
var dynamodb_auth aws.Auth
type DynamoDBTest struct {
server *dynamodb.Server
aws.Region // Exports Region
TableDescriptionT dynamodb.TableDescriptionT
table *dynamodb.Table
}
// Delete all items in the table
func (s *DynamoDBTest) TearDownTest(c *C) {
pk, err := s.TableDescriptionT.BuildPrimaryKey()
if err != nil {
c.Fatal(err)
}
attrs, err := s.table.Scan(nil)
if err != nil {
c.Fatal(err)
}
for _, a := range attrs {
key := &dynamodb.Key{
HashKey: a[pk.KeyAttribute.Name].Value,
}
if pk.HasRange() {
key.RangeKey = a[pk.RangeAttribute.Name].Value
}
if ok, err := s.table.DeleteItem(key); !ok {
c.Fatal(err)
}
}
}
func (s *DynamoDBTest) TearDownSuite(c *C) {
// return immediately in the case of calling c.Skip() in SetUpSuite()
if s.server == nil {
return
}
// check whether the table exists
if tables, err := s.server.ListTables(); err != nil {
c.Fatal(err)
} else {
if !findTableByName(tables, s.TableDescriptionT.TableName) {
return
}
}
// Delete the table and wait
if _, err := s.server.DeleteTable(s.TableDescriptionT); err != nil {
c.Fatal(err)
}
done := make(chan bool)
timeout := time.After(TIMEOUT)
go func() {
for {
select {
case <-done:
return
default:
tables, err := s.server.ListTables()
if err != nil {
c.Fatal(err)
}
if findTableByName(tables, s.TableDescriptionT.TableName) {
time.Sleep(5 * time.Second)
} else {
done <- true
return
}
}
}
}()
select {
case <-done:
break
case <-timeout:
c.Error("Expect the table to be deleted but timed out")
close(done)
}
}
func (s *DynamoDBTest) WaitUntilStatus(c *C, status string) {
// We should wait until the table is in specified status because a real DynamoDB has some delay for ready
done := make(chan bool)
timeout := time.After(TIMEOUT)
go func() {
for {
select {
case <-done:
return
default:
desc, err := s.table.DescribeTable()
if err != nil {
c.Fatal(err)
}
if desc.TableStatus == status {
done <- true
return
}
time.Sleep(5 * time.Second)
}
}
}()
select {
case <-done:
break
case <-timeout:
c.Errorf("Expect a status to be %s, but timed out", status)
close(done)
}
}
func setUpAuth(c *C) {
if !*amazon {
c.Skip("Test against amazon not enabled.")
}
if *local {
c.Log("Using local server")
dynamodb_region = aws.Region{
DynamoDBEndpoint: "http://127.0.0.1:8000",
DynamoDBStreamsEndpoint: "http://127.0.0.1:8000",
}
dynamodb_auth = aws.Auth{AccessKey: "DUMMY_KEY", SecretKey: "DUMMY_SECRET"}
} else {
c.Log("Using REAL AMAZON SERVER")
dynamodb_region = aws.USEast
auth, err := aws.EnvAuth()
if err != nil {
c.Fatal(err)
}
dynamodb_auth = auth
}
}
func findTableByName(tables []string, name string) bool {
for _, t := range tables {
if t == name {
return true
}
}
return false
}
func Test(t *testing.T) {
TestingT(t)
}

351
vendor/github.com/goamz/goamz/dynamodb/item.go сгенерированный поставляемый
Просмотреть файл

@@ -1,351 +0,0 @@
package dynamodb
import simplejson "github.com/bitly/go-simplejson"
import (
"errors"
"fmt"
"log"
)
type BatchGetItem struct {
Server *Server
Keys map[*Table][]Key
}
type BatchWriteItem struct {
Server *Server
ItemActions map[*Table]map[string][][]Attribute
}
func (t *Table) BatchGetItems(keys []Key) *BatchGetItem {
batchGetItem := &BatchGetItem{t.Server, make(map[*Table][]Key)}
batchGetItem.Keys[t] = keys
return batchGetItem
}
func (t *Table) BatchWriteItems(itemActions map[string][][]Attribute) *BatchWriteItem {
batchWriteItem := &BatchWriteItem{t.Server, make(map[*Table]map[string][][]Attribute)}
batchWriteItem.ItemActions[t] = itemActions
return batchWriteItem
}
func (batchGetItem *BatchGetItem) AddTable(t *Table, keys *[]Key) *BatchGetItem {
batchGetItem.Keys[t] = *keys
return batchGetItem
}
func (batchWriteItem *BatchWriteItem) AddTable(t *Table, itemActions *map[string][][]Attribute) *BatchWriteItem {
batchWriteItem.ItemActions[t] = *itemActions
return batchWriteItem
}
func (batchGetItem *BatchGetItem) Execute() (map[string][]map[string]*Attribute, error) {
q := NewEmptyQuery()
q.AddGetRequestItems(batchGetItem.Keys)
jsonResponse, err := batchGetItem.Server.queryServer("DynamoDB_20120810.BatchGetItem", q)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
results := make(map[string][]map[string]*Attribute)
tables, err := json.Get("Responses").Map()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
for table, entries := range tables {
var tableResult []map[string]*Attribute
jsonEntriesArray, ok := entries.([]interface{})
if !ok {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
for _, entry := range jsonEntriesArray {
item, ok := entry.(map[string]interface{})
if !ok {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
unmarshalledItem := parseAttributes(item)
tableResult = append(tableResult, unmarshalledItem)
}
results[table] = tableResult
}
return results, nil
}
func (batchWriteItem *BatchWriteItem) Execute() (map[string]interface{}, error) {
q := NewEmptyQuery()
q.AddWriteRequestItems(batchWriteItem.ItemActions)
jsonResponse, err := batchWriteItem.Server.queryServer("DynamoDB_20120810.BatchWriteItem", q)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
unprocessed, err := json.Get("UnprocessedItems").Map()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
if len(unprocessed) == 0 {
return nil, nil
} else {
return unprocessed, errors.New("One or more unprocessed items.")
}
}
func (t *Table) GetItem(key *Key) (map[string]*Attribute, error) {
return t.getItem(key, false)
}
func (t *Table) GetItemConsistent(key *Key, consistentRead bool) (map[string]*Attribute, error) {
return t.getItem(key, consistentRead)
}
func (t *Table) getItem(key *Key, consistentRead bool) (map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKey(t, key)
if consistentRead {
q.ConsistentRead(consistentRead)
}
jsonResponse, err := t.Server.queryServer(target("GetItem"), q)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
itemJson, ok := json.CheckGet("Item")
if !ok {
// We got an empty from amz. The item doesn't exist.
return nil, ErrNotFound
}
item, err := itemJson.Map()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
return parseAttributes(item), nil
}
func (t *Table) PutItem(hashKey string, rangeKey string, attributes []Attribute) (bool, error) {
return t.putItem(hashKey, rangeKey, attributes, nil)
}
func (t *Table) ConditionalPutItem(hashKey, rangeKey string, attributes, expected []Attribute) (bool, error) {
return t.putItem(hashKey, rangeKey, attributes, expected)
}
func (t *Table) putItem(hashKey, rangeKey string, attributes, expected []Attribute) (bool, error) {
if len(attributes) == 0 {
return false, errors.New("At least one attribute is required.")
}
q := NewQuery(t)
keys := t.Key.Clone(hashKey, rangeKey)
attributes = append(attributes, keys...)
q.AddItem(attributes)
if expected != nil {
q.AddExpected(expected)
}
jsonResponse, err := t.Server.queryServer(target("PutItem"), q)
if err != nil {
return false, err
}
_, err = simplejson.NewJson(jsonResponse)
if err != nil {
return false, err
}
return true, nil
}
func (t *Table) deleteItem(key *Key, expected []Attribute) (bool, error) {
q := NewQuery(t)
q.AddKey(t, key)
if expected != nil {
q.AddExpected(expected)
}
jsonResponse, err := t.Server.queryServer(target("DeleteItem"), q)
if err != nil {
return false, err
}
_, err = simplejson.NewJson(jsonResponse)
if err != nil {
return false, err
}
return true, nil
}
func (t *Table) DeleteItem(key *Key) (bool, error) {
return t.deleteItem(key, nil)
}
func (t *Table) ConditionalDeleteItem(key *Key, expected []Attribute) (bool, error) {
return t.deleteItem(key, expected)
}
func (t *Table) AddAttributes(key *Key, attributes []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, nil, "ADD")
}
func (t *Table) UpdateAttributes(key *Key, attributes []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, nil, "PUT")
}
func (t *Table) DeleteAttributes(key *Key, attributes []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, nil, "DELETE")
}
func (t *Table) ConditionalAddAttributes(key *Key, attributes, expected []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, expected, "ADD")
}
func (t *Table) ConditionalUpdateAttributes(key *Key, attributes, expected []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, expected, "PUT")
}
func (t *Table) ConditionalDeleteAttributes(key *Key, attributes, expected []Attribute) (bool, error) {
return t.modifyAttributes(key, attributes, expected, "DELETE")
}
func (t *Table) modifyAttributes(key *Key, attributes, expected []Attribute, action string) (bool, error) {
if len(attributes) == 0 {
return false, errors.New("At least one attribute is required.")
}
q := NewQuery(t)
q.AddKey(t, key)
q.AddUpdates(attributes, action)
if expected != nil {
q.AddExpected(expected)
}
jsonResponse, err := t.Server.queryServer(target("UpdateItem"), q)
if err != nil {
return false, err
}
_, err = simplejson.NewJson(jsonResponse)
if err != nil {
return false, err
}
return true, nil
}
func parseAttributes(s map[string]interface{}) map[string]*Attribute {
results := map[string]*Attribute{}
for key, value := range s {
if v, ok := value.(map[string]interface{}); ok {
if val, ok := v[TYPE_STRING].(string); ok {
results[key] = &Attribute{
Type: TYPE_STRING,
Name: key,
Value: val,
}
} else if val, ok := v[TYPE_NUMBER].(string); ok {
results[key] = &Attribute{
Type: TYPE_NUMBER,
Name: key,
Value: val,
}
} else if val, ok := v[TYPE_BINARY].(string); ok {
results[key] = &Attribute{
Type: TYPE_BINARY,
Name: key,
Value: val,
}
} else if vals, ok := v[TYPE_STRING_SET].([]interface{}); ok {
arry := make([]string, len(vals))
for i, ivalue := range vals {
if val, ok := ivalue.(string); ok {
arry[i] = val
}
}
results[key] = &Attribute{
Type: TYPE_STRING_SET,
Name: key,
SetValues: arry,
}
} else if vals, ok := v[TYPE_NUMBER_SET].([]interface{}); ok {
arry := make([]string, len(vals))
for i, ivalue := range vals {
if val, ok := ivalue.(string); ok {
arry[i] = val
}
}
results[key] = &Attribute{
Type: TYPE_NUMBER_SET,
Name: key,
SetValues: arry,
}
} else if vals, ok := v[TYPE_BINARY_SET].([]interface{}); ok {
arry := make([]string, len(vals))
for i, ivalue := range vals {
if val, ok := ivalue.(string); ok {
arry[i] = val
}
}
results[key] = &Attribute{
Type: TYPE_BINARY_SET,
Name: key,
SetValues: arry,
}
}
} else {
log.Printf("type assertion to map[string] interface{} failed for : %s\n ", value)
}
}
return results
}

446
vendor/github.com/goamz/goamz/dynamodb/item_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,446 +0,0 @@
package dynamodb_test
import (
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
type ItemSuite struct {
TableDescriptionT dynamodb.TableDescriptionT
DynamoDBTest
WithRange bool
}
func (s *ItemSuite) SetUpSuite(c *C) {
setUpAuth(c)
s.DynamoDBTest.TableDescriptionT = s.TableDescriptionT
s.server = &dynamodb.Server{dynamodb_auth, dynamodb_region}
pk, err := s.TableDescriptionT.BuildPrimaryKey()
if err != nil {
c.Skip(err.Error())
}
s.table = s.server.NewTable(s.TableDescriptionT.TableName, pk)
// Cleanup
s.TearDownSuite(c)
_, err = s.server.CreateTable(s.TableDescriptionT)
if err != nil {
c.Fatal(err)
}
s.WaitUntilStatus(c, "ACTIVE")
}
var item_suite = &ItemSuite{
TableDescriptionT: dynamodb.TableDescriptionT{
TableName: "DynamoDBTestMyTable",
AttributeDefinitions: []dynamodb.AttributeDefinitionT{
dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
},
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
},
WithRange: true,
}
var item_without_range_suite = &ItemSuite{
TableDescriptionT: dynamodb.TableDescriptionT{
TableName: "DynamoDBTestMyTable",
AttributeDefinitions: []dynamodb.AttributeDefinitionT{
dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
},
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
},
WithRange: false,
}
var _ = Suite(item_suite)
var _ = Suite(item_without_range_suite)
func (s *ItemSuite) TestConditionalPutUpdateDeleteItem(c *C) {
if s.WithRange {
// No rangekey test required
return
}
attrs := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr1Val"),
}
pk := &dynamodb.Key{HashKey: "NewHashKeyVal"}
// Put
if ok, err := s.table.PutItem("NewHashKeyVal", "", attrs); !ok {
c.Fatal(err)
}
{
// Put with condition failed
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "expectedAttr1Val").SetExists(true),
*dynamodb.NewStringAttribute("AttrNotExists", "").SetExists(false),
}
if ok, err := s.table.ConditionalPutItem("NewHashKeyVal", "", attrs, expected); ok {
c.Errorf("Expect condition does not meet.")
} else {
c.Check(err.Error(), Matches, "ConditionalCheckFailedException.*")
}
// Add attributes with condition failed
if ok, err := s.table.ConditionalAddAttributes(pk, attrs, expected); ok {
c.Errorf("Expect condition does not meet.")
} else {
c.Check(err.Error(), Matches, "ConditionalCheckFailedException.*")
}
// Update attributes with condition failed
if ok, err := s.table.ConditionalUpdateAttributes(pk, attrs, expected); ok {
c.Errorf("Expect condition does not meet.")
} else {
c.Check(err.Error(), Matches, "ConditionalCheckFailedException.*")
}
// Delete attributes with condition failed
if ok, err := s.table.ConditionalDeleteAttributes(pk, attrs, expected); ok {
c.Errorf("Expect condition does not meet.")
} else {
c.Check(err.Error(), Matches, "ConditionalCheckFailedException.*")
}
}
{
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr1Val").SetExists(true),
}
// Add attributes with condition met
addNewAttrs := []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("AddNewAttr1", "10"),
*dynamodb.NewNumericAttribute("AddNewAttr2", "20"),
}
if ok, err := s.table.ConditionalAddAttributes(pk, addNewAttrs, nil); !ok {
c.Errorf("Expect condition met. %s", err)
}
// Update attributes with condition met
updateAttrs := []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("AddNewAttr1", "100"),
}
if ok, err := s.table.ConditionalUpdateAttributes(pk, updateAttrs, expected); !ok {
c.Errorf("Expect condition met. %s", err)
}
// Delete attributes with condition met
deleteAttrs := []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("AddNewAttr2", ""),
}
if ok, err := s.table.ConditionalDeleteAttributes(pk, deleteAttrs, expected); !ok {
c.Errorf("Expect condition met. %s", err)
}
// Get to verify operations that condition are met
item, err := s.table.GetItem(pk)
if err != nil {
c.Fatal(err)
}
if val, ok := item["AddNewAttr1"]; ok {
c.Check(val, DeepEquals, dynamodb.NewNumericAttribute("AddNewAttr1", "100"))
} else {
c.Error("Expect AddNewAttr1 attribute to be added and updated")
}
if _, ok := item["AddNewAttr2"]; ok {
c.Error("Expect AddNewAttr2 attribute to be deleted")
}
}
{
// Put with condition met
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr1Val").SetExists(true),
}
newattrs := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr2Val"),
}
if ok, err := s.table.ConditionalPutItem("NewHashKeyVal", "", newattrs, expected); !ok {
c.Errorf("Expect condition met. %s", err)
}
// Get to verify Put operation that condition are met
item, err := s.table.GetItem(pk)
if err != nil {
c.Fatal(err)
}
if val, ok := item["Attr1"]; ok {
c.Check(val, DeepEquals, dynamodb.NewStringAttribute("Attr1", "Attr2Val"))
} else {
c.Error("Expect Attr1 attribute to be updated")
}
}
{
// Delete with condition failed
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "expectedAttr1Val").SetExists(true),
}
if ok, err := s.table.ConditionalDeleteItem(pk, expected); ok {
c.Errorf("Expect condition does not meet.")
} else {
c.Check(err.Error(), Matches, "ConditionalCheckFailedException.*")
}
}
{
// Delete with condition met
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr2Val").SetExists(true),
}
if ok, _ := s.table.ConditionalDeleteItem(pk, expected); !ok {
c.Errorf("Expect condition met.")
}
// Get to verify Delete operation
_, err := s.table.GetItem(pk)
c.Check(err.Error(), Matches, "Item not found")
}
}
func (s *ItemSuite) TestPutGetDeleteItem(c *C) {
attrs := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("Attr1", "Attr1Val"),
}
var rk string
if s.WithRange {
rk = "1"
}
// Put
if ok, err := s.table.PutItem("NewHashKeyVal", rk, attrs); !ok {
c.Fatal(err)
}
// Get to verify Put operation
pk := &dynamodb.Key{HashKey: "NewHashKeyVal", RangeKey: rk}
item, err := s.table.GetItem(pk)
if err != nil {
c.Fatal(err)
}
if val, ok := item["TestHashKey"]; ok {
c.Check(val, DeepEquals, dynamodb.NewStringAttribute("TestHashKey", "NewHashKeyVal"))
} else {
c.Error("Expect TestHashKey to be found")
}
if s.WithRange {
if val, ok := item["TestRangeKey"]; ok {
c.Check(val, DeepEquals, dynamodb.NewNumericAttribute("TestRangeKey", "1"))
} else {
c.Error("Expect TestRangeKey to be found")
}
}
// Delete
if ok, _ := s.table.DeleteItem(pk); !ok {
c.Fatal(err)
}
// Get to verify Delete operation
_, err = s.table.GetItem(pk)
c.Check(err.Error(), Matches, "Item not found")
}
func (s *ItemSuite) TestUpdateItem(c *C) {
attrs := []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("count", "0"),
}
var rk string
if s.WithRange {
rk = "1"
}
if ok, err := s.table.PutItem("NewHashKeyVal", rk, attrs); !ok {
c.Fatal(err)
}
// UpdateItem with Add
attrs = []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("count", "10"),
}
pk := &dynamodb.Key{HashKey: "NewHashKeyVal", RangeKey: rk}
if ok, err := s.table.AddAttributes(pk, attrs); !ok {
c.Error(err)
}
// Get to verify Add operation
if item, err := s.table.GetItemConsistent(pk, true); err != nil {
c.Error(err)
} else {
if val, ok := item["count"]; ok {
c.Check(val, DeepEquals, dynamodb.NewNumericAttribute("count", "10"))
} else {
c.Error("Expect count to be found")
}
}
// UpdateItem with Put
attrs = []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("count", "100"),
}
if ok, err := s.table.UpdateAttributes(pk, attrs); !ok {
c.Error(err)
}
// Get to verify Put operation
if item, err := s.table.GetItem(pk); err != nil {
c.Fatal(err)
} else {
if val, ok := item["count"]; ok {
c.Check(val, DeepEquals, dynamodb.NewNumericAttribute("count", "100"))
} else {
c.Error("Expect count to be found")
}
}
// UpdateItem with Delete
attrs = []dynamodb.Attribute{
*dynamodb.NewNumericAttribute("count", ""),
}
if ok, err := s.table.DeleteAttributes(pk, attrs); !ok {
c.Error(err)
}
// Get to verify Delete operation
if item, err := s.table.GetItem(pk); err != nil {
c.Error(err)
} else {
if _, ok := item["count"]; ok {
c.Error("Expect count not to be found")
}
}
}
func (s *ItemSuite) TestUpdateItemWithSet(c *C) {
attrs := []dynamodb.Attribute{
*dynamodb.NewStringSetAttribute("list", []string{"A", "B"}),
}
var rk string
if s.WithRange {
rk = "1"
}
if ok, err := s.table.PutItem("NewHashKeyVal", rk, attrs); !ok {
c.Error(err)
}
// UpdateItem with Add
attrs = []dynamodb.Attribute{
*dynamodb.NewStringSetAttribute("list", []string{"C"}),
}
pk := &dynamodb.Key{HashKey: "NewHashKeyVal", RangeKey: rk}
if ok, err := s.table.AddAttributes(pk, attrs); !ok {
c.Error(err)
}
// Get to verify Add operation
if item, err := s.table.GetItem(pk); err != nil {
c.Error(err)
} else {
if val, ok := item["list"]; ok {
c.Check(val, DeepEquals, dynamodb.NewStringSetAttribute("list", []string{"A", "B", "C"}))
} else {
c.Error("Expect count to be found")
}
}
// UpdateItem with Delete
attrs = []dynamodb.Attribute{
*dynamodb.NewStringSetAttribute("list", []string{"A"}),
}
if ok, err := s.table.DeleteAttributes(pk, attrs); !ok {
c.Error(err)
}
// Get to verify Delete operation
if item, err := s.table.GetItem(pk); err != nil {
c.Error(err)
} else {
if val, ok := item["list"]; ok {
c.Check(val, DeepEquals, dynamodb.NewStringSetAttribute("list", []string{"B", "C"}))
} else {
c.Error("Expect list to be remained")
}
}
}
func (s *ItemSuite) TestUpdateItem_new(c *C) {
attrs := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("intval", "1"),
}
var rk string
if s.WithRange {
rk = "1"
}
pk := &dynamodb.Key{HashKey: "UpdateKeyVal", RangeKey: rk}
num := func(a, b string) dynamodb.Attribute {
return *dynamodb.NewNumericAttribute(a, b)
}
checkVal := func(i string) {
if item, err := s.table.GetItem(pk); err != nil {
c.Error(err)
} else {
c.Check(item["intval"], DeepEquals, dynamodb.NewNumericAttribute("intval", i))
}
}
if ok, err := s.table.PutItem("UpdateKeyVal", rk, attrs); !ok {
c.Error(err)
}
checkVal("1")
// Simple Increment
s.table.UpdateItem(pk).UpdateExpression("SET intval = intval + :incr", num(":incr", "5")).Execute()
checkVal("6")
conditionalUpdate := func(check string) {
s.table.UpdateItem(pk).
ConditionExpression("intval = :check").
UpdateExpression("SET intval = intval + :incr").
ExpressionAttributes(num(":check", check), num(":incr", "4")).
Execute()
}
// Conditional increment should be a no-op.
conditionalUpdate("42")
checkVal("6")
// conditional increment should succeed this time
conditionalUpdate("6")
checkVal("10")
// Update with new values getting values
result, err := s.table.UpdateItem(pk).
ReturnValues(dynamodb.UPDATED_NEW).
UpdateExpression("SET intval = intval + :incr", num(":incr", "2")).
Execute()
c.Check(err, IsNil)
c.Check(result.Attributes["intval"], DeepEquals, num("intval", "12"))
checkVal("12")
}

626
vendor/github.com/goamz/goamz/dynamodb/marshaller.go сгенерированный поставляемый
Просмотреть файл

@@ -1,626 +0,0 @@
package dynamodb
import (
"encoding/base64"
"encoding/json"
"fmt"
"math"
"reflect"
"sort"
"strconv"
"strings"
"sync"
"unicode"
)
func MarshalAttributes(m interface{}) ([]Attribute, error) {
v := reflect.ValueOf(m).Elem()
builder := &attributeBuilder{}
builder.buffer = []Attribute{}
for _, f := range cachedTypeFields(v.Type()) { // loop on each field
fv := fieldByIndex(v, f.index)
if !fv.IsValid() || isEmptyValueToOmit(fv) {
continue
}
err := builder.reflectToDynamoDBAttribute(f.name, fv)
if err != nil {
return builder.buffer, err
}
}
return builder.buffer, nil
}
func UnmarshalAttributes(attributesRef *map[string]*Attribute, m interface{}) error {
rv := reflect.ValueOf(m)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return fmt.Errorf("InvalidUnmarshalError reflect.ValueOf(v): %#v, m interface{}: %#v", rv, reflect.TypeOf(m))
}
v := reflect.ValueOf(m).Elem()
attributes := *attributesRef
for _, f := range cachedTypeFields(v.Type()) { // loop on each field
fv := fieldByIndex(v, f.index)
correlatedAttribute := attributes[f.name]
if correlatedAttribute == nil {
continue
}
err := unmarshallAttribute(correlatedAttribute, fv)
if err != nil {
return err
}
}
return nil
}
type attributeBuilder struct {
buffer []Attribute
}
func (builder *attributeBuilder) Push(attribute *Attribute) {
builder.buffer = append(builder.buffer, *attribute)
}
func unmarshallAttribute(a *Attribute, v reflect.Value) error {
switch v.Kind() {
case reflect.Bool:
n, err := strconv.ParseInt(a.Value, 10, 64)
if err != nil {
return fmt.Errorf("UnmarshalTypeError (bool) %#v: %#v", a.Value, err)
}
v.SetBool(n != 0)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(a.Value, 10, 64)
if err != nil || v.OverflowInt(n) {
return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err)
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(a.Value, 10, 64)
if err != nil || v.OverflowUint(n) {
return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err)
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(a.Value, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
return fmt.Errorf("UnmarshalTypeError (number) %#v: %#v", a.Value, err)
}
v.SetFloat(n)
case reflect.String:
v.SetString(a.Value)
case reflect.Slice:
if v.Type().Elem().Kind() == reflect.Uint8 { // byte arrays are a special case
b := make([]byte, base64.StdEncoding.DecodedLen(len(a.Value)))
n, err := base64.StdEncoding.Decode(b, []byte(a.Value))
if err != nil {
return fmt.Errorf("UnmarshalTypeError (byte) %#v: %#v", a.Value, err)
}
v.Set(reflect.ValueOf(b[0:n]))
break
}
if a.SetType() { // Special NS and SS types should be correctly handled
nativeSetCreated := false
switch v.Type().Elem().Kind() {
case reflect.Bool:
nativeSetCreated = true
arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues))
for i, aval := range a.SetValues {
n, err := strconv.ParseInt(aval, 10, 64)
if err != nil {
return fmt.Errorf("UnmarshalSetTypeError (bool) %#v: %#v", aval, err)
}
arry.Index(i).SetBool(n != 0)
}
v.Set(arry)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
nativeSetCreated = true
arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues))
for i, aval := range a.SetValues {
n, err := strconv.ParseInt(aval, 10, 64)
if err != nil || arry.Index(i).OverflowInt(n) {
return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err)
}
arry.Index(i).SetInt(n)
}
v.Set(arry)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
nativeSetCreated = true
arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues))
for i, aval := range a.SetValues {
n, err := strconv.ParseUint(aval, 10, 64)
if err != nil || arry.Index(i).OverflowUint(n) {
return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err)
}
arry.Index(i).SetUint(n)
}
v.Set(arry)
case reflect.Float32, reflect.Float64:
nativeSetCreated = true
arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues))
for i, aval := range a.SetValues {
n, err := strconv.ParseFloat(aval, arry.Index(i).Type().Bits())
if err != nil || arry.Index(i).OverflowFloat(n) {
return fmt.Errorf("UnmarshalSetTypeError (number) %#v: %#v", aval, err)
}
arry.Index(i).SetFloat(n)
}
v.Set(arry)
case reflect.String:
nativeSetCreated = true
arry := reflect.MakeSlice(v.Type(), len(a.SetValues), len(a.SetValues))
for i, aval := range a.SetValues {
arry.Index(i).SetString(aval)
}
v.Set(arry)
}
if nativeSetCreated {
break
}
}
// Slices can be marshalled as nil, but otherwise are handled
// as arrays.
fallthrough
case reflect.Array, reflect.Struct, reflect.Map, reflect.Interface, reflect.Ptr:
unmarshalled := reflect.New(v.Type())
err := json.Unmarshal([]byte(a.Value), unmarshalled.Interface())
if err != nil {
return err
}
v.Set(unmarshalled.Elem())
default:
return fmt.Errorf("UnsupportedTypeError %#v", v.Type())
}
return nil
}
// reflectValueQuoted writes the value in v to the output.
// If quoted is true, the serialization is wrapped in a JSON string.
func (e *attributeBuilder) reflectToDynamoDBAttribute(name string, v reflect.Value) error {
if !v.IsValid() {
return nil
} // don't build
switch v.Kind() {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
rv, err := numericReflectedValueString(v)
if err != nil {
return err
}
e.Push(NewNumericAttribute(name, rv))
case reflect.String:
e.Push(NewStringAttribute(name, v.String()))
case reflect.Slice:
if v.IsNil() {
break
}
if v.Type().Elem().Kind() == reflect.Uint8 {
// Byte slices are treated as errors
s := v.Bytes()
dst := make([]byte, base64.StdEncoding.EncodedLen(len(s)))
base64.StdEncoding.Encode(dst, s)
e.Push(NewStringAttribute(name, string(dst)))
break
}
// Special NS and SS types should be correctly handled
nativeSetCreated := false
switch v.Type().Elem().Kind() {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
nativeSetCreated = true
arrystrings := make([]string, v.Len())
for i, _ := range arrystrings {
var err error
arrystrings[i], err = numericReflectedValueString(v.Index(i))
if err != nil {
return err
}
}
e.Push(NewNumericSetAttribute(name, arrystrings))
case reflect.String: // simple copy will suffice
nativeSetCreated = true
arrystrings := make([]string, v.Len())
for i, _ := range arrystrings {
arrystrings[i] = v.Index(i).String()
}
e.Push(NewStringSetAttribute(name, arrystrings))
}
if nativeSetCreated {
break
}
// Slices can be marshalled as nil, but otherwise are handled
// as arrays.
fallthrough
case reflect.Array, reflect.Struct, reflect.Map, reflect.Interface, reflect.Ptr:
jsonVersion, err := json.Marshal(v.Interface())
if err != nil {
return err
}
escapedJson := `"` + string(jsonVersion) + `"` // strconv.Quote not required because the entire string is escaped from json Marshall
e.Push(NewStringAttribute(name, escapedJson[1:len(escapedJson)-1]))
default:
return fmt.Errorf("UnsupportedTypeError %#v", v.Type())
}
return nil
}
func numericReflectedValueString(v reflect.Value) (string, error) {
switch v.Kind() {
case reflect.Bool:
x := v.Bool()
if x {
return "1", nil
} else {
return "0", nil
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10), nil
case reflect.Float32, reflect.Float64:
f := v.Float()
if math.IsInf(f, 0) || math.IsNaN(f) {
return "", fmt.Errorf("UnsupportedValueError %#v (formatted float: %s)", v, strconv.FormatFloat(f, 'g', -1, v.Type().Bits()))
}
return strconv.FormatFloat(f, 'g', -1, v.Type().Bits()), nil
}
return "", fmt.Errorf("UnsupportedNumericValueError %#v", v.Type())
}
// In DynamoDB we should omit empty value in some type
// See http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html
func isEmptyValueToOmit(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String, reflect.Interface, reflect.Ptr:
// should omit if empty value
return isEmptyValue(v)
}
// otherwise should not omit
return false
}
// ---------------- Below are copied handy functions from http://golang.org/src/pkg/encoding/json/encode.go --------------------------------
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}
return false
}
func fieldByIndex(v reflect.Value, index []int) reflect.Value {
for _, i := range index {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return reflect.Value{}
}
v = v.Elem()
}
v = v.Field(i)
}
return v
}
// A field represents a single field found in a struct.
type field struct {
name string
tag bool
index []int
typ reflect.Type
omitEmpty bool
quoted bool
}
// byName sorts field by name, breaking ties with depth,
// then breaking ties with "name came from json tag", then
// breaking ties with index sequence.
type byName []field
func (x byName) Len() int { return len(x) }
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byName) Less(i, j int) bool {
if x[i].name != x[j].name {
return x[i].name < x[j].name
}
if len(x[i].index) != len(x[j].index) {
return len(x[i].index) < len(x[j].index)
}
if x[i].tag != x[j].tag {
return x[i].tag
}
return byIndex(x).Less(i, j)
}
// byIndex sorts field by index sequence.
type byIndex []field
func (x byIndex) Len() int { return len(x) }
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byIndex) Less(i, j int) bool {
for k, xik := range x[i].index {
if k >= len(x[j].index) {
return false
}
if xik != x[j].index[k] {
return xik < x[j].index[k]
}
}
return len(x[i].index) < len(x[j].index)
}
func isValidTag(s string) bool {
if s == "" {
return false
}
for _, c := range s {
switch {
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
// Backslash and quote chars are reserved, but
// otherwise any punctuation chars are allowed
// in a tag name.
default:
if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
return false
}
}
}
return true
}
// tagOptions is the string following a comma in a struct field's "json"
// tag, or the empty string. It does not include the leading comma.
type tagOptions string
// Contains returns whether checks that a comma-separated list of options
// contains a particular substr flag. substr must be surrounded by a
// string boundary or commas.
func (o tagOptions) Contains(optionName string) bool {
if len(o) == 0 {
return false
}
s := string(o)
for s != "" {
var next string
i := strings.Index(s, ",")
if i >= 0 {
s, next = s[:i], s[i+1:]
}
if s == optionName {
return true
}
s = next
}
return false
}
// parseTag splits a struct field's json tag into its name and
// comma-separated options.
func parseTag(tag string) (string, tagOptions) {
if idx := strings.Index(tag, ","); idx != -1 {
return tag[:idx], tagOptions(tag[idx+1:])
}
return tag, tagOptions("")
}
// typeFields returns a list of fields that JSON should recognize for the given type.
// The algorithm is breadth-first search over the set of structs to include - the top struct
// and then any reachable anonymous structs.
func typeFields(t reflect.Type) []field {
// Anonymous fields to explore at the current level and the next.
current := []field{}
next := []field{{typ: t}}
// Count of queued names for current level and the next.
count := map[reflect.Type]int{}
nextCount := map[reflect.Type]int{}
// Types already visited at an earlier level.
visited := map[reflect.Type]bool{}
// Fields found.
var fields []field
for len(next) > 0 {
current, next = next, current[:0]
count, nextCount = nextCount, map[reflect.Type]int{}
for _, f := range current {
if visited[f.typ] {
continue
}
visited[f.typ] = true
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
if sf.PkgPath != "" { // unexported
continue
}
tag := sf.Tag.Get("json")
if tag == "-" {
continue
}
name, opts := parseTag(tag)
if !isValidTag(name) {
name = ""
}
index := make([]int, len(f.index)+1)
copy(index, f.index)
index[len(f.index)] = i
ft := sf.Type
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
// Follow pointer.
ft = ft.Elem()
}
// Record found field and index sequence.
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
tagged := name != ""
if name == "" {
name = sf.Name
}
fields = append(fields, field{name, tagged, index, ft,
opts.Contains("omitempty"), opts.Contains("string")})
if count[f.typ] > 1 {
// If there were multiple instances, add a second,
// so that the annihilation code will see a duplicate.
// It only cares about the distinction between 1 or 2,
// so don't bother generating any more copies.
fields = append(fields, fields[len(fields)-1])
}
continue
}
// Record new anonymous struct to explore in next round.
nextCount[ft]++
if nextCount[ft] == 1 {
next = append(next, field{name: ft.Name(), index: index, typ: ft})
}
}
}
}
sort.Sort(byName(fields))
// Delete all fields that are hidden by the Go rules for embedded fields,
// except that fields with JSON tags are promoted.
// The fields are sorted in primary order of name, secondary order
// of field index length. Loop over names; for each name, delete
// hidden fields by choosing the one dominant field that survives.
out := fields[:0]
for advance, i := 0, 0; i < len(fields); i += advance {
// One iteration per name.
// Find the sequence of fields with the name of this first field.
fi := fields[i]
name := fi.name
for advance = 1; i+advance < len(fields); advance++ {
fj := fields[i+advance]
if fj.name != name {
break
}
}
if advance == 1 { // Only one field with this name
out = append(out, fi)
continue
}
dominant, ok := dominantField(fields[i : i+advance])
if ok {
out = append(out, dominant)
}
}
fields = out
sort.Sort(byIndex(fields))
return fields
}
// dominantField looks through the fields, all of which are known to
// have the same name, to find the single field that dominates the
// others using Go's embedding rules, modified by the presence of
// JSON tags. If there are multiple top-level fields, the boolean
// will be false: This condition is an error in Go and we skip all
// the fields.
func dominantField(fields []field) (field, bool) {
// The fields are sorted in increasing index-length order. The winner
// must therefore be one with the shortest index length. Drop all
// longer entries, which is easy: just truncate the slice.
length := len(fields[0].index)
tagged := -1 // Index of first tagged field.
for i, f := range fields {
if len(f.index) > length {
fields = fields[:i]
break
}
if f.tag {
if tagged >= 0 {
// Multiple tagged fields at the same level: conflict.
// Return no field.
return field{}, false
}
tagged = i
}
}
if tagged >= 0 {
return fields[tagged], true
}
// All remaining fields have the same length. If there's more than one,
// we have a conflict (two fields named "X" at the same level) and we
// return no field.
if len(fields) > 1 {
return field{}, false
}
return fields[0], true
}
var fieldCache struct {
sync.RWMutex
m map[reflect.Type][]field
}
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) []field {
fieldCache.RLock()
f := fieldCache.m[t]
fieldCache.RUnlock()
if f != nil {
return f
}
// Compute fields without lock.
// Might duplicate effort but won't hold other computations back.
f = typeFields(t)
if f == nil {
f = []field{}
}
fieldCache.Lock()
if fieldCache.m == nil {
fieldCache.m = map[reflect.Type][]field{}
}
fieldCache.m[t] = f
fieldCache.Unlock()
return f
}

283
vendor/github.com/goamz/goamz/dynamodb/marshaller_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,283 +0,0 @@
package dynamodb_test
import (
"time"
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
type TestSubStruct struct {
SubBool bool
SubInt int
SubString string
SubStringArray []string
}
type TestStruct struct {
TestBool bool
TestInt int
TestInt32 int32
TestInt64 int64
TestUint uint
TestFloat32 float32
TestFloat64 float64
TestString string
TestByteArray []byte
TestStringArray []string
TestIntArray []int
TestInt8Array []int8
TestFloatArray []float64
TestSub TestSubStruct
}
type TestStructTime struct {
TestTime time.Time
}
func testObject() *TestStruct {
return &TestStruct{
TestBool: true,
TestInt: -99,
TestInt32: 999,
TestInt64: 9999,
TestUint: 99,
TestFloat32: 9.9999,
TestFloat64: 99.999999,
TestString: "test",
TestByteArray: []byte("bytes"),
TestStringArray: []string{"test1", "test2", "test3", "test4"},
TestIntArray: []int{0, 1, 12, 123, 1234, 12345},
TestInt8Array: []int8{0, 1, 12, 123},
TestFloatArray: []float64{0.1, 1.1, 1.2, 1.23, 1.234, 1.2345},
TestSub: TestSubStruct{
SubBool: true,
SubInt: 2,
SubString: "subtest",
SubStringArray: []string{"sub1", "sub2", "sub3"},
},
}
}
func testObjectTime() *TestStructTime {
t, _ := time.Parse("Jan 2, 2006 at 3:04pm", "Mar 3, 2003 at 5:03pm")
return &TestStructTime{
TestTime: t,
}
}
func testObjectWithZeroValues() *TestStruct {
return &TestStruct{}
}
func testObjectWithNilSets() *TestStruct {
return &TestStruct{
TestBool: true,
TestInt: -99,
TestInt32: 999,
TestInt64: 9999,
TestUint: 99,
TestFloat32: 9.9999,
TestFloat64: 99.999999,
TestString: "test",
TestByteArray: []byte("bytes"),
TestStringArray: []string(nil),
TestIntArray: []int(nil),
TestFloatArray: []float64(nil),
TestSub: TestSubStruct{
SubBool: true,
SubInt: 2,
SubString: "subtest",
SubStringArray: []string{"sub1", "sub2", "sub3"},
},
}
}
func testObjectWithEmptySets() *TestStruct {
return &TestStruct{
TestBool: true,
TestInt: -99,
TestInt32: 999,
TestInt64: 9999,
TestUint: 99,
TestFloat32: 9.9999,
TestFloat64: 99.999999,
TestString: "test",
TestByteArray: []byte("bytes"),
TestStringArray: []string{},
TestIntArray: []int{},
TestFloatArray: []float64{},
TestSub: TestSubStruct{
SubBool: true,
SubInt: 2,
SubString: "subtest",
SubStringArray: []string{"sub1", "sub2", "sub3"},
},
}
}
func testAttrs() []dynamodb.Attribute {
return []dynamodb.Attribute{
dynamodb.Attribute{Type: "N", Name: "TestBool", Value: "1", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt", Value: "-99", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt32", Value: "999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt64", Value: "9999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestUint", Value: "99", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat32", Value: "9.9999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat64", Value: "99.999999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestString", Value: "test", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestByteArray", Value: "Ynl0ZXM=", SetValues: []string(nil)},
dynamodb.Attribute{Type: "SS", Name: "TestStringArray", Value: "", SetValues: []string{"test1", "test2", "test3", "test4"}},
dynamodb.Attribute{Type: "NS", Name: "TestIntArray", Value: "", SetValues: []string{"0", "1", "12", "123", "1234", "12345"}},
dynamodb.Attribute{Type: "NS", Name: "TestInt8Array", Value: "", SetValues: []string{"0", "1", "12", "123"}},
dynamodb.Attribute{Type: "NS", Name: "TestFloatArray", Value: "", SetValues: []string{"0.1", "1.1", "1.2", "1.23", "1.234", "1.2345"}},
dynamodb.Attribute{Type: "S", Name: "TestSub", Value: `{"SubBool":true,"SubInt":2,"SubString":"subtest","SubStringArray":["sub1","sub2","sub3"]}`, SetValues: []string(nil)},
}
}
func testAttrsTime() []dynamodb.Attribute {
return []dynamodb.Attribute{
dynamodb.Attribute{Type: "S", Name: "TestTime", Value: "\"2003-03-03T17:03:00Z\"", SetValues: []string(nil)},
}
}
func testAttrsWithZeroValues() []dynamodb.Attribute {
return []dynamodb.Attribute{
dynamodb.Attribute{Type: "N", Name: "TestBool", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt32", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt64", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestUint", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat32", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat64", Value: "0", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestSub", Value: `{"SubBool":false,"SubInt":0,"SubString":"","SubStringArray":null}`, SetValues: []string(nil)},
}
}
func testAttrsWithNilSets() []dynamodb.Attribute {
return []dynamodb.Attribute{
dynamodb.Attribute{Type: "N", Name: "TestBool", Value: "1", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt", Value: "-99", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt32", Value: "999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestInt64", Value: "9999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestUint", Value: "99", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat32", Value: "9.9999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "N", Name: "TestFloat64", Value: "99.999999", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestString", Value: "test", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestByteArray", Value: "Ynl0ZXM=", SetValues: []string(nil)},
dynamodb.Attribute{Type: "S", Name: "TestSub", Value: `{"SubBool":true,"SubInt":2,"SubString":"subtest","SubStringArray":["sub1","sub2","sub3"]}`, SetValues: []string(nil)},
}
}
type MarshallerSuite struct {
}
var _ = Suite(&MarshallerSuite{})
func (s *MarshallerSuite) TestMarshal(c *C) {
testObj := testObject()
attrs, err := dynamodb.MarshalAttributes(testObj)
if err != nil {
c.Errorf("Error from dynamodb.MarshalAttributes: %#v", err)
}
expected := testAttrs()
c.Check(attrs, DeepEquals, expected)
}
func (s *MarshallerSuite) TestUnmarshal(c *C) {
testObj := &TestStruct{}
attrMap := map[string]*dynamodb.Attribute{}
attrs := testAttrs()
for i, _ := range attrs {
attrMap[attrs[i].Name] = &attrs[i]
}
err := dynamodb.UnmarshalAttributes(&attrMap, testObj)
if err != nil {
c.Fatalf("Error from dynamodb.UnmarshalAttributes: %#v (Built: %#v)", err, testObj)
}
expected := testObject()
c.Check(testObj, DeepEquals, expected)
}
func (s *MarshallerSuite) TestMarshalTime(c *C) {
testObj := testObjectTime()
attrs, err := dynamodb.MarshalAttributes(testObj)
if err != nil {
c.Errorf("Error from dynamodb.MarshalAttributes: %#v", err)
}
expected := testAttrsTime()
c.Check(attrs, DeepEquals, expected)
}
func (s *MarshallerSuite) TestUnmarshalTime(c *C) {
testObj := &TestStructTime{}
attrMap := map[string]*dynamodb.Attribute{}
attrs := testAttrsTime()
for i, _ := range attrs {
attrMap[attrs[i].Name] = &attrs[i]
}
err := dynamodb.UnmarshalAttributes(&attrMap, testObj)
if err != nil {
c.Fatalf("Error from dynamodb.UnmarshalAttributes: %#v (Built: %#v)", err, testObj)
}
expected := testObjectTime()
c.Check(testObj, DeepEquals, expected)
}
func (s *MarshallerSuite) TestMarshalNilSets(c *C) {
testObj := testObjectWithNilSets()
attrs, err := dynamodb.MarshalAttributes(testObj)
if err != nil {
c.Errorf("Error from dynamodb.MarshalAttributes: %#v", err)
}
expected := testAttrsWithNilSets()
c.Check(attrs, DeepEquals, expected)
}
func (s *MarshallerSuite) TestMarshalZeroValues(c *C) {
testObj := testObjectWithZeroValues()
attrs, err := dynamodb.MarshalAttributes(testObj)
if err != nil {
c.Errorf("Error from dynamodb.MarshalAttributes: %#v", err)
}
expected := testAttrsWithZeroValues()
c.Check(attrs, DeepEquals, expected)
}
func (s *MarshallerSuite) TestMarshalEmptySets(c *C) {
testObj := testObjectWithEmptySets()
attrs, err := dynamodb.MarshalAttributes(testObj)
if err != nil {
c.Errorf("Error from dynamodb.MarshalAttributes: %#v", err)
}
expected := testAttrsWithNilSets()
c.Check(attrs, DeepEquals, expected)
}
func (s *MarshallerSuite) TestUnmarshalEmptySets(c *C) {
testObj := &TestStruct{}
attrMap := map[string]*dynamodb.Attribute{}
attrs := testAttrsWithNilSets()
for i, _ := range attrs {
attrMap[attrs[i].Name] = &attrs[i]
}
err := dynamodb.UnmarshalAttributes(&attrMap, testObj)
if err != nil {
c.Fatalf("Error from dynamodb.UnmarshalAttributes: %#v (Built: %#v)", err, testObj)
}
expected := testObjectWithNilSets()
c.Check(testObj, DeepEquals, expected)
}

111
vendor/github.com/goamz/goamz/dynamodb/query.go сгенерированный поставляемый
Просмотреть файл

@@ -1,111 +0,0 @@
package dynamodb
import (
"errors"
"fmt"
simplejson "github.com/bitly/go-simplejson"
)
func (t *Table) Query(attributeComparisons []AttributeComparison) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
return runQuery(q, t)
}
func (t *Table) QueryOnIndex(attributeComparisons []AttributeComparison, indexName string) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddIndex(indexName)
return runQuery(q, t)
}
func (t *Table) QueryOnIndexDescending(attributeComparisons []AttributeComparison, indexName string) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddIndex(indexName)
q.ScanIndexDescending()
return runQuery(q, t)
}
func (t *Table) LimitedQuery(attributeComparisons []AttributeComparison, limit int64) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddLimit(limit)
return runQuery(q, t)
}
func (t *Table) LimitedQueryOnIndex(attributeComparisons []AttributeComparison, indexName string, limit int64) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddIndex(indexName)
q.AddLimit(limit)
return runQuery(q, t)
}
func (t *Table) LimitedQueryDescending(attributeComparisons []AttributeComparison, limit int64) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddLimit(limit)
q.ScanIndexDescending()
return runQuery(q, t)
}
func (t *Table) LimitedQueryOnIndexDescending(attributeComparisons []AttributeComparison, indexName string, limit int64) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddIndex(indexName)
q.AddLimit(limit)
q.ScanIndexDescending()
return runQuery(q, t)
}
func (t *Table) CountQuery(attributeComparisons []AttributeComparison) (int64, error) {
q := NewQuery(t)
q.AddKeyConditions(attributeComparisons)
q.AddSelect("COUNT")
jsonResponse, err := t.Server.queryServer("DynamoDB_20120810.Query", q)
if err != nil {
return 0, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return 0, err
}
itemCount, err := json.Get("Count").Int64()
if err != nil {
return 0, err
}
return itemCount, nil
}
func runQuery(q *Query, t *Table) ([]map[string]*Attribute, error) {
jsonResponse, err := t.Server.queryServer("DynamoDB_20120810.Query", q)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
itemCount, err := json.Get("Count").Int()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
results := make([]map[string]*Attribute, itemCount)
for i, _ := range results {
item, err := json.Get("Items").GetIndex(i).Map()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
results[i] = parseAttributes(item)
}
return results, nil
}

362
vendor/github.com/goamz/goamz/dynamodb/query_builder.go сгенерированный поставляемый
Просмотреть файл

@@ -1,362 +0,0 @@
package dynamodb
import (
"encoding/json"
"sort"
)
type msi map[string]interface{}
type Query struct {
buffer msi
}
func NewEmptyQuery() *Query {
return &Query{msi{}}
}
func NewQuery(t *Table) *Query {
q := &Query{msi{}}
q.addTable(t)
return q
}
// This way of specifing the key is used when doing a Get.
// If rangeKey is "", it is assumed to not want to be used
func (q *Query) AddKey(t *Table, key *Key) {
k := t.Key
keymap := msi{
k.KeyAttribute.Name: msi{
k.KeyAttribute.Type: key.HashKey},
}
if k.HasRange() {
keymap[k.RangeAttribute.Name] = msi{k.RangeAttribute.Type: key.RangeKey}
}
q.buffer["Key"] = keymap
}
func keyAttributes(t *Table, key *Key) msi {
k := t.Key
out := msi{}
out[k.KeyAttribute.Name] = msi{k.KeyAttribute.Type: key.HashKey}
if k.HasRange() {
out[k.RangeAttribute.Name] = msi{k.RangeAttribute.Type: key.RangeKey}
}
return out
}
func (q *Query) AddAttributesToGet(attributes []string) {
if len(attributes) == 0 {
return
}
q.buffer["AttributesToGet"] = attributes
}
func (q *Query) ConsistentRead(c bool) {
if c == true {
q.buffer["ConsistentRead"] = "true" //String "true", not bool true
}
}
func (q *Query) AddGetRequestItems(tableKeys map[*Table][]Key) {
requestitems := msi{}
for table, keys := range tableKeys {
keyslist := []msi{}
for _, key := range keys {
keyslist = append(keyslist, keyAttributes(table, &key))
}
requestitems[table.Name] = msi{"Keys": keyslist}
}
q.buffer["RequestItems"] = requestitems
}
func (q *Query) AddWriteRequestItems(tableItems map[*Table]map[string][][]Attribute) {
b := q.buffer
b["RequestItems"] = func() msi {
out := msi{}
for table, itemActions := range tableItems {
out[table.Name] = func() interface{} {
out2 := []interface{}{}
// here breaks an order of array....
// For now, we iterate over sorted key by action for stable testing
keys := []string{}
for k := range itemActions {
keys = append(keys, k)
}
sort.Strings(keys)
for ki := range keys {
action := keys[ki]
items := itemActions[action]
for _, attributes := range items {
Item_or_Key := map[bool]string{true: "Item", false: "Key"}[action == "Put"]
out2 = append(out2, msi{action + "Request": msi{Item_or_Key: attributeList(attributes)}})
}
}
return out2
}()
}
return out
}()
}
func (q *Query) AddCreateRequestTable(description TableDescriptionT) {
b := q.buffer
attDefs := []interface{}{}
for _, attr := range description.AttributeDefinitions {
attDefs = append(attDefs, msi{
"AttributeName": attr.Name,
"AttributeType": attr.Type,
})
}
b["AttributeDefinitions"] = attDefs
b["KeySchema"] = description.KeySchema
b["TableName"] = description.TableName
b["ProvisionedThroughput"] = msi{
"ReadCapacityUnits": int(description.ProvisionedThroughput.ReadCapacityUnits),
"WriteCapacityUnits": int(description.ProvisionedThroughput.WriteCapacityUnits),
}
if description.StreamSpecification.StreamEnabled {
b["StreamSpecification"] = msi{
"StreamEnabled": "true",
"StreamViewType": description.StreamSpecification.StreamViewType,
}
}
localSecondaryIndexes := []interface{}{}
for _, ind := range description.LocalSecondaryIndexes {
localSecondaryIndexes = append(localSecondaryIndexes, msi{
"IndexName": ind.IndexName,
"KeySchema": ind.KeySchema,
"Projection": ind.Projection,
})
}
globalSecondaryIndexes := []interface{}{}
intmax := func(x, y int64) int64 {
if x > y {
return x
}
return y
}
for _, ind := range description.GlobalSecondaryIndexes {
rec := msi{
"IndexName": ind.IndexName,
"KeySchema": ind.KeySchema,
"Projection": ind.Projection,
}
// need at least one unit, and since go's max() is float based.
rec["ProvisionedThroughput"] = msi{
"ReadCapacityUnits": intmax(1, ind.ProvisionedThroughput.ReadCapacityUnits),
"WriteCapacityUnits": intmax(1, ind.ProvisionedThroughput.WriteCapacityUnits),
}
globalSecondaryIndexes = append(globalSecondaryIndexes, rec)
}
if len(localSecondaryIndexes) > 0 {
b["LocalSecondaryIndexes"] = localSecondaryIndexes
}
if len(globalSecondaryIndexes) > 0 {
b["GlobalSecondaryIndexes"] = globalSecondaryIndexes
}
}
func (q *Query) AddDeleteRequestTable(description TableDescriptionT) {
b := q.buffer
b["TableName"] = description.TableName
}
func (q *Query) AddUpdateRequestTable(description TableDescriptionT) {
b := q.buffer
attDefs := []interface{}{}
for _, attr := range description.AttributeDefinitions {
attDefs = append(attDefs, msi{
"AttributeName": attr.Name,
"AttributeType": attr.Type,
})
}
if len(attDefs) > 0 {
b["AttributeDefinitions"] = attDefs
}
b["TableName"] = description.TableName
b["ProvisionedThroughput"] = msi{
"ReadCapacityUnits": int(description.ProvisionedThroughput.ReadCapacityUnits),
"WriteCapacityUnits": int(description.ProvisionedThroughput.WriteCapacityUnits),
}
}
func (q *Query) AddKeyConditions(comparisons []AttributeComparison) {
q.buffer["KeyConditions"] = buildComparisons(comparisons)
}
func (q *Query) AddLimit(limit int64) {
q.buffer["Limit"] = limit
}
func (q *Query) AddSelect(value string) {
q.buffer["Select"] = value
}
func (q *Query) AddIndex(value string) {
q.buffer["IndexName"] = value
}
func (q *Query) ScanIndexDescending() {
q.buffer["ScanIndexForward"] = "false"
}
/*
"ScanFilter":{
"AttributeName1":{"AttributeValueList":[{"S":"AttributeValue"}],"ComparisonOperator":"EQ"}
},
*/
func (q *Query) AddScanFilter(comparisons []AttributeComparison) {
q.buffer["ScanFilter"] = buildComparisons(comparisons)
}
func (q *Query) AddParallelScanConfiguration(segment int, totalSegments int) {
q.buffer["Segment"] = segment
q.buffer["TotalSegments"] = totalSegments
}
func buildComparisons(comparisons []AttributeComparison) msi {
out := msi{}
for _, c := range comparisons {
avlist := []interface{}{}
for _, attributeValue := range c.AttributeValueList {
avlist = append(avlist, msi{attributeValue.Type: attributeValue.Value})
}
out[c.AttributeName] = msi{
"AttributeValueList": avlist,
"ComparisonOperator": c.ComparisonOperator,
}
}
return out
}
// The primary key must be included in attributes.
func (q *Query) AddItem(attributes []Attribute) {
q.buffer["Item"] = attributeList(attributes)
}
func (q *Query) AddUpdates(attributes []Attribute, action string) {
updates := msi{}
for _, a := range attributes {
au := msi{
"Value": msi{
a.Type: map[bool]interface{}{true: a.SetValues, false: a.Value}[a.SetType()],
},
"Action": action,
}
// Delete 'Value' from AttributeUpdates if Type is not Set
if action == "DELETE" && !a.SetType() {
delete(au, "Value")
}
updates[a.Name] = au
}
q.buffer["AttributeUpdates"] = updates
}
func (q *Query) AddExpected(attributes []Attribute) {
expected := msi{}
for _, a := range attributes {
value := msi{}
if a.Exists != "" {
value["Exists"] = a.Exists
}
// If set Exists to false, we must remove Value
if value["Exists"] != "false" {
value["Value"] = msi{a.Type: map[bool]interface{}{true: a.SetValues, false: a.Value}[a.SetType()]}
}
expected[a.Name] = value
}
q.buffer["Expected"] = expected
}
// Add the ReturnValues parameter, used in UpdateItem queries.
func (q *Query) AddReturnValues(returnValues ReturnValues) {
q.buffer["ReturnValues"] = string(returnValues)
}
// Add the UpdateExpression parameter, used in UpdateItem queries.
func (q *Query) AddUpdateExpression(expression string) {
q.buffer["UpdateExpression"] = expression
}
// Add the ConditionExpression parameter, used in UpdateItem queries.
func (q *Query) AddConditionExpression(expression string) {
q.buffer["ConditionExpression"] = expression
}
func (q *Query) AddExpressionAttributes(attributes []Attribute) {
existing, ok := q.buffer["ExpressionAttributes"].(msi)
if !ok {
existing = msi{}
q.buffer["ExpressionAttributes"] = existing
}
for key, val := range attributeList(attributes) {
existing[key] = val
}
}
func (q *Query) AddExclusiveStartStreamArn(arn string) {
q.buffer["ExclusiveStartStreamArn"] = arn
}
func (q *Query) AddStreamArn(arn string) {
q.buffer["StreamArn"] = arn
}
func (q *Query) AddExclusiveStartShardId(shardId string) {
q.buffer["ExclusiveStartShardId"] = shardId
}
func (q *Query) AddShardId(shardId string) {
q.buffer["ShardId"] = shardId
}
func (q *Query) AddShardIteratorType(shardIteratorType string) {
q.buffer["ShardIteratorType"] = shardIteratorType
}
func (q *Query) AddSequenceNumber(sequenceNumber string) {
q.buffer["SequenceNumber"] = sequenceNumber
}
func (q *Query) AddShardIterator(shardIterator string) {
q.buffer["ShardIterator"] = shardIterator
}
func attributeList(attributes []Attribute) msi {
b := msi{}
for _, a := range attributes {
//UGH!! (I miss the query operator)
b[a.Name] = msi{a.Type: map[bool]interface{}{true: a.SetValues, false: a.Value}[a.SetType()]}
}
return b
}
func (q *Query) addTable(t *Table) {
q.addTableByName(t.Name)
}
func (q *Query) addTableByName(tableName string) {
q.buffer["TableName"] = tableName
}
func (q *Query) String() string {
bytes, _ := json.Marshal(q.buffer)
return string(bytes)
}

380
vendor/github.com/goamz/goamz/dynamodb/query_builder_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,380 +0,0 @@
package dynamodb_test
import (
simplejson "github.com/bitly/go-simplejson"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
type QueryBuilderSuite struct {
server *dynamodb.Server
}
var _ = Suite(&QueryBuilderSuite{})
func (s *QueryBuilderSuite) SetUpSuite(c *C) {
auth := &aws.Auth{AccessKey: "", SecretKey: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"}
s.server = &dynamodb.Server{*auth, aws.USEast}
}
func (s *QueryBuilderSuite) TestEmptyQuery(c *C) {
q := dynamodb.NewEmptyQuery()
queryString := q.String()
expectedString := "{}"
c.Check(queryString, Equals, expectedString)
if expectedString != queryString {
c.Fatalf("Unexpected Query String : %s\n", queryString)
}
}
func (s *QueryBuilderSuite) TestAddWriteRequestItems(c *C) {
primary := dynamodb.NewStringAttribute("WidgetFoo", "")
secondary := dynamodb.NewNumericAttribute("Created", "")
key := dynamodb.PrimaryKey{primary, secondary}
table := s.server.NewTable("FooData", key)
primary2 := dynamodb.NewStringAttribute("TestHashKey", "")
secondary2 := dynamodb.NewNumericAttribute("TestRangeKey", "")
key2 := dynamodb.PrimaryKey{primary2, secondary2}
table2 := s.server.NewTable("TestTable", key2)
q := dynamodb.NewEmptyQuery()
attribute1 := dynamodb.NewNumericAttribute("testing", "4")
attribute2 := dynamodb.NewNumericAttribute("testingbatch", "2111")
attribute3 := dynamodb.NewStringAttribute("testingstrbatch", "mystr")
item1 := []dynamodb.Attribute{*attribute1, *attribute2, *attribute3}
attribute4 := dynamodb.NewNumericAttribute("testing", "444")
attribute5 := dynamodb.NewNumericAttribute("testingbatch", "93748249272")
attribute6 := dynamodb.NewStringAttribute("testingstrbatch", "myotherstr")
item2 := []dynamodb.Attribute{*attribute4, *attribute5, *attribute6}
attributeDel1 := dynamodb.NewStringAttribute("TestHashKeyDel", "DelKey")
attributeDel2 := dynamodb.NewNumericAttribute("TestRangeKeyDel", "7777777")
itemDel := []dynamodb.Attribute{*attributeDel1, *attributeDel2}
attributeTest1 := dynamodb.NewStringAttribute("TestHashKey", "MyKey")
attributeTest2 := dynamodb.NewNumericAttribute("TestRangeKey", "0193820384293")
itemTest := []dynamodb.Attribute{*attributeTest1, *attributeTest2}
tableItems := map[*dynamodb.Table]map[string][][]dynamodb.Attribute{}
actionItems := make(map[string][][]dynamodb.Attribute)
actionItems["Put"] = [][]dynamodb.Attribute{item1, item2}
actionItems["Delete"] = [][]dynamodb.Attribute{itemDel}
tableItems[table] = actionItems
actionItems2 := make(map[string][][]dynamodb.Attribute)
actionItems2["Put"] = [][]dynamodb.Attribute{itemTest}
tableItems[table2] = actionItems2
q.AddWriteRequestItems(tableItems)
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"RequestItems": {
"TestTable": [
{
"PutRequest": {
"Item": {
"TestRangeKey": {
"N": "0193820384293"
},
"TestHashKey": {
"S": "MyKey"
}
}
}
}
],
"FooData": [
{
"DeleteRequest": {
"Key": {
"TestRangeKeyDel": {
"N": "7777777"
},
"TestHashKeyDel": {
"S": "DelKey"
}
}
}
},
{
"PutRequest": {
"Item": {
"testingstrbatch": {
"S": "mystr"
},
"testingbatch": {
"N": "2111"
},
"testing": {
"N": "4"
}
}
}
},
{
"PutRequest": {
"Item": {
"testingstrbatch": {
"S": "myotherstr"
},
"testingbatch": {
"N": "93748249272"
},
"testing": {
"N": "444"
}
}
}
}
]
}
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
func (s *QueryBuilderSuite) TestAddExpectedQuery(c *C) {
primary := dynamodb.NewStringAttribute("domain", "")
key := dynamodb.PrimaryKey{primary, nil}
table := s.server.NewTable("sites", key)
q := dynamodb.NewQuery(table)
q.AddKey(table, &dynamodb.Key{HashKey: "test"})
expected := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("domain", "expectedTest").SetExists(true),
*dynamodb.NewStringAttribute("testKey", "").SetExists(false),
}
q.AddExpected(expected)
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"Expected": {
"domain": {
"Exists": "true",
"Value": {
"S": "expectedTest"
}
},
"testKey": {
"Exists": "false"
}
},
"Key": {
"domain": {
"S": "test"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
func (s *QueryBuilderSuite) TestGetItemQuery(c *C) {
primary := dynamodb.NewStringAttribute("domain", "")
key := dynamodb.PrimaryKey{primary, nil}
table := s.server.NewTable("sites", key)
q := dynamodb.NewQuery(table)
q.AddKey(table, &dynamodb.Key{HashKey: "test"})
{
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"Key": {
"domain": {
"S": "test"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
// Use ConsistentRead
{
q.ConsistentRead(true)
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"ConsistentRead": "true",
"Key": {
"domain": {
"S": "test"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
}
func (s *QueryBuilderSuite) TestUpdateQuery(c *C) {
primary := dynamodb.NewStringAttribute("domain", "")
rangek := dynamodb.NewNumericAttribute("time", "")
key := dynamodb.PrimaryKey{primary, rangek}
table := s.server.NewTable("sites", key)
countAttribute := dynamodb.NewNumericAttribute("count", "4")
attributes := []dynamodb.Attribute{*countAttribute}
q := dynamodb.NewQuery(table)
q.AddKey(table, &dynamodb.Key{HashKey: "test", RangeKey: "1234"})
q.AddUpdates(attributes, "ADD")
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"AttributeUpdates": {
"count": {
"Action": "ADD",
"Value": {
"N": "4"
}
}
},
"Key": {
"domain": {
"S": "test"
},
"time": {
"N": "1234"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
func (s *QueryBuilderSuite) TestAddUpdates(c *C) {
primary := dynamodb.NewStringAttribute("domain", "")
key := dynamodb.PrimaryKey{primary, nil}
table := s.server.NewTable("sites", key)
q := dynamodb.NewQuery(table)
q.AddKey(table, &dynamodb.Key{HashKey: "test"})
attr := dynamodb.NewStringSetAttribute("StringSet", []string{"str", "str2"})
q.AddUpdates([]dynamodb.Attribute{*attr}, "ADD")
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"AttributeUpdates": {
"StringSet": {
"Action": "ADD",
"Value": {
"SS": ["str", "str2"]
}
}
},
"Key": {
"domain": {
"S": "test"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}
func (s *QueryBuilderSuite) TestAddKeyConditions(c *C) {
primary := dynamodb.NewStringAttribute("domain", "")
key := dynamodb.PrimaryKey{primary, nil}
table := s.server.NewTable("sites", key)
q := dynamodb.NewQuery(table)
acs := []dynamodb.AttributeComparison{
*dynamodb.NewStringAttributeComparison("domain", "EQ", "example.com"),
*dynamodb.NewStringAttributeComparison("path", "EQ", "/"),
}
q.AddKeyConditions(acs)
queryJson, err := simplejson.NewJson([]byte(q.String()))
if err != nil {
c.Fatal(err)
}
expectedJson, err := simplejson.NewJson([]byte(`
{
"KeyConditions": {
"domain": {
"AttributeValueList": [
{
"S": "example.com"
}
],
"ComparisonOperator": "EQ"
},
"path": {
"AttributeValueList": [
{
"S": "/"
}
],
"ComparisonOperator": "EQ"
}
},
"TableName": "sites"
}
`))
if err != nil {
c.Fatal(err)
}
c.Check(queryJson, DeepEquals, expectedJson)
}

51
vendor/github.com/goamz/goamz/dynamodb/scan.go сгенерированный поставляемый
Просмотреть файл

@@ -1,51 +0,0 @@
package dynamodb
import (
"errors"
"fmt"
simplejson "github.com/bitly/go-simplejson"
)
func (t *Table) FetchResults(query *Query) ([]map[string]*Attribute, error) {
jsonResponse, err := t.Server.queryServer(target("Scan"), query)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
itemCount, err := json.Get("Count").Int()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
results := make([]map[string]*Attribute, itemCount)
for i, _ := range results {
item, err := json.Get("Items").GetIndex(i).Map()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
results[i] = parseAttributes(item)
}
return results, nil
}
func (t *Table) Scan(attributeComparisons []AttributeComparison) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddScanFilter(attributeComparisons)
return t.FetchResults(q)
}
func (t *Table) ParallelScan(attributeComparisons []AttributeComparison, segment int, totalSegments int) ([]map[string]*Attribute, error) {
q := NewQuery(t)
q.AddScanFilter(attributeComparisons)
q.AddParallelScanConfiguration(segment, totalSegments)
return t.FetchResults(q)
}

307
vendor/github.com/goamz/goamz/dynamodb/stream.go сгенерированный поставляемый
Просмотреть файл

@@ -1,307 +0,0 @@
package dynamodb
import (
"encoding/json"
"errors"
"fmt"
"reflect"
simplejson "github.com/bitly/go-simplejson"
)
type Stream struct {
Server *Server
Arn string
}
type StreamListItemT struct {
StreamArn string
StreamLabel string
TableName string
}
type SequenceNumberRangeT struct {
EndingSequenceNumber string
StartingSequenceNumber string
}
type ShardT struct {
ParentShardId string
SequenceNumberRange SequenceNumberRangeT
ShardId string
}
type StreamDescriptionT struct {
CreationDateTime float64
KeySchema []KeySchemaT
LastEvaluatedShardId string
Shards []ShardT
StreamArn string
StreamLabel string
StreamStatus string
StreamViewType string
TableName string
}
type RecordT struct {
AwsRegion string
EventID string
EventName string
EventSource string
EventVersion string
StreamRecord *StreamRecordT
}
type StreamRecordT struct {
Keys map[string]*Attribute
NewImage map[string]*Attribute
OldImage map[string]*Attribute
SequenceNumber string
StreamViewType string
SizeBytes int64
}
type listStreamsResponse struct {
Streams []StreamListItemT
}
type describeStreamResponse struct {
StreamDescription StreamDescriptionT
}
var ErrNoRecords = errors.New("No records")
func (s *Server) ListStreams(startArn string) ([]StreamListItemT, error) {
return s.LimitedListTableStreams("", startArn, 0)
}
func (s *Server) LimitedListStreams(startArn string, limit int64) ([]StreamListItemT, error) {
return s.LimitedListTableStreams("", startArn, limit)
}
func (s *Server) ListTableStreams(table, startArn string) ([]StreamListItemT, error) {
return s.LimitedListTableStreams(table, startArn, 0)
}
func (s *Server) LimitedListTableStreams(table, startArn string, limit int64) ([]StreamListItemT, error) {
query := NewEmptyQuery()
if len(table) != 0 {
query.addTableByName(table)
}
if len(startArn) != 0 {
query.AddExclusiveStartStreamArn(startArn)
}
if limit > 0 {
query.AddLimit(limit)
}
jsonResponse, err := s.queryServer(streamsTarget("ListStreams"), query)
if err != nil {
return nil, err
}
var r listStreamsResponse
err = json.Unmarshal(jsonResponse, &r)
if err != nil {
return nil, err
}
return r.Streams, nil
}
func (s *Server) DescribeStream(arn, startShardId string) (*StreamDescriptionT, error) {
return s.LimitedDescribeStream(arn, startShardId, 0)
}
func (s *Server) LimitedDescribeStream(arn, startShardId string, limit int64) (*StreamDescriptionT, error) {
query := NewEmptyQuery()
query.AddStreamArn(arn)
if len(startShardId) != 0 {
query.AddExclusiveStartShardId(startShardId)
}
if limit > 0 {
query.AddLimit(limit)
}
jsonResponse, err := s.queryServer(streamsTarget("DescribeStream"), query)
if err != nil {
return nil, err
}
var r describeStreamResponse
err = json.Unmarshal(jsonResponse, &r)
if err != nil {
return nil, err
}
return &r.StreamDescription, nil
}
func (s *Server) NewStream(streamArn string) *Stream {
return &Stream{s, streamArn}
}
func (s *Stream) DescribeStream(startShardId string) (*StreamDescriptionT, error) {
return s.Server.DescribeStream(s.Arn, startShardId)
}
func (s *Stream) LimitedDescribeStream(startShardId string, limit int64) (*StreamDescriptionT, error) {
return s.Server.LimitedDescribeStream(s.Arn, startShardId, limit)
}
func (s *Server) GetShardIterator(streamArn, shardId, shardIteratorType, sequenceNumber string) (string, error) {
query := NewEmptyQuery()
query.AddStreamArn(streamArn)
query.AddShardId(shardId)
query.AddShardIteratorType(shardIteratorType)
if len(sequenceNumber) != 0 {
query.AddSequenceNumber(sequenceNumber)
}
jsonResponse, err := s.queryServer(streamsTarget("GetShardIterator"), query)
if err != nil {
return "unknown", err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return "unknown", err
}
return json.Get("ShardIterator").MustString(), nil
}
func (s *Stream) GetShardIterator(shardId, shardIteratorType, sequenceNumber string) (string, error) {
return s.Server.GetShardIterator(s.Arn, shardId, shardIteratorType, sequenceNumber)
}
func (s *Server) GetRecords(shardIterator string) (string, []*RecordT, error) {
return s.LimitedGetRecords(shardIterator, 0)
}
func (s *Server) LimitedGetRecords(shardIterator string, limit int64) (string, []*RecordT, error) {
query := NewEmptyQuery()
query.AddShardIterator(shardIterator)
if limit > 0 {
query.AddLimit(limit)
}
jsonResponse, err := s.queryServer(streamsTarget("GetRecords"), query)
if err != nil {
return "", nil, err
}
jsonParsed, err := simplejson.NewJson(jsonResponse)
if err != nil {
return "", nil, err
}
nextShardIt := ""
nextShardItJson, ok := jsonParsed.CheckGet("NextShardIterator")
if ok {
nextShardIt, err = nextShardItJson.String()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return "", nil, errors.New(message)
}
}
recordsJson, ok := jsonParsed.CheckGet("Records")
if !ok {
return nextShardIt, nil, ErrNoRecords
}
recordsArray, err := recordsJson.Array()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nextShardIt, nil, errors.New(message)
}
var records []*RecordT
for _, record := range recordsArray {
if recordMap, ok := record.(map[string]interface{}); ok {
r := parseRecord(recordMap)
records = append(records, r)
}
}
return nextShardIt, records, nil
}
func (s *Stream) GetRecords(shardIterator string) (string, []*RecordT, error) {
return s.Server.GetRecords(shardIterator)
}
func (s *Stream) LimitedGetRecords(shardIterator string, limit int64) (string, []*RecordT, error) {
return s.Server.LimitedGetRecords(shardIterator, limit)
}
func parseRecord(r map[string]interface{}) *RecordT {
record := RecordT{}
rValue := reflect.ValueOf(&record)
keys := []string{"awsRegion", "eventID", "eventName", "eventSource", "eventVersion"}
for i, key := range keys {
if value, ok := r[key]; ok {
if valueStr, ok := value.(string); ok {
rValue.Elem().Field(i).SetString(valueStr)
}
}
}
if streamRecord, ok := r["dynamodb"]; ok {
if streamRecordMap, ok := streamRecord.(map[string]interface{}); ok {
record.StreamRecord = parseStreamRecord(streamRecordMap)
}
}
return &record
}
func parseStreamRecord(s map[string]interface{}) *StreamRecordT {
sr := StreamRecordT{}
rValue := reflect.ValueOf(&sr)
attrKeys := []string{"Keys", "NewImage", "OldImage"}
numAttrKeys := len(attrKeys)
for i, key := range attrKeys {
if value, ok := s[key]; ok {
if valueMap, ok := value.(map[string]interface{}); ok {
attrs := parseAttributes(valueMap)
rValue.Elem().Field(i).Set(reflect.ValueOf(attrs))
}
}
}
strKeys := []string{"SequenceNumber", "StreamViewType"}
numStrKeys := len(strKeys)
for i, key := range strKeys {
if value, ok := s[key]; ok {
if valueStr, ok := value.(string); ok {
rValue.Elem().Field(i + numAttrKeys).SetString(valueStr)
}
}
}
intKeys := []string{"SizeBytes"}
for i, key := range intKeys {
if value, ok := s[key]; ok {
if valueNumber, ok := value.(json.Number); ok {
if valueInt, err := valueNumber.Int64(); err == nil {
rValue.Elem().Field(i + numAttrKeys + numStrKeys).SetInt(valueInt)
}
}
}
}
return &sr
}

198
vendor/github.com/goamz/goamz/dynamodb/stream_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,198 +0,0 @@
package dynamodb_test
import (
"strconv"
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
type StreamSuite struct {
TableDescriptionT dynamodb.TableDescriptionT
DynamoDBTest
}
func (s *StreamSuite) SetUpSuite(c *C) {
setUpAuth(c)
s.DynamoDBTest.TableDescriptionT = s.TableDescriptionT
s.server = &dynamodb.Server{dynamodb_auth, dynamodb_region}
pk, err := s.TableDescriptionT.BuildPrimaryKey()
if err != nil {
c.Skip(err.Error())
}
s.table = s.server.NewTable(s.TableDescriptionT.TableName, pk)
// Cleanup
s.TearDownSuite(c)
_, err = s.server.CreateTable(s.TableDescriptionT)
if err != nil {
c.Fatal(err)
}
s.WaitUntilStatus(c, "ACTIVE")
}
var stream_suite_keys_only = &StreamSuite{
TableDescriptionT: dynamodb.TableDescriptionT{
TableName: "StreamTable",
AttributeDefinitions: []dynamodb.AttributeDefinitionT{
dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
},
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
StreamSpecification: dynamodb.StreamSpecificationT{
StreamEnabled: true,
StreamViewType: "KEYS_ONLY",
},
},
}
var stream_suite_new_image = &StreamSuite{
TableDescriptionT: dynamodb.TableDescriptionT{
TableName: "StreamTable",
AttributeDefinitions: []dynamodb.AttributeDefinitionT{
dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
},
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
StreamSpecification: dynamodb.StreamSpecificationT{
StreamEnabled: true,
StreamViewType: "NEW_IMAGE",
},
},
}
var _ = Suite(stream_suite_keys_only)
var _ = Suite(stream_suite_new_image)
func (s *StreamSuite) TestStream(c *C) {
checkStream(s.table, c)
}
func checkStream(table *dynamodb.Table, c *C) {
// list the table's streams
streams, err := table.ListStreams("")
if err != nil {
c.Fatal(err)
}
c.Check(len(streams), Not(Equals), 0)
c.Check(streams[0].TableName, Equals, table.Name)
// stick a couple of items in the table
attrs := []dynamodb.Attribute{
*dynamodb.NewStringAttribute("TestAttr", "0"),
}
if ok, err := table.PutItem("0", "0", attrs); !ok {
c.Fatal(err)
}
attrs = []dynamodb.Attribute{
*dynamodb.NewStringAttribute("TestAttr", "1"),
}
if ok, err := table.PutItem("1", "1", attrs); !ok {
c.Fatal(err)
}
// create a stream object
stream := table.Server.NewStream(streams[0].StreamArn)
// describe the steam
desc, err := stream.DescribeStream("")
if err != nil {
c.Fatal(err)
}
tableDesc, err := table.DescribeTable()
if err != nil {
c.Fatal(err)
}
c.Check(desc.KeySchema[0], Equals, tableDesc.KeySchema[0])
c.Check(desc.StreamArn, Equals, streams[0].StreamArn)
c.Check(desc.StreamStatus, Equals, "ENABLED")
c.Check(desc.StreamViewType, Equals, tableDesc.StreamSpecification.StreamViewType)
c.Check(desc.TableName, Equals, table.Name)
c.Check(len(desc.Shards), Equals, 1)
// get a shard iterator
shardIt, err := stream.GetShardIterator(desc.Shards[0].ShardId, "TRIM_HORIZON", "")
if err != nil {
c.Fatal(err)
}
c.Check(len(shardIt), Not(Equals), 0)
// poll for records
nextIt, records, err := stream.GetRecords(shardIt)
if err != nil {
c.Fatal(err)
}
c.Check(len(nextIt), Not(Equals), 0)
c.Check(len(records), Equals, 2)
for index, record := range records {
c.Check(record.EventSource, Equals, "aws:dynamodb")
c.Check(record.EventName, Equals, "INSERT")
c.Check(len(record.EventID), Not(Equals), 0)
// look at the actual record
streamRec := record.StreamRecord
c.Check(streamRec.StreamViewType, Equals, desc.StreamViewType)
c.Check(len(streamRec.SequenceNumber), Not(Equals), 0)
if streamRec.SizeBytes <= 0 {
c.Errorf("Expected greater-than-zero size, got: %d", streamRec.SizeBytes)
}
// check the keys
if streamRec.StreamViewType == "KEYS_ONLY" {
checkKeys(streamRec.Keys, index, c)
}
// check the image
if streamRec.StreamViewType == "NEW_IMAGE" {
checkNewImage(streamRec.NewImage, index, c)
}
}
}
func checkKeys(keys map[string]*dynamodb.Attribute, expect int, c *C) {
c.Check(len(keys), Equals, 2)
value, err := strconv.Atoi(keys["TestHashKey"].Value)
if err != nil {
c.Fatal(err)
}
c.Check(value, Equals, expect)
value, err = strconv.Atoi(keys["TestRangeKey"].Value)
if err != nil {
c.Fatal(err)
}
c.Check(value, Equals, expect)
}
func checkNewImage(image map[string]*dynamodb.Attribute, expect int, c *C) {
c.Check(len(image), Equals, 3)
value, err := strconv.Atoi(image["TestHashKey"].Value)
if err != nil {
c.Fatal(err)
}
c.Check(value, Equals, expect)
value, err = strconv.Atoi(image["TestRangeKey"].Value)
if err != nil {
c.Fatal(err)
}
c.Check(value, Equals, expect)
value, err = strconv.Atoi(image["TestAttr"].Value)
if err != nil {
c.Fatal(err)
}
c.Check(value, Equals, expect)
}

259
vendor/github.com/goamz/goamz/dynamodb/table.go сгенерированный поставляемый
Просмотреть файл

@@ -1,259 +0,0 @@
package dynamodb
import (
"encoding/json"
"errors"
"fmt"
simplejson "github.com/bitly/go-simplejson"
)
type Table struct {
Server *Server
Name string
Key PrimaryKey
}
type AttributeDefinitionT struct {
Name string `json:"AttributeName"`
Type string `json:"AttributeType"`
}
type KeySchemaT struct {
AttributeName string
KeyType string
}
type ProjectionT struct {
ProjectionType string
}
type GlobalSecondaryIndexT struct {
IndexName string
IndexSizeBytes int64
ItemCount int64
KeySchema []KeySchemaT
Projection ProjectionT
ProvisionedThroughput ProvisionedThroughputT
}
type LocalSecondaryIndexT struct {
IndexName string
IndexSizeBytes int64
ItemCount int64
KeySchema []KeySchemaT
Projection ProjectionT
}
type ProvisionedThroughputT struct {
NumberOfDecreasesToday int64
ReadCapacityUnits int64
WriteCapacityUnits int64
}
type StreamSpecificationT struct {
StreamEnabled bool
StreamViewType string
}
type TableDescriptionT struct {
AttributeDefinitions []AttributeDefinitionT
CreationDateTime float64
ItemCount int64
KeySchema []KeySchemaT
GlobalSecondaryIndexes []GlobalSecondaryIndexT
LocalSecondaryIndexes []LocalSecondaryIndexT
ProvisionedThroughput ProvisionedThroughputT
StreamSpecification StreamSpecificationT
TableName string
TableSizeBytes int64
TableStatus string
LatestStreamArn string
LatestStreamLabel string
}
type describeTableResponse struct {
Table TableDescriptionT
}
func findAttributeDefinitionByName(ads []AttributeDefinitionT, name string) *AttributeDefinitionT {
for _, a := range ads {
if a.Name == name {
return &a
}
}
return nil
}
func (a *AttributeDefinitionT) GetEmptyAttribute() *Attribute {
switch a.Type {
case "S":
return NewStringAttribute(a.Name, "")
case "N":
return NewNumericAttribute(a.Name, "")
case "B":
return NewBinaryAttribute(a.Name, "")
default:
return nil
}
}
func (t *TableDescriptionT) BuildPrimaryKey() (pk PrimaryKey, err error) {
for _, k := range t.KeySchema {
var attr *Attribute
ad := findAttributeDefinitionByName(t.AttributeDefinitions, k.AttributeName)
if ad == nil {
return pk, errors.New("An inconsistency found in TableDescriptionT")
}
attr = ad.GetEmptyAttribute()
if attr == nil {
return pk, errors.New("An inconsistency found in TableDescriptionT")
}
switch k.KeyType {
case "HASH":
pk.KeyAttribute = attr
case "RANGE":
pk.RangeAttribute = attr
}
}
return
}
func (s *Server) NewTable(name string, key PrimaryKey) *Table {
return &Table{s, name, key}
}
func (s *Server) ListTables() ([]string, error) {
var tables []string
query := NewEmptyQuery()
jsonResponse, err := s.queryServer(target("ListTables"), query)
if err != nil {
return nil, err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
response, err := json.Get("TableNames").Array()
if err != nil {
message := fmt.Sprintf("Unexpected response %s", jsonResponse)
return nil, errors.New(message)
}
for _, value := range response {
if t, ok := (value).(string); ok {
tables = append(tables, t)
}
}
return tables, nil
}
func (s *Server) CreateTable(tableDescription TableDescriptionT) (string, error) {
query := NewEmptyQuery()
query.AddCreateRequestTable(tableDescription)
jsonResponse, err := s.queryServer(target("CreateTable"), query)
if err != nil {
return "unknown", err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return "unknown", err
}
return json.Get("TableDescription").Get("TableStatus").MustString(), nil
}
func (s *Server) DeleteTable(tableDescription TableDescriptionT) (string, error) {
query := NewEmptyQuery()
query.AddDeleteRequestTable(tableDescription)
jsonResponse, err := s.queryServer(target("DeleteTable"), query)
if err != nil {
return "unknown", err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return "unknown", err
}
return json.Get("TableDescription").Get("TableStatus").MustString(), nil
}
func (t *Table) DescribeTable() (*TableDescriptionT, error) {
return t.Server.DescribeTable(t.Name)
}
func (s *Server) DescribeTable(name string) (*TableDescriptionT, error) {
q := NewEmptyQuery()
q.addTableByName(name)
jsonResponse, err := s.queryServer(target("DescribeTable"), q)
if err != nil {
return nil, err
}
var r describeTableResponse
err = json.Unmarshal(jsonResponse, &r)
if err != nil {
return nil, err
}
return &r.Table, nil
}
func (s *Server) UpdateTable(tableDescription TableDescriptionT) (string, error) {
query := NewEmptyQuery()
query.AddUpdateRequestTable(tableDescription)
jsonResponse, err := s.queryServer(target("UpdateTable"), query)
if err != nil {
return "unknown", err
}
json, err := simplejson.NewJson(jsonResponse)
if err != nil {
return "unknown", err
}
return json.Get("TableDescription").Get("TableStatus").MustString(), nil
}
func (t *Table) ListStreams(startArn string) ([]StreamListItemT, error) {
return t.Server.ListTableStreams(t.Name, startArn)
}
func (t *Table) LimitedListStreams(startArn string, limit int64) ([]StreamListItemT, error) {
return t.Server.LimitedListTableStreams(t.Name, startArn, limit)
}
func keyParam(k *PrimaryKey, hashKey string, rangeKey string) string {
value := fmt.Sprintf("{\"HashKeyElement\":{%s}", keyValue(k.KeyAttribute.Type, hashKey))
if k.RangeAttribute != nil {
value = fmt.Sprintf("%s,\"RangeKeyElement\":{%s}", value,
keyValue(k.RangeAttribute.Type, rangeKey))
}
return fmt.Sprintf("\"Key\":%s}", value)
}
func keyValue(key string, value string) string {
return fmt.Sprintf("\"%s\":\"%s\"", key, value)
}

79
vendor/github.com/goamz/goamz/dynamodb/table_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,79 +0,0 @@
package dynamodb_test
import (
"github.com/goamz/goamz/dynamodb"
. "gopkg.in/check.v1"
)
type TableSuite struct {
TableDescriptionT dynamodb.TableDescriptionT
DynamoDBTest
}
func (s *TableSuite) SetUpSuite(c *C) {
setUpAuth(c)
s.DynamoDBTest.TableDescriptionT = s.TableDescriptionT
s.server = &dynamodb.Server{dynamodb_auth, dynamodb_region}
pk, err := s.TableDescriptionT.BuildPrimaryKey()
if err != nil {
c.Skip(err.Error())
}
s.table = s.server.NewTable(s.TableDescriptionT.TableName, pk)
// Cleanup
s.TearDownSuite(c)
}
var table_suite = &TableSuite{
TableDescriptionT: dynamodb.TableDescriptionT{
TableName: "DynamoDBTestMyTable",
AttributeDefinitions: []dynamodb.AttributeDefinitionT{
dynamodb.AttributeDefinitionT{"TestHashKey", "S"},
dynamodb.AttributeDefinitionT{"TestRangeKey", "N"},
dynamodb.AttributeDefinitionT{"TestSecKey", "N"},
},
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
dynamodb.KeySchemaT{"TestRangeKey", "RANGE"},
},
GlobalSecondaryIndexes: []dynamodb.GlobalSecondaryIndexT{
dynamodb.GlobalSecondaryIndexT{
IndexName: "gsiTest",
KeySchema: []dynamodb.KeySchemaT{
dynamodb.KeySchemaT{"TestHashKey", "HASH"},
dynamodb.KeySchemaT{"TestSecKey", "RANGE"},
},
Projection: dynamodb.ProjectionT{"ALL"},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
},
},
ProvisionedThroughput: dynamodb.ProvisionedThroughputT{
ReadCapacityUnits: 1,
WriteCapacityUnits: 1,
},
},
}
var _ = Suite(table_suite)
func (s *TableSuite) TestCreateListTable(c *C) {
status, err := s.server.CreateTable(s.TableDescriptionT)
if err != nil {
c.Fatal(err)
}
if status != "ACTIVE" && status != "CREATING" {
c.Error("Expect status to be ACTIVE or CREATING")
}
s.WaitUntilStatus(c, "ACTIVE")
tables, err := s.server.ListTables()
if err != nil {
c.Fatal(err)
}
c.Check(len(tables), Not(Equals), 0)
c.Check(findTableByName(tables, s.TableDescriptionT.TableName), Equals, true)
}

94
vendor/github.com/goamz/goamz/dynamodb/update_item.go сгенерированный поставляемый
Просмотреть файл

@@ -1,94 +0,0 @@
package dynamodb
import simplejson "github.com/bitly/go-simplejson"
/*
Construct an update item query.
The query can be composed via chaining and then executed via Execute()
Usage:
update := table.UpdateItem(key)
.ReturnValues(dynamodb.UPDATED_NEW)
.UpdateExpression("SET Counter = Counter + :incr")
.UpdateCondition("Counter < :checkVal")
.ExpressionAttributes(NewNumberAttribute(":incr", "1"), NewNumberAttribute(":checkVal", 42))
result, err := update.Execute()
if err == nil {
log.Printf("Counter is now %v", result.Attributes["Counter"].Value)
}
*/
func (t *Table) UpdateItem(key *Key) *UpdateItem {
q := NewQuery(t)
q.AddKey(t, key)
return &UpdateItem{table: t, query: q}
}
type UpdateItem struct {
table *Table
query *Query
hasReturnValues bool
}
// Specify how return values are to be provided.
func (u *UpdateItem) ReturnValues(returnValues ReturnValues) *UpdateItem {
u.hasReturnValues = (returnValues != NONE)
u.query.AddReturnValues(returnValues)
return u
}
/*
Specify an update expression and optional attribute settings at the same time.
update.UpdateExpression("SET Foo = Foo + :incr", dynamodb.NewNumberAttribute(":incr", "7"))
is equivalent to
update.UpdateExpression("SET Foo = Foo + :incr")
.ExpressionAttributes(NewNumberAttribute(":incr", "7"))
*/
func (u *UpdateItem) UpdateExpression(expression string, attributes ...Attribute) *UpdateItem {
u.query.AddUpdateExpression(expression)
u.ExpressionAttributes(attributes...)
return u
}
// Specify attribute substitutions to be used in expressions.
func (u *UpdateItem) ExpressionAttributes(attributes ...Attribute) *UpdateItem {
u.query.AddExpressionAttributes(attributes)
return u
}
// Specify a check condition for conditional updates.
func (u *UpdateItem) ConditionExpression(expression string) *UpdateItem {
u.query.AddConditionExpression(expression)
return u
}
// Execute this query.
func (u *UpdateItem) Execute() (*UpdateResult, error) {
jsonResponse, err := u.table.Server.queryServer(target("UpdateItem"), u.query)
if err != nil {
return nil, err
}
if u.hasReturnValues {
resp, err := simplejson.NewJson(jsonResponse)
if err != nil {
return nil, err
}
attrib, err := resp.Get("Attributes").Map()
if err != nil {
return nil, err
}
return &UpdateResult{parseAttributes(attrib)}, nil
}
return nil, nil
}
type UpdateResult struct {
Attributes map[string]*Attribute
}

2267
vendor/github.com/goamz/goamz/ec2/ec2.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1280
vendor/github.com/goamz/goamz/ec2/ec2_test.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

204
vendor/github.com/goamz/goamz/ec2/ec2i_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,204 +0,0 @@
package ec2_test
import (
"crypto/rand"
"fmt"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/ec2"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
// AmazonServer represents an Amazon EC2 server.
type AmazonServer struct {
auth aws.Auth
}
func (s *AmazonServer) SetUp(c *C) {
auth, err := aws.EnvAuth()
if err != nil {
c.Fatal(err.Error())
}
s.auth = auth
}
// Suite cost per run: 0.02 USD
var _ = Suite(&AmazonClientSuite{})
// AmazonClientSuite tests the client against a live EC2 server.
type AmazonClientSuite struct {
srv AmazonServer
ClientTests
}
func (s *AmazonClientSuite) SetUpSuite(c *C) {
if !testutil.Amazon {
c.Skip("AmazonClientSuite tests not enabled")
}
s.srv.SetUp(c)
s.ec2 = ec2.NewWithClient(s.srv.auth, aws.USEast, testutil.DefaultClient)
}
// ClientTests defines integration tests designed to test the client.
// It is not used as a test suite in itself, but embedded within
// another type.
type ClientTests struct {
ec2 *ec2.EC2
}
var imageId = "ami-ccf405a5" // Ubuntu Maverick, i386, EBS store
// Cost: 0.00 USD
func (s *ClientTests) TestRunInstancesError(c *C) {
options := ec2.RunInstancesOptions{
ImageId: "ami-a6f504cf", // Ubuntu Maverick, i386, instance store
InstanceType: "t1.micro", // Doesn't work with micro, results in 400.
}
resp, err := s.ec2.RunInstances(&options)
c.Assert(resp, IsNil)
c.Assert(err, ErrorMatches, "AMI.*root device.*not supported.*")
ec2err, ok := err.(*ec2.Error)
c.Assert(ok, Equals, true)
c.Assert(ec2err.StatusCode, Equals, 400)
c.Assert(ec2err.Code, Equals, "UnsupportedOperation")
c.Assert(ec2err.Message, Matches, "AMI.*root device.*not supported.*")
c.Assert(ec2err.RequestId, Matches, ".+")
}
// Cost: 0.02 USD
func (s *ClientTests) TestRunAndTerminate(c *C) {
options := ec2.RunInstancesOptions{
ImageId: imageId,
InstanceType: "t1.micro",
}
resp1, err := s.ec2.RunInstances(&options)
c.Assert(err, IsNil)
c.Check(resp1.ReservationId, Matches, "r-[0-9a-f]*")
c.Check(resp1.OwnerId, Matches, "[0-9]+")
c.Check(resp1.Instances, HasLen, 1)
c.Check(resp1.Instances[0].InstanceType, Equals, "t1.micro")
instId := resp1.Instances[0].InstanceId
resp2, err := s.ec2.DescribeInstances([]string{instId}, nil)
c.Assert(err, IsNil)
if c.Check(resp2.Reservations, HasLen, 1) && c.Check(len(resp2.Reservations[0].Instances), Equals, 1) {
inst := resp2.Reservations[0].Instances[0]
c.Check(inst.InstanceId, Equals, instId)
}
resp3, err := s.ec2.TerminateInstances([]string{instId})
c.Assert(err, IsNil)
c.Check(resp3.StateChanges, HasLen, 1)
c.Check(resp3.StateChanges[0].InstanceId, Equals, instId)
c.Check(resp3.StateChanges[0].CurrentState.Name, Equals, "shutting-down")
c.Check(resp3.StateChanges[0].CurrentState.Code, Equals, 32)
}
// Cost: 0.00 USD
func (s *ClientTests) TestSecurityGroups(c *C) {
name := "goamz-test"
descr := "goamz security group for tests"
// Clean it up, if a previous test left it around and avoid leaving it around.
s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
defer s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
resp1, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: name, Description: descr})
c.Assert(err, IsNil)
c.Assert(resp1.RequestId, Matches, ".+")
c.Assert(resp1.Name, Equals, name)
c.Assert(resp1.Id, Matches, ".+")
resp1, err = s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: name, Description: descr})
ec2err, _ := err.(*ec2.Error)
c.Assert(resp1, IsNil)
c.Assert(ec2err, NotNil)
c.Assert(ec2err.Code, Equals, "InvalidGroup.Duplicate")
perms := []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 0,
ToPort: 1024,
SourceIPs: []string{"127.0.0.1/24"},
}}
resp2, err := s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms)
c.Assert(err, IsNil)
c.Assert(resp2.RequestId, Matches, ".+")
resp3, err := s.ec2.SecurityGroups(ec2.SecurityGroupNames(name), nil)
c.Assert(err, IsNil)
c.Assert(resp3.RequestId, Matches, ".+")
c.Assert(resp3.Groups, HasLen, 1)
g0 := resp3.Groups[0]
c.Assert(g0.Name, Equals, name)
c.Assert(g0.Description, Equals, descr)
c.Assert(g0.IPPerms, HasLen, 1)
c.Assert(g0.IPPerms[0].Protocol, Equals, "tcp")
c.Assert(g0.IPPerms[0].FromPort, Equals, 0)
c.Assert(g0.IPPerms[0].ToPort, Equals, 1024)
c.Assert(g0.IPPerms[0].SourceIPs, DeepEquals, []string{"127.0.0.1/24"})
resp2, err = s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
c.Assert(err, IsNil)
c.Assert(resp2.RequestId, Matches, ".+")
}
var sessionId = func() string {
buf := make([]byte, 8)
// if we have no randomness, we'll just make do, so ignore the error.
rand.Read(buf)
return fmt.Sprintf("%x", buf)
}()
// sessionName reutrns a name that is probably
// unique to this test session.
func sessionName(prefix string) string {
return prefix + "-" + sessionId
}
var allRegions = []aws.Region{
aws.USEast,
aws.USWest,
aws.EUWest,
aws.APSoutheast,
aws.APNortheast,
}
// Communicate with all EC2 endpoints to see if they are alive.
func (s *ClientTests) TestRegions(c *C) {
name := sessionName("goamz-region-test")
perms := []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 80,
ToPort: 80,
SourceIPs: []string{"127.0.0.1/32"},
}}
errs := make(chan error, len(allRegions))
for _, region := range allRegions {
go func(r aws.Region) {
e := ec2.NewWithClient(s.ec2.Auth, r, testutil.DefaultClient)
_, err := e.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms)
errs <- err
}(region)
}
for _ = range allRegions {
err := <-errs
if err != nil {
ec2_err, ok := err.(*ec2.Error)
if ok {
c.Check(ec2_err.Code, Matches, "InvalidGroup.NotFound")
} else {
c.Errorf("Non-EC2 error: %s", err)
}
} else {
c.Errorf("Test should have errored but it seems to have succeeded")
}
}
}

581
vendor/github.com/goamz/goamz/ec2/ec2t_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,581 +0,0 @@
package ec2_test
import (
"fmt"
"regexp"
"sort"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/ec2"
"github.com/goamz/goamz/ec2/ec2test"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
// LocalServer represents a local ec2test fake server.
type LocalServer struct {
auth aws.Auth
region aws.Region
srv *ec2test.Server
}
func (s *LocalServer) SetUp(c *C) {
srv, err := ec2test.NewServer()
c.Assert(err, IsNil)
c.Assert(srv, NotNil)
s.srv = srv
s.region = aws.Region{EC2Endpoint: srv.URL()}
}
// LocalServerSuite defines tests that will run
// against the local ec2test server. It includes
// selected tests from ClientTests;
// when the ec2test functionality is sufficient, it should
// include all of them, and ClientTests can be simply embedded.
type LocalServerSuite struct {
srv LocalServer
ServerTests
clientTests ClientTests
}
var _ = Suite(&LocalServerSuite{})
func (s *LocalServerSuite) SetUpSuite(c *C) {
s.srv.SetUp(c)
s.ServerTests.ec2 = ec2.NewWithClient(s.srv.auth, s.srv.region, testutil.DefaultClient)
s.clientTests.ec2 = ec2.NewWithClient(s.srv.auth, s.srv.region, testutil.DefaultClient)
}
func (s *LocalServerSuite) TestRunAndTerminate(c *C) {
s.clientTests.TestRunAndTerminate(c)
}
func (s *LocalServerSuite) TestSecurityGroups(c *C) {
s.clientTests.TestSecurityGroups(c)
}
// TestUserData is not defined on ServerTests because it
// requires the ec2test server to function.
func (s *LocalServerSuite) TestUserData(c *C) {
data := make([]byte, 256)
for i := range data {
data[i] = byte(i)
}
inst, err := s.ec2.RunInstances(&ec2.RunInstancesOptions{
ImageId: imageId,
InstanceType: "t1.micro",
UserData: data,
})
c.Assert(err, IsNil)
c.Assert(inst, NotNil)
c.Assert(inst.Instances[0].DNSName, Equals, inst.Instances[0].InstanceId+".example.com")
id := inst.Instances[0].InstanceId
defer s.ec2.TerminateInstances([]string{id})
tinst := s.srv.srv.Instance(id)
c.Assert(tinst, NotNil)
c.Assert(tinst.UserData, DeepEquals, data)
}
// AmazonServerSuite runs the ec2test server tests against a live EC2 server.
// It will only be activated if the -all flag is specified.
type AmazonServerSuite struct {
srv AmazonServer
ServerTests
}
var _ = Suite(&AmazonServerSuite{})
func (s *AmazonServerSuite) SetUpSuite(c *C) {
if !testutil.Amazon {
c.Skip("AmazonServerSuite tests not enabled")
}
s.srv.SetUp(c)
s.ServerTests.ec2 = ec2.NewWithClient(s.srv.auth, aws.USEast, testutil.DefaultClient)
}
// ServerTests defines a set of tests designed to test
// the ec2test local fake ec2 server.
// It is not used as a test suite in itself, but embedded within
// another type.
type ServerTests struct {
ec2 *ec2.EC2
}
func terminateInstances(c *C, e *ec2.EC2, insts []*ec2.Instance) {
var ids []string
for _, inst := range insts {
if inst != nil {
ids = append(ids, inst.InstanceId)
}
}
_, err := e.TerminateInstances(ids)
c.Check(err, IsNil, Commentf("%d INSTANCES LEFT RUNNING!!!", len(ids)))
}
func (s *ServerTests) makeTestGroup(c *C, name, descr string) ec2.SecurityGroup {
// Clean it up if a previous test left it around.
_, err := s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
if err != nil && err.(*ec2.Error).Code != "InvalidGroup.NotFound" {
c.Fatalf("delete security group: %v", err)
}
resp, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: name, Description: descr})
c.Assert(err, IsNil)
c.Assert(resp.Name, Equals, name)
return resp.SecurityGroup
}
func (s *ServerTests) TestIPPerms(c *C) {
g0 := s.makeTestGroup(c, "goamz-test0", "ec2test group 0")
defer s.ec2.DeleteSecurityGroup(g0)
g1 := s.makeTestGroup(c, "goamz-test1", "ec2test group 1")
defer s.ec2.DeleteSecurityGroup(g1)
resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{g0, g1}, nil)
c.Assert(err, IsNil)
c.Assert(resp.Groups, HasLen, 2)
c.Assert(resp.Groups[0].IPPerms, HasLen, 0)
c.Assert(resp.Groups[1].IPPerms, HasLen, 0)
ownerId := resp.Groups[0].OwnerId
// test some invalid parameters
// TODO more
_, err = s.ec2.AuthorizeSecurityGroup(g0, []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 0,
ToPort: 1024,
SourceIPs: []string{"z127.0.0.1/24"},
}})
c.Assert(err, NotNil)
c.Check(err.(*ec2.Error).Code, Equals, "InvalidPermission.Malformed")
// Check that AuthorizeSecurityGroup adds the correct authorizations.
_, err = s.ec2.AuthorizeSecurityGroup(g0, []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 2000,
ToPort: 2001,
SourceIPs: []string{"127.0.0.0/24"},
SourceGroups: []ec2.UserSecurityGroup{{
Name: g1.Name,
}, {
Id: g0.Id,
}},
}, {
Protocol: "tcp",
FromPort: 2000,
ToPort: 2001,
SourceIPs: []string{"200.1.1.34/32"},
}})
c.Assert(err, IsNil)
resp, err = s.ec2.SecurityGroups([]ec2.SecurityGroup{g0}, nil)
c.Assert(err, IsNil)
c.Assert(resp.Groups, HasLen, 1)
c.Assert(resp.Groups[0].IPPerms, HasLen, 1)
perm := resp.Groups[0].IPPerms[0]
srcg := perm.SourceGroups
c.Assert(srcg, HasLen, 2)
// Normalize so we don't care about returned order.
if srcg[0].Name == g1.Name {
srcg[0], srcg[1] = srcg[1], srcg[0]
}
c.Check(srcg[0].Name, Equals, g0.Name)
c.Check(srcg[0].Id, Equals, g0.Id)
c.Check(srcg[0].OwnerId, Equals, ownerId)
c.Check(srcg[1].Name, Equals, g1.Name)
c.Check(srcg[1].Id, Equals, g1.Id)
c.Check(srcg[1].OwnerId, Equals, ownerId)
sort.Strings(perm.SourceIPs)
c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24", "200.1.1.34/32"})
// Check that we can't delete g1 (because g0 is using it)
_, err = s.ec2.DeleteSecurityGroup(g1)
c.Assert(err, NotNil)
c.Check(err.(*ec2.Error).Code, Equals, "InvalidGroup.InUse")
_, err = s.ec2.RevokeSecurityGroup(g0, []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 2000,
ToPort: 2001,
SourceGroups: []ec2.UserSecurityGroup{{Id: g1.Id}},
}, {
Protocol: "tcp",
FromPort: 2000,
ToPort: 2001,
SourceIPs: []string{"200.1.1.34/32"},
}})
c.Assert(err, IsNil)
resp, err = s.ec2.SecurityGroups([]ec2.SecurityGroup{g0}, nil)
c.Assert(err, IsNil)
c.Assert(resp.Groups, HasLen, 1)
c.Assert(resp.Groups[0].IPPerms, HasLen, 1)
perm = resp.Groups[0].IPPerms[0]
srcg = perm.SourceGroups
c.Assert(srcg, HasLen, 1)
c.Check(srcg[0].Name, Equals, g0.Name)
c.Check(srcg[0].Id, Equals, g0.Id)
c.Check(srcg[0].OwnerId, Equals, ownerId)
c.Check(perm.SourceIPs, DeepEquals, []string{"127.0.0.0/24"})
// We should be able to delete g1 now because we've removed its only use.
_, err = s.ec2.DeleteSecurityGroup(g1)
c.Assert(err, IsNil)
_, err = s.ec2.DeleteSecurityGroup(g0)
c.Assert(err, IsNil)
f := ec2.NewFilter()
f.Add("group-id", g0.Id, g1.Id)
resp, err = s.ec2.SecurityGroups(nil, f)
c.Assert(err, IsNil)
c.Assert(resp.Groups, HasLen, 0)
}
func (s *ServerTests) TestDuplicateIPPerm(c *C) {
name := "goamz-test"
descr := "goamz security group for tests"
// Clean it up, if a previous test left it around and avoid leaving it around.
s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
defer s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: name})
resp1, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: name, Description: descr})
c.Assert(err, IsNil)
c.Assert(resp1.Name, Equals, name)
perms := []ec2.IPPerm{{
Protocol: "tcp",
FromPort: 200,
ToPort: 1024,
SourceIPs: []string{"127.0.0.1/24"},
}, {
Protocol: "tcp",
FromPort: 0,
ToPort: 100,
SourceIPs: []string{"127.0.0.1/24"},
}}
_, err = s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms[0:1])
c.Assert(err, IsNil)
_, err = s.ec2.AuthorizeSecurityGroup(ec2.SecurityGroup{Name: name}, perms[0:2])
c.Assert(err, ErrorMatches, `.*\(InvalidPermission.Duplicate\)`)
}
type filterSpec struct {
name string
values []string
}
func (s *ServerTests) TestInstanceFiltering(c *C) {
groupResp, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName("testgroup1"), Description: "testgroup one description"})
c.Assert(err, IsNil)
group1 := groupResp.SecurityGroup
defer s.ec2.DeleteSecurityGroup(group1)
groupResp, err = s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName("testgroup2"), Description: "testgroup two description"})
c.Assert(err, IsNil)
group2 := groupResp.SecurityGroup
defer s.ec2.DeleteSecurityGroup(group2)
insts := make([]*ec2.Instance, 3)
inst, err := s.ec2.RunInstances(&ec2.RunInstancesOptions{
MinCount: 2,
ImageId: imageId,
InstanceType: "t1.micro",
SecurityGroups: []ec2.SecurityGroup{group1},
})
c.Assert(err, IsNil)
insts[0] = &inst.Instances[0]
insts[1] = &inst.Instances[1]
defer terminateInstances(c, s.ec2, insts)
imageId2 := "ami-e358958a" // Natty server, i386, EBS store
inst, err = s.ec2.RunInstances(&ec2.RunInstancesOptions{
ImageId: imageId2,
InstanceType: "t1.micro",
SecurityGroups: []ec2.SecurityGroup{group2},
})
c.Assert(err, IsNil)
insts[2] = &inst.Instances[0]
ids := func(indices ...int) (instIds []string) {
for _, index := range indices {
instIds = append(instIds, insts[index].InstanceId)
}
return
}
tests := []struct {
about string
instanceIds []string // instanceIds argument to Instances method.
filters []filterSpec // filters argument to Instances method.
resultIds []string // set of instance ids of expected results.
allowExtra bool // resultIds may be incomplete.
err string // expected error.
}{
{
about: "check that Instances returns all instances",
resultIds: ids(0, 1, 2),
allowExtra: true,
}, {
about: "check that specifying two instance ids returns them",
instanceIds: ids(0, 2),
resultIds: ids(0, 2),
}, {
about: "check that specifying a non-existent instance id gives an error",
instanceIds: append(ids(0), "i-deadbeef"),
err: `.*\(InvalidInstanceID\.NotFound\)`,
}, {
about: "check that a filter allowed both instances returns both of them",
filters: []filterSpec{
{"instance-id", ids(0, 2)},
},
resultIds: ids(0, 2),
}, {
about: "check that a filter allowing only one instance returns it",
filters: []filterSpec{
{"instance-id", ids(1)},
},
resultIds: ids(1),
}, {
about: "check that a filter allowing no instances returns none",
filters: []filterSpec{
{"instance-id", []string{"i-deadbeef12345"}},
},
}, {
about: "check that filtering on group id works",
filters: []filterSpec{
{"group-id", []string{group1.Id}},
},
resultIds: ids(0, 1),
}, {
about: "check that filtering on group name works",
filters: []filterSpec{
{"group-name", []string{group1.Name}},
},
resultIds: ids(0, 1),
}, {
about: "check that filtering on image id works",
filters: []filterSpec{
{"image-id", []string{imageId}},
},
resultIds: ids(0, 1),
allowExtra: true,
}, {
about: "combination filters 1",
filters: []filterSpec{
{"image-id", []string{imageId, imageId2}},
{"group-name", []string{group1.Name}},
},
resultIds: ids(0, 1),
}, {
about: "combination filters 2",
filters: []filterSpec{
{"image-id", []string{imageId2}},
{"group-name", []string{group1.Name}},
},
},
}
for i, t := range tests {
c.Logf("%d. %s", i, t.about)
var f *ec2.Filter
if t.filters != nil {
f = ec2.NewFilter()
for _, spec := range t.filters {
f.Add(spec.name, spec.values...)
}
}
resp, err := s.ec2.DescribeInstances(t.instanceIds, f)
if t.err != "" {
c.Check(err, ErrorMatches, t.err)
continue
}
c.Assert(err, IsNil)
insts := make(map[string]*ec2.Instance)
for _, r := range resp.Reservations {
for j := range r.Instances {
inst := &r.Instances[j]
c.Check(insts[inst.InstanceId], IsNil, Commentf("duplicate instance id: %q", inst.InstanceId))
insts[inst.InstanceId] = inst
}
}
if !t.allowExtra {
c.Check(insts, HasLen, len(t.resultIds), Commentf("expected %d instances got %#v", len(t.resultIds), insts))
}
for j, id := range t.resultIds {
c.Check(insts[id], NotNil, Commentf("instance id %d (%q) not found; got %#v", j, id, insts))
}
}
}
func idsOnly(gs []ec2.SecurityGroup) []ec2.SecurityGroup {
for i := range gs {
gs[i].Name = ""
}
return gs
}
func namesOnly(gs []ec2.SecurityGroup) []ec2.SecurityGroup {
for i := range gs {
gs[i].Id = ""
}
return gs
}
func (s *ServerTests) TestGroupFiltering(c *C) {
g := make([]ec2.SecurityGroup, 4)
for i := range g {
resp, err := s.ec2.CreateSecurityGroup(ec2.SecurityGroup{Name: sessionName(fmt.Sprintf("testgroup%d", i)), Description: fmt.Sprintf("testdescription%d", i)})
c.Assert(err, IsNil)
g[i] = resp.SecurityGroup
c.Logf("group %d: %v", i, g[i])
defer s.ec2.DeleteSecurityGroup(g[i])
}
perms := [][]ec2.IPPerm{
{{
Protocol: "tcp",
FromPort: 100,
ToPort: 200,
SourceIPs: []string{"1.2.3.4/32"},
}},
{{
Protocol: "tcp",
FromPort: 200,
ToPort: 300,
SourceGroups: []ec2.UserSecurityGroup{{Id: g[1].Id}},
}},
{{
Protocol: "udp",
FromPort: 200,
ToPort: 400,
SourceGroups: []ec2.UserSecurityGroup{{Id: g[1].Id}},
}},
}
for i, ps := range perms {
_, err := s.ec2.AuthorizeSecurityGroup(g[i], ps)
c.Assert(err, IsNil)
}
groups := func(indices ...int) (gs []ec2.SecurityGroup) {
for _, index := range indices {
gs = append(gs, g[index])
}
return
}
type groupTest struct {
about string
groups []ec2.SecurityGroup // groupIds argument to SecurityGroups method.
filters []filterSpec // filters argument to SecurityGroups method.
results []ec2.SecurityGroup // set of expected result groups.
allowExtra bool // specified results may be incomplete.
err string // expected error.
}
filterCheck := func(name, val string, gs []ec2.SecurityGroup) groupTest {
return groupTest{
about: "filter check " + name,
filters: []filterSpec{{name, []string{val}}},
results: gs,
allowExtra: true,
}
}
tests := []groupTest{
{
about: "check that SecurityGroups returns all groups",
results: groups(0, 1, 2, 3),
allowExtra: true,
}, {
about: "check that specifying two group ids returns them",
groups: idsOnly(groups(0, 2)),
results: groups(0, 2),
}, {
about: "check that specifying names only works",
groups: namesOnly(groups(0, 2)),
results: groups(0, 2),
}, {
about: "check that specifying a non-existent group id gives an error",
groups: append(groups(0), ec2.SecurityGroup{Id: "sg-eeeeeeeee"}),
err: `.*\(InvalidGroup\.NotFound\)`,
}, {
about: "check that a filter allowed two groups returns both of them",
filters: []filterSpec{
{"group-id", []string{g[0].Id, g[2].Id}},
},
results: groups(0, 2),
},
{
about: "check that the previous filter works when specifying a list of ids",
groups: groups(1, 2),
filters: []filterSpec{
{"group-id", []string{g[0].Id, g[2].Id}},
},
results: groups(2),
}, {
about: "check that a filter allowing no groups returns none",
filters: []filterSpec{
{"group-id", []string{"sg-eeeeeeeee"}},
},
},
filterCheck("description", "testdescription1", groups(1)),
filterCheck("group-name", g[2].Name, groups(2)),
filterCheck("ip-permission.cidr", "1.2.3.4/32", groups(0)),
filterCheck("ip-permission.group-name", g[1].Name, groups(1, 2)),
filterCheck("ip-permission.protocol", "udp", groups(2)),
filterCheck("ip-permission.from-port", "200", groups(1, 2)),
filterCheck("ip-permission.to-port", "200", groups(0)),
// TODO owner-id
}
for i, t := range tests {
c.Logf("%d. %s", i, t.about)
var f *ec2.Filter
if t.filters != nil {
f = ec2.NewFilter()
for _, spec := range t.filters {
f.Add(spec.name, spec.values...)
}
}
resp, err := s.ec2.SecurityGroups(t.groups, f)
if t.err != "" {
c.Check(err, ErrorMatches, t.err)
continue
}
c.Assert(err, IsNil)
groups := make(map[string]*ec2.SecurityGroup)
for j := range resp.Groups {
group := &resp.Groups[j].SecurityGroup
c.Check(groups[group.Id], IsNil, Commentf("duplicate group id: %q", group.Id))
groups[group.Id] = group
}
// If extra groups may be returned, eliminate all groups that
// we did not create in this session apart from the default group.
if t.allowExtra {
namePat := regexp.MustCompile(sessionName("testgroup[0-9]"))
for id, g := range groups {
if !namePat.MatchString(g.Name) {
delete(groups, id)
}
}
}
c.Check(groups, HasLen, len(t.results))
for j, g := range t.results {
rg := groups[g.Id]
c.Assert(rg, NotNil, Commentf("group %d (%v) not found; got %#v", j, g, groups))
c.Check(rg.Name, Equals, g.Name, Commentf("group %d (%v)", j, g))
}
}
}

84
vendor/github.com/goamz/goamz/ec2/ec2test/filter.go сгенерированный поставляемый
Просмотреть файл

@@ -1,84 +0,0 @@
package ec2test
import (
"fmt"
"net/url"
"strings"
)
// filter holds an ec2 filter. A filter maps an attribute to a set of
// possible values for that attribute. For an item to pass through the
// filter, every attribute of the item mentioned in the filter must match
// at least one of its given values.
type filter map[string][]string
// newFilter creates a new filter from the Filter fields in the url form.
//
// The filtering is specified through a map of name=>values, where the
// name is a well-defined key identifying the data to be matched,
// and the list of values holds the possible values the filtered
// item can take for the key to be included in the
// result set. For example:
//
// Filter.1.Name=instance-type
// Filter.1.Value.1=m1.small
// Filter.1.Value.2=m1.large
//
func newFilter(form url.Values) filter {
// TODO return an error if the fields are not well formed?
names := make(map[int]string)
values := make(map[int][]string)
maxId := 0
for name, fvalues := range form {
var rest string
var id int
if x, _ := fmt.Sscanf(name, "Filter.%d.%s", &id, &rest); x != 2 {
continue
}
if id > maxId {
maxId = id
}
if rest == "Name" {
names[id] = fvalues[0]
continue
}
if !strings.HasPrefix(rest, "Value.") {
continue
}
values[id] = append(values[id], fvalues[0])
}
f := make(filter)
for id, name := range names {
f[name] = values[id]
}
return f
}
func notDigit(r rune) bool {
return r < '0' || r > '9'
}
// filterable represents an object that can be passed through a filter.
type filterable interface {
// matchAttr returns true if given attribute of the
// object matches value. It returns an error if the
// attribute is not recognised or the value is malformed.
matchAttr(attr, value string) (bool, error)
}
// ok returns true if x passes through the filter.
func (f filter) ok(x filterable) (bool, error) {
next:
for a, vs := range f {
for _, v := range vs {
if ok, err := x.matchAttr(a, v); ok {
continue next
} else if err != nil {
return false, fmt.Errorf("bad attribute or value %q=%q for type %T: %v", a, v, x, err)
}
}
return false, nil
}
return true, nil
}

993
vendor/github.com/goamz/goamz/ec2/ec2test/server.go сгенерированный поставляемый
Просмотреть файл

@@ -1,993 +0,0 @@
// The ec2test package implements a fake EC2 provider with
// the capability of inducing errors on any given operation,
// and retrospectively determining what operations have been
// carried out.
package ec2test
import (
"encoding/base64"
"encoding/xml"
"fmt"
"github.com/goamz/goamz/ec2"
"io"
"net"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"sync"
)
var b64 = base64.StdEncoding
// Action represents a request that changes the ec2 state.
type Action struct {
RequestId string
// Request holds the requested action as a url.Values instance
Request url.Values
// If the action succeeded, Response holds the value that
// was marshalled to build the XML response for the request.
Response interface{}
// If the action failed, Err holds an error giving details of the failure.
Err *ec2.Error
}
// TODO possible other things:
// - some virtual time stamp interface, so a client
// can ask for all actions after a certain virtual time.
// Server implements an EC2 simulator for use in testing.
type Server struct {
url string
listener net.Listener
mu sync.Mutex
reqs []*Action
instances map[string]*Instance // id -> instance
reservations map[string]*reservation // id -> reservation
groups map[string]*securityGroup // id -> group
maxId counter
reqId counter
reservationId counter
groupId counter
initialInstanceState ec2.InstanceState
}
// reservation holds a simulated ec2 reservation.
type reservation struct {
id string
instances map[string]*Instance
groups []*securityGroup
}
// instance holds a simulated ec2 instance
type Instance struct {
// UserData holds the data that was passed to the RunInstances request
// when the instance was started.
UserData []byte
id string
imageId string
reservation *reservation
instType string
state ec2.InstanceState
}
// permKey represents permission for a given security
// group or IP address (but not both) to access a given range of
// ports. Equality of permKeys is used in the implementation of
// permission sets, relying on the uniqueness of securityGroup
// instances.
type permKey struct {
protocol string
fromPort int
toPort int
group *securityGroup
ipAddr string
}
// securityGroup holds a simulated ec2 security group.
// Instances of securityGroup should only be created through
// Server.createSecurityGroup to ensure that groups can be
// compared by pointer value.
type securityGroup struct {
id string
name string
description string
perms map[permKey]bool
}
func (g *securityGroup) ec2SecurityGroup() ec2.SecurityGroup {
return ec2.SecurityGroup{
Name: g.name,
Id: g.id,
}
}
func (g *securityGroup) matchAttr(attr, value string) (ok bool, err error) {
switch attr {
case "description":
return g.description == value, nil
case "group-id":
return g.id == value, nil
case "group-name":
return g.name == value, nil
case "ip-permission.cidr":
return g.hasPerm(func(k permKey) bool { return k.ipAddr == value }), nil
case "ip-permission.group-name":
return g.hasPerm(func(k permKey) bool {
return k.group != nil && k.group.name == value
}), nil
case "ip-permission.from-port":
port, err := strconv.Atoi(value)
if err != nil {
return false, err
}
return g.hasPerm(func(k permKey) bool { return k.fromPort == port }), nil
case "ip-permission.to-port":
port, err := strconv.Atoi(value)
if err != nil {
return false, err
}
return g.hasPerm(func(k permKey) bool { return k.toPort == port }), nil
case "ip-permission.protocol":
return g.hasPerm(func(k permKey) bool { return k.protocol == value }), nil
case "owner-id":
return value == ownerId, nil
}
return false, fmt.Errorf("unknown attribute %q", attr)
}
func (g *securityGroup) hasPerm(test func(k permKey) bool) bool {
for k := range g.perms {
if test(k) {
return true
}
}
return false
}
// ec2Perms returns the list of EC2 permissions granted
// to g. It groups permissions by port range and protocol.
func (g *securityGroup) ec2Perms() (perms []ec2.IPPerm) {
// The grouping is held in result. We use permKey for convenience,
// (ensuring that the group and ipAddr of each key is zero). For
// each protocol/port range combination, we build up the permission
// set in the associated value.
result := make(map[permKey]*ec2.IPPerm)
for k := range g.perms {
groupKey := k
groupKey.group = nil
groupKey.ipAddr = ""
ec2p := result[groupKey]
if ec2p == nil {
ec2p = &ec2.IPPerm{
Protocol: k.protocol,
FromPort: k.fromPort,
ToPort: k.toPort,
}
result[groupKey] = ec2p
}
if k.group != nil {
ec2p.SourceGroups = append(ec2p.SourceGroups,
ec2.UserSecurityGroup{
Id: k.group.id,
Name: k.group.name,
OwnerId: ownerId,
})
} else {
ec2p.SourceIPs = append(ec2p.SourceIPs, k.ipAddr)
}
}
for _, ec2p := range result {
perms = append(perms, *ec2p)
}
return
}
var actions = map[string]func(*Server, http.ResponseWriter, *http.Request, string) interface{}{
"RunInstances": (*Server).runInstances,
"TerminateInstances": (*Server).terminateInstances,
"DescribeInstances": (*Server).describeInstances,
"CreateSecurityGroup": (*Server).createSecurityGroup,
"DescribeSecurityGroups": (*Server).describeSecurityGroups,
"DeleteSecurityGroup": (*Server).deleteSecurityGroup,
"AuthorizeSecurityGroupIngress": (*Server).authorizeSecurityGroupIngress,
"RevokeSecurityGroupIngress": (*Server).revokeSecurityGroupIngress,
}
const ownerId = "9876"
// newAction allocates a new action and adds it to the
// recorded list of server actions.
func (srv *Server) newAction() *Action {
srv.mu.Lock()
defer srv.mu.Unlock()
a := new(Action)
srv.reqs = append(srv.reqs, a)
return a
}
// NewServer returns a new server.
func NewServer() (*Server, error) {
srv := &Server{
instances: make(map[string]*Instance),
groups: make(map[string]*securityGroup),
reservations: make(map[string]*reservation),
initialInstanceState: Pending,
}
// Add default security group.
g := &securityGroup{
name: "default",
description: "default group",
id: fmt.Sprintf("sg-%d", srv.groupId.next()),
}
g.perms = map[permKey]bool{
permKey{
protocol: "icmp",
fromPort: -1,
toPort: -1,
group: g,
}: true,
permKey{
protocol: "tcp",
fromPort: 0,
toPort: 65535,
group: g,
}: true,
permKey{
protocol: "udp",
fromPort: 0,
toPort: 65535,
group: g,
}: true,
}
srv.groups[g.id] = g
l, err := net.Listen("tcp", "localhost:0")
if err != nil {
return nil, fmt.Errorf("cannot listen on localhost: %v", err)
}
srv.listener = l
srv.url = "http://" + l.Addr().String()
// we use HandlerFunc rather than *Server directly so that we
// can avoid exporting HandlerFunc from *Server.
go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
srv.serveHTTP(w, req)
}))
return srv, nil
}
// Quit closes down the server.
func (srv *Server) Quit() {
srv.listener.Close()
}
// SetInitialInstanceState sets the state that any new instances will be started in.
func (srv *Server) SetInitialInstanceState(state ec2.InstanceState) {
srv.mu.Lock()
srv.initialInstanceState = state
srv.mu.Unlock()
}
// URL returns the URL of the server.
func (srv *Server) URL() string {
return srv.url
}
// serveHTTP serves the EC2 protocol.
func (srv *Server) serveHTTP(w http.ResponseWriter, req *http.Request) {
req.ParseForm()
a := srv.newAction()
a.RequestId = fmt.Sprintf("req%d", srv.reqId.next())
a.Request = req.Form
// Methods on Server that deal with parsing user data
// may fail. To save on error handling code, we allow these
// methods to call fatalf, which will panic with an *ec2.Error
// which will be caught here and returned
// to the client as a properly formed EC2 error.
defer func() {
switch err := recover().(type) {
case *ec2.Error:
a.Err = err
err.RequestId = a.RequestId
writeError(w, err)
case nil:
default:
panic(err)
}
}()
f := actions[req.Form.Get("Action")]
if f == nil {
fatalf(400, "InvalidParameterValue", "Unrecognized Action")
}
response := f(srv, w, req, a.RequestId)
a.Response = response
w.Header().Set("Content-Type", `xml version="1.0" encoding="UTF-8"`)
xmlMarshal(w, response)
}
// Instance returns the instance for the given instance id.
// It returns nil if there is no such instance.
func (srv *Server) Instance(id string) *Instance {
srv.mu.Lock()
defer srv.mu.Unlock()
return srv.instances[id]
}
// writeError writes an appropriate error response.
// TODO how should we deal with errors when the
// error itself is potentially generated by backend-agnostic
// code?
func writeError(w http.ResponseWriter, err *ec2.Error) {
// Error encapsulates an error returned by EC2.
// TODO merge with ec2.Error when xml supports ignoring a field.
type ec2error struct {
Code string // EC2 error code ("UnsupportedOperation", ...)
Message string // The human-oriented error message
RequestId string
}
type Response struct {
RequestId string
Errors []ec2error `xml:"Errors>Error"`
}
w.Header().Set("Content-Type", `xml version="1.0" encoding="UTF-8"`)
w.WriteHeader(err.StatusCode)
xmlMarshal(w, Response{
RequestId: err.RequestId,
Errors: []ec2error{{
Code: err.Code,
Message: err.Message,
}},
})
}
// xmlMarshal is the same as xml.Marshal except that
// it panics on error. The marshalling should not fail,
// but we want to know if it does.
func xmlMarshal(w io.Writer, x interface{}) {
if err := xml.NewEncoder(w).Encode(x); err != nil {
panic(fmt.Errorf("error marshalling %#v: %v", x, err))
}
}
// formToGroups parses a set of SecurityGroup form values
// as found in a RunInstances request, and returns the resulting
// slice of security groups.
// It calls fatalf if a group is not found.
func (srv *Server) formToGroups(form url.Values) []*securityGroup {
var groups []*securityGroup
for name, values := range form {
switch {
case strings.HasPrefix(name, "SecurityGroupId."):
if g := srv.groups[values[0]]; g != nil {
groups = append(groups, g)
} else {
fatalf(400, "InvalidGroup.NotFound", "unknown group id %q", values[0])
}
case strings.HasPrefix(name, "SecurityGroup."):
var found *securityGroup
for _, g := range srv.groups {
if g.name == values[0] {
found = g
}
}
if found == nil {
fatalf(400, "InvalidGroup.NotFound", "unknown group name %q", values[0])
}
groups = append(groups, found)
}
}
return groups
}
// runInstances implements the EC2 RunInstances entry point.
func (srv *Server) runInstances(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
min := atoi(req.Form.Get("MinCount"))
max := atoi(req.Form.Get("MaxCount"))
if min < 0 || max < 1 {
fatalf(400, "InvalidParameterValue", "bad values for MinCount or MaxCount")
}
if min > max {
fatalf(400, "InvalidParameterCombination", "MinCount is greater than MaxCount")
}
var userData []byte
if data := req.Form.Get("UserData"); data != "" {
var err error
userData, err = b64.DecodeString(data)
if err != nil {
fatalf(400, "InvalidParameterValue", "bad UserData value: %v", err)
}
}
// TODO attributes still to consider:
// ImageId: accept anything, we can verify later
// KeyName ?
// InstanceType ?
// KernelId ?
// RamdiskId ?
// AvailabilityZone ?
// GroupName tag
// Monitoring ignore?
// SubnetId ?
// DisableAPITermination bool
// ShutdownBehavior string
// PrivateIPAddress string
srv.mu.Lock()
defer srv.mu.Unlock()
// make sure that form fields are correct before creating the reservation.
instType := req.Form.Get("InstanceType")
imageId := req.Form.Get("ImageId")
r := srv.newReservation(srv.formToGroups(req.Form))
var resp ec2.RunInstancesResp
resp.RequestId = reqId
resp.ReservationId = r.id
resp.OwnerId = ownerId
for i := 0; i < max; i++ {
inst := srv.newInstance(r, instType, imageId, srv.initialInstanceState)
inst.UserData = userData
resp.Instances = append(resp.Instances, inst.ec2instance())
}
return &resp
}
func (srv *Server) group(group ec2.SecurityGroup) *securityGroup {
if group.Id != "" {
return srv.groups[group.Id]
}
for _, g := range srv.groups {
if g.name == group.Name {
return g
}
}
return nil
}
// NewInstances creates n new instances in srv with the given instance type,
// image ID, initial state and security groups. If any group does not already
// exist, it will be created. NewInstances returns the ids of the new instances.
func (srv *Server) NewInstances(n int, instType string, imageId string, state ec2.InstanceState, groups []ec2.SecurityGroup) []string {
srv.mu.Lock()
defer srv.mu.Unlock()
rgroups := make([]*securityGroup, len(groups))
for i, group := range groups {
g := srv.group(group)
if g == nil {
fatalf(400, "InvalidGroup.NotFound", "no such group %v", g)
}
rgroups[i] = g
}
r := srv.newReservation(rgroups)
ids := make([]string, n)
for i := 0; i < n; i++ {
inst := srv.newInstance(r, instType, imageId, state)
ids[i] = inst.id
}
return ids
}
func (srv *Server) newInstance(r *reservation, instType string, imageId string, state ec2.InstanceState) *Instance {
inst := &Instance{
id: fmt.Sprintf("i-%d", srv.maxId.next()),
instType: instType,
imageId: imageId,
state: state,
reservation: r,
}
srv.instances[inst.id] = inst
r.instances[inst.id] = inst
return inst
}
func (srv *Server) newReservation(groups []*securityGroup) *reservation {
r := &reservation{
id: fmt.Sprintf("r-%d", srv.reservationId.next()),
instances: make(map[string]*Instance),
groups: groups,
}
srv.reservations[r.id] = r
return r
}
func (srv *Server) terminateInstances(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
srv.mu.Lock()
defer srv.mu.Unlock()
var resp ec2.TerminateInstancesResp
resp.RequestId = reqId
var insts []*Instance
for attr, vals := range req.Form {
if strings.HasPrefix(attr, "InstanceId.") {
id := vals[0]
inst := srv.instances[id]
if inst == nil {
fatalf(400, "InvalidInstanceID.NotFound", "no such instance id %q", id)
}
insts = append(insts, inst)
}
}
for _, inst := range insts {
resp.StateChanges = append(resp.StateChanges, inst.terminate())
}
return &resp
}
func (inst *Instance) terminate() (d ec2.InstanceStateChange) {
d.PreviousState = inst.state
inst.state = ShuttingDown
d.CurrentState = inst.state
d.InstanceId = inst.id
return d
}
func (inst *Instance) ec2instance() ec2.Instance {
return ec2.Instance{
InstanceId: inst.id,
InstanceType: inst.instType,
ImageId: inst.imageId,
DNSName: fmt.Sprintf("%s.example.com", inst.id),
// TODO the rest
}
}
func (inst *Instance) matchAttr(attr, value string) (ok bool, err error) {
switch attr {
case "architecture":
return value == "i386", nil
case "instance-id":
return inst.id == value, nil
case "group-id":
for _, g := range inst.reservation.groups {
if g.id == value {
return true, nil
}
}
return false, nil
case "group-name":
for _, g := range inst.reservation.groups {
if g.name == value {
return true, nil
}
}
return false, nil
case "image-id":
return value == inst.imageId, nil
case "instance-state-code":
code, err := strconv.Atoi(value)
if err != nil {
return false, err
}
return code&0xff == inst.state.Code, nil
case "instance-state-name":
return value == inst.state.Name, nil
}
return false, fmt.Errorf("unknown attribute %q", attr)
}
var (
Pending = ec2.InstanceState{0, "pending"}
Running = ec2.InstanceState{16, "running"}
ShuttingDown = ec2.InstanceState{32, "shutting-down"}
Terminated = ec2.InstanceState{16, "terminated"}
Stopped = ec2.InstanceState{16, "stopped"}
)
func (srv *Server) createSecurityGroup(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
name := req.Form.Get("GroupName")
if name == "" {
fatalf(400, "InvalidParameterValue", "empty security group name")
}
srv.mu.Lock()
defer srv.mu.Unlock()
if srv.group(ec2.SecurityGroup{Name: name}) != nil {
fatalf(400, "InvalidGroup.Duplicate", "group %q already exists", name)
}
g := &securityGroup{
name: name,
description: req.Form.Get("GroupDescription"),
id: fmt.Sprintf("sg-%d", srv.groupId.next()),
perms: make(map[permKey]bool),
}
srv.groups[g.id] = g
// we define a local type for this because ec2.CreateSecurityGroupResp
// contains SecurityGroup, but the response to this request
// should not contain the security group name.
type CreateSecurityGroupResponse struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"`
GroupId string `xml:"groupId"`
}
r := &CreateSecurityGroupResponse{
RequestId: reqId,
Return: true,
GroupId: g.id,
}
return r
}
func (srv *Server) notImplemented(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
fatalf(500, "InternalError", "not implemented")
panic("not reached")
}
func (srv *Server) describeInstances(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
srv.mu.Lock()
defer srv.mu.Unlock()
insts := make(map[*Instance]bool)
for name, vals := range req.Form {
if !strings.HasPrefix(name, "InstanceId.") {
continue
}
inst := srv.instances[vals[0]]
if inst == nil {
fatalf(400, "InvalidInstanceID.NotFound", "instance %q not found", vals[0])
}
insts[inst] = true
}
f := newFilter(req.Form)
var resp ec2.DescribeInstancesResp
resp.RequestId = reqId
for _, r := range srv.reservations {
var instances []ec2.Instance
for _, inst := range r.instances {
if len(insts) > 0 && !insts[inst] {
continue
}
ok, err := f.ok(inst)
if ok {
instances = append(instances, inst.ec2instance())
} else if err != nil {
fatalf(400, "InvalidParameterValue", "describe instances: %v", err)
}
}
if len(instances) > 0 {
var groups []ec2.SecurityGroup
for _, g := range r.groups {
groups = append(groups, g.ec2SecurityGroup())
}
resp.Reservations = append(resp.Reservations, ec2.Reservation{
ReservationId: r.id,
OwnerId: ownerId,
Instances: instances,
SecurityGroups: groups,
})
}
}
return &resp
}
func (srv *Server) describeSecurityGroups(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
// BUG similar bug to describeInstances, but for GroupName and GroupId
srv.mu.Lock()
defer srv.mu.Unlock()
var groups []*securityGroup
for name, vals := range req.Form {
var g ec2.SecurityGroup
switch {
case strings.HasPrefix(name, "GroupName."):
g.Name = vals[0]
case strings.HasPrefix(name, "GroupId."):
g.Id = vals[0]
default:
continue
}
sg := srv.group(g)
if sg == nil {
fatalf(400, "InvalidGroup.NotFound", "no such group %v", g)
}
groups = append(groups, sg)
}
if len(groups) == 0 {
for _, g := range srv.groups {
groups = append(groups, g)
}
}
f := newFilter(req.Form)
var resp ec2.SecurityGroupsResp
resp.RequestId = reqId
for _, group := range groups {
ok, err := f.ok(group)
if ok {
resp.Groups = append(resp.Groups, ec2.SecurityGroupInfo{
OwnerId: ownerId,
SecurityGroup: group.ec2SecurityGroup(),
Description: group.description,
IPPerms: group.ec2Perms(),
})
} else if err != nil {
fatalf(400, "InvalidParameterValue", "describe security groups: %v", err)
}
}
return &resp
}
func (srv *Server) authorizeSecurityGroupIngress(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
srv.mu.Lock()
defer srv.mu.Unlock()
g := srv.group(ec2.SecurityGroup{
Name: req.Form.Get("GroupName"),
Id: req.Form.Get("GroupId"),
})
if g == nil {
fatalf(400, "InvalidGroup.NotFound", "group not found")
}
perms := srv.parsePerms(req)
for _, p := range perms {
if g.perms[p] {
fatalf(400, "InvalidPermission.Duplicate", "Permission has already been authorized on the specified group")
}
}
for _, p := range perms {
g.perms[p] = true
}
return &ec2.SimpleResp{
XMLName: xml.Name{"", "AuthorizeSecurityGroupIngressResponse"},
RequestId: reqId,
}
}
func (srv *Server) revokeSecurityGroupIngress(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
srv.mu.Lock()
defer srv.mu.Unlock()
g := srv.group(ec2.SecurityGroup{
Name: req.Form.Get("GroupName"),
Id: req.Form.Get("GroupId"),
})
if g == nil {
fatalf(400, "InvalidGroup.NotFound", "group not found")
}
perms := srv.parsePerms(req)
// Note EC2 does not give an error if asked to revoke an authorization
// that does not exist.
for _, p := range perms {
delete(g.perms, p)
}
return &ec2.SimpleResp{
XMLName: xml.Name{"", "RevokeSecurityGroupIngressResponse"},
RequestId: reqId,
}
}
var secGroupPat = regexp.MustCompile(`^sg-[a-z0-9]+$`)
var ipPat = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$`)
var ownerIdPat = regexp.MustCompile(`^[0-9]+$`)
// parsePerms returns a slice of permKey values extracted
// from the permission fields in req.
func (srv *Server) parsePerms(req *http.Request) []permKey {
// perms maps an index found in the form to its associated
// IPPerm. For instance, the form value with key
// "IpPermissions.3.FromPort" will be stored in perms[3].FromPort
perms := make(map[int]ec2.IPPerm)
type subgroupKey struct {
id1, id2 int
}
// Each IPPerm can have many source security groups. The form key
// for a source security group contains two indices: the index
// of the IPPerm and the sub-index of the security group. The
// sourceGroups map maps from a subgroupKey containing these
// two indices to the associated security group. For instance,
// the form value with key "IPPermissions.3.Groups.2.GroupName"
// will be stored in sourceGroups[subgroupKey{3, 2}].Name.
sourceGroups := make(map[subgroupKey]ec2.UserSecurityGroup)
// For each value in the form we store its associated information in the
// above maps. The maps are necessary because the form keys may
// arrive in any order, and the indices are not
// necessarily sequential or even small.
for name, vals := range req.Form {
val := vals[0]
var id1 int
var rest string
if x, _ := fmt.Sscanf(name, "IpPermissions.%d.%s", &id1, &rest); x != 2 {
continue
}
ec2p := perms[id1]
switch {
case rest == "FromPort":
ec2p.FromPort = atoi(val)
case rest == "ToPort":
ec2p.ToPort = atoi(val)
case rest == "IpProtocol":
switch val {
case "tcp", "udp", "icmp":
ec2p.Protocol = val
default:
// check it's a well formed number
atoi(val)
ec2p.Protocol = val
}
case strings.HasPrefix(rest, "Groups."):
k := subgroupKey{id1: id1}
if x, _ := fmt.Sscanf(rest[len("Groups."):], "%d.%s", &k.id2, &rest); x != 2 {
continue
}
g := sourceGroups[k]
switch rest {
case "UserId":
// BUG if the user id is blank, this does not conform to the
// way that EC2 handles it - a specified but blank owner id
// can cause RevokeSecurityGroupIngress to fail with
// "group not found" even if the security group id has been
// correctly specified.
// By failing here, we ensure that we fail early in this case.
if !ownerIdPat.MatchString(val) {
fatalf(400, "InvalidUserID.Malformed", "Invalid user ID: %q", val)
}
g.OwnerId = val
case "GroupName":
g.Name = val
case "GroupId":
if !secGroupPat.MatchString(val) {
fatalf(400, "InvalidGroupId.Malformed", "Invalid group ID: %q", val)
}
g.Id = val
default:
fatalf(400, "UnknownParameter", "unknown parameter %q", name)
}
sourceGroups[k] = g
case strings.HasPrefix(rest, "IpRanges."):
var id2 int
if x, _ := fmt.Sscanf(rest[len("IpRanges."):], "%d.%s", &id2, &rest); x != 2 {
continue
}
switch rest {
case "CidrIp":
if !ipPat.MatchString(val) {
fatalf(400, "InvalidPermission.Malformed", "Invalid IP range: %q", val)
}
ec2p.SourceIPs = append(ec2p.SourceIPs, val)
default:
fatalf(400, "UnknownParameter", "unknown parameter %q", name)
}
default:
fatalf(400, "UnknownParameter", "unknown parameter %q", name)
}
perms[id1] = ec2p
}
// Associate each set of source groups with its IPPerm.
for k, g := range sourceGroups {
p := perms[k.id1]
p.SourceGroups = append(p.SourceGroups, g)
perms[k.id1] = p
}
// Now that we have built up the IPPerms we need, we check for
// parameter errors and build up a permKey for each permission,
// looking up security groups from srv as we do so.
var result []permKey
for _, p := range perms {
if p.FromPort > p.ToPort {
fatalf(400, "InvalidParameterValue", "invalid port range")
}
k := permKey{
protocol: p.Protocol,
fromPort: p.FromPort,
toPort: p.ToPort,
}
for _, g := range p.SourceGroups {
if g.OwnerId != "" && g.OwnerId != ownerId {
fatalf(400, "InvalidGroup.NotFound", "group %q not found", g.Name)
}
var ec2g ec2.SecurityGroup
switch {
case g.Id != "":
ec2g.Id = g.Id
case g.Name != "":
ec2g.Name = g.Name
}
k.group = srv.group(ec2g)
if k.group == nil {
fatalf(400, "InvalidGroup.NotFound", "group %v not found", g)
}
result = append(result, k)
}
k.group = nil
for _, ip := range p.SourceIPs {
k.ipAddr = ip
result = append(result, k)
}
}
return result
}
func (srv *Server) deleteSecurityGroup(w http.ResponseWriter, req *http.Request, reqId string) interface{} {
srv.mu.Lock()
defer srv.mu.Unlock()
g := srv.group(ec2.SecurityGroup{
Name: req.Form.Get("GroupName"),
Id: req.Form.Get("GroupId"),
})
if g == nil {
fatalf(400, "InvalidGroup.NotFound", "group not found")
}
for _, r := range srv.reservations {
for _, h := range r.groups {
if h == g && r.hasRunningMachine() {
fatalf(500, "InvalidGroup.InUse", "group is currently in use by a running instance")
}
}
}
for _, sg := range srv.groups {
// If a group refers to itself, it's ok to delete it.
if sg == g {
continue
}
for k := range sg.perms {
if k.group == g {
fatalf(500, "InvalidGroup.InUse", "group is currently in use by group %q", sg.id)
}
}
}
delete(srv.groups, g.id)
return &ec2.SimpleResp{
XMLName: xml.Name{"", "DeleteSecurityGroupResponse"},
RequestId: reqId,
}
}
func (r *reservation) hasRunningMachine() bool {
for _, inst := range r.instances {
if inst.state.Code != ShuttingDown.Code && inst.state.Code != Terminated.Code {
return true
}
}
return false
}
type counter int
func (c *counter) next() (i int) {
i = int(*c)
(*c)++
return
}
// atoi is like strconv.Atoi but is fatal if the
// string is not well formed.
func atoi(s string) int {
i, err := strconv.Atoi(s)
if err != nil {
fatalf(400, "InvalidParameterValue", "bad number: %v", err)
}
return i
}
func fatalf(statusCode int, code string, f string, a ...interface{}) {
panic(&ec2.Error{
StatusCode: statusCode,
Code: code,
Message: fmt.Sprintf(f, a...),
})
}

22
vendor/github.com/goamz/goamz/ec2/export_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,22 +0,0 @@
package ec2
import (
"github.com/goamz/goamz/aws"
"time"
)
func Sign(auth aws.Auth, method, path string, params map[string]string, host string) {
sign(auth, method, path, params, host)
}
func fixedTime() time.Time {
return time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC)
}
func FakeTime(fakeIt bool) {
if fakeIt {
timeNow = fixedTime
} else {
timeNow = time.Now
}
}

1084
vendor/github.com/goamz/goamz/ec2/responses_test.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

45
vendor/github.com/goamz/goamz/ec2/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,45 +0,0 @@
package ec2
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"github.com/goamz/goamz/aws"
"sort"
"strings"
)
// ----------------------------------------------------------------------------
// EC2 signing (http://goo.gl/fQmAN)
var b64 = base64.StdEncoding
func sign(auth aws.Auth, method, path string, params map[string]string, host string) {
params["AWSAccessKeyId"] = auth.AccessKey
params["SignatureVersion"] = "2"
params["SignatureMethod"] = "HmacSHA256"
if auth.Token() != "" {
params["SecurityToken"] = auth.Token()
}
// AWS specifies that the parameters in a signed request must
// be provided in the natural order of the keys. This is distinct
// from the natural order of the encoded value of key=value.
// Percent and equals affect the sorting order.
var keys, sarray []string
for k, _ := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(params[k]))
}
joined := strings.Join(sarray, "&")
payload := method + "\n" + host + "\n" + path + "\n" + joined
hash := hmac.New(sha256.New, []byte(auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}

68
vendor/github.com/goamz/goamz/ec2/sign_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,68 +0,0 @@
package ec2_test
import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/ec2"
. "gopkg.in/check.v1"
)
// EC2 ReST authentication docs: http://goo.gl/fQmAN
var testAuth = aws.Auth{AccessKey: "user", SecretKey: "secret"}
func (s *S) TestBasicSignature(c *C) {
params := map[string]string{}
ec2.Sign(testAuth, "GET", "/path", params, "localhost")
c.Assert(params["SignatureVersion"], Equals, "2")
c.Assert(params["SignatureMethod"], Equals, "HmacSHA256")
expected := "6lSe5QyXum0jMVc7cOUz32/52ZnL7N5RyKRk/09yiK4="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestParamSignature(c *C) {
params := map[string]string{
"param1": "value1",
"param2": "value2",
"param3": "value3",
}
ec2.Sign(testAuth, "GET", "/path", params, "localhost")
expected := "XWOR4+0lmK8bD8CGDGZ4kfuSPbb2JibLJiCl/OPu1oU="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestManyParams(c *C) {
params := map[string]string{
"param1": "value10",
"param2": "value2",
"param3": "value3",
"param4": "value4",
"param5": "value5",
"param6": "value6",
"param7": "value7",
"param8": "value8",
"param9": "value9",
"param10": "value1",
}
ec2.Sign(testAuth, "GET", "/path", params, "localhost")
expected := "di0sjxIvezUgQ1SIL6i+C/H8lL+U0CQ9frLIak8jkVg="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestEscaping(c *C) {
params := map[string]string{"Nonce": "+ +"}
ec2.Sign(testAuth, "GET", "/path", params, "localhost")
c.Assert(params["Nonce"], Equals, "+ +")
expected := "bqffDELReIqwjg/W0DnsnVUmfLK4wXVLO4/LuG+1VFA="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestSignatureExample1(c *C) {
params := map[string]string{
"Timestamp": "2009-02-01T12:53:20+00:00",
"Version": "2007-11-07",
"Action": "ListDomains",
}
ec2.Sign(aws.Auth{AccessKey: "access", SecretKey: "secret"}, "GET", "/", params, "sdb.amazonaws.com")
expected := "okj96/5ucWBSc1uR2zXVfm6mDHtgfNv657rRtt/aunQ="
c.Assert(params["Signature"], Equals, expected)
}

399
vendor/github.com/goamz/goamz/ec2/vpc.go сгенерированный поставляемый
Просмотреть файл

@@ -1,399 +0,0 @@
package ec2
// RouteTable describes a route table which contains a set of rules, called routes
// that are used to determine where network traffic is directed.
//
// See http://goo.gl/bI9hkg for more details.
type RouteTable struct {
Id string `xml:"routeTableId"`
VpcId string `xml:"vpcId"`
Routes []Route `xml:"routeSet>item"`
Associations []RouteTableAssociation `xml:"associationSet>item"`
PropagatingVgws []PropagatingVgw `xml:"propagatingVgwSet>item"`
Tags []Tag `xml:"tagSet>item"`
}
// Route describes a route in a route table.
//
// See http://goo.gl/hE5Kxe for more details.
type Route struct {
DestinationCidrBlock string `xml:"destinationCidrBlock"` // The CIDR block used for the destination match.
GatewayId string `xml:"gatewayId"` // The ID of a gateway attached to your VPC.
InstanceId string `xml:"instanceId"` // The ID of a NAT instance in your VPC.
InstanceOwnerId string `xml:"instanceOwnerId"` // The AWS account ID of the owner of the instance.
NetworkInterfaceId string `xml:"networkInterfaceId"` // The ID of the network interface.
State string `xml:"state"` // The state of the route. Valid values: active | blackhole
Origin string `xml:"origin"` // Describes how the route was created. Valid values: Valid values: CreateRouteTable | CreateRoute | EnableVgwRoutePropagation
VpcPeeringConnectionId string `xml:"vpcPeeringConnectionId"` // The ID of the VPC peering connection.
}
// RouteTableAssociation describes an association between a route table and a subnet.
//
// See http://goo.gl/BZB8o8 for more details.
type RouteTableAssociation struct {
Id string `xml:"routeTableAssociationId"` // The ID of the association between a route table and a subnet.
RouteTableId string `xml:"routeTableId"` // The ID of the route table.
SubnetId string `xml:"subnetId"` // The ID of the subnet.
Main bool `xml:"main"` // Indicates whether this is the main route table.
}
// PropagatingVgw describes a virtual private gateway propagating route.
//
// See http://goo.gl/myGQtG for more details.
type PropagatingVgw struct {
GatewayId string `xml:"gatewayID"`
}
// CreateRouteTableResp represents a response from a CreateRouteTable request
//
// See http://goo.gl/LD0TqP for more details.
type CreateRouteTableResp struct {
RequestId string `xml:"requestId"`
RouteTable RouteTable `xml:"routeTable"`
}
// CreateRouteTable creates a route table for the specified VPC.
// After you create a route table, you can add routes and associate the table with a subnet.
//
// See http://goo.gl/V9h6gE for more details..
func (ec2 *EC2) CreateRouteTable(vpcId string) (resp *CreateRouteTableResp, err error) {
params := makeParams("CreateRouteTable")
params["VpcId"] = vpcId
resp = &CreateRouteTableResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DescribeRouteTablesResp represents a response from a DescribeRouteTables call
//
// See http://goo.gl/T3tVsg for more details.
type DescribeRouteTablesResp struct {
RequestId string `xml:"requestId"`
RouteTables []RouteTable `xml:"routeTableSet>item"`
}
// DescribeRouteTables describes one or more of your route tables
//
// See http://goo.gl/S0RVos for more details.
func (ec2 *EC2) DescribeRouteTables(routeTableIds []string, filter *Filter) (resp *DescribeRouteTablesResp, err error) {
params := makeParams("DescribeRouteTables")
addParamsList(params, "RouteTableId", routeTableIds)
filter.addParams(params)
resp = &DescribeRouteTablesResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// AssociateRouteTableResp represents a response from an AssociateRouteTable call
//
// See http://goo.gl/T4KlYk for more details.
type AssociateRouteTableResp struct {
RequestId string `xml:"requestId"`
AssociationId string `xml:"associationId"`
}
// AssociateRouteTable associates a subnet with a route table.
//
// The subnet and route table must be in the same VPC. This association causes
// traffic originating from the subnet to be routed according to the routes
// in the route table. The action returns an association ID, which you need in
// order to disassociate the route table from the subnet later.
// A route table can be associated with multiple subnets.
//
// See http://goo.gl/bfnONU for more details.
func (ec2 *EC2) AssociateRouteTable(routeTableId, subnetId string) (resp *AssociateRouteTableResp, err error) {
params := makeParams("AssociateRouteTable")
params["RouteTableId"] = routeTableId
params["SubnetId"] = subnetId
resp = &AssociateRouteTableResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DisassociateRouteTableResp represents the response from a DisassociateRouteTable request
//
// See http://goo.gl/1v4reT for more details.
type DisassociateRouteTableResp struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"` // True if the request succeeds
}
// DisassociateRouteTable disassociates a subnet from a route table.
//
// See http://goo.gl/A4NJum for more details.
func (ec2 *EC2) DisassociateRouteTable(associationId string) (resp *DisassociateRouteTableResp, err error) {
params := makeParams("DisassociateRouteTable")
params["AssociationId"] = associationId
resp = &DisassociateRouteTableResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// ReplaceRouteTableAssociationResp represents a response from a ReplaceRouteTableAssociation call
//
// See http://goo.gl/VhILGe for more details.
type ReplaceRouteTableAssociationResp struct {
RequestId string `xml:"requestId"`
NewAssociationId string `xml:"newAssociationId"`
}
// ReplaceRouteTableAssociation changes the route table associated with a given subnet in a VPC.
//
// See http://goo.gl/kiit8j for more details.
func (ec2 *EC2) ReplaceRouteTableAssociation(associationId, routeTableId string) (resp *ReplaceRouteTableAssociationResp, err error) {
params := makeParams("ReplaceRouteTableAssociation")
params["AssociationId"] = associationId
params["RouteTableId"] = routeTableId
resp = &ReplaceRouteTableAssociationResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DeleteRouteTableResp represents a response from a DeleteRouteTable request
//
// See http://goo.gl/b8usig for more details.
type DeleteRouteTableResp struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"` // True if the request succeeds
}
// DeleteRouteTable deletes the specified route table.
// You must disassociate the route table from any subnets before you can delete it.
// You can't delete the main route table.
//
// See http://goo.gl/crHxT2 for more details.
func (ec2 *EC2) DeleteRouteTable(routeTableId string) (resp *DeleteRouteTableResp, err error) {
params := makeParams("DeleteRouteTable")
params["RouteTableId"] = routeTableId
resp = &DeleteRouteTableResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// VPC describes a VPC.
//
// See http://goo.gl/WjX0Es for more details.
type VPC struct {
CidrBlock string `xml:"cidrBlock"`
DHCPOptionsID string `xml:"dhcpOptionsId"`
State string `xml:"state"`
VpcId string `xml:"vpcId"`
InstanceTenancy string `xml:"instanceTenancy"`
IsDefault bool `xml:"isDefault"`
Tags []Tag `xml:"tagSet>item"`
}
// CreateVpcResp represents a response from a CreateVpcResp request
//
// See http://goo.gl/QoK11F for more details.
type CreateVpcResp struct {
RequestId string `xml:"requestId"`
VPC VPC `xml:"vpc"` // Information about the VPC.
}
// CreateVpc creates a VPC with the specified CIDR block.
//
// The smallest VPC you can create uses a /28 netmask (16 IP addresses),
// and the largest uses a /16 netmask (65,536 IP addresses).
//
// By default, each instance you launch in the VPC has the default DHCP options,
// which includes only a default DNS server that Amazon provides (AmazonProvidedDNS).
//
// See http://goo.gl/QoK11F for more details.
func (ec2 *EC2) CreateVpc(cidrBlock, instanceTenancy string) (resp *CreateVpcResp, err error) {
params := makeParams("CreateVpc")
params["CidrBlock"] = cidrBlock
if instanceTenancy != "" {
params["InstanceTenancy"] = instanceTenancy
}
resp = &CreateVpcResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DeleteVpcResp represents a response from a DeleteVpc request
//
// See http://goo.gl/qawyrz for more details.
type DeleteVpcResp struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"` // True if the request succeeds
}
// DeleteVpc deletes the specified VPC.
//
// You must detach or delete all gateways and resources that are associated with
// the VPC before you can delete it. For example, you must terminate all
// instances running in the VPC, delete all security groups associated with
// the VPC (except the default one), delete all route tables associated with
// the VPC (except the default one), and so on.
//
// See http://goo.gl/qawyrz for more details.
func (ec2 *EC2) DeleteVpc(vpcId string) (resp *DeleteVpcResp, err error) {
params := makeParams("DeleteVpc")
params["VpcId"] = vpcId
resp = &DeleteVpcResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DescribeVpcsResp represents a response from a DescribeVpcs request
//
// See http://goo.gl/DWQWvZ for more details.
type DescribeVpcsResp struct {
RequestId string `xml:"requestId"`
VPCs []VPC `xml:"vpcSet>item"` // Information about one or more VPCs.
}
// DescribeVpcs describes one or more of your VPCs.
//
// See http://goo.gl/DWQWvZ for more details.
func (ec2 *EC2) DescribeVpcs(vpcIds []string, filter *Filter) (resp *DescribeVpcsResp, err error) {
params := makeParams("DescribeVpcs")
addParamsList(params, "VpcId", vpcIds)
filter.addParams(params)
resp = &DescribeVpcsResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// DeleteRouteResp represents a response from a DeleteRoute request
//
// See http://goo.gl/Uqyt3w for more details.
type DeleteRouteResp struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"` // True if the request succeeds
}
// DeleteRoute deletes the specified route from the specified route table.
//
// See http://goo.gl/Uqyt3w for more details.
func (ec2 *EC2) DeleteRoute(routeTableId, destinationCidrBlock string) (resp *DeleteRouteResp, err error) {
params := makeParams("DeleteRoute")
params["RouteTableId"] = routeTableId
params["DestinationCidrBlock"] = destinationCidrBlock
resp = &DeleteRouteResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// CreateRouteResp represents a response from a CreateRoute request
//
// See http://goo.gl/c6Bg7e for more details.
type CreateRouteResp struct {
RequestId string `xml:"requestId"`
Return bool `xml:"return"` // True if the request succeeds
}
// CreateRoute structure contains the options for a CreateRoute API call.
type CreateRoute struct {
DestinationCidrBlock string
GatewayId string
InstanceId string
NetworkInterfaceId string
VpcPeeringConnectionId string
}
// CreateRoute creates a route in a route table within a VPC.
// You must specify one of the following targets: Internet gateway or virtual
// private gateway, NAT instance, VPC peering connection, or network interface.
//
// See http://goo.gl/c6Bg7e for more details.
func (ec2 *EC2) CreateRoute(routeTableId string, options *CreateRoute) (resp *CreateRouteResp, err error) {
params := makeParams("CreateRoute")
params["RouteTableId"] = routeTableId
if options.DestinationCidrBlock != "" {
params["DestinationCidrBlock"] = options.DestinationCidrBlock
}
if options.GatewayId != "" {
params["GatewayId"] = options.GatewayId
}
if options.InstanceId != "" {
params["InstanceId"] = options.InstanceId
}
if options.NetworkInterfaceId != "" {
params["NetworkInterfaceId"] = options.NetworkInterfaceId
}
if options.VpcPeeringConnectionId != "" {
params["VpcPeeringConnectionId"] = options.VpcPeeringConnectionId
}
resp = &CreateRouteResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}
// Subnet describes a subnet
//
// See http://goo.gl/bifW4R
type Subnet struct {
AvailabilityZone string `xml:"availabilityZone"`
AvailableIpAddressCount int `xml:"availableIpAddressCount"`
CidrBlock string `xml:"cidrBlock"`
DefaultForAZ bool `xml:"defaultForAz"`
MapPublicIpOnLaunch bool `xml:"mapPublicIpOnLaunch"`
State string `xml:"state"`
SubnetId string `xml:"subnetId"`
Tags []Tag `xml:"tagSet>item"`
VpcId string `xml:"vpcId"`
}
// DescribeSubnetsResp represents a response from a DescribeSubnets request
//
// See https://goo.gl/1s0UQd for more details.
type DescribeSubnetsResp struct {
RequestId string `xml:"requestId"`
Subnets []Subnet `xml:"subnetSet>item"`
}
// DescribeSubnets describes one or more Subnets.
//
// See https://goo.gl/1s0UQd for more details.
func (ec2 *EC2) DescribeSubnets(subnetIds []string, filter *Filter) (resp *DescribeSubnetsResp, err error) {
params := makeParams("DescribeSubnets")
addParamsList(params, "SubnetId", subnetIds)
filter.addParams(params)
resp = &DescribeSubnetsResp{}
err = ec2.query(params, resp)
if err != nil {
return nil, err
}
return
}

224
vendor/github.com/goamz/goamz/ec2/vpc_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,224 +0,0 @@
package ec2_test
import (
"github.com/goamz/goamz/ec2"
. "gopkg.in/check.v1"
)
func (s *S) TestCreateRouteTable(c *C) {
testServer.Response(200, nil, CreateRouteTableExample)
resp, err := s.ec2.CreateRouteTable("vpc-11ad4878")
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"CreateRouteTable"})
c.Assert(req.Form["VpcId"], DeepEquals, []string{"vpc-11ad4878"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "59abcd43-35bd-4eac-99ed-be587EXAMPLE")
c.Assert(resp.RouteTable.Id, Equals, "rtb-f9ad4890")
c.Assert(resp.RouteTable.VpcId, Equals, "vpc-11ad4878")
c.Assert(resp.RouteTable.Routes, HasLen, 1)
c.Assert(resp.RouteTable.Routes[0], DeepEquals, ec2.Route{
DestinationCidrBlock: "10.0.0.0/22",
GatewayId: "local",
State: "active",
})
c.Assert(resp.RouteTable.Associations, HasLen, 0)
c.Assert(resp.RouteTable.Tags, HasLen, 0)
}
func (s *S) TestDescribeRouteTables(c *C) {
testServer.Response(200, nil, DescribeRouteTablesExample)
filter := ec2.NewFilter()
filter.Add("key1", "value1")
filter.Add("key2", "value2", "value3")
resp, err := s.ec2.DescribeRouteTables([]string{"rt1", "rt2"}, nil)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeRouteTables"})
c.Assert(req.Form["RouteTableId.1"], DeepEquals, []string{"rt1"})
c.Assert(req.Form["RouteTableId.2"], DeepEquals, []string{"rt2"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "6f570b0b-9c18-4b07-bdec-73740dcf861aEXAMPLE")
c.Assert(resp.RouteTables, HasLen, 2)
rt1 := resp.RouteTables[0]
c.Assert(rt1.Id, Equals, "rtb-13ad487a")
c.Assert(rt1.VpcId, Equals, "vpc-11ad4878")
c.Assert(rt1.Routes, DeepEquals, []ec2.Route{
{DestinationCidrBlock: "10.0.0.0/22", GatewayId: "local", State: "active", Origin: "CreateRouteTable"},
})
c.Assert(rt1.Associations, DeepEquals, []ec2.RouteTableAssociation{
{Id: "rtbassoc-12ad487b", RouteTableId: "rtb-13ad487a", Main: true},
})
rt2 := resp.RouteTables[1]
c.Assert(rt2.Id, Equals, "rtb-f9ad4890")
c.Assert(rt2.VpcId, Equals, "vpc-11ad4878")
c.Assert(rt2.Routes, DeepEquals, []ec2.Route{
{DestinationCidrBlock: "10.0.0.0/22", GatewayId: "local", State: "active", Origin: "CreateRouteTable"},
{DestinationCidrBlock: "0.0.0.0/0", GatewayId: "igw-eaad4883", State: "active"},
})
c.Assert(rt2.Associations, DeepEquals, []ec2.RouteTableAssociation{
{Id: "rtbassoc-faad4893", RouteTableId: "rtb-f9ad4890", SubnetId: "subnet-15ad487c"},
})
}
func (s *S) TestAssociateRouteTable(c *C) {
testServer.Response(200, nil, AssociateRouteTableExample)
resp, err := s.ec2.AssociateRouteTable("rtb-e4ad488d", "subnet-15ad487c")
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"AssociateRouteTable"})
c.Assert(req.Form["RouteTableId"], DeepEquals, []string{"rtb-e4ad488d"})
c.Assert(req.Form["SubnetId"], DeepEquals, []string{"subnet-15ad487c"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-99ed-be587EXAMPLE")
c.Assert(resp.AssociationId, Equals, "rtbassoc-f8ad4891")
}
func (s *S) TestDisassociateRouteTable(c *C) {
testServer.Response(200, nil, DisassociateRouteTableExample)
resp, err := s.ec2.DisassociateRouteTable("rtbassoc-f8ad4891")
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DisassociateRouteTable"})
c.Assert(req.Form["AssociationId"], DeepEquals, []string{"rtbassoc-f8ad4891"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-99ed-be587EXAMPLE")
c.Assert(resp.Return, Equals, true)
}
func (s *S) TestReplaceRouteTableAssociation(c *C) {
testServer.Response(200, nil, ReplaceRouteTableAssociationExample)
resp, err := s.ec2.ReplaceRouteTableAssociation("rtbassoc-f8ad4891", "rtb-f9ad4890")
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"ReplaceRouteTableAssociation"})
c.Assert(req.Form["RouteTableId"], DeepEquals, []string{"rtb-f9ad4890"})
c.Assert(req.Form["AssociationId"], DeepEquals, []string{"rtbassoc-f8ad4891"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-88ed-be587EXAMPLE")
c.Assert(resp.NewAssociationId, Equals, "rtbassoc-faad2958")
}
func (s *S) TestDeleteRouteTable(c *C) {
testServer.Response(200, nil, DeleteRouteTableExample)
resp, err := s.ec2.DeleteRouteTable("rtb-f9ad4890")
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DeleteRouteTable"})
c.Assert(req.Form["RouteTableId"], DeepEquals, []string{"rtb-f9ad4890"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "49dbff89-35bd-4eac-99ed-be587EXAMPLE")
c.Assert(resp.Return, Equals, true)
}
func (s *S) TestDescribeVpcs(c *C) {
testServer.Response(200, nil, DescribeVpcsExample)
filter := ec2.NewFilter()
filter.Add("key1", "value1")
filter.Add("key2", "value2", "value3")
resp, err := s.ec2.DescribeVpcs([]string{"id1", "id2"}, filter)
req := testServer.WaitRequest()
c.Assert(req.Form["Action"], DeepEquals, []string{"DescribeVpcs"})
c.Assert(req.Form["VpcId.1"], DeepEquals, []string{"id1"})
c.Assert(req.Form["VpcId.2"], DeepEquals, []string{"id2"})
c.Assert(req.Form["VpcId.3"], IsNil)
c.Assert(req.Form["Filter.1.Name"], DeepEquals, []string{"key1"})
c.Assert(req.Form["Filter.1.Value.1"], DeepEquals, []string{"value1"})
c.Assert(req.Form["Filter.1.Value.2"], IsNil)
c.Assert(req.Form["Filter.2.Name"], DeepEquals, []string{"key2"})
c.Assert(req.Form["Filter.2.Value.1"], DeepEquals, []string{"value2"})
c.Assert(req.Form["Filter.2.Value.2"], DeepEquals, []string{"value3"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "7a62c49f-347e-4fc4-9331-6e8eEXAMPLE")
c.Assert(resp.VPCs[0].VpcId, Equals, "vpc-1a2b3c4d")
c.Assert(resp.VPCs, HasLen, 1)
}
func (s *S) TestCreateVpc(c *C) {
testServer.Response(200, nil, CreateVpcExample)
resp, err := s.ec2.CreateVpc("foo", "bar")
req := testServer.WaitRequest()
c.Assert(req.Form["CidrBlock"], DeepEquals, []string{"foo"})
c.Assert(req.Form["InstanceTenancy"], DeepEquals, []string{"bar"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "7a62c49f-347e-4fc4-9331-6e8eEXAMPLE")
c.Assert(resp.VPC.VpcId, Equals, "vpc-1a2b3c4d")
c.Assert(resp.VPC.State, Equals, "pending")
c.Assert(resp.VPC.CidrBlock, Equals, "10.0.0.0/16")
c.Assert(resp.VPC.DHCPOptionsID, Equals, "dopt-1a2b3c4d2")
c.Assert(resp.VPC.InstanceTenancy, Equals, "default")
}
func (s *S) TestDeleteVpc(c *C) {
testServer.Response(200, nil, DeleteVpcExample)
resp, err := s.ec2.DeleteVpc("id1")
req := testServer.WaitRequest()
c.Assert(req.Form["VpcId"], DeepEquals, []string{"id1"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "7a62c49f-347e-4fc4-9331-6e8eEXAMPLE")
}
func (s *S) TestCreateRoute(c *C) {
testServer.Response(200, nil, CreateRouteExample)
options := ec2.CreateRoute{
DestinationCidrBlock: "12.34.56.78/90",
GatewayId: "foo",
InstanceId: "i-bar",
NetworkInterfaceId: "foobar",
VpcPeeringConnectionId: "barfoo",
}
resp, err := s.ec2.CreateRoute("rtb-deadbeef", &options)
req := testServer.WaitRequest()
c.Assert(req.Form["RouteTableId"], DeepEquals, []string{"rtb-deadbeef"})
c.Assert(req.Form["DestinationCidrBlock"], DeepEquals, []string{"12.34.56.78/90"})
c.Assert(req.Form["GatewayId"], DeepEquals, []string{"foo"})
c.Assert(req.Form["InstanceId"], DeepEquals, []string{"i-bar"})
c.Assert(req.Form["NetworkInterfaceId"], DeepEquals, []string{"foobar"})
c.Assert(req.Form["VpcPeeringConnectionId"], DeepEquals, []string{"barfoo"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "b4998629-3000-437f-b382-cc96fEXAMPLE")
c.Assert(resp.Return, Equals, true)
}
func (s *S) TestDeleteRoute(c *C) {
testServer.Response(200, nil, DeleteRouteExample)
resp, err := s.ec2.DeleteRoute("rtb-baddcafe", "foobar")
req := testServer.WaitRequest()
c.Assert(req.Form["RouteTableId"], DeepEquals, []string{"rtb-baddcafe"})
c.Assert(req.Form["DestinationCidrBlock"], DeepEquals, []string{"foobar"})
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Equals, "59dbff89-35bd-4eac-99ed-be587EXAMPLE")
c.Assert(resp.Return, Equals, true)
}

1075
vendor/github.com/goamz/goamz/ecs/ecs.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

806
vendor/github.com/goamz/goamz/ecs/ecs_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,806 +0,0 @@
package ecs
import (
"testing"
. "gopkg.in/check.v1"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/testutil"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
ecs *ECS
}
var testServer = testutil.NewHTTPServer()
var mockTest bool
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.ecs = New(auth, aws.Region{ECSEndpoint: testServer.URL})
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
// --------------------------------------------------------------------------
// Detailed Unit Tests
func (s *S) TestCreateCluster(c *C) {
testServer.Response(200, nil, CreateClusterResponse)
req := &CreateClusterReq{
ClusterName: "default",
}
resp, err := s.ecs.CreateCluster(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "CreateCluster")
c.Assert(values.Get("clusterName"), Equals, "default")
c.Assert(resp.Cluster.ClusterArn, Equals, "arn:aws:ecs:region:aws_account_id:cluster/default")
c.Assert(resp.Cluster.ClusterName, Equals, "default")
c.Assert(resp.Cluster.Status, Equals, "ACTIVE")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDeregisterContainerInstance(c *C) {
testServer.Response(200, nil, DeregisterContainerInstanceResponse)
req := &DeregisterContainerInstanceReq{
Cluster: "default",
ContainerInstance: "uuid",
Force: true,
}
resp, err := s.ecs.DeregisterContainerInstance(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DeregisterContainerInstance")
c.Assert(values.Get("cluster"), Equals, "default")
c.Assert(values.Get("containerInstance"), Equals, "uuid")
c.Assert(values.Get("force"), Equals, "true")
expectedResource := []Resource{
{
DoubleValue: 0.0,
IntegerValue: 2048,
LongValue: 0,
Name: "CPU",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 3955,
LongValue: 0,
Name: "MEMORY",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 0,
LongValue: 0,
Name: "PORTS",
StringSetValue: []string{"2376", "22", "51678", "2375"},
Type: "STRINGSET",
},
}
c.Assert(resp.ContainerInstance.AgentConnected, Equals, false)
c.Assert(resp.ContainerInstance.ContainerInstanceArn, Equals, "arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID")
c.Assert(resp.ContainerInstance.Status, Equals, "INACTIVE")
c.Assert(resp.ContainerInstance.Ec2InstanceId, Equals, "instance_id")
c.Assert(resp.ContainerInstance.RegisteredResources, DeepEquals, expectedResource)
c.Assert(resp.ContainerInstance.RemainingResources, DeepEquals, expectedResource)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDeregisterTaskDefinition(c *C) {
testServer.Response(200, nil, DeregisterTaskDefinitionResponse)
req := &DeregisterTaskDefinitionReq{
TaskDefinition: "sleep360:2",
}
resp, err := s.ecs.DeregisterTaskDefinition(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DeregisterTaskDefinition")
c.Assert(values.Get("taskDefinition"), Equals, "sleep360:2")
expected := TaskDefinition{
Family: "sleep360",
Revision: 2,
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
ContainerDefinitions: []ContainerDefinition{
{
Command: []string{"sleep", "360"},
Cpu: 10,
EntryPoint: []string{"/bin/sh"},
Environment: []KeyValuePair{
{
Name: "envVar",
Value: "foo",
},
},
Essential: true,
Image: "busybox",
Memory: 10,
Name: "sleep",
},
},
}
c.Assert(resp.TaskDefinition, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDescribeClusters(c *C) {
testServer.Response(200, nil, DescribeClustersResponse)
req := &DescribeClustersReq{
Clusters: []string{"test", "default"},
}
resp, err := s.ecs.DescribeClusters(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DescribeClusters")
c.Assert(values.Get("clusters.member.1"), Equals, "test")
c.Assert(values.Get("clusters.member.2"), Equals, "default")
expected := []Cluster{
{
ClusterName: "test",
ClusterArn: "arn:aws:ecs:us-east-1:aws_account_id:cluster/test",
Status: "ACTIVE",
},
{
ClusterName: "default",
ClusterArn: "arn:aws:ecs:us-east-1:aws_account_id:cluster/default",
Status: "ACTIVE",
},
}
c.Assert(resp.Clusters, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDescribeContainerInstances(c *C) {
testServer.Response(200, nil, DescribeContainerInstancesResponse)
req := &DescribeContainerInstancesReq{
Cluster: "test",
ContainerInstances: []string{"arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID"},
}
resp, err := s.ecs.DescribeContainerInstances(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DescribeContainerInstances")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("containerInstances.member.1"),
Equals, "arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID")
expected := []ContainerInstance{
ContainerInstance{
AgentConnected: true,
ContainerInstanceArn: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID",
Status: "ACTIVE",
Ec2InstanceId: "instance_id",
RegisteredResources: []Resource{
{
DoubleValue: 0.0,
IntegerValue: 2048,
LongValue: 0,
Name: "CPU",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 3955,
LongValue: 0,
Name: "MEMORY",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 0,
LongValue: 0,
Name: "PORTS",
StringSetValue: []string{"2376", "22", "51678", "2375"},
Type: "STRINGSET",
},
},
RemainingResources: []Resource{
{
DoubleValue: 0.0,
IntegerValue: 2048,
LongValue: 0,
Name: "CPU",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 3955,
LongValue: 0,
Name: "MEMORY",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 0,
LongValue: 0,
Name: "PORTS",
StringSetValue: []string{"2376", "22", "51678", "2375"},
Type: "STRINGSET",
},
},
},
}
c.Assert(resp.ContainerInstances, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDescribeTaskDefinition(c *C) {
testServer.Response(200, nil, DescribeTaskDefinitionResponse)
req := &DescribeTaskDefinitionReq{
TaskDefinition: "sleep360:2",
}
resp, err := s.ecs.DescribeTaskDefinition(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DescribeTaskDefinition")
c.Assert(values.Get("taskDefinition"), Equals, "sleep360:2")
expected := TaskDefinition{
Family: "sleep360",
Revision: 2,
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
ContainerDefinitions: []ContainerDefinition{
{
Command: []string{"sleep", "360"},
Cpu: 10,
EntryPoint: []string{"/bin/sh"},
Environment: []KeyValuePair{
{
Name: "envVar",
Value: "foo",
},
},
Essential: true,
Image: "busybox",
Memory: 10,
Name: "sleep",
},
},
}
c.Assert(resp.TaskDefinition, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDescribeTasks(c *C) {
testServer.Response(200, nil, DescribeTasksResponse)
req := &DescribeTasksReq{
Cluster: "test",
Tasks: []string{"arn:aws:ecs:us-east-1:aws_account_id:task/UUID"},
}
resp, err := s.ecs.DescribeTasks(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DescribeTasks")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("tasks.member.1"),
Equals, "arn:aws:ecs:us-east-1:aws_account_id:task/UUID")
expected := []Task{
Task{
Containers: []Container{
{
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
Name: "sleep",
ContainerArn: "arn:aws:ecs:us-east-1:aws_account_id:container/UUID",
LastStatus: "RUNNING",
},
},
Overrides: TaskOverride{
ContainerOverrides: []ContainerOverride{
{
Name: "sleep",
},
},
},
DesiredStatus: "RUNNING",
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
ContainerInstanceArn: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID",
LastStatus: "RUNNING",
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
},
}
c.Assert(resp.Tasks, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestDiscoverPollEndpoint(c *C) {
testServer.Response(200, nil, DiscoverPollEndpointResponse)
req := &DiscoverPollEndpointReq{
ContainerInstance: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID",
}
resp, err := s.ecs.DiscoverPollEndpoint(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "DiscoverPollEndpoint")
c.Assert(values.Get("containerInstance"),
Equals, "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID")
c.Assert(resp.Endpoint, Equals, "https://ecs-x-1.us-east-1.amazonaws.com/")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestListClusters(c *C) {
testServer.Response(200, nil, ListClustersResponse)
req := &ListClustersReq{
MaxResults: 2,
NextToken: "Token_UUID",
}
resp, err := s.ecs.ListClusters(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "ListClusters")
c.Assert(values.Get("maxResults"), Equals, "2")
c.Assert(values.Get("nextToken"), Equals, "Token_UUID")
c.Assert(resp.ClusterArns, DeepEquals, []string{"arn:aws:ecs:us-east-1:aws_account_id:cluster/default",
"arn:aws:ecs:us-east-1:aws_account_id:cluster/test"})
c.Assert(resp.NextToken, Equals, "token_UUID")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestListContainerInstances(c *C) {
testServer.Response(200, nil, ListContainerInstancesResponse)
req := &ListContainerInstancesReq{
MaxResults: 2,
NextToken: "Token_UUID",
Cluster: "test",
}
resp, err := s.ecs.ListContainerInstances(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "ListContainerInstances")
c.Assert(values.Get("maxResults"), Equals, "2")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("nextToken"), Equals, "Token_UUID")
c.Assert(resp.ContainerInstanceArns, DeepEquals, []string{
"arn:aws:ecs:us-east-1:aws_account_id:container-instance/uuid-1",
"arn:aws:ecs:us-east-1:aws_account_id:container-instance/uuid-2"})
c.Assert(resp.NextToken, Equals, "token_UUID")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestListTaskDefinitions(c *C) {
testServer.Response(200, nil, ListTaskDefinitionsResponse)
req := &ListTaskDefinitionsReq{
MaxResults: 2,
NextToken: "Token_UUID",
FamilyPrefix: "sleep360",
}
resp, err := s.ecs.ListTaskDefinitions(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "ListTaskDefinitions")
c.Assert(values.Get("maxResults"), Equals, "2")
c.Assert(values.Get("familyPrefix"), Equals, "sleep360")
c.Assert(values.Get("nextToken"), Equals, "Token_UUID")
c.Assert(resp.TaskDefinitionArns, DeepEquals, []string{
"arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:1",
"arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2"})
c.Assert(resp.NextToken, Equals, "token_UUID")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestListTasks(c *C) {
testServer.Response(200, nil, ListTasksResponse)
req := &ListTasksReq{
MaxResults: 2,
NextToken: "Token_UUID",
Family: "sleep360",
Cluster: "test",
ContainerInstance: "container_uuid",
}
resp, err := s.ecs.ListTasks(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "ListTasks")
c.Assert(values.Get("maxResults"), Equals, "2")
c.Assert(values.Get("family"), Equals, "sleep360")
c.Assert(values.Get("containerInstance"), Equals, "container_uuid")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("nextToken"), Equals, "Token_UUID")
c.Assert(resp.TaskArns, DeepEquals, []string{
"arn:aws:ecs:us-east-1:aws_account_id:task/uuid_1",
"arn:aws:ecs:us-east-1:aws_account_id:task/uuid_2"})
c.Assert(resp.NextToken, Equals, "token_UUID")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestRegisterContainerInstance(c *C) {
testServer.Response(200, nil, RegisterContainerInstanceResponse)
resources := []Resource{
{
DoubleValue: 0.0,
IntegerValue: 2048,
LongValue: 0,
Name: "CPU",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 3955,
LongValue: 0,
Name: "MEMORY",
Type: "INTEGER",
},
{
DoubleValue: 0.0,
IntegerValue: 0,
LongValue: 0,
Name: "PORTS",
StringSetValue: []string{"2376", "22", "51678", "2375"},
Type: "STRINGSET",
},
}
req := &RegisterContainerInstanceReq{
Cluster: "default",
InstanceIdentityDocument: "foo",
InstanceIdentityDocumentSignature: "baz",
TotalResources: resources,
}
resp, err := s.ecs.RegisterContainerInstance(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "RegisterContainerInstance")
c.Assert(values.Get("cluster"), Equals, "default")
c.Assert(values.Get("instanceIdentityDocument"), Equals, "foo")
c.Assert(values.Get("instanceIdentityDocumentSignature"), Equals, "baz")
c.Assert(values.Get("totalResources.member.1.doubleValue"), Equals, "0.0")
c.Assert(values.Get("totalResources.member.1.integerValue"), Equals, "2048")
c.Assert(values.Get("totalResources.member.1.longValue"), Equals, "0")
c.Assert(values.Get("totalResources.member.1.name"), Equals, "CPU")
c.Assert(values.Get("totalResources.member.1.type"), Equals, "INTEGER")
c.Assert(values.Get("totalResources.member.2.doubleValue"), Equals, "0.0")
c.Assert(values.Get("totalResources.member.2.integerValue"), Equals, "3955")
c.Assert(values.Get("totalResources.member.2.longValue"), Equals, "0")
c.Assert(values.Get("totalResources.member.2.name"), Equals, "MEMORY")
c.Assert(values.Get("totalResources.member.2.type"), Equals, "INTEGER")
c.Assert(values.Get("totalResources.member.3.doubleValue"), Equals, "0.0")
c.Assert(values.Get("totalResources.member.3.integerValue"), Equals, "0")
c.Assert(values.Get("totalResources.member.3.longValue"), Equals, "0")
c.Assert(values.Get("totalResources.member.3.name"), Equals, "PORTS")
c.Assert(values.Get("totalResources.member.3.stringSetValue.member.1"), Equals, "2376")
c.Assert(values.Get("totalResources.member.3.stringSetValue.member.2"), Equals, "22")
c.Assert(values.Get("totalResources.member.3.stringSetValue.member.3"), Equals, "51678")
c.Assert(values.Get("totalResources.member.3.stringSetValue.member.4"), Equals, "2375")
c.Assert(values.Get("totalResources.member.3.type"), Equals, "STRINGSET")
c.Assert(resp.ContainerInstance.AgentConnected, Equals, true)
c.Assert(resp.ContainerInstance.ContainerInstanceArn, Equals, "arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID")
c.Assert(resp.ContainerInstance.Status, Equals, "ACTIVE")
c.Assert(resp.ContainerInstance.Ec2InstanceId, Equals, "instance_id")
c.Assert(resp.ContainerInstance.RegisteredResources, DeepEquals, resources)
c.Assert(resp.ContainerInstance.RemainingResources, DeepEquals, resources)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestRegisterTaskDefinition(c *C) {
testServer.Response(200, nil, RegisterTaskDefinitionResponse)
CDefinitions := []ContainerDefinition{
{
Command: []string{"sleep", "360"},
Cpu: 10,
EntryPoint: []string{"/bin/sh"},
Environment: []KeyValuePair{
{
Name: "envVar",
Value: "foo",
},
},
Essential: true,
Image: "busybox",
Memory: 10,
Name: "sleep",
MountPoints: []MountPoint{
{
ContainerPath: "/tmp/myfile",
ReadOnly: false,
SourceVolume: "/srv/myfile",
},
{
ContainerPath: "/tmp/myfile2",
ReadOnly: true,
SourceVolume: "/srv/myfile2",
},
},
VolumesFrom: []VolumeFrom{
{
ReadOnly: true,
SourceContainer: "foo",
},
},
},
}
req := &RegisterTaskDefinitionReq{
Family: "sleep360",
ContainerDefinitions: CDefinitions,
Volumes: []Volume{
{
Name: "/srv/myfile",
Host: HostVolumeProperties{
SourcePath: "/srv/myfile",
},
},
},
}
resp, err := s.ecs.RegisterTaskDefinition(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "RegisterTaskDefinition")
c.Assert(values.Get("containerDefinitions.member.1.command.member.1"), Equals, "sleep")
c.Assert(values.Get("containerDefinitions.member.1.command.member.2"), Equals, "360")
c.Assert(values.Get("containerDefinitions.member.1.cpu"), Equals, "10")
c.Assert(values.Get("containerDefinitions.member.1.memory"), Equals, "10")
c.Assert(values.Get("containerDefinitions.member.1.entryPoint.member.1"), Equals, "/bin/sh")
c.Assert(values.Get("containerDefinitions.member.1.environment.member.1.name"), Equals, "envVar")
c.Assert(values.Get("containerDefinitions.member.1.environment.member.1.value"), Equals, "foo")
c.Assert(values.Get("containerDefinitions.member.1.essential"), Equals, "true")
c.Assert(values.Get("containerDefinitions.member.1.image"), Equals, "busybox")
c.Assert(values.Get("containerDefinitions.member.1.memory"), Equals, "10")
c.Assert(values.Get("containerDefinitions.member.1.name"), Equals, "sleep")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.1.containerPath"), Equals, "/tmp/myfile")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.1.readOnly"), Equals, "false")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.1.sourceVolume"), Equals, "/srv/myfile")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.2.containerPath"), Equals, "/tmp/myfile2")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.2.readOnly"), Equals, "true")
c.Assert(values.Get("containerDefinitions.member.1.mountPoints.member.2.sourceVolume"), Equals, "/srv/myfile2")
c.Assert(values.Get("containerDefinitions.member.1.volumesFrom.member.1.readOnly"), Equals, "true")
c.Assert(values.Get("containerDefinitions.member.1.volumesFrom.member.1.sourceContainer"), Equals, "foo")
c.Assert(values.Get("family"), Equals, "sleep360")
c.Assert(values.Get("volumes.member.1.name"), Equals, "/srv/myfile")
c.Assert(values.Get("volumes.member.1.host.sourcePath"), Equals, "/srv/myfile")
expected := TaskDefinition{
Family: "sleep360",
Revision: 2,
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
ContainerDefinitions: CDefinitions,
Volumes: []Volume{
{
Name: "/srv/myfile",
Host: HostVolumeProperties{
SourcePath: "/srv/myfile",
},
},
},
}
c.Assert(resp.TaskDefinition, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestRunTask(c *C) {
testServer.Response(200, nil, RunTaskResponse)
req := &RunTaskReq{
Cluster: "test",
Count: 1,
TaskDefinition: "sleep360:2",
}
resp, err := s.ecs.RunTask(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "RunTask")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("count"), Equals, "1")
c.Assert(values.Get("taskDefinition"), Equals, "sleep360:2")
expected := []Task{
Task{
Containers: []Container{
{
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
Name: "sleep",
ContainerArn: "arn:aws:ecs:us-east-1:aws_account_id:container/UUID",
LastStatus: "RUNNING",
},
},
Overrides: TaskOverride{
ContainerOverrides: []ContainerOverride{
{
Name: "sleep",
},
},
},
DesiredStatus: "RUNNING",
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
ContainerInstanceArn: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID",
LastStatus: "PENDING",
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
},
}
c.Assert(resp.Tasks, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestStartTask(c *C) {
testServer.Response(200, nil, StartTaskResponse)
req := &StartTaskReq{
Cluster: "test",
ContainerInstances: []string{"containerUUID"},
TaskDefinition: "sleep360:2",
}
resp, err := s.ecs.StartTask(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "StartTask")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("taskDefinition"), Equals, "sleep360:2")
c.Assert(values.Get("containerInstances.member.1"), Equals, "containerUUID")
expected := []Task{
Task{
Containers: []Container{
{
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
Name: "sleep",
ContainerArn: "arn:aws:ecs:us-east-1:aws_account_id:container/UUID",
LastStatus: "RUNNING",
},
},
Overrides: TaskOverride{
ContainerOverrides: []ContainerOverride{
{
Name: "sleep",
},
},
},
DesiredStatus: "RUNNING",
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
ContainerInstanceArn: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID",
LastStatus: "PENDING",
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
},
}
c.Assert(resp.Tasks, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestStopTask(c *C) {
testServer.Response(200, nil, StopTaskResponse)
req := &StopTaskReq{
Cluster: "test",
Task: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
}
resp, err := s.ecs.StopTask(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "StopTask")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("task"), Equals, "arn:aws:ecs:us-east-1:aws_account_id:task/UUID")
expected := Task{
Containers: []Container{
{
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
Name: "sleep",
ContainerArn: "arn:aws:ecs:us-east-1:aws_account_id:container/UUID",
LastStatus: "RUNNING",
},
},
Overrides: TaskOverride{
ContainerOverrides: []ContainerOverride{
{
Name: "sleep",
},
},
},
DesiredStatus: "STOPPED",
TaskArn: "arn:aws:ecs:us-east-1:aws_account_id:task/UUID",
ContainerInstanceArn: "arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID",
LastStatus: "RUNNING",
TaskDefinitionArn: "arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2",
}
c.Assert(resp.Task, DeepEquals, expected)
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestSubmitContainerStateChange(c *C) {
testServer.Response(200, nil, SubmitContainerStateChangeResponse)
networkBindings := []NetworkBinding{
{
BindIp: "127.0.0.1",
ContainerPort: 80,
HostPort: 80,
},
}
req := &SubmitContainerStateChangeReq{
Cluster: "test",
ContainerName: "container",
ExitCode: 0,
Reason: "reason",
Status: "status",
Task: "taskUUID",
NetworkBindings: networkBindings,
}
resp, err := s.ecs.SubmitContainerStateChange(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "SubmitContainerStateChange")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("containerName"), Equals, "container")
c.Assert(values.Get("exitCode"), Equals, "0")
c.Assert(values.Get("reason"), Equals, "reason")
c.Assert(values.Get("status"), Equals, "status")
c.Assert(values.Get("task"), Equals, "taskUUID")
c.Assert(values.Get("networkBindings.member.1.bindIp"), Equals, "127.0.0.1")
c.Assert(values.Get("networkBindings.member.1.containerPort"), Equals, "80")
c.Assert(values.Get("networkBindings.member.1.hostPort"), Equals, "80")
c.Assert(resp.Acknowledgment, Equals, "ACK")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}
func (s *S) TestSubmitTaskStateChange(c *C) {
testServer.Response(200, nil, SubmitTaskStateChangeResponse)
req := &SubmitTaskStateChangeReq{
Cluster: "test",
Reason: "reason",
Status: "status",
Task: "taskUUID",
}
resp, err := s.ecs.SubmitTaskStateChange(req)
c.Assert(err, IsNil)
values := testServer.WaitRequest().PostForm
c.Assert(values.Get("Version"), Equals, "2014-11-13")
c.Assert(values.Get("Action"), Equals, "SubmitTaskStateChange")
c.Assert(values.Get("cluster"), Equals, "test")
c.Assert(values.Get("reason"), Equals, "reason")
c.Assert(values.Get("status"), Equals, "status")
c.Assert(values.Get("task"), Equals, "taskUUID")
c.Assert(resp.Acknowledgment, Equals, "ACK")
c.Assert(resp.RequestId, Equals, "8d798a29-f083-11e1-bdfb-cb223EXAMPLE")
}

637
vendor/github.com/goamz/goamz/ecs/responses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,637 +0,0 @@
package ecs
var CreateClusterResponse = `
<CreateClusterResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
<CreateClusterResult>
<cluster>
<clusterArn>arn:aws:ecs:region:aws_account_id:cluster/default</clusterArn>
<clusterName>default</clusterName>
<status>ACTIVE</status>
</cluster>
</CreateClusterResult>
</CreateClusterResponse>
`
var DeregisterContainerInstanceResponse = `
<DeregisterContainerInstanceResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
<DeregisterContainerInstanceResult>
<containerInstance>
<agentConnected>False</agentConnected>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID</containerInstanceArn>
<ec2InstanceId>instance_id</ec2InstanceId>
<status>INACTIVE</status>
<registeredResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</registeredResources>
<remainingResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</remainingResources>
</containerInstance>
</DeregisterContainerInstanceResult>
</DeregisterContainerInstanceResponse>
`
var DeregisterTaskDefinitionResponse = `
<DeregisterTaskDefinitionResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<DeregisterTaskDefinitionResult>
<taskDefinition>
<revision>2</revision>
<family>sleep360</family>
<containerDefinitions>
<member>
<portMappings/>
<essential>true</essential>
<environment>
<member>
<name>envVar</name>
<value>foo</value>
</member>
</environment>
<entryPoint>
<member>/bin/sh</member>
</entryPoint>
<name>sleep</name>
<command>
<member>sleep</member>
<member>360</member>
</command>
<cpu>10</cpu>
<image>busybox</image>
<memory>10</memory>
</member>
</containerDefinitions>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</taskDefinition>
</DeregisterTaskDefinitionResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DeregisterTaskDefinitionResponse>
`
var DescribeClustersResponse = `
<DescribeClustersResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<DescribeClustersResult>
<failures/>
<clusters>
<member>
<clusterName>test</clusterName>
<clusterArn>arn:aws:ecs:us-east-1:aws_account_id:cluster/test</clusterArn>
<status>ACTIVE</status>
</member>
<member>
<clusterName>default</clusterName>
<clusterArn>arn:aws:ecs:us-east-1:aws_account_id:cluster/default</clusterArn>
<status>ACTIVE</status>
</member>
</clusters>
</DescribeClustersResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeClustersResponse>
`
var DescribeContainerInstancesResponse = `
<DescribeContainerInstancesResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
<DescribeContainerInstancesResult>
<failures/>
<containerInstances>
<member>
<agentConnected>true</agentConnected>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID</containerInstanceArn>
<ec2InstanceId>instance_id</ec2InstanceId>
<status>ACTIVE</status>
<registeredResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</registeredResources>
<remainingResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</remainingResources>
</member>
</containerInstances>
</DescribeContainerInstancesResult>
</DescribeContainerInstancesResponse>
`
var DescribeTaskDefinitionResponse = `
<DescribeTaskDefinitionResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<DescribeTaskDefinitionResult>
<taskDefinition>
<revision>2</revision>
<family>sleep360</family>
<containerDefinitions>
<member>
<portMappings/>
<essential>true</essential>
<environment>
<member>
<name>envVar</name>
<value>foo</value>
</member>
</environment>
<entryPoint>
<member>/bin/sh</member>
</entryPoint>
<name>sleep</name>
<command>
<member>sleep</member>
<member>360</member>
</command>
<cpu>10</cpu>
<image>busybox</image>
<memory>10</memory>
</member>
</containerDefinitions>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</taskDefinition>
</DescribeTaskDefinitionResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeTaskDefinitionResponse>
`
var DescribeTasksResponse = `
<DescribeTasksResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<DescribeTasksResult>
<failures/>
<tasks>
<member>
<containers>
<member>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<name>sleep</name>
<containerArn>arn:aws:ecs:us-east-1:aws_account_id:container/UUID</containerArn>
<networkBindings/>
<lastStatus>RUNNING</lastStatus>
</member>
</containers>
<overrides>
<containerOverrides>
<member>
<name>sleep</name>
</member>
</containerOverrides>
</overrides>
<desiredStatus>RUNNING</desiredStatus>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID</containerInstanceArn>
<lastStatus>RUNNING</lastStatus>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</member>
</tasks>
</DescribeTasksResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeTasksResponse>
`
var DiscoverPollEndpointResponse = `
<DiscoverPollEndpointResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<DiscoverPollEndpointResult>
<endpoint>https://ecs-x-1.us-east-1.amazonaws.com/</endpoint>
</DiscoverPollEndpointResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</DiscoverPollEndpointResponse>
`
var ListClustersResponse = `
<ListClustersResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ListClustersResult>
<clusterArns>
<member>arn:aws:ecs:us-east-1:aws_account_id:cluster/default</member>
<member>arn:aws:ecs:us-east-1:aws_account_id:cluster/test</member>
</clusterArns>
<nextToken>token_UUID</nextToken>
</ListClustersResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</ListClustersResponse>
`
var ListContainerInstancesResponse = `
<ListContainerInstancesResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ListContainerInstancesResult>
<containerInstanceArns>
<member>arn:aws:ecs:us-east-1:aws_account_id:container-instance/uuid-1</member>
<member>arn:aws:ecs:us-east-1:aws_account_id:container-instance/uuid-2</member>
</containerInstanceArns>
<nextToken>token_UUID</nextToken>
</ListContainerInstancesResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</ListContainerInstancesResponse>
`
var ListTaskDefinitionsResponse = `
<ListTaskDefinitionsResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ListTaskDefinitionsResult>
<taskDefinitionArns>
<member>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:1</member>
<member>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</member>
</taskDefinitionArns>
<nextToken>token_UUID</nextToken>
</ListTaskDefinitionsResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</ListTaskDefinitionsResponse>
`
var ListTasksResponse = `
<ListTasksResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ListTasksResult>
<taskArns>
<member>arn:aws:ecs:us-east-1:aws_account_id:task/uuid_1</member>
<member>arn:aws:ecs:us-east-1:aws_account_id:task/uuid_2</member>
</taskArns>
<nextToken>token_UUID</nextToken>
</ListTasksResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</ListTasksResponse>
`
var RegisterContainerInstanceResponse = `
<RegisterContainerInstanceResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
<RegisterContainerInstanceResult>
<containerInstance>
<agentConnected>True</agentConnected>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_UUID</containerInstanceArn>
<ec2InstanceId>instance_id</ec2InstanceId>
<status>ACTIVE</status>
<registeredResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</registeredResources>
<remainingResources>
<member>
<integerValue>2048</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>CPU</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>3955</integerValue>
<longValue>0</longValue>
<type>INTEGER</type>
<name>MEMORY</name>
<doubleValue>0.0</doubleValue>
</member>
<member>
<integerValue>0</integerValue>
<longValue>0</longValue>
<type>STRINGSET</type>
<stringSetValue>
<member>2376</member>
<member>22</member>
<member>51678</member>
<member>2375</member>
</stringSetValue>
<name>PORTS</name>
<doubleValue>0.0</doubleValue>
</member>
</remainingResources>
</containerInstance>
</RegisterContainerInstanceResult>
</RegisterContainerInstanceResponse>
`
var RegisterTaskDefinitionResponse = `
<RegisterTaskDefinitionResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<RegisterTaskDefinitionResult>
<taskDefinition>
<revision>2</revision>
<family>sleep360</family>
<containerDefinitions>
<member>
<portMappings/>
<essential>true</essential>
<environment>
<member>
<name>envVar</name>
<value>foo</value>
</member>
</environment>
<entryPoint>
<member>/bin/sh</member>
</entryPoint>
<name>sleep</name>
<command>
<member>sleep</member>
<member>360</member>
</command>
<cpu>10</cpu>
<image>busybox</image>
<memory>10</memory>
<mountPoints>
<member>
<containerPath>/tmp/myfile</containerPath>
<readOnly>false</readOnly>
<sourceVolume>/srv/myfile</sourceVolume>
</member>
<member>
<containerPath>/tmp/myfile2</containerPath>
<readOnly>true</readOnly>
<sourceVolume>/srv/myfile2</sourceVolume>
</member>
</mountPoints>
<volumesFrom>
<member>
<readOnly>true</readOnly>
<sourceContainer>foo</sourceContainer>
</member>
</volumesFrom>
</member>
</containerDefinitions>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
<volumes>
<member>
<name>/srv/myfile</name>
<host>
<sourcePath>/srv/myfile</sourcePath>
</host>
</member>
</volumes>
</taskDefinition>
</RegisterTaskDefinitionResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</RegisterTaskDefinitionResponse>
`
var RunTaskResponse = `
<RunTaskResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<RunTaskResult>
<failures/>
<tasks>
<member>
<containers>
<member>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<name>sleep</name>
<containerArn>arn:aws:ecs:us-east-1:aws_account_id:container/UUID</containerArn>
<networkBindings/>
<lastStatus>RUNNING</lastStatus>
</member>
</containers>
<overrides>
<containerOverrides>
<member>
<name>sleep</name>
</member>
</containerOverrides>
</overrides>
<desiredStatus>RUNNING</desiredStatus>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID</containerInstanceArn>
<lastStatus>PENDING</lastStatus>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</member>
</tasks>
</RunTaskResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</RunTaskResponse>
`
var StartTaskResponse = `
<StartTaskResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<StartTaskResult>
<failures/>
<tasks>
<member>
<containers>
<member>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<name>sleep</name>
<containerArn>arn:aws:ecs:us-east-1:aws_account_id:container/UUID</containerArn>
<networkBindings/>
<lastStatus>RUNNING</lastStatus>
</member>
</containers>
<overrides>
<containerOverrides>
<member>
<name>sleep</name>
</member>
</containerOverrides>
</overrides>
<desiredStatus>RUNNING</desiredStatus>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID</containerInstanceArn>
<lastStatus>PENDING</lastStatus>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</member>
</tasks>
</StartTaskResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</StartTaskResponse>
`
var StopTaskResponse = `
<StopTaskResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<StopTaskResult>
<task>
<containers>
<member>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<name>sleep</name>
<containerArn>arn:aws:ecs:us-east-1:aws_account_id:container/UUID</containerArn>
<networkBindings/>
<lastStatus>RUNNING</lastStatus>
</member>
</containers>
<overrides>
<containerOverrides>
<member>
<name>sleep</name>
</member>
</containerOverrides>
</overrides>
<desiredStatus>STOPPED</desiredStatus>
<taskArn>arn:aws:ecs:us-east-1:aws_account_id:task/UUID</taskArn>
<containerInstanceArn>arn:aws:ecs:us-east-1:aws_account_id:container-instance/UUID</containerInstanceArn>
<lastStatus>RUNNING</lastStatus>
<taskDefinitionArn>arn:aws:ecs:us-east-1:aws_account_id:task-definition/sleep360:2</taskDefinitionArn>
</task>
</StopTaskResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</StopTaskResponse>
`
var SubmitContainerStateChangeResponse = `
<SubmitContainerStateChangeResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<SubmitContainerStateChangeResult>
<acknowledgment>ACK</acknowledgment>
</SubmitContainerStateChangeResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</SubmitContainerStateChangeResponse>
`
var SubmitTaskStateChangeResponse = `
<SubmitTaskStateChangeResponse xmlns="http://ecs.amazonaws.com/doc/2014-11-13/">
<SubmitTaskStateChangeResult>
<acknowledgment>ACK</acknowledgment>
</SubmitTaskStateChangeResult>
<ResponseMetadata>
<RequestId>8d798a29-f083-11e1-bdfb-cb223EXAMPLE</RequestId>
</ResponseMetadata>
</SubmitTaskStateChangeResponse>
`

435
vendor/github.com/goamz/goamz/elb/elb.go сгенерированный поставляемый
Просмотреть файл

@@ -1,435 +0,0 @@
// This package provides types and functions to interact Elastic Load Balancing service
package elb
import (
"encoding/xml"
"fmt"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"github.com/goamz/goamz/aws"
)
type ELB struct {
aws.Auth
aws.Region
}
func New(auth aws.Auth, region aws.Region) *ELB {
return &ELB{auth, region}
}
// The CreateLoadBalancer type encapsulates options for the respective request in AWS.
// The creation of a Load Balancer may differ inside EC2 and VPC.
//
// See http://goo.gl/4QFKi for more details.
type CreateLoadBalancer struct {
Name string
AvailabilityZones []string
Listeners []Listener
Scheme string
SecurityGroups []string
Subnets []string
}
// Listener to configure in Load Balancer.
//
// See http://goo.gl/NJQCj for more details.
type Listener struct {
InstancePort int
InstanceProtocol string
LoadBalancerPort int
Protocol string
SSLCertificateId string
}
// Response to a CreateLoadBalance request.
//
// See http://goo.gl/4QFKi for more details.
type CreateLoadBalancerResp struct {
DNSName string `xml:"CreateLoadBalancerResult>DNSName"`
}
type SimpleResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// Creates a Load Balancer in Amazon.
//
// See http://goo.gl/4QFKi for more details.
func (elb *ELB) CreateLoadBalancer(options *CreateLoadBalancer) (resp *CreateLoadBalancerResp, err error) {
params := makeCreateParams(options)
resp = new(CreateLoadBalancerResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return
}
// Deletes a Load Balancer.
//
// See http://goo.gl/sDmPp for more details.
func (elb *ELB) DeleteLoadBalancer(name string) (resp *SimpleResp, err error) {
params := map[string]string{
"Action": "DeleteLoadBalancer",
"LoadBalancerName": name,
}
resp = new(SimpleResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
type RegisterInstancesResp struct {
InstanceIds []string `xml:"RegisterInstancesWithLoadBalancerResult>Instances>member>InstanceId"`
}
// Register N instances with a given Load Balancer.
//
// See http://goo.gl/x9hru for more details.
func (elb *ELB) RegisterInstancesWithLoadBalancer(instanceIds []string, lbName string) (resp *RegisterInstancesResp, err error) {
// TODO: change params order and use ..., e.g (lbName string, instanceIds ...string)
params := map[string]string{
"Action": "RegisterInstancesWithLoadBalancer",
"LoadBalancerName": lbName,
}
for i, instanceId := range instanceIds {
key := fmt.Sprintf("Instances.member.%d.InstanceId", i+1)
params[key] = instanceId
}
resp = new(RegisterInstancesResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Deregister N instances from a given Load Balancer.
//
// See http://goo.gl/Hgo4U for more details.
func (elb *ELB) DeregisterInstancesFromLoadBalancer(instanceIds []string, lbName string) (resp *SimpleResp, err error) {
// TODO: change params order and use ..., e.g (lbName string, instanceIds ...string)
params := map[string]string{
"Action": "DeregisterInstancesFromLoadBalancer",
"LoadBalancerName": lbName,
}
for i, instanceId := range instanceIds {
key := fmt.Sprintf("Instances.member.%d.InstanceId", i+1)
params[key] = instanceId
}
resp = new(SimpleResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
type DescribeLoadBalancerResp struct {
LoadBalancerDescriptions []LoadBalancerDescription `xml:"DescribeLoadBalancersResult>LoadBalancerDescriptions>member"`
}
type LoadBalancerDescription struct {
AvailabilityZones []string `xml:"AvailabilityZones>member"`
BackendServerDescriptions []BackendServerDescriptions `xml:"BackendServerDescriptions>member"`
CanonicalHostedZoneName string `xml:"CanonicalHostedZoneName"`
CanonicalHostedZoneNameId string `xml:"CanonicalHostedZoneNameID"`
CreatedTime time.Time `xml:"CreatedTime"`
DNSName string `xml:"DNSName"`
HealthCheck HealthCheck `xml:"HealthCheck"`
Instances []Instance `xml:"Instances>member"`
ListenerDescriptions []ListenerDescription `xml:"ListenerDescriptions>member"`
LoadBalancerName string `xml:"LoadBalancerName"`
Policies Policies `xml:"Policies"`
Scheme string `xml:"Scheme"`
SecurityGroups []string `xml:"SecurityGroups>member"` //vpc only
SourceSecurityGroup SourceSecurityGroup `xml:"SourceSecurityGroup"`
Subnets []string `xml:"Subnets>member"`
VPCId string `xml:"VPCId"`
}
// Describe Load Balancers.
// It can be used to describe all Load Balancers or specific ones.
//
// See http://goo.gl/wofJA for more details.
func (elb *ELB) DescribeLoadBalancers(names ...string) (*DescribeLoadBalancerResp, error) {
params := map[string]string{"Action": "DescribeLoadBalancers"}
for i, name := range names {
index := fmt.Sprintf("LoadBalancerNames.member.%d", i+1)
params[index] = name
}
resp := new(DescribeLoadBalancerResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
type BackendServerDescriptions struct {
InstancePort int `xml:"InstancePort"`
PolicyNames []string `xml:"PolicyNames>member"`
}
type HealthCheck struct {
HealthyThreshold int `xml:"HealthyThreshold"`
Interval int `xml:"Interval"`
Target string `xml:"Target"`
Timeout int `xml:"Timeout"`
UnhealthyThreshold int `xml:"UnhealthyThreshold"`
}
type Instance struct {
InstanceId string `xml:"InstanceId"`
}
type ListenerDescription struct {
Listener Listener `xml:"Listener"`
PolicyNames []string `xml:"PolicyNames>member"`
}
type Policies struct {
AppCookieStickinessPolicies []AppCookieStickinessPolicies `xml:"AppCookieStickinessPolicies>member"`
LBCookieStickinessPolicies []LBCookieStickinessPolicies `xml:"LBCookieStickinessPolicies>member"`
OtherPolicies []string `xml:"OtherPolicies>member"`
}
// see http://goo.gl/clXGV for more information.
type AppCookieStickinessPolicies struct {
CookieName string `xml:"CookieName"`
PolicyName string `xml:"PolicyName"`
}
type LBCookieStickinessPolicies struct {
CookieExpirationPeriod int `xml:"CookieExpirationPeriod"`
PolicyName string `xml:"PolicyName"`
}
type SourceSecurityGroup struct {
GroupName string `xml:"GroupName"`
OwnerAlias string `xml:"OwnerAlias"`
}
// Represents a XML response for DescribeInstanceHealth action
//
// See http://goo.gl/ovIB1 for more information.
type DescribeInstanceHealthResp struct {
InstanceStates []InstanceState `xml:"DescribeInstanceHealthResult>InstanceStates>member"`
}
// See http://goo.gl/dzWfP for more information.
type InstanceState struct {
Description string `xml:"Description"`
InstanceId string `xml:"InstanceId"`
ReasonCode string `xml:"ReasonCode"`
State string `xml:"State"`
}
// Describe instance health.
//
// See http://goo.gl/ovIB1 for more information.
func (elb *ELB) DescribeInstanceHealth(lbName string, instanceIds ...string) (*DescribeInstanceHealthResp, error) {
params := map[string]string{
"Action": "DescribeInstanceHealth",
"LoadBalancerName": lbName,
}
for i, iId := range instanceIds {
key := fmt.Sprintf("Instances.member.%d.InstanceId", i+1)
params[key] = iId
}
resp := new(DescribeInstanceHealthResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
type HealthCheckResp struct {
HealthCheck *HealthCheck `xml:"ConfigureHealthCheckResult>HealthCheck"`
}
// Configure health check for a LB
//
// See http://goo.gl/2HE6a for more information
func (elb *ELB) ConfigureHealthCheck(lbName string, healthCheck *HealthCheck) (*HealthCheckResp, error) {
params := map[string]string{
"Action": "ConfigureHealthCheck",
"LoadBalancerName": lbName,
"HealthCheck.HealthyThreshold": strconv.Itoa(healthCheck.HealthyThreshold),
"HealthCheck.Interval": strconv.Itoa(healthCheck.Interval),
"HealthCheck.Target": healthCheck.Target,
"HealthCheck.Timeout": strconv.Itoa(healthCheck.Timeout),
"HealthCheck.UnhealthyThreshold": strconv.Itoa(healthCheck.UnhealthyThreshold),
}
resp := new(HealthCheckResp)
if err := elb.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Add tags to the named ELB
//
// Note that AWS only accepts one ELB name at a time (even though it is sent as a list)
//
// See http://goo.gl/6JW4Wf for the rest of the details
func (elb *ELB) AddTags(elbName string, tags map[string]string) (*SimpleResp, error) {
var sortedKeys []string
params := make(map[string]string)
response := &SimpleResp{}
for tagKey := range tags {
sortedKeys = append(sortedKeys, tagKey)
}
sort.Strings(sortedKeys)
for _, key := range sortedKeys {
number := len(tags)
params[fmt.Sprintf("Tags.member.%d.Key", number)] = key
params[fmt.Sprintf("Tags.member.%d.Value", number)] = tags[key]
delete(tags, key)
}
params["Action"] = "AddTags"
params["LoadBalancerNames.member.1"] = elbName
if err := elb.query(params, response); err != nil {
return nil, err
}
return response, nil
}
// Remove tags from the named ELB
//
// Note that AWS only accepts one ELB name at a time (even though it is sent as a list)
//
// see http://goo.gl/ochFqo for more details
func (elb *ELB) RemoveTags(elbName string, tagKeys []string) (*SimpleResp, error) {
response := &SimpleResp{}
params := make(map[string]string)
params["Action"] = "RemoveTags"
params["LoadBalancerNames.member.1"] = elbName
for i, tagKey := range tagKeys {
params[fmt.Sprintf("Tags.member.%d.Key", i+1)] = tagKey
}
if err := elb.query(params, response); err != nil {
return nil, err
}
return response, nil
}
func (elb *ELB) query(params map[string]string, resp interface{}) error {
params["Version"] = "2012-06-01"
params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
data := strings.NewReader(multimap(params).Encode())
hreq, err := http.NewRequest("GET", elb.Region.ELBEndpoint+"/", data)
if err != nil {
return err
}
hreq.URL.RawQuery = multimap(params).Encode()
token := elb.Auth.Token()
if token != "" {
hreq.Header.Set("X-Amz-Security-Token", token)
}
signer := aws.NewV4Signer(elb.Auth, "elasticloadbalancing", elb.Region)
signer.Sign(hreq)
r, err := http.DefaultClient.Do(hreq)
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode != 200 {
return buildError(r)
}
return xml.NewDecoder(r.Body).Decode(resp)
}
// Error encapsulates an error returned by ELB.
type Error struct {
// HTTP status code
StatusCode int
// AWS error code
Code string
// The human-oriented error message
Message string
}
func (err *Error) Error() string {
if err.Code == "" {
return err.Message
}
return fmt.Sprintf("%s (%s)", err.Message, err.Code)
}
type xmlErrors struct {
Errors []Error `xml:"Error"`
}
func buildError(r *http.Response) error {
var (
err Error
errors xmlErrors
)
xml.NewDecoder(r.Body).Decode(&errors)
if len(errors.Errors) > 0 {
err = errors.Errors[0]
}
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
func makeCreateParams(createLB *CreateLoadBalancer) map[string]string {
params := make(map[string]string)
params["LoadBalancerName"] = createLB.Name
params["Action"] = "CreateLoadBalancer"
if createLB.Scheme != "" {
params["Scheme"] = createLB.Scheme
}
for i, s := range createLB.SecurityGroups {
key := fmt.Sprintf("SecurityGroups.member.%d", i+1)
params[key] = s
}
for i, s := range createLB.Subnets {
key := fmt.Sprintf("Subnets.member.%d", i+1)
params[key] = s
}
for i, l := range createLB.Listeners {
key := "Listeners.member.%d.%s"
index := i + 1
params[fmt.Sprintf(key, index, "InstancePort")] = strconv.Itoa(l.InstancePort)
params[fmt.Sprintf(key, index, "InstanceProtocol")] = l.InstanceProtocol
params[fmt.Sprintf(key, index, "Protocol")] = l.Protocol
params[fmt.Sprintf(key, index, "LoadBalancerPort")] = strconv.Itoa(l.LoadBalancerPort)
}
for i, az := range createLB.AvailabilityZones {
key := fmt.Sprintf("AvailabilityZones.member.%d", i+1)
params[key] = az
}
return params
}

369
vendor/github.com/goamz/goamz/elb/elb_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,369 +0,0 @@
package elb_test
import (
"time"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/elb"
. "gopkg.in/check.v1"
)
type S struct {
HTTPSuite
elb *elb.ELB
}
var _ = Suite(&S{})
func (s *S) SetUpSuite(c *C) {
s.HTTPSuite.SetUpSuite(c)
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.elb = elb.New(auth, aws.Region{ELBEndpoint: testServer.URL})
}
func (s *S) TestCreateLoadBalancer(c *C) {
testServer.PrepareResponse(200, nil, CreateLoadBalancer)
createLB := &elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a", "us-east-1b"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
Protocol: "http",
LoadBalancerPort: 80,
},
},
}
resp, err := s.elb.CreateLoadBalancer(createLB)
c.Assert(err, IsNil)
defer s.elb.DeleteLoadBalancer(createLB.Name)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Action"), Equals, "CreateLoadBalancer")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(values.Get("AvailabilityZones.member.1"), Equals, "us-east-1a")
c.Assert(values.Get("AvailabilityZones.member.2"), Equals, "us-east-1b")
c.Assert(values.Get("Listeners.member.1.InstancePort"), Equals, "80")
c.Assert(values.Get("Listeners.member.1.InstanceProtocol"), Equals, "http")
c.Assert(values.Get("Listeners.member.1.Protocol"), Equals, "http")
c.Assert(values.Get("Listeners.member.1.LoadBalancerPort"), Equals, "80")
c.Assert(resp.DNSName, Equals, "testlb-339187009.us-east-1.elb.amazonaws.com")
}
func (s *S) TestCreateLoadBalancerWithSubnetsAndMoreListeners(c *C) {
testServer.PrepareResponse(200, nil, CreateLoadBalancer)
createLB := &elb.CreateLoadBalancer{
Name: "testlb",
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
Protocol: "http",
LoadBalancerPort: 80,
},
{
InstancePort: 8080,
InstanceProtocol: "http",
Protocol: "http",
LoadBalancerPort: 8080,
},
},
Subnets: []string{"subnetid-1", "subnetid-2"},
SecurityGroups: []string{"sg-1", "sg-2"},
}
_, err := s.elb.CreateLoadBalancer(createLB)
c.Assert(err, IsNil)
defer s.elb.DeleteLoadBalancer(createLB.Name)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Listeners.member.1.InstancePort"), Equals, "80")
c.Assert(values.Get("Listeners.member.1.LoadBalancerPort"), Equals, "80")
c.Assert(values.Get("Listeners.member.2.InstancePort"), Equals, "8080")
c.Assert(values.Get("Listeners.member.2.LoadBalancerPort"), Equals, "8080")
c.Assert(values.Get("Subnets.member.1"), Equals, "subnetid-1")
c.Assert(values.Get("Subnets.member.2"), Equals, "subnetid-2")
c.Assert(values.Get("SecurityGroups.member.1"), Equals, "sg-1")
c.Assert(values.Get("SecurityGroups.member.2"), Equals, "sg-2")
}
func (s *S) TestCreateLoadBalancerWithWrongParamsCombination(c *C) {
testServer.PrepareResponse(400, nil, CreateLoadBalancerBadRequest)
createLB := &elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a", "us-east-1b"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
Protocol: "http",
LoadBalancerPort: 80,
},
},
Subnets: []string{"subnetid-1", "subnetid2"},
}
resp, err := s.elb.CreateLoadBalancer(createLB)
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
e, ok := err.(*elb.Error)
c.Assert(ok, Equals, true)
c.Assert(e.Message, Equals, "Only one of SubnetIds or AvailabilityZones may be specified")
c.Assert(e.Code, Equals, "ValidationError")
}
func (s *S) TestDeleteLoadBalancer(c *C) {
testServer.PrepareResponse(200, nil, DeleteLoadBalancer)
resp, err := s.elb.DeleteLoadBalancer("testlb")
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "DeleteLoadBalancer")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(resp.RequestId, Equals, "8d7223db-49d7-11e2-bba9-35ba56032fe1")
}
func (s *S) TestRegisterInstancesWithLoadBalancer(c *C) {
testServer.PrepareResponse(200, nil, RegisterInstancesWithLoadBalancer)
resp, err := s.elb.RegisterInstancesWithLoadBalancer([]string{"i-b44db8ca", "i-461ecf38"}, "testlb")
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "RegisterInstancesWithLoadBalancer")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(values.Get("Instances.member.1.InstanceId"), Equals, "i-b44db8ca")
c.Assert(values.Get("Instances.member.2.InstanceId"), Equals, "i-461ecf38")
c.Assert(resp.InstanceIds, DeepEquals, []string{"i-b44db8ca", "i-461ecf38"})
}
func (s *S) TestRegisterInstancesWithLoadBalancerBadRequest(c *C) {
testServer.PrepareResponse(400, nil, RegisterInstancesWithLoadBalancerBadRequest)
resp, err := s.elb.RegisterInstancesWithLoadBalancer([]string{"i-b44db8ca", "i-461ecf38"}, "absentLB")
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
e, ok := err.(*elb.Error)
c.Assert(ok, Equals, true)
c.Assert(e.Message, Equals, "There is no ACTIVE Load Balancer named 'absentLB'")
c.Assert(e.Code, Equals, "LoadBalancerNotFound")
}
func (s *S) TestDeregisterInstancesFromLoadBalancer(c *C) {
testServer.PrepareResponse(200, nil, DeregisterInstancesFromLoadBalancer)
resp, err := s.elb.DeregisterInstancesFromLoadBalancer([]string{"i-b44db8ca", "i-461ecf38"}, "testlb")
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "DeregisterInstancesFromLoadBalancer")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(values.Get("Instances.member.1.InstanceId"), Equals, "i-b44db8ca")
c.Assert(values.Get("Instances.member.2.InstanceId"), Equals, "i-461ecf38")
c.Assert(resp.RequestId, Equals, "d6490837-49fd-11e2-bba9-35ba56032fe1")
}
func (s *S) TestDeregisterInstancesFromLoadBalancerBadRequest(c *C) {
testServer.PrepareResponse(400, nil, DeregisterInstancesFromLoadBalancerBadRequest)
resp, err := s.elb.DeregisterInstancesFromLoadBalancer([]string{"i-b44db8ca", "i-461ecf38"}, "testlb")
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
e, ok := err.(*elb.Error)
c.Assert(ok, Equals, true)
c.Assert(e.Message, Equals, "There is no ACTIVE Load Balancer named 'absentlb'")
c.Assert(e.Code, Equals, "LoadBalancerNotFound")
}
func (s *S) TestDescribeLoadBalancers(c *C) {
testServer.PrepareResponse(200, nil, DescribeLoadBalancers)
resp, err := s.elb.DescribeLoadBalancers()
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "DescribeLoadBalancers")
t, _ := time.Parse(time.RFC3339, "2012-12-27T11:51:52.970Z")
expected := &elb.DescribeLoadBalancerResp{
[]elb.LoadBalancerDescription{
{
AvailabilityZones: []string{"us-east-1a"},
BackendServerDescriptions: []elb.BackendServerDescriptions(nil),
CanonicalHostedZoneName: "testlb-2087227216.us-east-1.elb.amazonaws.com",
CanonicalHostedZoneNameId: "Z3DZXE0Q79N41H",
CreatedTime: t,
DNSName: "testlb-2087227216.us-east-1.elb.amazonaws.com",
HealthCheck: elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "TCP:80",
Timeout: 5,
UnhealthyThreshold: 2,
},
Instances: []elb.Instance(nil),
ListenerDescriptions: []elb.ListenerDescription{
{
Listener: elb.Listener{
Protocol: "HTTP",
LoadBalancerPort: 80,
InstanceProtocol: "HTTP",
InstancePort: 80,
},
},
},
LoadBalancerName: "testlb",
//Policies: elb.Policies(nil),
Scheme: "internet-facing",
SecurityGroups: []string(nil),
SourceSecurityGroup: elb.SourceSecurityGroup{
GroupName: "amazon-elb-sg",
OwnerAlias: "amazon-elb",
},
Subnets: []string(nil),
},
},
}
c.Assert(resp, DeepEquals, expected)
}
func (s *S) TestDescribeLoadBalancersByName(c *C) {
testServer.PrepareResponse(200, nil, DescribeLoadBalancers)
s.elb.DescribeLoadBalancers("somelb")
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "DescribeLoadBalancers")
c.Assert(values.Get("LoadBalancerNames.member.1"), Equals, "somelb")
}
func (s *S) TestDescribeLoadBalancersBadRequest(c *C) {
testServer.PrepareResponse(400, nil, DescribeLoadBalancersBadRequest)
resp, err := s.elb.DescribeLoadBalancers()
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, `^Cannot find Load Balancer absentlb \(LoadBalancerNotFound\)$`)
}
func (s *S) TestDescribeInstanceHealth(c *C) {
testServer.PrepareResponse(200, nil, DescribeInstanceHealth)
resp, err := s.elb.DescribeInstanceHealth("testlb", "i-b44db8ca")
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "DescribeInstanceHealth")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(values.Get("Instances.member.1.InstanceId"), Equals, "i-b44db8ca")
c.Assert(len(resp.InstanceStates) > 0, Equals, true)
c.Assert(resp.InstanceStates[0].Description, Equals, "Instance registration is still in progress.")
c.Assert(resp.InstanceStates[0].InstanceId, Equals, "i-b44db8ca")
c.Assert(resp.InstanceStates[0].State, Equals, "OutOfService")
c.Assert(resp.InstanceStates[0].ReasonCode, Equals, "ELB")
}
func (s *S) TestDescribeInstanceHealthBadRequest(c *C) {
testServer.PrepareResponse(400, nil, DescribeInstanceHealthBadRequest)
resp, err := s.elb.DescribeInstanceHealth("testlb", "i-foooo")
c.Assert(err, NotNil)
c.Assert(resp, IsNil)
c.Assert(err, ErrorMatches, ".*i-foooo.*(InvalidInstance).*")
}
func (s *S) TestConfigureHealthCheck(c *C) {
testServer.PrepareResponse(200, nil, ConfigureHealthCheck)
hc := elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "HTTP:80/",
Timeout: 5,
UnhealthyThreshold: 2,
}
resp, err := s.elb.ConfigureHealthCheck("testlb", &hc)
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("Action"), Equals, "ConfigureHealthCheck")
c.Assert(values.Get("LoadBalancerName"), Equals, "testlb")
c.Assert(values.Get("HealthCheck.HealthyThreshold"), Equals, "10")
c.Assert(values.Get("HealthCheck.Interval"), Equals, "30")
c.Assert(values.Get("HealthCheck.Target"), Equals, "HTTP:80/")
c.Assert(values.Get("HealthCheck.Timeout"), Equals, "5")
c.Assert(values.Get("HealthCheck.UnhealthyThreshold"), Equals, "2")
c.Assert(resp.HealthCheck.HealthyThreshold, Equals, 10)
c.Assert(resp.HealthCheck.Interval, Equals, 30)
c.Assert(resp.HealthCheck.Target, Equals, "HTTP:80/")
c.Assert(resp.HealthCheck.Timeout, Equals, 5)
c.Assert(resp.HealthCheck.UnhealthyThreshold, Equals, 2)
}
func (s *S) TestConfigureHealthCheckBadRequest(c *C) {
testServer.PrepareResponse(400, nil, ConfigureHealthCheckBadRequest)
hc := elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "HTTP:80/",
Timeout: 5,
UnhealthyThreshold: 2,
}
resp, err := s.elb.ConfigureHealthCheck("foolb", &hc)
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, ".*foolb.*(LoadBalancerNotFound).*")
}
func (s *S) TestAddTags(c *C) {
testServer.PrepareResponse(200, nil, AddTagsSuccessResponse)
tagsToAdd := map[string]string{
"my-key": "my-value",
"my-super-silly-tag": "its-another-valid-value",
}
resp, err := s.elb.AddTags("my-elb", tagsToAdd)
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Action"), Equals, "AddTags")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("LoadBalancerNames.member.1"), Equals, "my-elb")
c.Assert(values.Get("Tags.member.1.Key"), Equals, "my-super-silly-tag")
c.Assert(values.Get("Tags.member.1.Value"), Equals, "its-another-valid-value")
c.Assert(values.Get("Tags.member.2.Key"), Equals, "my-key")
c.Assert(values.Get("Tags.member.2.Value"), Equals, "my-value")
c.Assert(resp.RequestId, Equals, "360e81f7-1100-11e4-b6ed-0f30SOME-SAUCY-EXAMPLE")
}
func (s *S) TestAddBadTags(c *C) {
testServer.PrepareResponse(400, nil, TagsBadRequest)
tagsToAdd := map[string]string{
"my-first-key": "an invalid value",
}
resp, err := s.elb.AddTags("my-bad-elb", tagsToAdd)
c.Assert(resp, IsNil)
c.Assert(err, ErrorMatches, ".*(InvalidParameterValue).*")
}
func (s *S) TestRemoveTags(c *C) {
testServer.PrepareResponse(200, nil, RemoveTagsSuccessResponse)
tagKeysToRemove := []string{"a-key-one", "a-key-two"}
resp, err := s.elb.RemoveTags("my-test-elb-1", tagKeysToRemove)
c.Assert(err, IsNil)
values := testServer.WaitRequest().URL.Query()
c.Assert(values.Get("Version"), Equals, "2012-06-01")
c.Assert(values.Get("Action"), Equals, "RemoveTags")
c.Assert(values.Get("Timestamp"), Not(Equals), "")
c.Assert(values.Get("LoadBalancerNames.member.1"), Equals, "my-test-elb-1")
c.Assert([]string{values.Get("Tags.member.1.Key"), values.Get("Tags.member.2.Key")}, DeepEquals, tagKeysToRemove)
c.Assert(resp.RequestId, Equals, "83c88b9d-12b7-11e3-8b82-87b12DIFFEXAMPLE")
}
func (s *S) TestRemoveTagsFailure(c *C) {
testServer.PrepareResponse(400, nil, TagsBadRequest)
resp, err := s.elb.RemoveTags("my-test-elb", []string{"non-existant-tag"})
c.Assert(resp, IsNil)
c.Assert(err, ErrorMatches, ".*(InvalidParameterValue).*")
}

308
vendor/github.com/goamz/goamz/elb/elbi_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,308 +0,0 @@
package elb_test
import (
"flag"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/ec2"
"github.com/goamz/goamz/elb"
. "gopkg.in/check.v1"
)
var amazon = flag.Bool("amazon", false, "Enable tests against amazon server")
// AmazonServer represents an Amazon AWS server.
type AmazonServer struct {
auth aws.Auth
}
func (s *AmazonServer) SetUp(c *C) {
auth, err := aws.EnvAuth()
if err != nil {
c.Fatal(err)
}
s.auth = auth
}
var _ = Suite(&AmazonClientSuite{})
// AmazonClientSuite tests the client against a live AWS server.
type AmazonClientSuite struct {
srv AmazonServer
ClientTests
}
// ClientTests defines integration tests designed to test the client.
// It is not used as a test suite in itself, but embedded within
// another type.
type ClientTests struct {
elb *elb.ELB
ec2 *ec2.EC2
}
func (s *AmazonClientSuite) SetUpSuite(c *C) {
if !*amazon {
c.Skip("AmazonClientSuite tests not enabled")
}
s.srv.SetUp(c)
s.elb = elb.New(s.srv.auth, aws.USEast)
s.ec2 = ec2.New(s.srv.auth, aws.USEast)
}
func (s *ClientTests) TestCreateAndDeleteLoadBalancer(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
resp, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
defer s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Assert(resp.DNSName, Not(Equals), "")
deleteResp, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Assert(err, IsNil)
c.Assert(deleteResp.RequestId, Not(Equals), "")
}
func (s *ClientTests) TestCreateLoadBalancerError(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Subnets: []string{"subnetid-1"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
resp, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
e, ok := err.(*elb.Error)
c.Assert(ok, Equals, true)
c.Assert(e.Message, Matches, "Only one of .* or .* may be specified")
c.Assert(e.Code, Equals, "ValidationError")
}
func (s *ClientTests) createInstanceAndLB(c *C) (*elb.CreateLoadBalancer, string) {
options := ec2.RunInstancesOptions{
ImageId: "ami-ccf405a5",
InstanceType: "t1.micro",
AvailabilityZone: "us-east-1c",
}
resp1, err := s.ec2.RunInstances(&options)
c.Assert(err, IsNil)
instId := resp1.Instances[0].InstanceId
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1c"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
_, err = s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
return &createLBReq, instId
}
// Cost: 0.02 USD
func (s *ClientTests) TestCreateRegisterAndDeregisterInstanceWithLoadBalancer(c *C) {
createLBReq, instId := s.createInstanceAndLB(c)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
_, err = s.ec2.TerminateInstances([]string{instId})
c.Check(err, IsNil)
}()
resp, err := s.elb.RegisterInstancesWithLoadBalancer([]string{instId}, createLBReq.Name)
c.Assert(err, IsNil)
c.Assert(resp.InstanceIds, DeepEquals, []string{instId})
resp2, err := s.elb.DeregisterInstancesFromLoadBalancer([]string{instId}, createLBReq.Name)
c.Assert(err, IsNil)
c.Assert(resp2, Not(Equals), "")
}
func (s *ClientTests) TestDescribeLoadBalancers(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
_, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
}()
resp, err := s.elb.DescribeLoadBalancers()
c.Assert(err, IsNil)
c.Assert(len(resp.LoadBalancerDescriptions) > 0, Equals, true)
c.Assert(resp.LoadBalancerDescriptions[0].AvailabilityZones, DeepEquals, []string{"us-east-1a"})
c.Assert(resp.LoadBalancerDescriptions[0].LoadBalancerName, Equals, "testlb")
c.Assert(resp.LoadBalancerDescriptions[0].Scheme, Equals, "internet-facing")
hc := elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "TCP:80",
Timeout: 5,
UnhealthyThreshold: 2,
}
c.Assert(resp.LoadBalancerDescriptions[0].HealthCheck, DeepEquals, hc)
ld := []elb.ListenerDescription{
{
Listener: elb.Listener{
Protocol: "HTTP",
LoadBalancerPort: 80,
InstanceProtocol: "HTTP",
InstancePort: 80,
},
},
}
c.Assert(resp.LoadBalancerDescriptions[0].ListenerDescriptions, DeepEquals, ld)
ssg := elb.SourceSecurityGroup{
GroupName: "amazon-elb-sg",
OwnerAlias: "amazon-elb",
}
c.Assert(resp.LoadBalancerDescriptions[0].SourceSecurityGroup, DeepEquals, ssg)
}
func (s *ClientTests) TestDescribeLoadBalancersBadRequest(c *C) {
resp, err := s.elb.DescribeLoadBalancers("absentlb")
c.Assert(err, NotNil)
c.Assert(resp, IsNil)
c.Assert(err, ErrorMatches, ".*(LoadBalancerNotFound).*")
}
func (s *ClientTests) TestDescribeInstanceHealth(c *C) {
createLBReq, instId := s.createInstanceAndLB(c)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
_, err = s.ec2.TerminateInstances([]string{instId})
c.Check(err, IsNil)
}()
_, err := s.elb.RegisterInstancesWithLoadBalancer([]string{instId}, createLBReq.Name)
c.Assert(err, IsNil)
resp, err := s.elb.DescribeInstanceHealth(createLBReq.Name, instId)
c.Assert(err, IsNil)
c.Assert(len(resp.InstanceStates) > 0, Equals, true)
c.Assert(resp.InstanceStates[0].Description, Equals, "Instance is in pending state.")
c.Assert(resp.InstanceStates[0].InstanceId, Equals, instId)
c.Assert(resp.InstanceStates[0].State, Equals, "OutOfService")
c.Assert(resp.InstanceStates[0].ReasonCode, Equals, "Instance")
}
func (s *ClientTests) TestDescribeInstanceHealthBadRequest(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
_, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
}()
resp, err := s.elb.DescribeInstanceHealth(createLBReq.Name, "i-foo")
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, ".*i-foo.*(InvalidInstance).*")
}
func (s *ClientTests) TestConfigureHealthCheck(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
_, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
}()
hc := elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "HTTP:80/",
Timeout: 5,
UnhealthyThreshold: 2,
}
resp, err := s.elb.ConfigureHealthCheck(createLBReq.Name, &hc)
c.Assert(err, IsNil)
c.Assert(resp.HealthCheck.HealthyThreshold, Equals, 10)
c.Assert(resp.HealthCheck.Interval, Equals, 30)
c.Assert(resp.HealthCheck.Target, Equals, "HTTP:80/")
c.Assert(resp.HealthCheck.Timeout, Equals, 5)
c.Assert(resp.HealthCheck.UnhealthyThreshold, Equals, 2)
}
func (s *ClientTests) TestConfigureHealthCheckBadRequest(c *C) {
createLBReq := elb.CreateLoadBalancer{
Name: "testlb",
AvailabilityZones: []string{"us-east-1a"},
Listeners: []elb.Listener{
{
InstancePort: 80,
InstanceProtocol: "http",
LoadBalancerPort: 80,
Protocol: "http",
},
},
}
_, err := s.elb.CreateLoadBalancer(&createLBReq)
c.Assert(err, IsNil)
defer func() {
_, err := s.elb.DeleteLoadBalancer(createLBReq.Name)
c.Check(err, IsNil)
}()
hc := elb.HealthCheck{
HealthyThreshold: 10,
Interval: 30,
Target: "HTTP:80",
Timeout: 5,
UnhealthyThreshold: 2,
}
resp, err := s.elb.ConfigureHealthCheck(createLBReq.Name, &hc)
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
expected := "HealthCheck HTTP Target must specify a port followed by a path that begins with a slash. e.g. HTTP:80/ping/this/path (ValidationError)"
c.Assert(err.Error(), Equals, expected)
}

243
vendor/github.com/goamz/goamz/elb/elbt_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,243 +0,0 @@
package elb_test
import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/elb"
"github.com/goamz/goamz/elb/elbtest"
. "gopkg.in/check.v1"
)
// LocalServer represents a local elbtest fake server.
type LocalServer struct {
auth aws.Auth
region aws.Region
srv *elbtest.Server
}
func (s *LocalServer) SetUp(c *C) {
srv, err := elbtest.NewServer()
c.Assert(err, IsNil)
c.Assert(srv, NotNil)
s.srv = srv
s.region = aws.Region{ELBEndpoint: srv.URL()}
}
// LocalServerSuite defines tests that will run
// against the local elbtest server. It includes
// selected tests from ClientTests;
// when the elbtest functionality is sufficient, it should
// include all of them, and ClientTests can be simply embedded.
type LocalServerSuite struct {
srv LocalServer
ServerTests
clientTests ClientTests
}
// ServerTests defines a set of tests designed to test
// the elbtest local fake elb server.
// It is not used as a test suite in itself, but embedded within
// another type.
type ServerTests struct {
elb *elb.ELB
}
// AmazonServerSuite runs the elbtest server tests against a live ELB server.
// It will only be activated if the -all flag is specified.
type AmazonServerSuite struct {
srv AmazonServer
ServerTests
}
var _ = Suite(&AmazonServerSuite{})
func (s *AmazonServerSuite) SetUpSuite(c *C) {
if !*amazon {
c.Skip("AmazonServerSuite tests not enabled")
}
s.srv.SetUp(c)
s.ServerTests.elb = elb.New(s.srv.auth, aws.USEast)
}
var _ = Suite(&LocalServerSuite{})
func (s *LocalServerSuite) SetUpSuite(c *C) {
s.srv.SetUp(c)
s.ServerTests.elb = elb.New(s.srv.auth, s.srv.region)
s.clientTests.elb = elb.New(s.srv.auth, s.srv.region)
}
func (s *LocalServerSuite) TestCreateLoadBalancer(c *C) {
s.clientTests.TestCreateAndDeleteLoadBalancer(c)
}
func (s *LocalServerSuite) TestCreateLoadBalancerError(c *C) {
s.clientTests.TestCreateLoadBalancerError(c)
}
func (s *LocalServerSuite) TestDescribeLoadBalancer(c *C) {
s.clientTests.TestDescribeLoadBalancers(c)
}
func (s *LocalServerSuite) TestDescribeLoadBalancerListsAddedByNewLoadbalancerFunc(c *C) {
srv := s.srv.srv
srv.NewLoadBalancer("wierdlb")
defer srv.RemoveLoadBalancer("wierdlb")
resp, err := s.clientTests.elb.DescribeLoadBalancers()
c.Assert(err, IsNil)
isPresent := false
for _, desc := range resp.LoadBalancerDescriptions {
if desc.LoadBalancerName == "wierdlb" {
isPresent = true
}
}
c.Assert(isPresent, Equals, true)
}
func (s *LocalServerSuite) TestDescribeLoadBalancerListsInstancesAddedByRegisterInstancesFunc(c *C) {
srv := s.srv.srv
lbName := "somelb"
srv.NewLoadBalancer(lbName)
defer srv.RemoveLoadBalancer(lbName)
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.RegisterInstance(instId, lbName) // no need to deregister, since we're removing the lb
resp, err := s.clientTests.elb.DescribeLoadBalancers()
c.Assert(err, IsNil)
c.Assert(len(resp.LoadBalancerDescriptions) > 0, Equals, true)
c.Assert(len(resp.LoadBalancerDescriptions[0].Instances) > 0, Equals, true)
c.Assert(resp.LoadBalancerDescriptions[0].Instances, DeepEquals, []elb.Instance{{InstanceId: instId}})
srv.DeregisterInstance(instId, lbName)
resp, err = s.clientTests.elb.DescribeLoadBalancers()
c.Assert(err, IsNil)
c.Assert(resp.LoadBalancerDescriptions[0].Instances, DeepEquals, []elb.Instance(nil))
}
func (s *LocalServerSuite) TestDescribeLoadBalancersBadRequest(c *C) {
s.clientTests.TestDescribeLoadBalancersBadRequest(c)
}
func (s *LocalServerSuite) TestRegisterInstanceWithLoadBalancer(c *C) {
srv := s.srv.srv
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
resp, err := s.clientTests.elb.RegisterInstancesWithLoadBalancer([]string{instId}, "testlb")
c.Assert(err, IsNil)
c.Assert(resp.InstanceIds, DeepEquals, []string{instId})
}
func (s *LocalServerSuite) TestRegisterInstanceWithLoadBalancerWithAbsentInstance(c *C) {
srv := s.srv.srv
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
resp, err := s.clientTests.elb.RegisterInstancesWithLoadBalancer([]string{"i-212"}, "testlb")
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, `^InvalidInstance found in \[i-212\]. Invalid id: "i-212" \(InvalidInstance\)$`)
c.Assert(resp, IsNil)
}
func (s *LocalServerSuite) TestRegisterInstanceWithLoadBalancerWithAbsentLoadBalancer(c *C) {
// the verification if the lb exists is done before the instances, so there is no need to create
// fixture instances for this test, it'll never get that far
resp, err := s.clientTests.elb.RegisterInstancesWithLoadBalancer([]string{"i-212"}, "absentlb")
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, `^There is no ACTIVE Load Balancer named 'absentlb' \(LoadBalancerNotFound\)$`)
c.Assert(resp, IsNil)
}
func (s *LocalServerSuite) TestDeregisterInstanceWithLoadBalancer(c *C) {
// there is no need to register the instance first, amazon returns the same response
// in both cases (instance registered or not)
srv := s.srv.srv
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
resp, err := s.clientTests.elb.DeregisterInstancesFromLoadBalancer([]string{instId}, "testlb")
c.Assert(err, IsNil)
c.Assert(resp.RequestId, Not(Equals), "")
}
func (s *LocalServerSuite) TestDeregisterInstanceWithLoadBalancerWithAbsentLoadBalancer(c *C) {
resp, err := s.clientTests.elb.DeregisterInstancesFromLoadBalancer([]string{"i-212"}, "absentlb")
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, `^There is no ACTIVE Load Balancer named 'absentlb' \(LoadBalancerNotFound\)$`)
}
func (s *LocalServerSuite) TestDeregisterInstancewithLoadBalancerWithAbsentInstance(c *C) {
srv := s.srv.srv
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
resp, err := s.clientTests.elb.DeregisterInstancesFromLoadBalancer([]string{"i-212"}, "testlb")
c.Assert(resp, IsNil)
c.Assert(err, NotNil)
c.Assert(err, ErrorMatches, `^InvalidInstance found in \[i-212\]. Invalid id: "i-212" \(InvalidInstance\)$`)
}
func (s *LocalServerSuite) TestDescribeInstanceHealth(c *C) {
srv := s.srv.srv
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
resp, err := s.clientTests.elb.DescribeInstanceHealth("testlb", instId)
c.Assert(err, IsNil)
c.Assert(len(resp.InstanceStates) > 0, Equals, true)
c.Assert(resp.InstanceStates[0].Description, Equals, "Instance is in pending state.")
c.Assert(resp.InstanceStates[0].InstanceId, Equals, instId)
c.Assert(resp.InstanceStates[0].State, Equals, "OutOfService")
c.Assert(resp.InstanceStates[0].ReasonCode, Equals, "Instance")
}
func (s *LocalServerSuite) TestDescribeInstanceHealthBadRequest(c *C) {
s.clientTests.TestDescribeInstanceHealthBadRequest(c)
}
func (s *LocalServerSuite) TestDescribeInstanceHealthWithoutSpecifyingInstances(c *C) {
srv := s.srv.srv
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.NewLoadBalancer("testlb")
defer srv.RemoveLoadBalancer("testlb")
srv.RegisterInstance(instId, "testlb")
resp, err := s.clientTests.elb.DescribeInstanceHealth("testlb")
c.Assert(err, IsNil)
c.Assert(len(resp.InstanceStates) > 0, Equals, true)
c.Assert(resp.InstanceStates[0].Description, Equals, "Instance is in pending state.")
c.Assert(resp.InstanceStates[0].InstanceId, Equals, instId)
c.Assert(resp.InstanceStates[0].State, Equals, "OutOfService")
c.Assert(resp.InstanceStates[0].ReasonCode, Equals, "Instance")
}
func (s *LocalServerSuite) TestDescribeInstanceHealthChangingIt(c *C) {
srv := s.srv.srv
instId := srv.NewInstance()
defer srv.RemoveInstance(instId)
srv.NewLoadBalancer("somelb")
defer srv.RemoveLoadBalancer("somelb")
srv.RegisterInstance(instId, "somelb")
state := elb.InstanceState{
Description: "Instance has failed at least the UnhealthyThreshold number of health checks consecutively",
InstanceId: instId,
State: "OutOfService",
ReasonCode: "Instance",
}
srv.ChangeInstanceState("somelb", state)
resp, err := s.clientTests.elb.DescribeInstanceHealth("somelb")
c.Assert(err, IsNil)
c.Assert(len(resp.InstanceStates) > 0, Equals, true)
c.Assert(resp.InstanceStates[0].Description, Equals, "Instance has failed at least the UnhealthyThreshold number of health checks consecutively")
c.Assert(resp.InstanceStates[0].InstanceId, Equals, instId)
c.Assert(resp.InstanceStates[0].State, Equals, "OutOfService")
c.Assert(resp.InstanceStates[0].ReasonCode, Equals, "Instance")
}
func (s *LocalServerSuite) TestConfigureHealthCheck(c *C) {
s.clientTests.TestConfigureHealthCheck(c)
}
func (s *LocalServerSuite) TestConfigureHealthCheckBadRequest(c *C) {
s.clientTests.TestConfigureHealthCheckBadRequest(c)
}

551
vendor/github.com/goamz/goamz/elb/elbtest/server.go сгенерированный поставляемый
Просмотреть файл

@@ -1,551 +0,0 @@
// Package elbtest implements a fake ELB provider with the capability of
// inducing errors on any given operation, and retrospectively determining what
// operations have been carried out.
package elbtest
import (
"encoding/xml"
"fmt"
"github.com/goamz/goamz/elb"
"net"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"sync"
)
// Server implements an ELB simulator for use in testing.
type Server struct {
url string
listener net.Listener
mutex sync.Mutex
reqId int
lbs map[string]*elb.LoadBalancerDescription
lbsReqs map[string]url.Values
instances []string
instanceStates map[string][]*elb.InstanceState
instCount int
}
// Starts and returns a new server
func NewServer() (*Server, error) {
l, err := net.Listen("tcp", "localhost:0")
if err != nil {
return nil, fmt.Errorf("cannot listen on localhost: %v", err)
}
srv := &Server{
listener: l,
url: "http://" + l.Addr().String(),
lbs: make(map[string]*elb.LoadBalancerDescription),
instanceStates: make(map[string][]*elb.InstanceState),
}
go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
srv.serveHTTP(w, req)
}))
return srv, nil
}
// Quit closes down the server.
func (srv *Server) Quit() {
srv.listener.Close()
}
// URL returns the URL of the server.
func (srv *Server) URL() string {
return srv.url
}
type xmlErrors struct {
XMLName string `xml:"ErrorResponse"`
Error elb.Error
}
func (srv *Server) error(w http.ResponseWriter, err *elb.Error) {
w.WriteHeader(err.StatusCode)
xmlErr := xmlErrors{Error: *err}
if e := xml.NewEncoder(w).Encode(xmlErr); e != nil {
panic(e)
}
}
func (srv *Server) serveHTTP(w http.ResponseWriter, req *http.Request) {
req.ParseForm()
srv.mutex.Lock()
defer srv.mutex.Unlock()
f := actions[req.Form.Get("Action")]
if f == nil {
srv.error(w, &elb.Error{
StatusCode: 400,
Code: "InvalidParameterValue",
Message: "Unrecognized Action",
})
}
reqId := fmt.Sprintf("req%0X", srv.reqId)
srv.reqId++
if resp, err := f(srv, w, req, reqId); err == nil {
if err := xml.NewEncoder(w).Encode(resp); err != nil {
panic(err)
}
} else {
switch err.(type) {
case *elb.Error:
srv.error(w, err.(*elb.Error))
default:
panic(err)
}
}
}
func (srv *Server) createLoadBalancer(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
composition := map[string]string{
"AvailabilityZones.member.1": "Subnets.member.1",
}
if err := srv.validateComposition(req, composition); err != nil {
return nil, err
}
required := []string{
"Listeners.member.1.InstancePort",
"Listeners.member.1.InstanceProtocol",
"Listeners.member.1.Protocol",
"Listeners.member.1.LoadBalancerPort",
"LoadBalancerName",
}
if err := srv.validate(req, required); err != nil {
return nil, err
}
path := req.FormValue("Path")
if path == "" {
path = "/"
}
lbName := req.FormValue("LoadBalancerName")
srv.lbs[lbName] = srv.makeLoadBalancerDescription(req.Form)
srv.lbs[lbName].DNSName = fmt.Sprintf("%s-some-aws-stuff.us-east-1.elb.amazonaws.com", lbName)
return elb.CreateLoadBalancerResp{
DNSName: srv.lbs[lbName].DNSName,
}, nil
}
func (srv *Server) deleteLoadBalancer(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
if err := srv.validate(req, []string{"LoadBalancerName"}); err != nil {
return nil, err
}
srv.RemoveLoadBalancer(req.FormValue("LoadBalancerName"))
return elb.SimpleResp{RequestId: reqId}, nil
}
func (srv *Server) registerInstancesWithLoadBalancer(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
required := []string{"LoadBalancerName", "Instances.member.1.InstanceId"}
if err := srv.validate(req, required); err != nil {
return nil, err
}
lbName := req.FormValue("LoadBalancerName")
if err := srv.lbExists(lbName); err != nil {
return nil, err
}
instIds := []string{}
instances := []elb.Instance{}
i := 1
instId := req.FormValue(fmt.Sprintf("Instances.member.%d.InstanceId", i))
for instId != "" {
if err := srv.instanceExists(instId); err != nil {
return nil, err
}
instIds = append(instIds, instId)
instances = append(instances, elb.Instance{InstanceId: instId})
i++
instId = req.FormValue(fmt.Sprintf("Instances.member.%d.InstanceId", i))
}
srv.instanceStates[lbName] = append(srv.instanceStates[lbName], srv.makeInstanceState(instId))
srv.lbs[lbName].Instances = append(srv.lbs[lbName].Instances, instances...)
return elb.RegisterInstancesResp{InstanceIds: instIds}, nil
}
func (srv *Server) deregisterInstancesFromLoadBalancer(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
required := []string{"LoadBalancerName"}
if err := srv.validate(req, required); err != nil {
return nil, err
}
lbName := req.FormValue("LoadBalancerName")
if err := srv.lbExists(lbName); err != nil {
return nil, err
}
i := 1
lb := srv.lbs[lbName]
instId := req.FormValue(fmt.Sprintf("Instances.member.%d.InstanceId", i))
for instId != "" {
if err := srv.instanceExists(instId); err != nil {
return nil, err
}
i++
removeInstanceFromLB(lb, instId)
instId = req.FormValue(fmt.Sprintf("Instances.member.%d.InstanceId", i))
}
srv.lbs[lbName] = lb
srv.removeInstanceStatesFromLoadBalancer(lbName, instId)
return elb.SimpleResp{RequestId: reqId}, nil
}
func (srv *Server) describeLoadBalancers(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
i := 1
lbName := req.FormValue(fmt.Sprintf("LoadBalancerNames.member.%d", i))
for lbName != "" {
key := fmt.Sprintf("LoadBalancerNames.member.%d", i)
if req.FormValue(key) != "" {
if err := srv.lbExists(req.FormValue(key)); err != nil {
return nil, err
}
}
i++
lbName = req.FormValue(fmt.Sprintf("LoadBalancerNames.member.%d", i))
}
lbsDesc := make([]elb.LoadBalancerDescription, len(srv.lbs))
i = 0
for _, lb := range srv.lbs {
lbsDesc[i] = *lb
i++
}
resp := elb.DescribeLoadBalancerResp{
LoadBalancerDescriptions: lbsDesc,
}
return resp, nil
}
// getParameters returns the value all parameters from a request that matches a
// prefix.
//
// For example, for the prefix "Subnets.member.", it will return a slice
// containing the value of keys "Subnets.member.1", "Subnets.member.2" ...
// "Subnets.member.N". The prefix must include the trailing dot.
func (srv *Server) getParameters(prefix string, values url.Values) []string {
i, key := 1, ""
var k = func(n int) string {
return fmt.Sprintf(prefix+"%d", n)
}
var result []string
for i, key = 2, k(i); values.Get(key) != ""; i, key = i+1, k(i) {
result = append(result, values.Get(key))
}
return result
}
func (srv *Server) makeInstanceState(id string) *elb.InstanceState {
return &elb.InstanceState{
Description: "Instance is in pending state.",
InstanceId: id,
State: "OutOfService",
ReasonCode: "Instance",
}
}
func removeInstanceFromLB(lb *elb.LoadBalancerDescription, id string) {
index := -1
for i, instance := range lb.Instances {
if instance.InstanceId == id {
index = i
break
}
}
if index > -1 {
copy(lb.Instances[index:], lb.Instances[index+1:])
lb.Instances = lb.Instances[:len(lb.Instances)-1]
}
}
func (srv *Server) removeInstanceStatesFromLoadBalancer(lb, id string) {
for i, state := range srv.instanceStates[lb] {
if state.InstanceId == id {
a := srv.instanceStates[lb]
a[i], a = a[len(a)-1], a[:len(a)-1]
srv.instanceStates[lb] = a
return
}
}
}
func (srv *Server) makeLoadBalancerDescription(value url.Values) *elb.LoadBalancerDescription {
lds := []elb.ListenerDescription{}
i := 1
protocol := value.Get(fmt.Sprintf("Listeners.member.%d.Protocol", i))
for protocol != "" {
key := fmt.Sprintf("Listeners.member.%d.", i)
lInstPort, _ := strconv.Atoi(value.Get(key + "InstancePort"))
lLBPort, _ := strconv.Atoi(value.Get(key + "LoadBalancerPort"))
lDescription := elb.ListenerDescription{
Listener: elb.Listener{
Protocol: strings.ToUpper(protocol),
InstanceProtocol: strings.ToUpper(value.Get(key + "InstanceProtocol")),
LoadBalancerPort: lLBPort,
InstancePort: lInstPort,
},
}
i++
protocol = value.Get(fmt.Sprintf("Listeners.member.%d.Protocol", i))
lds = append(lds, lDescription)
}
sourceSecGroup := srv.makeSourceSecGroup(value)
lbDesc := elb.LoadBalancerDescription{
AvailabilityZones: srv.getParameters("AvailabilityZones.member.", value),
Subnets: srv.getParameters("Subnets.member.", value),
SecurityGroups: srv.getParameters("SecurityGroups.member.", value),
HealthCheck: srv.makeHealthCheck(value),
ListenerDescriptions: lds,
Scheme: value.Get("Scheme"),
SourceSecurityGroup: sourceSecGroup,
LoadBalancerName: value.Get("LoadBalancerName"),
}
if lbDesc.Scheme == "" {
lbDesc.Scheme = "internet-facing"
}
return &lbDesc
}
func (srv *Server) makeHealthCheck(value url.Values) elb.HealthCheck {
ht := 10
timeout := 5
ut := 2
interval := 30
target := "TCP:80"
if v := value.Get("HealthCheck.HealthyThreshold"); v != "" {
ht, _ = strconv.Atoi(v)
}
if v := value.Get("HealthCheck.Timeout"); v != "" {
timeout, _ = strconv.Atoi(v)
}
if v := value.Get("HealthCheck.UnhealthyThreshold"); v != "" {
ut, _ = strconv.Atoi(v)
}
if v := value.Get("HealthCheck.Interval"); v != "" {
interval, _ = strconv.Atoi(v)
}
if v := value.Get("HealthCheck.Target"); v != "" {
target = v
}
return elb.HealthCheck{
HealthyThreshold: ht,
Interval: interval,
Target: target,
Timeout: timeout,
UnhealthyThreshold: ut,
}
}
func (srv *Server) makeSourceSecGroup(value url.Values) elb.SourceSecurityGroup {
name := "amazon-elb-sg"
alias := "amazon-elb"
if v := value.Get("SourceSecurityGroup.GroupName"); v != "" {
name = v
}
if v := value.Get("SourceSecurityGroup.OwnerAlias"); v != "" {
alias = v
}
return elb.SourceSecurityGroup{
GroupName: name,
OwnerAlias: alias,
}
}
func (srv *Server) describeInstanceHealth(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
if err := srv.lbExists(req.FormValue("LoadBalancerName")); err != nil {
return nil, err
}
resp := elb.DescribeInstanceHealthResp{
InstanceStates: []elb.InstanceState{},
}
for _, state := range srv.instanceStates[req.FormValue("LoadBalancerName")] {
resp.InstanceStates = append(resp.InstanceStates, *state)
}
i := 1
instanceId := req.FormValue("Instances.member.1.InstanceId")
for instanceId != "" {
if err := srv.instanceExists(instanceId); err != nil {
return nil, err
}
is := elb.InstanceState{
Description: "Instance is in pending state.",
InstanceId: instanceId,
State: "OutOfService",
ReasonCode: "Instance",
}
resp.InstanceStates = append(resp.InstanceStates, is)
i++
instanceId = req.FormValue(fmt.Sprintf("Instances.member.%d.InstanceId", i))
}
return resp, nil
}
func (srv *Server) configureHealthCheck(w http.ResponseWriter, req *http.Request, reqId string) (interface{}, error) {
required := []string{
"LoadBalancerName",
"HealthCheck.HealthyThreshold",
"HealthCheck.Interval",
"HealthCheck.Target",
"HealthCheck.Timeout",
"HealthCheck.UnhealthyThreshold",
}
if err := srv.validate(req, required); err != nil {
return nil, err
}
target := req.FormValue("HealthCheck.Target")
r, err := regexp.Compile(`[\w]+:[\d]+\/+`)
if err != nil {
panic(err)
}
if m := r.FindStringSubmatch(target); m == nil {
return nil, &elb.Error{
StatusCode: 400,
Code: "ValidationError",
Message: "HealthCheck HTTP Target must specify a port followed by a path that begins with a slash. e.g. HTTP:80/ping/this/path",
}
}
ht, _ := strconv.Atoi(req.FormValue("HealthCheck.HealthyThreshold"))
interval, _ := strconv.Atoi(req.FormValue("HealthCheck.Interval"))
timeout, _ := strconv.Atoi(req.FormValue("HealthCheck.Timeout"))
ut, _ := strconv.Atoi(req.FormValue("HealthCheck.UnhealthyThreshold"))
return elb.HealthCheckResp{
HealthCheck: &elb.HealthCheck{
HealthyThreshold: ht,
Interval: interval,
Target: target,
Timeout: timeout,
UnhealthyThreshold: ut,
},
}, nil
}
func (srv *Server) instanceExists(id string) error {
for _, instId := range srv.instances {
if instId == id {
return nil
}
}
return &elb.Error{
StatusCode: 400,
Code: "InvalidInstance",
Message: fmt.Sprintf("InvalidInstance found in [%s]. Invalid id: \"%s\"", id, id),
}
}
func (srv *Server) lbExists(name string) error {
if _, ok := srv.lbs[name]; !ok {
return &elb.Error{
StatusCode: 400,
Code: "LoadBalancerNotFound",
Message: fmt.Sprintf("There is no ACTIVE Load Balancer named '%s'", name),
}
}
return nil
}
func (srv *Server) validate(req *http.Request, required []string) error {
for _, field := range required {
if req.FormValue(field) == "" {
return &elb.Error{
StatusCode: 400,
Code: "ValidationError",
Message: fmt.Sprintf("%s is required.", field),
}
}
}
return nil
}
// Validates the composition of the fields.
//
// Some fields cannot be together in the same request, such as AvailabilityZones and Subnets.
// A sample map with the above requirement would be
// c := map[string]string{
// "AvailabilityZones.member.1": "Subnets.member.1",
// }
//
// The server also requires that at least one of those fields are specified.
func (srv *Server) validateComposition(req *http.Request, composition map[string]string) error {
for k, v := range composition {
if req.FormValue(k) != "" && req.FormValue(v) != "" {
return &elb.Error{
StatusCode: 400,
Code: "ValidationError",
Message: fmt.Sprintf("Only one of %s or %s may be specified", k, v),
}
}
if req.FormValue(k) == "" && req.FormValue(v) == "" {
return &elb.Error{
StatusCode: 400,
Code: "ValidationError",
Message: fmt.Sprintf("Either %s or %s must be specified", k, v),
}
}
}
return nil
}
// Creates a fake instance in the server
func (srv *Server) NewInstance() string {
srv.instCount++
instId := fmt.Sprintf("i-%d", srv.instCount)
srv.instances = append(srv.instances, instId)
return instId
}
// Removes a fake instance from the server
//
// If no instance is found it does nothing
func (srv *Server) RemoveInstance(instId string) {
for i, id := range srv.instances {
if id == instId {
srv.instances[i], srv.instances = srv.instances[len(srv.instances)-1], srv.instances[:len(srv.instances)-1]
}
}
}
// Creates a fake load balancer in the fake server
func (srv *Server) NewLoadBalancer(name string) {
srv.lbs[name] = &elb.LoadBalancerDescription{
LoadBalancerName: name,
DNSName: fmt.Sprintf("%s-some-aws-stuff.sa-east-1.amazonaws.com", name),
}
}
// Removes a fake load balancer from the fake server
func (srv *Server) RemoveLoadBalancer(name string) {
delete(srv.lbs, name)
}
// Register a fake instance with a fake Load Balancer
//
// If the Load Balancer does not exists it does nothing
func (srv *Server) RegisterInstance(instId, lbName string) {
lb, ok := srv.lbs[lbName]
if !ok {
fmt.Println("lb not found :/")
return
}
lb.Instances = append(lb.Instances, elb.Instance{InstanceId: instId})
srv.instanceStates[lbName] = append(srv.instanceStates[lbName], srv.makeInstanceState(instId))
}
func (srv *Server) DeregisterInstance(instId, lbName string) {
removeInstanceFromLB(srv.lbs[lbName], instId)
srv.removeInstanceStatesFromLoadBalancer(lbName, instId)
}
func (srv *Server) ChangeInstanceState(lb string, state elb.InstanceState) {
states := srv.instanceStates[lb]
for i, s := range states {
if s.InstanceId == state.InstanceId {
srv.instanceStates[lb][i] = &state
return
}
}
}
var actions = map[string]func(*Server, http.ResponseWriter, *http.Request, string) (interface{}, error){
"CreateLoadBalancer": (*Server).createLoadBalancer,
"DeleteLoadBalancer": (*Server).deleteLoadBalancer,
"RegisterInstancesWithLoadBalancer": (*Server).registerInstancesWithLoadBalancer,
"DeregisterInstancesFromLoadBalancer": (*Server).deregisterInstancesFromLoadBalancer,
"DescribeLoadBalancers": (*Server).describeLoadBalancers,
"DescribeInstanceHealth": (*Server).describeInstanceHealth,
"ConfigureHealthCheck": (*Server).configureHealthCheck,
}

9
vendor/github.com/goamz/goamz/elb/export_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,9 +0,0 @@
package elb
import (
"github.com/goamz/goamz/aws"
)
func Sign(auth aws.Auth, method, path string, params map[string]string, host string) {
sign(auth, method, path, params, host)
}

234
vendor/github.com/goamz/goamz/elb/response_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,234 +0,0 @@
package elb_test
var CreateLoadBalancer = `
<CreateLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<CreateLoadBalancerResult>
<DNSName>testlb-339187009.us-east-1.elb.amazonaws.com</DNSName>
</CreateLoadBalancerResult>
<ResponseMetadata>
<RequestId>0c3a8e29-490e-11e2-8647-e14ad5151f1f</RequestId>
</ResponseMetadata>
</CreateLoadBalancerResponse>
`
var CreateLoadBalancerBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>ValidationError</Code>
<Message>Only one of SubnetIds or AvailabilityZones may be specified</Message>
</Error>
<RequestId>159253fc-49dc-11e2-a47d-cde463c91a3c</RequestId>
</ErrorResponse>
`
var DeleteLoadBalancer = `
<DeleteLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DeleteLoadBalancerResult/>
<ResponseMetadata>
<RequestId>8d7223db-49d7-11e2-bba9-35ba56032fe1</RequestId>
</ResponseMetadata>
</DeleteLoadBalancerResponse>
`
var RegisterInstancesWithLoadBalancer = `
<RegisterInstancesWithLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<RegisterInstancesWithLoadBalancerResult>
<Instances>
<member>
<InstanceId>i-b44db8ca</InstanceId>
</member>
<member>
<InstanceId>i-461ecf38</InstanceId>
</member>
</Instances>
</RegisterInstancesWithLoadBalancerResult>
<ResponseMetadata>
<RequestId>0fc82478-49e1-11e2-b947-8768f15220aa</RequestId>
</ResponseMetadata>
</RegisterInstancesWithLoadBalancerResponse>
`
var RegisterInstancesWithLoadBalancerBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>LoadBalancerNotFound</Code>
<Message>There is no ACTIVE Load Balancer named 'absentLB'</Message>
</Error>
<RequestId>19a0bb97-49f7-11e2-90b4-6bb9ec8331bf</RequestId>
</ErrorResponse>
`
var DeregisterInstancesFromLoadBalancer = `
<DeregisterInstancesFromLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DeregisterInstancesFromLoadBalancerResult>
<Instances/>
</DeregisterInstancesFromLoadBalancerResult>
<ResponseMetadata>
<RequestId>d6490837-49fd-11e2-bba9-35ba56032fe1</RequestId>
</ResponseMetadata>
</DeregisterInstancesFromLoadBalancerResponse>
`
var DeregisterInstancesFromLoadBalancerBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>LoadBalancerNotFound</Code>
<Message>There is no ACTIVE Load Balancer named 'absentlb'</Message>
</Error>
<RequestId>498e2b4a-4aa1-11e2-8839-d19a879f2eec</RequestId>
</ErrorResponse>
`
var DescribeLoadBalancers = `
<DescribeLoadBalancersResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeLoadBalancersResult>
<LoadBalancerDescriptions>
<member>
<SecurityGroups/>
<CreatedTime>2012-12-27T11:51:52.970Z</CreatedTime>
<LoadBalancerName>testlb</LoadBalancerName>
<HealthCheck>
<Interval>30</Interval>
<Target>TCP:80</Target>
<HealthyThreshold>10</HealthyThreshold>
<Timeout>5</Timeout>
<UnhealthyThreshold>2</UnhealthyThreshold>
</HealthCheck>
<ListenerDescriptions>
<member>
<PolicyNames/>
<Listener>
<Protocol>HTTP</Protocol>
<LoadBalancerPort>80</LoadBalancerPort>
<InstanceProtocol>HTTP</InstanceProtocol>
<InstancePort>80</InstancePort>
</Listener>
</member>
</ListenerDescriptions>
<Instances/>
<Policies>
<AppCookieStickinessPolicies/>
<OtherPolicies/>
<LBCookieStickinessPolicies/>
</Policies>
<AvailabilityZones>
<member>us-east-1a</member>
</AvailabilityZones>
<CanonicalHostedZoneName>testlb-2087227216.us-east-1.elb.amazonaws.com</CanonicalHostedZoneName>
<CanonicalHostedZoneNameID>Z3DZXE0Q79N41H</CanonicalHostedZoneNameID>
<Scheme>internet-facing</Scheme>
<SourceSecurityGroup>
<OwnerAlias>amazon-elb</OwnerAlias>
<GroupName>amazon-elb-sg</GroupName>
</SourceSecurityGroup>
<DNSName>testlb-2087227216.us-east-1.elb.amazonaws.com</DNSName>
<BackendServerDescriptions/>
<Subnets/>
</member>
</LoadBalancerDescriptions>
</DescribeLoadBalancersResult>
<ResponseMetadata>
<RequestId>e2e81963-5055-11e2-99c7-434205631d9b</RequestId>
</ResponseMetadata>
</DescribeLoadBalancersResponse>
`
var DescribeLoadBalancersBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>LoadBalancerNotFound</Code>
<Message>Cannot find Load Balancer absentlb</Message>
</Error>
<RequestId>f14f348e-50f7-11e2-9831-f770dd71c209</RequestId>
</ErrorResponse>
`
var DescribeInstanceHealth = `
<DescribeInstanceHealthResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeInstanceHealthResult>
<InstanceStates>
<member>
<Description>Instance registration is still in progress.</Description>
<InstanceId>i-b44db8ca</InstanceId>
<State>OutOfService</State>
<ReasonCode>ELB</ReasonCode>
</member>
</InstanceStates>
</DescribeInstanceHealthResult>
<ResponseMetadata>
<RequestId>da0d0f9e-5669-11e2-9f81-319facce7423</RequestId>
</ResponseMetadata>
</DescribeInstanceHealthResponse>
`
var DescribeInstanceHealthBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>InvalidInstance</Code>
<Message>Could not find EC2 instance i-foooo.</Message>
</Error>
<RequestId>352e00d6-566c-11e2-a46d-313272bbb522</RequestId>
</ErrorResponse>
`
var ConfigureHealthCheck = `
<ConfigureHealthCheckResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<ConfigureHealthCheckResult>
<HealthCheck>
<Interval>30</Interval>
<Target>HTTP:80/</Target>
<HealthyThreshold>10</HealthyThreshold>
<Timeout>5</Timeout>
<UnhealthyThreshold>2</UnhealthyThreshold>
</HealthCheck>
</ConfigureHealthCheckResult>
<ResponseMetadata>
<RequestId>a882d12c-5694-11e2-b647-594652c9487c</RequestId>
</ResponseMetadata>
</ConfigureHealthCheckResponse>
`
var ConfigureHealthCheckBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>LoadBalancerNotFound</Code>
<Message>There is no ACTIVE Load Balancer named 'foolb'</Message>
</Error>
<RequestId>2d9fe4a5-5697-11e2-9415-e325c02171d7</RequestId>
</ErrorResponse>
`
var AddTagsSuccessResponse = `
<AddTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06- 01/">
<AddTagsResult/>
<ResponseMetadata>
<RequestId>360e81f7-1100-11e4-b6ed-0f30SOME-SAUCY-EXAMPLE</RequestId>
</ResponseMetadata>
</AddTagsResponse>
`
var TagsBadRequest = `
<ErrorResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<Error>
<Type>Sender</Type>
<Code>InvalidParameterValue</Code>
<Message>An invalid or out-of-range value was supplied for the input parameter.</Message>
</Error>
<RequestId>terrible-request-id</RequestId>
</ErrorResponse>
`
var RemoveTagsSuccessResponse = `
<RemoveTagsResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<RemoveTagsResult/>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12DIFFEXAMPLE</RequestId>
</ResponseMetadata>
</RemoveTagsResponse>
`

35
vendor/github.com/goamz/goamz/elb/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,35 +0,0 @@
package elb
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"github.com/goamz/goamz/aws"
"sort"
"strings"
)
var b64 = base64.StdEncoding
func sign(auth aws.Auth, method, path string, params map[string]string, host string) {
params["AWSAccessKeyId"] = auth.AccessKey
params["SignatureVersion"] = "2"
params["SignatureMethod"] = "HmacSHA256"
var keys, sarray []string
for k := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(params[k]))
}
joined := strings.Join(sarray, "&")
payload := method + "\n" + host + "\n" + path + "\n" + joined
hash := hmac.New(sha256.New, []byte(auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}

66
vendor/github.com/goamz/goamz/elb/sign_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,66 +0,0 @@
package elb_test
import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/elb"
. "gopkg.in/check.v1"
)
var testAuth = aws.Auth{AccessKey: "user", SecretKey: "secret"}
func (s *S) TestBasicSignature(c *C) {
params := map[string]string{}
elb.Sign(testAuth, "GET", "/path", params, "localhost")
c.Assert(params["SignatureVersion"], Equals, "2")
c.Assert(params["SignatureMethod"], Equals, "HmacSHA256")
expected := "6lSe5QyXum0jMVc7cOUz32/52ZnL7N5RyKRk/09yiK4="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestParamSignature(c *C) {
params := map[string]string{
"param1": "value1",
"param2": "value2",
"param3": "value3",
}
elb.Sign(testAuth, "GET", "/path", params, "localhost")
expected := "XWOR4+0lmK8bD8CGDGZ4kfuSPbb2JibLJiCl/OPu1oU="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestManyParams(c *C) {
params := map[string]string{
"param1": "value10",
"param2": "value2",
"param3": "value3",
"param4": "value4",
"param5": "value5",
"param6": "value6",
"param7": "value7",
"param8": "value8",
"param9": "value9",
"param10": "value1",
}
elb.Sign(testAuth, "GET", "/path", params, "localhost")
expected := "di0sjxIvezUgQ1SIL6i+C/H8lL+U0CQ9frLIak8jkVg="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestEscaping(c *C) {
params := map[string]string{"Nonce": "+ +"}
elb.Sign(testAuth, "GET", "/path", params, "localhost")
c.Assert(params["Nonce"], Equals, "+ +")
expected := "bqffDELReIqwjg/W0DnsnVUmfLK4wXVLO4/LuG+1VFA="
c.Assert(params["Signature"], Equals, expected)
}
func (s *S) TestSignatureExample1(c *C) {
params := map[string]string{
"Timestamp": "2009-02-01T12:53:20+00:00",
"Version": "2007-11-07",
"Action": "ListDomains",
}
elb.Sign(aws.Auth{AccessKey: "access", SecretKey: "secret"}, "GET", "/", params, "sdb.amazonaws.com")
expected := "okj96/5ucWBSc1uR2zXVfm6mDHtgfNv657rRtt/aunQ="
c.Assert(params["Signature"], Equals, expected)
}

119
vendor/github.com/goamz/goamz/elb/suite_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,119 +0,0 @@
package elb_test
import (
"fmt"
"net/http"
"net/url"
"os"
"testing"
"time"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
type HTTPSuite struct{}
var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second)
func (s *HTTPSuite) SetUpSuite(c *C) {
testServer.Start()
}
func (s *HTTPSuite) TearDownTest(c *C) {
testServer.FlushRequests()
}
type TestHTTPServer struct {
URL string
Timeout time.Duration
started bool
request chan *http.Request
response chan *testResponse
pending chan bool
}
type testResponse struct {
Status int
Headers map[string]string
Body string
}
func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer {
return &TestHTTPServer{URL: url, Timeout: timeout}
}
func (s *TestHTTPServer) Start() {
if s.started {
return
}
s.started = true
s.request = make(chan *http.Request, 64)
s.response = make(chan *testResponse, 64)
s.pending = make(chan bool, 64)
url, _ := url.Parse(s.URL)
go http.ListenAndServe(url.Host, s)
s.PrepareResponse(202, nil, "Nothing.")
for {
// Wait for it to be up.
resp, err := http.Get(s.URL)
if err == nil && resp.StatusCode == 202 {
break
}
time.Sleep(1e8)
}
s.WaitRequest() // Consume dummy request.
}
// FlushRequests discards requests which were not yet consumed by WaitRequest.
func (s *TestHTTPServer) FlushRequests() {
for {
select {
case <-s.request:
default:
return
}
}
}
func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
s.request <- req
var resp *testResponse
select {
case resp = <-s.response:
case <-time.After(s.Timeout):
fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n")
resp = &testResponse{500, nil, ""}
}
if resp.Headers != nil {
h := w.Header()
for k, v := range resp.Headers {
h.Set(k, v)
}
}
if resp.Status != 0 {
w.WriteHeader(resp.Status)
}
w.Write([]byte(resp.Body))
}
func (s *TestHTTPServer) WaitRequest() *http.Request {
select {
case req := <-s.request:
req.ParseForm()
return req
case <-time.After(s.Timeout):
panic("Timeout waiting for goamz request")
}
panic("unreached")
}
func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) {
s.response <- &testResponse{status, headers, body}
}

66
vendor/github.com/goamz/goamz/exp/mturk/example_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,66 +0,0 @@
package mturk_test
import (
"fmt"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/mturk"
)
var turk *mturk.MTurk
func ExampleNew() {
// These are your AWS tokens. Note that Turk do not support IAM.
// So you'll have to use your main profile's tokens.
var auth = aws.Auth{AccessKey: "<ACCESS_KEY>", SecretKey: "<SECRET_KEY>"}
turk = mturk.New(auth, true) // true to use sandbox mode
}
func Examplemturk_CreateHIT_withExternalQuestion() {
question := mturk.ExternalQuestion{
ExternalURL: "http://www.amazon.com",
FrameHeight: 200,
}
reward := mturk.Price{
Amount: "0.01",
CurrencyCode: "USD",
}
hit, err := turk.CreateHIT("title", "description", question, reward, 30, 30, "key1,key2", 3, nil, "annotation")
if err == nil {
fmt.Println(hit)
}
}
func Examplemturk_CreateHIT_withHTMLQuestion() {
question := mturk.HTMLQuestion{
HTMLContent: mturk.HTMLContent{`<![CDATA[
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
<script type='text/javascript' src='https://s3.amazonaws.com/mturk-public/externalHIT_v1.js'></script>
</head>
<body>
<form name='mturk_form' method='post' id='mturk_form' action='https://www.mturk.com/mturk/externalSubmit'>
<input type='hidden' value='' name='assignmentId' id='assignmentId'/>
<h1>What's up?</h1>
<p><textarea name='comment' cols='80' rows='3'></textarea></p>
<p><input type='submit' id='submitButton' value='Submit' /></p></form>
<script language='Javascript'>turkSetAssignmentID();</script>
</body>
</html>
]]>`},
FrameHeight: 200,
}
reward := mturk.Price{
Amount: "0.01",
CurrencyCode: "USD",
}
hit, err := turk.CreateHIT("title", "description", question, reward, 30, 30, "key1,key2", 3, nil, "")
if err == nil {
fmt.Println(hit)
}
}

9
vendor/github.com/goamz/goamz/exp/mturk/export_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,9 +0,0 @@
package mturk
import (
"github.com/goamz/goamz/aws"
)
func Sign(auth aws.Auth, service, method, timestamp string, params map[string]string) {
sign(auth, service, method, timestamp, params)
}

480
vendor/github.com/goamz/goamz/exp/mturk/mturk.go сгенерированный поставляемый
Просмотреть файл

@@ -1,480 +0,0 @@
//
// goamz - Go packages to interact with the Amazon Web Services.
//
// https://wiki.ubuntu.com/goamz
//
// Copyright (c) 2011 Canonical Ltd.
//
// Written by Graham Miller <graham.miller@gmail.com>
// This package is in an experimental state, and does not currently
// follow conventions and style of the rest of goamz or common
// Go conventions. It must be polished before it's considered a
// first-class package in goamz.
package mturk
import (
"encoding/xml"
"errors"
"fmt"
"github.com/goamz/goamz/aws"
"net/http"
//"net/http/httputil"
"net/url"
"strconv"
"strings"
"time"
)
type MTurk struct {
aws.Auth
URL *url.URL
}
func New(auth aws.Auth, sandbox bool) *MTurk {
mt := &MTurk{Auth: auth}
var err error
if sandbox {
mt.URL, err = url.Parse("https://mechanicalturk.sandbox.amazonaws.com/")
} else {
mt.URL, err = url.Parse("https://mechanicalturk.amazonaws.com/")
}
if err != nil {
panic(err.Error())
}
return mt
}
// ----------------------------------------------------------------------------
// Request dispatching logic.
// Error encapsulates an error returned by MTurk.
type Error struct {
StatusCode int // HTTP status code (200, 403, ...)
Code string // EC2 error code ("UnsupportedOperation", ...)
Message string // The human-oriented error message
RequestId string
}
func (err *Error) Error() string {
return err.Message
}
// The request stanza included in several response types, for example
// in a "CreateHITResponse". http://goo.gl/qGeKf
type xmlRequest struct {
RequestId string
IsValid string
Errors []Error `xml:"Errors>Error"`
}
/*
A Price represents an amount of money in a given currency.
Reference:
http://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/ApiReference_PriceDataStructureArticle.html
*/
type Price struct {
// The amount of money, as a number. The amount is in the currency specified
// by the CurrencyCode. For example, if CurrencyCode is USD, the amount will
// be in United States dollars (e.g. 12.75 is $12.75 US).
Amount string
// A code that represents the country and units of the currency. Its value is
// Type an ISO 4217 currency code, such as USD for United States dollars.
//
// Constraints: Currently only USD is supported.
CurrencyCode string
// A textual representation of the price, using symbols and formatting
// appropriate for the currency. Symbols are represented using the Unicode
// character set. You do not need to specify FormattedPrice in a request.
// It is only provided by the service in responses, as a convenience to
// your application.
FormattedPrice string
}
/*
Really just a country string.
Reference:
- http://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/ApiReference_LocaleDataStructureArticle.html
- http://www.iso.org/iso/country_codes/country_codes
*/
type Locale string
/*
A QualificationRequirement describes a Qualification a Worker must
have before the Worker is allowed to accept a HIT. A requirement may optionally
state that a Worker must have the Qualification to preview the HIT.
Reference:
http://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/ApiReference_QualificationRequirementDataStructureArticle.html
*/
type QualificationRequirement struct {
// The ID of the Qualification type for the requirement.
// See http://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/ApiReference_QualificationRequirementDataStructureArticle.html#ApiReference_QualificationType-IDs
QualificationTypeId string
// The kind of comparison to make against a Qualification's value.
// Two values can be compared to see if one value is "LessThan",
// "LessThanOrEqualTo", "GreaterThan", "GreaterThanOrEqualTo", "EqualTo", or
// "NotEqualTo" the other. A Qualification requirement can also test if a
// Qualification "Exists" in the user's profile, regardless of its value.
Comparator string
// The integer value to compare against the Qualification's value.
IntegerValue int
// The locale value to compare against the Qualification's value, if the
// Qualification being compared is the locale Qualification.
LocaleValue Locale
// If true, the question data for the HIT will not be shown when a Worker
// whose Qualifications do not meet this requirement tries to preview the HIT.
// That is, a Worker's Qualifications must meet all of the requirements for
// which RequiredToPreview is true in order to preview the HIT.
//
// If a Worker meets all of the requirements where RequiredToPreview is true
// (or if there are no such requirements), but does not meet all of the
// requirements for the HIT, the Worker will be allowed to preview the HIT's
// question data, but will not be allowed to accept and complete the HIT.
RequiredToPreview bool
}
// Data structure holding the contents of an "external"
// question. http://goo.gl/NP8Aa
type ExternalQuestion struct {
XMLName xml.Name `xml:"http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2006-07-14/ExternalQuestion.xsd ExternalQuestion"`
ExternalURL string
FrameHeight int
}
// Holds the html content of the HTMLQuestion.
type HTMLContent struct {
Content string `xml:",innerxml"`
}
// Data structure holding the contents of an "html"
// question. http://goo.gl/hQn5An
type HTMLQuestion struct {
XMLName xml.Name `xml:"http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd HTMLQuestion"`
HTMLContent HTMLContent
FrameHeight int
}
// The data structure representing a "human interface task" (HIT)
// Currently only supports "external" questions, because Go
// structs don't support union types. http://goo.gl/NP8Aa
// This type is returned, for example, from SearchHITs
// http://goo.gl/PskcX
type HIT struct {
Request xmlRequest
HITId string
HITTypeId string
CreationTime string
Title string
Description string
Keywords string
HITStatus string
Reward Price
LifetimeInSeconds uint
AssignmentDurationInSeconds uint
MaxAssignments uint
AutoApprovalDelayInSeconds uint
QualificationRequirement QualificationRequirement
Question interface{}
RequesterAnnotation string
NumberofSimilarHITs uint
HITReviewStatus string
NumberOfAssignmentsPending uint
NumberOfAssignmentsAvailable uint
NumberOfAssignmentsCompleted uint
}
// The main data structure returned by SearchHITs
// http://goo.gl/PskcX
type SearchHITsResult struct {
NumResults uint
PageNumber uint
TotalNumResults uint
HITs []HIT `xml:"HIT"`
}
// The wrapper data structure returned by SearchHITs
// http://goo.gl/PskcX
type SearchHITsResponse struct {
RequestId string `xml:"OperationRequest>RequestId"`
SearchHITsResult SearchHITsResult
}
// The wrapper data structure returned by CreateHIT
// http://goo.gl/PskcX
type CreateHITResponse struct {
RequestId string `xml:"OperationRequest>RequestId"`
HIT HIT
}
type Assignment struct {
AssignmentId string
WorkerId string
HITId string
AssignmentStatus string
AutoApprovalTime string
AcceptTime string
SubmitTime string
ApprovalTime string
Answer string
}
func (a Assignment) Answers() (answers map[string]string) {
answers = make(map[string]string)
decoder := xml.NewDecoder(strings.NewReader(a.Answer))
for {
token, _ := decoder.Token()
if token == nil {
break
}
switch startElement := token.(type) {
case xml.StartElement:
if startElement.Name.Local == "Answer" {
var answer struct {
QuestionIdentifier string
FreeText string
}
decoder.DecodeElement(&answer, &startElement)
answers[answer.QuestionIdentifier] = answer.FreeText
}
}
}
return
}
type GetAssignmentsForHITResponse struct {
RequestId string `xml:"OperationRequest>RequestId"`
GetAssignmentsForHITResult struct {
Request xmlRequest
NumResults uint
TotalNumResults uint
PageNumber uint
Assignment Assignment
}
}
/*
CreateHIT corresponds to the "CreateHIT" operation of the Mechanical Turk
API. Currently only supports "external" questions (see "HIT" struct above).
Here are the detailed description for the parameters:
title Required. A title should be short and descriptive about the
kind of task the HIT contains. On the Amazon Mechanical Turk
web site, the HIT title appears in search results, and
everywhere the HIT is mentioned.
description Required. A description includes detailed information about the
kind of task the HIT contains. On the Amazon Mechanical Turk
web site, the HIT description appears in the expanded view of
search results, and in the HIT and assignment screens. A good
description gives the user enough information to evaluate the
HIT before accepting it.
question Required. The data the person completing the HIT uses to produce
the results. Consstraints: Must be a QuestionForm data structure,
an ExternalQuestion data structure, or an HTMLQuestion data
structure. The XML question data must not be larger than 64
kilobytes (65,535 bytes) in size, including whitespace.
reward Required. The amount of money the Requester will pay a Worker
for successfully completing the HIT.
assignmentDurationInSeconds Required. The amount of time, in seconds, that
a Worker has to complete the HIT after accepting
it. If a Worker does not complete the assignment
within the specified duration, the assignment is
considered abandoned. If the HIT is still
active (that is, its lifetime has not elapsed),
the assignment becomes available for other users
to find and accept. Valid Values: any integer
between 30 (30 seconds) and 31536000 (365 days).
lifetimeInSeconds Required. An amount of time, in seconds, after which the
HIT is no longer available for users to accept. After
the lifetime of the HIT elapses, the HIT no longer
appears in HIT searches, even if not all of the
assignments for the HIT have been accepted. Valid Values:
any integer between 30 (30 seconds) and 31536000 (365 days).
keywords One or more words or phrases that describe the HIT,
separated by commas. These words are used in searches to
find HITs. Constraints: cannot be more than 1,000
characters.
maxAssignments The number of times the HIT can be accepted and completed
before the HIT becomes unavailable. Valid Values: any
integer between 1 and 1000000000 (1 billion). Default: 1
qualificationRequirement A condition that a Worker's Qualifications must
meet before the Worker is allowed to accept and
complete the HIT. Constraints: no more than 10
QualificationRequirement for each HIT.
requesterAnnotation An arbitrary data field. The RequesterAnnotation
parameter lets your application attach arbitrary data to
the HIT for tracking purposes. For example, the
RequesterAnnotation parameter could be an identifier
internal to the Requester's application that corresponds
with the HIT. Constraints: must not be longer than 255
characters in length.
Reference:
http://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/ApiReference_CreateHITOperation.html
*/
func (mt *MTurk) CreateHIT(
title, description string,
question interface{},
reward Price,
assignmentDurationInSeconds,
lifetimeInSeconds uint,
keywords string,
maxAssignments uint,
qualificationRequirement *QualificationRequirement,
requesterAnnotation string) (h *HIT, err error) {
params := make(map[string]string)
params["Title"] = title
params["Description"] = description
params["Question"], err = xmlEncode(&question)
if err != nil {
return
}
params["Reward.1.Amount"] = reward.Amount
params["Reward.1.CurrencyCode"] = reward.CurrencyCode
params["AssignmentDurationInSeconds"] = strconv.FormatUint(uint64(assignmentDurationInSeconds), 10)
params["LifetimeInSeconds"] = strconv.FormatUint(uint64(lifetimeInSeconds), 10)
if keywords != "" {
params["Keywords"] = keywords
}
if maxAssignments != 0 {
params["MaxAssignments"] = strconv.FormatUint(uint64(maxAssignments), 10)
}
if qualificationRequirement != nil {
params["QualificationRequirement"], err = xmlEncode(qualificationRequirement)
if err != nil {
return
}
}
if requesterAnnotation != "" {
params["RequesterAnnotation"] = requesterAnnotation
}
var response CreateHITResponse
err = mt.query(params, "CreateHIT", &response)
if err == nil {
h = &response.HIT
}
return
}
// Corresponds to the "CreateHIT" operation of the Mechanical Turk
// API, using an existing "hit type". http://goo.gl/cDBRc Currently only
// supports "external" questions (see "HIT" struct above). If
// "maxAssignments" or "requesterAnnotation" are the zero value for
// their types, they will not be included in the request.
func (mt *MTurk) CreateHITOfType(hitTypeId string, q ExternalQuestion, lifetimeInSeconds uint, maxAssignments uint, requesterAnnotation string) (h *HIT, err error) {
params := make(map[string]string)
params["HITTypeId"] = hitTypeId
params["Question"], err = xmlEncode(&q)
if err != nil {
return
}
params["LifetimeInSeconds"] = strconv.FormatUint(uint64(lifetimeInSeconds), 10)
if maxAssignments != 0 {
params["MaxAssignments"] = strconv.FormatUint(uint64(maxAssignments), 10)
}
if requesterAnnotation != "" {
params["RequesterAnnotation"] = requesterAnnotation
}
var response CreateHITResponse
err = mt.query(params, "CreateHIT", &response)
if err == nil {
h = &response.HIT
}
return
}
// Get the Assignments for a HIT.
func (mt *MTurk) GetAssignmentsForHIT(hitId string) (r *Assignment, err error) {
params := make(map[string]string)
params["HITId"] = hitId
var response GetAssignmentsForHITResponse
err = mt.query(params, "GetAssignmentsForHIT", &response)
if err == nil {
r = &response.GetAssignmentsForHITResult.Assignment
}
return
}
// Corresponds to "SearchHITs" operation of Mechanical Turk. http://goo.gl/PskcX
// Currenlty supports none of the optional parameters.
func (mt *MTurk) SearchHITs() (s *SearchHITsResult, err error) {
params := make(map[string]string)
var response SearchHITsResponse
err = mt.query(params, "SearchHITs", &response)
if err == nil {
s = &response.SearchHITsResult
}
return
}
// Adds common parameters to the "params" map, signs the request,
// adds the signature to the "params" map and sends the request
// to the server. It then unmarshals the response in to the "resp"
// parameter using xml.Unmarshal()
func (mt *MTurk) query(params map[string]string, operation string, resp interface{}) error {
service := "AWSMechanicalTurkRequester"
timestamp := time.Now().UTC().Format("2006-01-02T15:04:05Z")
params["AWSAccessKeyId"] = mt.Auth.AccessKey
params["Service"] = service
params["Timestamp"] = timestamp
params["Operation"] = operation
// make a copy
url := *mt.URL
sign(mt.Auth, service, operation, timestamp, params)
url.RawQuery = multimap(params).Encode()
r, err := http.Get(url.String())
if err != nil {
return err
}
//dump, _ := httputil.DumpResponse(r, true)
//println("DUMP:\n", string(dump))
if r.StatusCode != 200 {
return errors.New(fmt.Sprintf("%d: unexpected status code", r.StatusCode))
}
dec := xml.NewDecoder(r.Body)
err = dec.Decode(resp)
r.Body.Close()
return err
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
func xmlEncode(i interface{}) (s string, err error) {
var buf []byte
buf, err = xml.Marshal(i)
if err != nil {
return
}
s = string(buf)
return
}

170
vendor/github.com/goamz/goamz/exp/mturk/mturk_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,170 +0,0 @@
package mturk_test
import (
"net/url"
"testing"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/mturk"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
mturk *mturk.MTurk
}
var testServer = testutil.NewHTTPServer()
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
u, err := url.Parse(testServer.URL)
if err != nil {
panic(err.Error())
}
s.mturk = &mturk.MTurk{
Auth: auth,
URL: u,
}
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func (s *S) TestCreateHITExternalQuestion(c *C) {
testServer.Response(200, nil, BasicHitResponse)
question := mturk.ExternalQuestion{
ExternalURL: "http://www.amazon.com",
FrameHeight: 200,
}
reward := mturk.Price{
Amount: "0.01",
CurrencyCode: "USD",
}
hit, err := s.mturk.CreateHIT("title", "description", question, reward, 1, 2, "key1,key2", 3, nil, "annotation")
testServer.WaitRequest()
c.Assert(err, IsNil)
c.Assert(hit, NotNil)
c.Assert(hit.HITId, Equals, "28J4IXKO2L927XKJTHO34OCDNASCDW")
c.Assert(hit.HITTypeId, Equals, "2XZ7D1X3V0FKQVW7LU51S7PKKGFKDF")
}
func (s *S) TestCreateHITHTMLQuestion(c *C) {
testServer.Response(200, nil, BasicHitResponse)
question := mturk.HTMLQuestion{
HTMLContent: mturk.HTMLContent{`<![CDATA[
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'/>
<script type='text/javascript' src='https://s3.amazonaws.com/mturk-public/externalHIT_v1.js'></script>
</head>
<body>
<form name='mturk_form' method='post' id='mturk_form' action='https://www.mturk.com/mturk/externalSubmit'>
<input type='hidden' value='' name='assignmentId' id='assignmentId'/>
<h1>What's up?</h1>
<p><textarea name='comment' cols='80' rows='3'></textarea></p>
<p><input type='submit' id='submitButton' value='Submit' /></p></form>
<script language='Javascript'>turkSetAssignmentID();</script>
</body>
</html>
]]>`},
FrameHeight: 200,
}
reward := mturk.Price{
Amount: "0.01",
CurrencyCode: "USD",
}
hit, err := s.mturk.CreateHIT("title", "description", question, reward, 1, 2, "key1,key2", 3, nil, "annotation")
testServer.WaitRequest()
c.Assert(err, IsNil)
c.Assert(hit, NotNil)
c.Assert(hit.HITId, Equals, "28J4IXKO2L927XKJTHO34OCDNASCDW")
c.Assert(hit.HITTypeId, Equals, "2XZ7D1X3V0FKQVW7LU51S7PKKGFKDF")
}
func (s *S) TestSearchHITs(c *C) {
testServer.Response(200, nil, SearchHITResponse)
hitResult, err := s.mturk.SearchHITs()
c.Assert(err, IsNil)
c.Assert(hitResult, NotNil)
c.Assert(hitResult.NumResults, Equals, uint(1))
c.Assert(hitResult.PageNumber, Equals, uint(1))
c.Assert(hitResult.TotalNumResults, Equals, uint(1))
c.Assert(len(hitResult.HITs), Equals, 1)
c.Assert(hitResult.HITs[0].HITId, Equals, "2BU26DG67D1XTE823B3OQ2JF2XWF83")
c.Assert(hitResult.HITs[0].HITTypeId, Equals, "22OWJ5OPB0YV6IGL5727KP9U38P5XR")
c.Assert(hitResult.HITs[0].CreationTime, Equals, "2011-12-28T19:56:20Z")
c.Assert(hitResult.HITs[0].Title, Equals, "test hit")
c.Assert(hitResult.HITs[0].Description, Equals, "please disregard, testing only")
c.Assert(hitResult.HITs[0].HITStatus, Equals, "Reviewable")
c.Assert(hitResult.HITs[0].MaxAssignments, Equals, uint(1))
c.Assert(hitResult.HITs[0].Reward.Amount, Equals, "0.01")
c.Assert(hitResult.HITs[0].Reward.CurrencyCode, Equals, "USD")
c.Assert(hitResult.HITs[0].AutoApprovalDelayInSeconds, Equals, uint(2592000))
c.Assert(hitResult.HITs[0].AssignmentDurationInSeconds, Equals, uint(30))
c.Assert(hitResult.HITs[0].NumberOfAssignmentsPending, Equals, uint(0))
c.Assert(hitResult.HITs[0].NumberOfAssignmentsAvailable, Equals, uint(1))
c.Assert(hitResult.HITs[0].NumberOfAssignmentsCompleted, Equals, uint(0))
}
func (s *S) TestGetAssignmentsForHIT_NoAnswer(c *C) {
testServer.Response(200, nil, GetAssignmentsForHITNoAnswerResponse)
assignment, err := s.mturk.GetAssignmentsForHIT("emptyassignment")
testServer.WaitRequest()
c.Assert(err, IsNil)
c.Assert(assignment, NotNil)
c.Assert(assignment.HITId, Equals, "")
}
func (s *S) TestGetAssignmentsForHIT_Answer(c *C) {
testServer.Response(200, nil, GetAssignmentsForHITAnswerResponse)
assignment, err := s.mturk.GetAssignmentsForHIT("emptyassignment")
testServer.WaitRequest()
c.Assert(err, IsNil)
c.Assert(assignment, NotNil)
c.Assert(assignment.AssignmentId, Equals, "2QKNTL0XULRGFAQWUWDD05FP94V2O3")
c.Assert(assignment.WorkerId, Equals, "A1ZUQ2YDM61713")
c.Assert(assignment.HITId, Equals, "2W36VCPWZ9RN5DX1MBJ7VN3D6WEPAM")
c.Assert(assignment.AssignmentStatus, Equals, "Submitted")
c.Assert(assignment.AutoApprovalTime, Equals, "2014-02-26T09:39:48Z")
c.Assert(assignment.AcceptTime, Equals, "2014-01-27T09:39:38Z")
c.Assert(assignment.SubmitTime, Equals, "2014-01-27T09:39:48Z")
c.Assert(assignment.ApprovalTime, Equals, "")
answers := assignment.Answers()
c.Assert(len(answers), Equals, 4)
c.Assert(answers["tags"], Equals, "asd")
c.Assert(answers["text_in_image"], Equals, "asd")
c.Assert(answers["is_pattern"], Equals, "yes")
c.Assert(answers["is_map"], Equals, "yes")
}

36
vendor/github.com/goamz/goamz/exp/mturk/responses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,36 +0,0 @@
package mturk_test
var BasicHitResponse = `<?xml version="1.0"?>
<CreateHITResponse><OperationRequest><RequestId>643b794b-66b6-4427-bb8a-4d3df5c9a20e</RequestId></OperationRequest><HIT><Request><IsValid>True</IsValid></Request><HITId>28J4IXKO2L927XKJTHO34OCDNASCDW</HITId><HITTypeId>2XZ7D1X3V0FKQVW7LU51S7PKKGFKDF</HITTypeId></HIT></CreateHITResponse>
`
var SearchHITResponse = `<?xml version="1.0"?>
<SearchHITsResponse><OperationRequest><RequestId>38862d9c-f015-4177-a2d3-924110a9d6f2</RequestId></OperationRequest><SearchHITsResult><Request><IsValid>True</IsValid></Request><NumResults>1</NumResults><TotalNumResults>1</TotalNumResults><PageNumber>1</PageNumber><HIT><HITId>2BU26DG67D1XTE823B3OQ2JF2XWF83</HITId><HITTypeId>22OWJ5OPB0YV6IGL5727KP9U38P5XR</HITTypeId><CreationTime>2011-12-28T19:56:20Z</CreationTime><Title>test hit</Title><Description>please disregard, testing only</Description><HITStatus>Reviewable</HITStatus><MaxAssignments>1</MaxAssignments><Reward><Amount>0.01</Amount><CurrencyCode>USD</CurrencyCode><FormattedPrice>$0.01</FormattedPrice></Reward><AutoApprovalDelayInSeconds>2592000</AutoApprovalDelayInSeconds><Expiration>2011-12-28T19:56:50Z</Expiration><AssignmentDurationInSeconds>30</AssignmentDurationInSeconds><NumberOfAssignmentsPending>0</NumberOfAssignmentsPending><NumberOfAssignmentsAvailable>1</NumberOfAssignmentsAvailable><NumberOfAssignmentsCompleted>0</NumberOfAssignmentsCompleted></HIT></SearchHITsResult></SearchHITsResponse>
`
var GetAssignmentsForHITNoAnswerResponse = `<?xml version="1.0"?>
<GetAssignmentsForHITResponse><OperationRequest><RequestId>536934be-a35b-4e4e-9822-72fbf36d5862</RequestId></OperationRequest><GetAssignmentsForHITResult><Request><IsValid>True</IsValid></Request><NumResults>0</NumResults><TotalNumResults>0</TotalNumResults><PageNumber>1</PageNumber></GetAssignmentsForHITResult></GetAssignmentsForHITResponse>
`
var GetAssignmentsForHITAnswerResponse = `<?xml version="1.0"?>
<GetAssignmentsForHITResponse><OperationRequest><RequestId>2f113bdf-2e3e-4c5a-a396-3ed01384ecb9</RequestId></OperationRequest><GetAssignmentsForHITResult><Request><IsValid>True</IsValid></Request><NumResults>1</NumResults><TotalNumResults>1</TotalNumResults><PageNumber>1</PageNumber><Assignment><AssignmentId>2QKNTL0XULRGFAQWUWDD05FP94V2O3</AssignmentId><WorkerId>A1ZUQ2YDM61713</WorkerId><HITId>2W36VCPWZ9RN5DX1MBJ7VN3D6WEPAM</HITId><AssignmentStatus>Submitted</AssignmentStatus><AutoApprovalTime>2014-02-26T09:39:48Z</AutoApprovalTime><AcceptTime>2014-01-27T09:39:38Z</AcceptTime><SubmitTime>2014-01-27T09:39:48Z</SubmitTime><Answer>&lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;
&lt;QuestionFormAnswers xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2005-10-01/QuestionFormAnswers.xsd"&gt;
&lt;Answer&gt;
&lt;QuestionIdentifier&gt;tags&lt;/QuestionIdentifier&gt;
&lt;FreeText&gt;asd&lt;/FreeText&gt;
&lt;/Answer&gt;
&lt;Answer&gt;
&lt;QuestionIdentifier&gt;text_in_image&lt;/QuestionIdentifier&gt;
&lt;FreeText&gt;asd&lt;/FreeText&gt;
&lt;/Answer&gt;
&lt;Answer&gt;
&lt;QuestionIdentifier&gt;is_pattern&lt;/QuestionIdentifier&gt;
&lt;FreeText&gt;yes&lt;/FreeText&gt;
&lt;/Answer&gt;
&lt;Answer&gt;
&lt;QuestionIdentifier&gt;is_map&lt;/QuestionIdentifier&gt;
&lt;FreeText&gt;yes&lt;/FreeText&gt;
&lt;/Answer&gt;
&lt;/QuestionFormAnswers&gt;
</Answer></Assignment></GetAssignmentsForHITResult></GetAssignmentsForHITResponse>
`

22
vendor/github.com/goamz/goamz/exp/mturk/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,22 +0,0 @@
package mturk
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"github.com/goamz/goamz/aws"
)
var b64 = base64.StdEncoding
// ----------------------------------------------------------------------------
// Mechanical Turk signing (http://goo.gl/wrzfn)
func sign(auth aws.Auth, service, method, timestamp string, params map[string]string) {
payload := service + method + timestamp
hash := hmac.New(sha1.New, []byte(auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}

19
vendor/github.com/goamz/goamz/exp/mturk/sign_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,19 +0,0 @@
package mturk_test
import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/mturk"
. "gopkg.in/check.v1"
)
// Mechanical Turk REST authentication docs: http://goo.gl/wrzfn
var testAuth = aws.Auth{AccessKey: "user", SecretKey: "secret"}
// == fIJy9wCApBNL2R4J2WjJGtIBFX4=
func (s *S) TestBasicSignature(c *C) {
params := map[string]string{}
mturk.Sign(testAuth, "AWSMechanicalTurkRequester", "CreateHIT", "2012-02-16T20:30:47Z", params)
expected := "b/TnvzrdeD/L/EyzdFrznPXhido="
c.Assert(params["Signature"], Equals, expected)
}

9
vendor/github.com/goamz/goamz/exp/sdb/export_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,9 +0,0 @@
package sdb
import (
"github.com/goamz/goamz/aws"
)
func Sign(auth aws.Auth, method, path string, params map[string][]string, headers map[string][]string) {
sign(auth, method, path, params, headers)
}

120
vendor/github.com/goamz/goamz/exp/sdb/responses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,120 +0,0 @@
package sdb_test
var TestCreateDomainXmlOK = `
<?xml version="1.0"?>
<CreateDomainResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ResponseMetadata>
<RequestId>63264005-7a5f-e01a-a224-395c63b89f6d</RequestId>
<BoxUsage>0.0055590279</BoxUsage>
</ResponseMetadata>
</CreateDomainResponse>
`
var TestListDomainsXmlOK = `
<?xml version="1.0"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ListDomainsResult>
<DomainName>Account</DomainName>
<DomainName>Domain</DomainName>
<DomainName>Record</DomainName>
</ListDomainsResult>
<ResponseMetadata>
<RequestId>15fcaf55-9914-63c2-21f3-951e31193790</RequestId>
<BoxUsage>0.0000071759</BoxUsage>
</ResponseMetadata>
</ListDomainsResponse>
`
var TestListDomainsWithNextTokenXmlOK = `
<?xml version="1.0"?>
<ListDomainsResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ListDomainsResult>
<DomainName>Domain1-200706011651</DomainName>
<DomainName>Domain2-200706011652</DomainName>
<NextToken>TWV0ZXJpbmdUZXN0RG9tYWluMS0yMDA3MDYwMTE2NTY=</NextToken>
</ListDomainsResult>
<ResponseMetadata>
<RequestId>eb13162f-1b95-4511-8b12-489b86acfd28</RequestId>
<BoxUsage>0.0000219907</BoxUsage>
</ResponseMetadata>
</ListDomainsResponse>
`
var TestDeleteDomainXmlOK = `
<?xml version="1.0"?>
<DeleteDomainResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ResponseMetadata>
<RequestId>039e1e25-9a64-2a74-93da-2fda36122a97</RequestId>
<BoxUsage>0.0055590278</BoxUsage>
</ResponseMetadata>
</DeleteDomainResponse>
`
var TestDomainMetadataXmlNoSuchDomain = `
<?xml version="1.0"?>
<Response xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<Errors>
<Error>
<Code>NoSuchDomain</Code>
<Message>The specified domain does not exist.</Message>
<BoxUsage>0.0000071759</BoxUsage>
</Error>
</Errors>
<RequestID>e050cea2-a772-f90e-2cb0-98ebd42c2898</RequestID>
</Response>
`
var TestPutAttrsXmlOK = `
<?xml version="1.0"?>
<PutAttributesResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<ResponseMetadata>
<RequestId>490206ce-8292-456c-a00f-61b335eb202b</RequestId>
<BoxUsage>0.0000219907</BoxUsage>
</ResponseMetadata>
</PutAttributesResponse>
`
var TestAttrsXmlOK = `
<?xml version="1.0"?>
<GetAttributesResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<GetAttributesResult>
<Attribute><Name>Color</Name><Value>Blue</Value></Attribute>
<Attribute><Name>Size</Name><Value>Med</Value></Attribute>
</GetAttributesResult>
<ResponseMetadata>
<RequestId>b1e8f1f7-42e9-494c-ad09-2674e557526d</RequestId>
<BoxUsage>0.0000219942</BoxUsage>
</ResponseMetadata>
</GetAttributesResponse>
`
var TestSelectXmlOK = `
<?xml version="1.0"?>
<SelectResponse xmlns="http://sdb.amazonaws.com/doc/2009-04-15/">
<SelectResult>
<Item>
<Name>Item_03</Name>
<Attribute><Name>Category</Name><Value>Clothes</Value></Attribute>
<Attribute><Name>Subcategory</Name><Value>Pants</Value></Attribute>
<Attribute><Name>Name</Name><Value>Sweatpants</Value></Attribute>
<Attribute><Name>Color</Name><Value>Blue</Value></Attribute>
<Attribute><Name>Color</Name><Value>Yellow</Value></Attribute>
<Attribute><Name>Color</Name><Value>Pink</Value></Attribute>
<Attribute><Name>Size</Name><Value>Large</Value></Attribute>
</Item>
<Item>
<Name>Item_06</Name>
<Attribute><Name>Category</Name><Value>Motorcycle Parts</Value></Attribute>
<Attribute><Name>Subcategory</Name><Value>Bodywork</Value></Attribute>
<Attribute><Name>Name</Name><Value>Fender Eliminator</Value></Attribute>
<Attribute><Name>Color</Name><Value>Blue</Value></Attribute>
<Attribute><Name>Make</Name><Value>Yamaha</Value></Attribute>
<Attribute><Name>Model</Name><Value>R1</Value></Attribute>
</Item>
</SelectResult>
<ResponseMetadata>
<RequestId>b1e8f1f7-42e9-494c-ad09-2674e557526d</RequestId>
<BoxUsage>0.0000219907</BoxUsage>
</ResponseMetadata>
</SelectResponse>
`

413
vendor/github.com/goamz/goamz/exp/sdb/sdb.go сгенерированный поставляемый
Просмотреть файл

@@ -1,413 +0,0 @@
//
// goamz - Go packages to interact with the Amazon Web Services.
//
// https://wiki.ubuntu.com/goamz
//
// Copyright (c) 2011 AppsAttic Ltd.
//
// sdb package written by:
//
// Andrew Chilton <chilts@appsattic.com>
// Brad Rydzewski <brad.rydzewski@gmail.com>
// This package is in an experimental state, and does not currently
// follow conventions and style of the rest of goamz or common
// Go conventions. It must be polished before it's considered a
// first-class package in goamz.
package sdb
// BUG: SelectResp isn't properly organized. It must change.
//
import (
"encoding/xml"
"github.com/goamz/goamz/aws"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"time"
)
const debug = false
// The SDB type encapsulates operations with a specific SimpleDB region.
type SDB struct {
aws.Auth
aws.Region
private byte // Reserve the right of using private data.
}
// New creates a new SDB.
func New(auth aws.Auth, region aws.Region) *SDB {
return &SDB{auth, region, 0}
}
// The Domain type represents a collection of items that are described
// by name-value attributes.
type Domain struct {
*SDB
Name string
}
// Domain returns a Domain with the given name.
func (sdb *SDB) Domain(name string) *Domain {
return &Domain{sdb, name}
}
// The Item type represent individual objects that contain one or more
// name-value attributes stored within a SDB Domain as rows.
type Item struct {
*SDB
*Domain
Name string
}
// Item returns an Item with the given name.
func (domain *Domain) Item(name string) *Item {
return &Item{domain.SDB, domain, name}
}
// The Attr type represent categories of data that can be assigned to items.
type Attr struct {
Name string
Value string
}
// ----------------------------------------------------------------------------
// Service-level operations.
// --- ListDomains
// Response to a ListDomains request.
//
// See http://goo.gl/3u0Cf for more details.
type ListDomainsResp struct {
Domains []string `xml:"ListDomainsResult>DomainName"`
NextToken string `xml:"ListDomainsResult>NextToken"`
ResponseMetadata ResponseMetadata
}
// ListDomains lists all domains in sdb.
//
// See http://goo.gl/Dsw15 for more details.
func (sdb *SDB) ListDomains() (resp *ListDomainsResp, err error) {
return sdb.ListDomainsN(0, "")
}
// ListDomainsN lists domains in sdb up to maxDomains.
// If nextToken is not empty, domains listed will start at the given token.
//
// See http://goo.gl/Dsw15 for more details.
func (sdb *SDB) ListDomainsN(maxDomains int, nextToken string) (resp *ListDomainsResp, err error) {
params := makeParams("ListDomains")
if maxDomains != 0 {
params["MaxNumberOfDomains"] = []string{strconv.Itoa(maxDomains)}
}
if nextToken != "" {
params["NextToken"] = []string{nextToken}
}
resp = &ListDomainsResp{}
err = sdb.query(nil, nil, params, nil, resp)
return
}
// --- SelectExpression
// Response to a Select request.
//
// See http://goo.gl/GTsSZ for more details.
type SelectResp struct {
Items []struct {
Name string
Attrs []Attr `xml:"Attribute"`
} `xml:"SelectResult>Item"`
ResponseMetadata ResponseMetadata
}
// Select returns a set of items and attributes that match expr.
// Select is similar to the standard SQL SELECT statement.
//
// See http://goo.gl/GTsSZ for more details.
func (sdb *SDB) Select(expr string, consistent bool) (resp *SelectResp, err error) {
resp = &SelectResp{}
params := makeParams("Select")
params["SelectExpression"] = []string{expr}
if consistent {
params["ConsistentRead"] = []string{"true"}
}
err = sdb.query(nil, nil, params, nil, resp)
return
}
// ----------------------------------------------------------------------------
// Domain-level operations.
// --- CreateDomain
// CreateDomain creates a new domain.
//
// See http://goo.gl/jDjGH for more details.
func (domain *Domain) CreateDomain() (resp *SimpleResp, err error) {
params := makeParams("CreateDomain")
resp = &SimpleResp{}
err = domain.SDB.query(domain, nil, params, nil, resp)
return
}
// DeleteDomain deletes an existing domain.
//
// See http://goo.gl/S0dCL for more details.
func (domain *Domain) DeleteDomain() (resp *SimpleResp, err error) {
params := makeParams("DeleteDomain")
resp = &SimpleResp{}
err = domain.SDB.query(domain, nil, params, nil, resp)
return
}
// ----------------------------------------------------------------------------
// Item-level operations.
type PutAttrs struct {
attrs []Attr
expected []Attr
replace map[string]bool
missing map[string]bool
}
func (pa *PutAttrs) Add(name, value string) {
pa.attrs = append(pa.attrs, Attr{name, value})
}
func (pa *PutAttrs) Replace(name, value string) {
pa.Add(name, value)
if pa.replace == nil {
pa.replace = make(map[string]bool)
}
pa.replace[name] = true
}
// The PutAttrs request will only succeed if the existing
// item in SimpleDB contains a matching name / value pair.
func (pa *PutAttrs) IfValue(name, value string) {
pa.expected = append(pa.expected, Attr{name, value})
}
// Flag to test the existence of an attribute while performing
// conditional updates. X can be any positive integer or 0.
//
// This should set Expected.N.Name=name and Expected.N.Exists=false
func (pa *PutAttrs) IfMissing(name string) {
if pa.missing == nil {
pa.missing = make(map[string]bool)
}
pa.missing[name] = true
}
// PutAttrs adds attrs to item.
//
// See http://goo.gl/yTAV4 for more details.
func (item *Item) PutAttrs(attrs *PutAttrs) (resp *SimpleResp, err error) {
params := makeParams("PutAttributes")
resp = &SimpleResp{}
// copy these attrs over to the parameters
itemNum := 1
for _, attr := range attrs.attrs {
itemNumStr := strconv.Itoa(itemNum)
// do the name, value and replace
params["Attribute."+itemNumStr+".Name"] = []string{attr.Name}
params["Attribute."+itemNumStr+".Value"] = []string{attr.Value}
if _, ok := attrs.replace[attr.Name]; ok {
params["Attribute."+itemNumStr+".Replace"] = []string{"true"}
}
itemNum++
}
//append expected values to params
expectedNum := 1
for _, attr := range attrs.expected {
expectedNumStr := strconv.Itoa(expectedNum)
params["Expected."+expectedNumStr+".Name"] = []string{attr.Name}
params["Expected."+expectedNumStr+".Value"] = []string{attr.Value}
if attrs.missing[attr.Name] {
params["Expected."+expectedNumStr+".Exists"] = []string{"false"}
}
expectedNum++
}
err = item.query(params, nil, resp)
if err != nil {
return nil, err
}
return
}
// Response to an Attrs request.
//
// See http://goo.gl/45X1M for more details.
type AttrsResp struct {
Attrs []Attr `xml:"GetAttributesResult>Attribute"`
ResponseMetadata ResponseMetadata
}
// Attrs returns one or more of the named attributes, or
// all of item's attributes if names is nil.
// If consistent is true, previous writes will necessarily
// be observed.
//
// See http://goo.gl/45X1M for more details.
func (item *Item) Attrs(names []string, consistent bool) (resp *AttrsResp, err error) {
params := makeParams("GetAttributes")
params["ItemName"] = []string{item.Name}
if consistent {
params["ConsistentRead"] = []string{"true"}
}
// Copy these attributes over to the parameters
for i, name := range names {
params["AttributeName."+strconv.Itoa(i+1)] = []string{name}
}
resp = &AttrsResp{}
err = item.query(params, nil, resp)
if err != nil {
return nil, err
}
return
}
// ----------------------------------------------------------------------------
// Generic data structures for all requests/responses.
// Error encapsulates an error returned by SDB.
type Error struct {
StatusCode int // HTTP status code (200, 403, ...)
StatusMsg string // HTTP status message ("Service Unavailable", "Bad Request", ...)
Code string // SimpleDB error code ("InvalidParameterValue", ...)
Message string // The human-oriented error message
RequestId string // A unique ID for this request
BoxUsage float64 // The measure of machine utilization for this request.
}
func (err *Error) Error() string {
return err.Message
}
// SimpleResp represents a response to an SDB request which on success
// will return no other information besides ResponseMetadata.
type SimpleResp struct {
ResponseMetadata ResponseMetadata
}
// ResponseMetadata
type ResponseMetadata struct {
RequestId string // A unique ID for tracking the request
BoxUsage float64 // The measure of machine utilization for this request.
}
func buildError(r *http.Response) error {
err := Error{}
err.StatusCode = r.StatusCode
err.StatusMsg = r.Status
xml.NewDecoder(r.Body).Decode(&err)
return &err
}
// ----------------------------------------------------------------------------
// Request dispatching logic.
func (item *Item) query(params url.Values, headers http.Header, resp interface{}) error {
return item.Domain.SDB.query(item.Domain, item, params, headers, resp)
}
func (domain *Domain) query(item *Item, params url.Values, headers http.Header, resp interface{}) error {
return domain.SDB.query(domain, item, params, headers, resp)
}
func (sdb *SDB) query(domain *Domain, item *Item, params url.Values, headers http.Header, resp interface{}) error {
// all SimpleDB operations have path="/"
method := "GET"
path := "/"
// if we have been given no headers or params, create them
if headers == nil {
headers = map[string][]string{}
}
if params == nil {
params = map[string][]string{}
}
// setup some default parameters
params["Version"] = []string{"2009-04-15"}
params["Timestamp"] = []string{time.Now().UTC().Format(time.RFC3339)}
// set the DomainName param (every request must have one)
if domain != nil {
params["DomainName"] = []string{domain.Name}
}
// set the ItemName if we have one
if item != nil {
params["ItemName"] = []string{item.Name}
}
// check the endpoint URL
u, err := url.Parse(sdb.Region.SDBEndpoint)
if err != nil {
return err
}
headers["Host"] = []string{u.Host}
sign(sdb.Auth, method, path, params, headers)
u.Path = path
if len(params) > 0 {
u.RawQuery = params.Encode()
}
req := http.Request{
URL: u,
Method: method,
ProtoMajor: 1,
ProtoMinor: 1,
Close: true,
Header: headers,
}
if v, ok := headers["Content-Length"]; ok {
req.ContentLength, _ = strconv.ParseInt(v[0], 10, 64)
delete(headers, "Content-Length")
}
r, err := http.DefaultClient.Do(&req)
if err != nil {
return err
}
defer r.Body.Close()
if debug {
dump, _ := httputil.DumpResponse(r, true)
log.Printf("response:\n")
log.Printf("%v\n}\n", string(dump))
}
// status code is always 200 when successful (since we're always doing a GET)
if r.StatusCode != 200 {
return buildError(r)
}
// everything was fine, so unmarshal the XML and return what it's err is (if any)
err = xml.NewDecoder(r.Body).Decode(resp)
return err
}
func makeParams(action string) map[string][]string {
params := make(map[string][]string)
params["Action"] = []string{action}
return params
}

219
vendor/github.com/goamz/goamz/exp/sdb/sdb_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,219 +0,0 @@
package sdb_test
import (
"testing"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/sdb"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
var _ = Suite(&S{})
type S struct {
sdb *sdb.SDB
}
var testServer = testutil.NewHTTPServer()
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.sdb = sdb.New(auth, aws.Region{SDBEndpoint: testServer.URL})
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func (s *S) TestCreateDomainOK(c *C) {
testServer.Response(200, nil, TestCreateDomainXmlOK)
domain := s.sdb.Domain("domain")
resp, err := domain.CreateDomain()
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "63264005-7a5f-e01a-a224-395c63b89f6d")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0055590279)
c.Assert(err, IsNil)
}
func (s *S) TestListDomainsOK(c *C) {
testServer.Response(200, nil, TestListDomainsXmlOK)
resp, err := s.sdb.ListDomains()
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "15fcaf55-9914-63c2-21f3-951e31193790")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000071759)
c.Assert(resp.Domains, DeepEquals, []string{"Account", "Domain", "Record"})
c.Assert(err, IsNil)
}
func (s *S) TestListDomainsWithNextTokenXmlOK(c *C) {
testServer.Response(200, nil, TestListDomainsWithNextTokenXmlOK)
resp, err := s.sdb.ListDomains()
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "eb13162f-1b95-4511-8b12-489b86acfd28")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000219907)
c.Assert(resp.Domains, DeepEquals, []string{"Domain1-200706011651", "Domain2-200706011652"})
c.Assert(resp.NextToken, Equals, "TWV0ZXJpbmdUZXN0RG9tYWluMS0yMDA3MDYwMTE2NTY=")
c.Assert(err, IsNil)
}
func (s *S) TestDeleteDomainOK(c *C) {
testServer.Response(200, nil, TestDeleteDomainXmlOK)
domain := s.sdb.Domain("domain")
resp, err := domain.DeleteDomain()
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "039e1e25-9a64-2a74-93da-2fda36122a97")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0055590278)
c.Assert(err, IsNil)
}
func (s *S) TestPutAttrsOK(c *C) {
testServer.Response(200, nil, TestPutAttrsXmlOK)
domain := s.sdb.Domain("MyDomain")
item := domain.Item("Item123")
putAttrs := new(sdb.PutAttrs)
putAttrs.Add("FirstName", "john")
putAttrs.Add("LastName", "smith")
putAttrs.Replace("MiddleName", "jacob")
putAttrs.IfValue("FirstName", "john")
putAttrs.IfMissing("FirstName")
resp, err := item.PutAttrs(putAttrs)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Form["Action"], DeepEquals, []string{"PutAttributes"})
c.Assert(req.Form["ItemName"], DeepEquals, []string{"Item123"})
c.Assert(req.Form["DomainName"], DeepEquals, []string{"MyDomain"})
c.Assert(req.Form["Attribute.1.Name"], DeepEquals, []string{"FirstName"})
c.Assert(req.Form["Attribute.1.Value"], DeepEquals, []string{"john"})
c.Assert(req.Form["Attribute.2.Name"], DeepEquals, []string{"LastName"})
c.Assert(req.Form["Attribute.2.Value"], DeepEquals, []string{"smith"})
c.Assert(req.Form["Attribute.3.Name"], DeepEquals, []string{"MiddleName"})
c.Assert(req.Form["Attribute.3.Value"], DeepEquals, []string{"jacob"})
c.Assert(req.Form["Attribute.3.Replace"], DeepEquals, []string{"true"})
c.Assert(req.Form["Expected.1.Name"], DeepEquals, []string{"FirstName"})
c.Assert(req.Form["Expected.1.Value"], DeepEquals, []string{"john"})
c.Assert(req.Form["Expected.1.Exists"], DeepEquals, []string{"false"})
c.Assert(err, IsNil)
c.Assert(resp.ResponseMetadata.RequestId, Equals, "490206ce-8292-456c-a00f-61b335eb202b")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000219907)
}
func (s *S) TestAttrsOK(c *C) {
testServer.Response(200, nil, TestAttrsXmlOK)
domain := s.sdb.Domain("MyDomain")
item := domain.Item("Item123")
resp, err := item.Attrs(nil, true)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(req.Form["Action"], DeepEquals, []string{"GetAttributes"})
c.Assert(req.Form["ItemName"], DeepEquals, []string{"Item123"})
c.Assert(req.Form["DomainName"], DeepEquals, []string{"MyDomain"})
c.Assert(req.Form["ConsistentRead"], DeepEquals, []string{"true"})
c.Assert(resp.Attrs[0].Name, Equals, "Color")
c.Assert(resp.Attrs[0].Value, Equals, "Blue")
c.Assert(resp.Attrs[1].Name, Equals, "Size")
c.Assert(resp.Attrs[1].Value, Equals, "Med")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "b1e8f1f7-42e9-494c-ad09-2674e557526d")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000219942)
c.Assert(err, IsNil)
}
func (s *S) TestAttrsSelectOK(c *C) {
testServer.Response(200, nil, TestAttrsXmlOK)
domain := s.sdb.Domain("MyDomain")
item := domain.Item("Item123")
resp, err := item.Attrs([]string{"Color", "Size"}, true)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(req.Form["Action"], DeepEquals, []string{"GetAttributes"})
c.Assert(req.Form["ItemName"], DeepEquals, []string{"Item123"})
c.Assert(req.Form["DomainName"], DeepEquals, []string{"MyDomain"})
c.Assert(req.Form["ConsistentRead"], DeepEquals, []string{"true"})
c.Assert(req.Form["AttributeName.1"], DeepEquals, []string{"Color"})
c.Assert(req.Form["AttributeName.2"], DeepEquals, []string{"Size"})
c.Assert(resp.Attrs[0].Name, Equals, "Color")
c.Assert(resp.Attrs[0].Value, Equals, "Blue")
c.Assert(resp.Attrs[1].Name, Equals, "Size")
c.Assert(resp.Attrs[1].Value, Equals, "Med")
c.Assert(resp.ResponseMetadata.RequestId, Equals, "b1e8f1f7-42e9-494c-ad09-2674e557526d")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000219942)
c.Assert(err, IsNil)
}
func (s *S) TestSelectOK(c *C) {
testServer.Response(200, nil, TestSelectXmlOK)
resp, err := s.sdb.Select("select Color from MyDomain where Color like 'Blue%'", true)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "GET")
c.Assert(req.URL.Path, Equals, "/")
c.Assert(req.Header["Date"], Not(Equals), "")
c.Assert(req.Form["Action"], DeepEquals, []string{"Select"})
c.Assert(req.Form["ConsistentRead"], DeepEquals, []string{"true"})
c.Assert(resp.ResponseMetadata.RequestId, Equals, "b1e8f1f7-42e9-494c-ad09-2674e557526d")
c.Assert(resp.ResponseMetadata.BoxUsage, Equals, 0.0000219907)
c.Assert(len(resp.Items), Equals, 2)
c.Assert(resp.Items[0].Name, Equals, "Item_03")
c.Assert(resp.Items[1].Name, Equals, "Item_06")
c.Assert(resp.Items[0].Attrs[0].Name, Equals, "Category")
c.Assert(resp.Items[0].Attrs[0].Value, Equals, "Clothes")
c.Assert(err, IsNil)
}

54
vendor/github.com/goamz/goamz/exp/sdb/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,54 +0,0 @@
package sdb
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"github.com/goamz/goamz/aws"
"net/http"
"net/url"
"sort"
"strings"
)
var b64 = base64.StdEncoding
// ----------------------------------------------------------------------------
// SimpleDB signing (http://goo.gl/CaY81)
func sign(auth aws.Auth, method, path string, params url.Values, headers http.Header) {
var host string
for k, v := range headers {
k = strings.ToLower(k)
switch k {
case "host":
host = v[0]
}
}
// set up some defaults used for signing the request
params["AWSAccessKeyId"] = []string{auth.AccessKey}
params["SignatureVersion"] = []string{"2"}
params["SignatureMethod"] = []string{"HmacSHA256"}
if auth.Token() != "" {
params["SecurityToken"] = []string{auth.Token()}
}
// join up all the incoming params
var sarray []string
for k, v := range params {
sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v[0]))
}
sort.StringSlice(sarray).Sort()
joined := strings.Join(sarray, "&")
// create the payload, sign it and create the signature
payload := strings.Join([]string{method, host, "/", joined}, "\n")
hash := hmac.New(sha256.New, []byte(auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
// add the signature to the outgoing params
params["Signature"] = []string{string(signature)}
}

29
vendor/github.com/goamz/goamz/exp/sdb/sign_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,29 +0,0 @@
package sdb_test
import (
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/sdb"
. "gopkg.in/check.v1"
)
// SimpleDB ReST authentication docs: http://goo.gl/CaY81
var testAuth = aws.Auth{AccessKey: "access-key-id-s8eBOWuU", SecretKey: "secret-access-key-UkQjTLd9"}
func (s *S) TestSignExampleDomainCreate(c *C) {
method := "GET"
params := map[string][]string{
"Action": {"CreateDomain"},
"DomainName": {"MyDomain"},
"Timestamp": {"2011-08-20T07:23:57+12:00"},
"Version": {"2009-04-15"},
}
headers := map[string][]string{
"Host": {"sdb.amazonaws.com"},
}
sdb.Sign(testAuth, method, "", params, headers)
expected := "ot2JaeeqMRJqgAqW67hkzUlffgxdOz4RykbrECB+tDU="
c.Assert(params["Signature"], DeepEquals, []string{expected})
}
// Do a few test methods which takes combinations of params

149
vendor/github.com/goamz/goamz/exp/ses/ses.go сгенерированный поставляемый
Просмотреть файл

@@ -1,149 +0,0 @@
// ses.go
package ses
import (
"encoding/xml"
"github.com/goamz/goamz/aws"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
)
type SES struct {
auth aws.Auth
region aws.Region
client *http.Client
}
// Initializes a pointer to an SES struct which can be used
// to perform SES API calls.
func NewSES(auth aws.Auth, region aws.Region) *SES {
ses := SES{auth, region, nil}
return &ses
}
// Sends an email to the specifications stored in the Email struct.
func (ses *SES) SendEmail(email *Email) error {
data := make(url.Values)
index := 0
for i := range email.destination.bccAddresses {
if len(email.destination.bccAddresses[i]) > 0 {
index += 1
key := "Destination.BccAddresses.member." + strconv.Itoa(index)
data.Add(key, email.destination.bccAddresses[i])
}
}
index = 0
for i := range email.destination.ccAddresses {
if len(email.destination.ccAddresses[i]) > 0 {
index += 1
key := "Destination.CcAddresses.member." + strconv.Itoa(index)
data.Add(key, email.destination.ccAddresses[i])
}
}
index = 0
for i := range email.destination.toAddresses {
if len(email.destination.toAddresses[i]) > 0 {
index += 1
key := "Destination.ToAddresses.member." + strconv.Itoa(index)
data.Add(key, email.destination.toAddresses[i])
}
}
index = 0
for i := range email.replyTo {
if len(email.replyTo[i]) > 0 {
index += 1
key := "ReplyToAddresses.member." + strconv.Itoa(index)
data.Add(key, email.replyTo[i])
}
}
if len(email.message.Subject.Data) > 0 {
if len(email.message.Subject.Charset) > 0 {
data.Add("Message.Subject.Charset", email.message.Subject.Charset)
}
data.Add("Message.Subject.Data", email.message.Subject.Data)
}
if len(email.message.Body.Html.Data) > 0 {
if len(email.message.Body.Html.Charset) > 0 {
data.Add("Message.Body.Html.Charset", email.message.Body.Html.Charset)
}
data.Add("Message.Body.Html.Data", email.message.Body.Html.Data)
}
if len(email.message.Body.Text.Data) > 0 {
if len(email.message.Body.Text.Charset) > 0 {
data.Add("Message.Body.Text.Charset", email.message.Body.Text.Charset)
}
data.Add("Message.Body.Text.Data", email.message.Body.Text.Data)
}
if len(email.returnPath) > 0 {
data.Add("ReturnPath", email.returnPath)
}
if len(email.source) > 0 {
data.Add("Source", email.source)
}
return ses.doPost("SendEmail", data)
}
// Do an SES POST action.
func (ses *SES) doPost(action string, data url.Values) error {
req := http.Request{
Method: "POST",
ProtoMajor: 1,
ProtoMinor: 1,
Close: true,
Header: http.Header{}}
URL, err := url.Parse(ses.region.SESEndpoint)
if err != nil {
return err
}
URL.Path = "/"
req.URL = URL
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
token := ses.auth.Token()
if token != "" {
req.Header.Set("X-Amz-Security-Token", token)
}
sign(ses.auth, "POST", req.Header)
data.Add("AWSAccessKeyId", ses.auth.AccessKey)
data.Add("Action", action)
body := data.Encode()
req.Header.Add("Content-Length", strconv.Itoa(len(body)))
req.Body = ioutil.NopCloser(strings.NewReader(body))
if ses.client == nil {
ses.client = &http.Client{}
}
resp, err := ses.client.Do(&req)
if err != nil {
return err
}
if resp.StatusCode > 204 {
defer resp.Body.Close()
return buildError(resp)
}
return nil
}
func buildError(r *http.Response) *SESError {
rootElem := errorResponse{}
xml.NewDecoder(r.Body).Decode(&rootElem)
return &rootElem.Error
}

69
vendor/github.com/goamz/goamz/exp/ses/ses_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,69 +0,0 @@
// ses_test
package ses_test
import (
"bytes"
"net/url"
"testing"
"github.com/goamz/goamz/aws"
"github.com/goamz/goamz/exp/ses"
"github.com/goamz/goamz/testutil"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) {
TestingT(t)
}
type S struct {
ses *ses.SES
}
var _ = Suite(&S{})
var testServer = testutil.NewHTTPServer()
func (s *S) SetUpSuite(c *C) {
testServer.Start()
auth := aws.Auth{AccessKey: "abc", SecretKey: "123"}
s.ses = ses.NewSES(auth, aws.Region{Name: "faux-region-1", S3Endpoint: testServer.URL})
}
func (s *S) TearDownStrategy(c *C) {
}
func (s *S) SetUpTest(c *C) {
}
func (s *S) TearDownTest(c *C) {
testServer.Flush()
}
func (s *S) TestSendEmail(c *C) {
testServer.Response(200, nil, "")
email := ses.NewEmail()
email.AddTo("test@test.com")
email.AddSource("test@test.com")
email.SetSubject("test")
email.SetBodyHtml("test")
s.ses.SendEmail(email)
req := testServer.WaitRequest()
c.Assert(req.Method, Equals, "POST")
c.Assert(req.Header["Date"], Not(Equals), "")
buf := new(bytes.Buffer)
buf.ReadFrom(req.Body)
body, _ := url.ParseQuery(buf.String())
c.Assert(body, Not(IsNil))
c.Assert(body["Destination.ToAddresses.member.1"], Equals, "test@test.com")
c.Assert(body["Source"], Equals, "test@test.com")
c.Assert(body["Message.Subject.Data"], Equals, "test")
c.Assert(body["Message.Body.Html.Data"], Equals, "test")
}

160
vendor/github.com/goamz/goamz/exp/ses/ses_types.go сгенерированный поставляемый
Просмотреть файл

@@ -1,160 +0,0 @@
// ses_types
package ses
// Private internal representation of message body.
type Body struct {
Html Content
Text Content
}
// Content data structure with charset and payload (Data).
type Content struct {
Charset string
Data string
}
// Email data structure. Should be main data structure used
// for sending emails using SES.
type Email struct {
destination *destination
message Message
replyTo []string
returnPath string
source string
}
// Private internal representation for email destinations.
type destination struct {
bccAddresses []string
ccAddresses []string
toAddresses []string
}
// Message data structure.
type Message struct {
Body Body
Subject Content
}
// SES Error structure.
type SESError struct {
Type string
Code string
Message string
Detail string
RequestId string
}
type errorResponse struct {
Error SESError
}
func (err *SESError) Error() string {
return err.Message
}
// Returns a pointer to an empty but initialized Email.
func NewEmail() *Email {
return &Email{
destination: newDestination(),
replyTo: make([]string, 5)}
}
// Private function to return an initialized destination.
func newDestination() *destination {
return &destination{
bccAddresses: make([]string, 5),
ccAddresses: make([]string, 5),
toAddresses: make([]string, 5)}
}
// Add a BCC destination to Email.
func (em *Email) AddBCC(address string) {
em.destination.bccAddresses = append(em.destination.bccAddresses, address)
}
// Add multiple BCC destinations to Email.
func (em *Email) AddBCCs(addresses []string) {
em.destination.bccAddresses = append(em.destination.bccAddresses, addresses...)
}
// Add a CC destination to Email.
func (em *Email) AddCC(address string) {
em.destination.ccAddresses = append(em.destination.ccAddresses, address)
}
// Add multiple CC destinations to Email.
func (em *Email) AddCCs(addresses []string) {
em.destination.ccAddresses = append(em.destination.ccAddresses, addresses...)
}
// Add a To destination to Email.
func (em *Email) AddTo(address string) {
em.destination.toAddresses = append(em.destination.toAddresses, address)
}
// Add multiple To destinations to Email.
func (em *Email) AddTos(addresses []string) {
em.destination.toAddresses = append(em.destination.toAddresses, addresses...)
}
// Add a reply-to address to Email.
func (em *Email) AddReplyTo(address string) {
em.replyTo = append(em.replyTo, address)
}
// Add multiple reply-to addresses to Email.
func (em *Email) AddReplyTos(addresses []string) {
em.replyTo = append(em.replyTo, addresses...)
}
// Set the return path for Email.
func (em *Email) SetReturnPath(path string) {
em.returnPath = path
}
// Set the source address for Email.
func (em *Email) SetSource(source string) {
em.source = source
}
// Set the Email message.
func (em *Email) SetMessage(message Message) {
em.message = message
}
// Set the subject for the Email message.
// Uses ASCII as charset.
func (em *Email) SetSubject(subject string) {
em.message.Subject = Content{Data: subject}
}
// Set the subject for the Email message.
// Uses the charset (or ASCII if none) of Content.
func (em *Email) SetSubjectAsContent(subject Content) {
em.message.Subject = subject
}
// Sets the HTML body of the Email message.
// Uses ASCII as charset.
func (em *Email) SetBodyHtml(html string) {
em.message.Body.Html = Content{Data: html}
}
// Sets the HTML body of the Email message.
// Uses the charset (or ASCII if none) of Content.
func (em *Email) SetBodyHtmlAsContent(html Content) {
em.message.Body.Html = html
}
// Sets the raw text body of the Email message.
// Uses ASCII as charset.
func (em *Email) SetBodyRawText(text string) {
em.message.Body.Text = Content{Data: text}
}
// Sets the raw test body of the Email message.
// Uses the charset (or ASCII if none) of Content.
func (em *Email) SetBodyRawTextAsContent(text Content) {
em.message.Body.Text = text
}

26
vendor/github.com/goamz/goamz/exp/ses/sign.go сгенерированный поставляемый
Просмотреть файл

@@ -1,26 +0,0 @@
// sign
package ses
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"github.com/goamz/goamz/aws"
"time"
)
const (
AMZ_DATE_STYLE = "Mon, 02 Jan 2006 15:04:05 -0700"
)
// Sign SES request as dictated by Amazon's Version 3 signature method.
func sign(auth aws.Auth, method string, headers map[string][]string) {
date := time.Now().UTC().Format(AMZ_DATE_STYLE)
h := hmac.New(sha256.New, []byte(auth.SecretKey))
h.Write([]byte(date))
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HmacSHA256, Signature=%s", auth.AccessKey, signature)
headers["Date"] = []string{date}
headers["X-Amzn-Authorization"] = []string{authHeader}
}

21
vendor/github.com/goamz/goamz/exp/sns/Makefile сгенерированный поставляемый
Просмотреть файл

@@ -1,21 +0,0 @@
include $(GOROOT)/src/Make.inc
TARG=launchpad.net/goamz/sns
GOFILES=\
sns.go\
sign.go\
include $(GOROOT)/src/Make.pkg
GOFMT=gofmt
BADFMT=$(shell $(GOFMT) -l $(GOFILES) 2> /dev/null)
gofmt: $(BADFMT)
@for F in $(BADFMT); do $(GOFMT) -w $$F && echo $$F; done
ifneq ($(BADFMT),)
ifneq ($(MAKECMDGOALS), gofmt)
#$(warning WARNING: make gofmt: $(BADFMT))
endif
endif

1
vendor/github.com/goamz/goamz/exp/sns/README сгенерированный поставляемый
Просмотреть файл

@@ -1 +0,0 @@
Amazon Simple Notification Service API for Golang.

132
vendor/github.com/goamz/goamz/exp/sns/endpoint.go сгенерированный поставляемый
Просмотреть файл

@@ -1,132 +0,0 @@
package sns
import (
"fmt"
"strconv"
)
type DeleteEndpointResponse struct {
ResponseMetadata
}
type GetEndpointAttributesResponse struct {
Attributes []AttributeEntry `xml:"GetEndpointAttributesResult>Attributes>entry"`
ResponseMetadata
}
type PlatformEndpointOpt struct {
Attributes []AttributeEntry
PlatformApplicationArn string
CustomUserData string
Token string
}
type CreatePlatformEndpointResponse struct {
EndpointArn string `xml:"CreatePlatformEndpointResult>EndpointArn"`
ResponseMetadata
}
type PlatformEndpoints struct {
EndpointArn string `xml:"EndpointArn"`
Attributes []AttributeEntry `xml:"Attributes>entry"`
}
type ListEndpointsByPlatformApplicationResponse struct {
Endpoints []PlatformEndpoints `xml:"ListEndpointsByPlatformApplicationResult>Endpoints>member"`
ResponseMetadata
}
type SetEndpointAttributesOpt struct {
Attributes []AttributeEntry
EndpointArn string
}
type SetEndpointAttributesResponse struct {
ResponseMetadata
}
// DeleteEndpoint
//
// See http://goo.gl/9SlUD9 for more details.
func (sns *SNS) DeleteEndpoint(endpointArn string) (resp *DeleteEndpointResponse, err error) {
resp = &DeleteEndpointResponse{}
params := makeParams("DeleteEndpoint")
params["EndpointArn"] = endpointArn
err = sns.query(params, resp)
return
}
// GetEndpointAttributes
//
// See http://goo.gl/c8E5X1 for more details.
func (sns *SNS) GetEndpointAttributes(endpointArn string) (resp *GetEndpointAttributesResponse, err error) {
resp = &GetEndpointAttributesResponse{}
params := makeParams("GetEndpointAttributes")
params["EndpointArn"] = endpointArn
err = sns.query(params, resp)
return
}
// CreatePlatformEndpoint
//
// See http://goo.gl/4tnngi for more details.
func (sns *SNS) CreatePlatformEndpoint(options *PlatformEndpointOpt) (resp *CreatePlatformEndpointResponse, err error) {
resp = &CreatePlatformEndpointResponse{}
params := makeParams("CreatePlatformEndpoint")
params["PlatformApplicationArn"] = options.PlatformApplicationArn
params["Token"] = options.Token
if options.CustomUserData != "" {
params["CustomUserData"] = options.CustomUserData
}
err = sns.query(params, resp)
return
}
// ListEndpointsByPlatformApplication
//
// See http://goo.gl/L7ioyR for more detail.
func (sns *SNS) ListEndpointsByPlatformApplication(platformApplicationArn, nextToken string) (resp *ListEndpointsByPlatformApplicationResponse, err error) {
resp = &ListEndpointsByPlatformApplicationResponse{}
params := makeParams("ListEndpointsByPlatformApplication")
params["PlatformApplicationArn"] = platformApplicationArn
if nextToken != "" {
params["NextToken"] = nextToken
}
err = sns.query(params, resp)
return
}
// SetEndpointAttributes
//
// See http://goo.gl/GTktCj for more detail.
func (sns *SNS) SetEndpointAttributes(options *SetEndpointAttributesOpt) (resp *SetEndpointAttributesResponse, err error) {
resp = &SetEndpointAttributesResponse{}
params := makeParams("SetEndpointAttributes")
params["EndpointArn"] = options.EndpointArn
for i, attr := range options.Attributes {
params[fmt.Sprintf("Attributes.entry.%s.key", strconv.Itoa(i+1))] = attr.Key
params[fmt.Sprintf("Attributes.entry.%s.value", strconv.Itoa(i+1))] = attr.Value
}
err = sns.query(params, resp)
return
}

51
vendor/github.com/goamz/goamz/exp/sns/permissions.go сгенерированный поставляемый
Просмотреть файл

@@ -1,51 +0,0 @@
package sns
import (
"strconv"
)
type Permission struct {
ActionName string
AccountId string
}
type AddPermissionResponse struct {
ResponseMetadata
}
// AddPermission
//
// See http://goo.gl/mbY4a for more details.
func (sns *SNS) AddPermission(permissions []Permission, Label, TopicArn string) (resp *AddPermissionResponse, err error) {
resp = &AddPermissionResponse{}
params := makeParams("AddPermission")
for i, p := range permissions {
params["AWSAccountId.member."+strconv.Itoa(i+1)] = p.AccountId
params["ActionName.member."+strconv.Itoa(i+1)] = p.ActionName
}
params["Label"] = Label
params["TopicArn"] = TopicArn
err = sns.query(params, resp)
return
}
type RemovePermissionResponse struct {
ResponseMetadata
}
// RemovePermission
//
// See http://goo.gl/wGl5j for more details.
func (sns *SNS) RemovePermission(Label, TopicArn string) (resp *RemovePermissionResponse, err error) {
resp = &RemovePermissionResponse{}
params := makeParams("RemovePermission")
params["Label"] = Label
params["TopicArn"] = TopicArn
err = sns.query(params, resp)
return
}

135
vendor/github.com/goamz/goamz/exp/sns/platform.go сгенерированный поставляемый
Просмотреть файл

@@ -1,135 +0,0 @@
package sns
import (
"fmt"
"strconv"
)
type CreatePlatformApplicationResponse struct {
PlatformApplicationArn string `xml:"CreatePlatformApplicationResult>PlatformApplicationArn"`
ResponseMetadata
}
type PlatformApplicationOpt struct {
Attributes []AttributeEntry
Name string
Platform string
}
type DeletePlatformApplicationResponse struct {
ResponseMetadata
}
type GetPlatformApplicationAttributesResponse struct {
Attributes []AttributeEntry `xml:"GetPlatformApplicationAttributesResult>Attributes>entry"`
ResponseMetadata
}
type SetPlatformApplicationAttributesOpt struct {
Attributes []AttributeEntry
PlatformApplicationArn string
}
type SetPlatformApplicationAttributesResponse struct {
ResponseMetadata
}
type PlatformApplication struct {
Attributes []AttributeEntry `xml:"Attributes>entry"`
PlatformApplicationArn string
}
type ListPlatformApplicationsResponse struct {
NextToken string
PlatformApplications []PlatformApplication `xml:"ListPlatformApplicationsResult>PlatformApplications>member"`
ResponseMetadata
}
// CreatePlatformApplication
//
// See http://goo.gl/Mbbl6Z for more details.
func (sns *SNS) CreatePlatformApplication(options *PlatformApplicationOpt) (resp *CreatePlatformApplicationResponse, err error) {
resp = &CreatePlatformApplicationResponse{}
params := makeParams("CreatePlatformApplication")
params["Platform"] = options.Platform
params["Name"] = options.Name
for i, attr := range options.Attributes {
params[fmt.Sprintf("Attributes.entry.%s.key", strconv.Itoa(i+1))] = attr.Key
params[fmt.Sprintf("Attributes.entry.%s.value", strconv.Itoa(i+1))] = attr.Value
}
err = sns.query(params, resp)
return
}
// DeletePlatformApplication
//
// See http://goo.gl/6GB3DN for more details.
func (sns *SNS) DeletePlatformApplication(platformApplicationArn string) (resp *DeletePlatformApplicationResponse, err error) {
resp = &DeletePlatformApplicationResponse{}
params := makeParams("DeletePlatformApplication")
params["PlatformApplicationArn"] = platformApplicationArn
err = sns.query(params, resp)
return
}
// GetPlatformApplicationAttributes
//
// See http://goo.gl/GswJ8I for more details.
func (sns *SNS) GetPlatformApplicationAttributes(platformApplicationArn, nextToken string) (resp *GetPlatformApplicationAttributesResponse, err error) {
resp = &GetPlatformApplicationAttributesResponse{}
params := makeParams("GetPlatformApplicationAttributes")
params["PlatformApplicationArn"] = platformApplicationArn
if nextToken != "" {
params["NextToken"] = nextToken
}
err = sns.query(params, resp)
return
}
// ListPlatformApplications
//
// See http://goo.gl/vQ3ooV for more detail.
func (sns *SNS) ListPlatformApplications(nextToken string) (resp *ListPlatformApplicationsResponse, err error) {
resp = &ListPlatformApplicationsResponse{}
params := makeParams("ListPlatformApplications")
if nextToken != "" {
params["NextToken"] = nextToken
}
err = sns.query(params, resp)
return
}
// SetPlatformApplicationAttributes
//
// See http://goo.gl/RWnzzb for more detail.
func (sns *SNS) SetPlatformApplicationAttributes(options *SetPlatformApplicationAttributesOpt) (resp *SetPlatformApplicationAttributesResponse, err error) {
resp = &SetPlatformApplicationAttributesResponse{}
params := makeParams("SetPlatformApplicationAttributes")
params["PlatformApplicationArn"] = options.PlatformApplicationArn
for i, attr := range options.Attributes {
params[fmt.Sprintf("Attributes.entry.%s.key", strconv.Itoa(i+1))] = attr.Key
params[fmt.Sprintf("Attributes.entry.%s.value", strconv.Itoa(i+1))] = attr.Value
}
err = sns.query(params, resp)
return
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше