Kaynağa Gözat

Merged with master, resolved conflicts

utkarshcmu 10 yıl önce
ebeveyn
işleme
9498c78576
100 değiştirilmiş dosya ile 12768 ekleme ve 1627 silme
  1. 1 0
      .gitignore
  2. 50 3
      CHANGELOG.md
  3. 33 22
      Godeps/Godeps.json
  4. 4 7
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
  5. 32 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
  6. 27 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
  7. 29 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
  8. 70 35
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
  9. 95 21
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
  10. 89 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
  11. 120 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go
  12. 4 8
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
  13. 12 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
  14. 48 17
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go
  15. 8 2
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go
  16. 17 14
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
  17. 11 5
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go
  18. 1 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
  19. 6 6
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go
  20. 34 29
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
  21. 14 16
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go
  22. 4 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/example.ini
  23. 16 12
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
  24. 12 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go
  25. 40 35
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
  26. 4 7
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go
  27. 64 27
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
  28. 4 4
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
  29. 8 7
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go
  30. 49 82
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
  31. 2 2
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/errors.go
  32. 28 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers.go
  33. 2 2
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go
  34. 26 95
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request.go
  35. 104 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
  36. 160 12
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go
  37. 42 9
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_test.go
  38. 10 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/retryer.go
  39. 0 133
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/service.go
  40. 0 15
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go
  41. 105 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go
  42. 20 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session_test.go
  43. 1 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types.go
  44. 1 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go
  45. 38 4
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go
  46. 8 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json
  47. 8 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go
  48. 20 7
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_test.go
  49. 1 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go
  50. 2 2
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_bench_test.go
  51. 316 147
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_test.go
  52. 433 139
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal_test.go
  53. 1 1
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build.go
  54. 539 196
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go
  55. 2 2
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go
  56. 620 228
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go
  57. 3 4
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/functional_test.go
  58. 8 8
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4.go
  59. 13 8
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4_test.go
  60. 136 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter.go
  61. 391 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter_test.go
  62. 3 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/api.go
  63. 2 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface/interface.go
  64. 0 15
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface/interface_test.go
  65. 12 11
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/examples_test.go
  66. 47 24
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/service.go
  67. 58 24
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go
  68. 18 20
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations.go
  69. 4 5
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go
  70. 4 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go
  71. 0 15
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface_test.go
  72. 112 111
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/examples_test.go
  73. 47 24
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/service.go
  74. 761 0
      Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/waiters.go
  75. 4 0
      Godeps/_workspace/src/github.com/go-ini/ini/.gitignore
  76. 191 0
      Godeps/_workspace/src/github.com/go-ini/ini/LICENSE
  77. 560 0
      Godeps/_workspace/src/github.com/go-ini/ini/README.md
  78. 547 0
      Godeps/_workspace/src/github.com/go-ini/ini/README_ZH.md
  79. 1226 0
      Godeps/_workspace/src/github.com/go-ini/ini/ini.go
  80. 512 0
      Godeps/_workspace/src/github.com/go-ini/ini/ini_test.go
  81. 350 0
      Godeps/_workspace/src/github.com/go-ini/ini/struct.go
  82. 239 0
      Godeps/_workspace/src/github.com/go-ini/ini/struct_test.go
  83. 2 0
      Godeps/_workspace/src/github.com/go-ini/ini/testdata/conf.ini
  84. 4 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/.gitignore
  85. 9 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/.travis.yml
  86. 13 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/LICENSE
  87. 44 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/Makefile
  88. 7 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/README.md
  89. 12 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/api.go
  90. 16 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/astnodetype_string.go
  91. 96 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/basic.json
  92. 257 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/boolean.json
  93. 25 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/current.json
  94. 46 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/escape.json
  95. 468 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/filters.json
  96. 825 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/functions.json
  97. 1377 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/identifiers.json
  98. 346 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/indices.json
  99. 185 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/literal.json
  100. 393 0
      Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/multiselect.json

+ 1 - 0
.gitignore

@@ -1,4 +1,5 @@
 node_modules
 node_modules
+npm-debug.log
 coverage/
 coverage/
 .aws-config.json
 .aws-config.json
 awsconfig
 awsconfig

+ 50 - 3
CHANGELOG.md

@@ -1,4 +1,51 @@
-# 2.5 (unreleased)
+# 3.0.0 (unrelased master branch)
+
+
+### Breaking changes
+**InfluxDB 0.8.x** The data source for the old version of influxdb (0.8.x) is no longer included in default builds. Can easily be installed via improved plugin system, closes #3523
+**KairosDB** The data source is no longer included in default builds. Can easily be installed via improved plugin system, closes #3524
+
+# 2.6.1 (unrelased, 2.6.x branch)
+
+### New Features
+* **Elasticsearch**: Support for derivative unit option, closes [#3512](https://github.com/grafana/grafana/issues/3512)
+
+# 2.6.0 (2015-12-14)
+
+### New Features
+* **Elasticsearch**: Support for pipeline aggregations Moving average and derivative, closes [#2715](https://github.com/grafana/grafana/issues/2715)
+* **Elasticsearch**: Support for inline script and missing options for metrics, closes [#3500](https://github.com/grafana/grafana/issues/3500)
+* **Syslog**: Support for syslog logging, closes [#3161](https://github.com/grafana/grafana/pull/3161)
+* **Timepicker**: Always show refresh button even with refresh rate, closes [#3498](https://github.com/grafana/grafana/pull/3498)
+* **Login**: Make it possible to change the login hint on the login page, closes [#2571](https://github.com/grafana/grafana/pull/2571)
+
+### Bug Fixes
+* **metric editors**: Fix for clicking typeahead auto dropdown option, fixes [#3428](https://github.com/grafana/grafana/issues/3428)
+* **influxdb**: Fixed issue showing Group By label only on first query, fixes [#3453](https://github.com/grafana/grafana/issues/3453)
+* **logging**: Add more verbose info logging for http reqeusts, closes [#3405](https://github.com/grafana/grafana/pull/3405)
+
+# 2.6.0-Beta1 (2015-12-04)
+
+### New Table Panel
+* **table**:  New powerful and flexible table panel, closes [#215](https://github.com/grafana/grafana/issues/215)
+
+### Enhancements
+* **CloudWatch**: Support for multiple AWS Credentials, closes [#3053](https://github.com/grafana/grafana/issues/3053), [#3080](https://github.com/grafana/grafana/issues/3080)
+* **Elasticsearch**: Support for dynamic daily indices for annotations, closes [#3061](https://github.com/grafana/grafana/issues/3061)
+* **Elasticsearch**: Support for setting min_doc_count for date histogram, closes [#3416](https://github.com/grafana/grafana/issues/3416)
+* **Graph Panel**: Option to hide series with all zeroes from legend and tooltip, closes [#1381](https://github.com/grafana/grafana/issues/1381), [#3336](https://github.com/grafana/grafana/issues/3336)
+
+### Bug Fixes
+* **cloudwatch**: fix for handling of period for long time ranges, fixes [#3086](https://github.com/grafana/grafana/issues/3086)
+* **dashboard**: fix for collapse row by clicking on row title, fixes [#3065](https://github.com/grafana/grafana/issues/3065)
+* **influxdb**: fix for relative time ranges `last x months` and `last x years`, fixes [#3067](https://github.com/grafana/grafana/issues/3067)
+* **graph**: layout fix for color picker when right side legend was enabled, fixes [#3093](https://github.com/grafana/grafana/issues/3093)
+* **elasticsearch**: disabling elastic query (via eye) caused error, fixes [#3300](https://github.com/grafana/grafana/issues/3300)
+
+### Breaking changes
+* **elasticsearch**: Manual json edited queries are not supported any more (They very barely worked in 2.5)
+
+# 2.5 (2015-10-28)
 
 
 **New Feature: Mix data sources**
 **New Feature: Mix data sources**
 - A built in data source is now available named `-- Mixed --`, When picked in the metrics tab,
 - A built in data source is now available named `-- Mixed --`, When picked in the metrics tab,
@@ -11,12 +58,12 @@ it allows you to add queries of differnet data source types & instances to the s
 
 
 **New Feature: New and much improved time picker**
 **New Feature: New and much improved time picker**
 - Support for quick ranges like `Today`, `This day last week`, `This week`, `The day so far`, etc.
 - Support for quick ranges like `Today`, `This day last week`, `This week`, `The day so far`, etc.
-- Muck improved UI and improved support for UTC, [Issue #2761](https://github.com/grafana/grafana/issues/2761) for more info.
+- Improved UI and improved support for UTC, [Issue #2761](https://github.com/grafana/grafana/issues/2761) for more info.
 
 
 **User Onboarding**
 **User Onboarding**
 - Org admin can now send email invites (or invite links) to people who are not yet Grafana users
 - Org admin can now send email invites (or invite links) to people who are not yet Grafana users
 - Sign up flow now supports email verification (if enabled)
 - Sign up flow now supports email verification (if enabled)
-- See [Issue #2353](https://github.com/grafana/grafana/issues/2354) for more info.
+- See [Issue #2353](https://github.com/grafana/grafana/issues/2353) for more info.
 
 
 **Other new Features && Enhancements**
 **Other new Features && Enhancements**
 - [Pull  #2720](https://github.com/grafana/grafana/pull/2720). Admin: Initial basic quota support (per Org)
 - [Pull  #2720](https://github.com/grafana/grafana/pull/2720). Admin: Initial basic quota support (per Org)

+ 33 - 22
Godeps/Godeps.json

@@ -20,53 +20,63 @@
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/aws",
 			"ImportPath": "github.com/aws/aws-sdk-go/aws",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
 			"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
+		},
+		{
+			"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/service/cloudwatch",
 			"ImportPath": "github.com/aws/aws-sdk-go/service/cloudwatch",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
 			"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
-			"Comment": "v0.9.16-3-g4944a94",
-			"Rev": "4944a94a3b092d1dad8a964415700a70f55e580a"
+			"Comment": "v1.0.0",
+			"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
 		},
 		},
 		{
 		{
 			"ImportPath": "github.com/davecgh/go-spew/spew",
 			"ImportPath": "github.com/davecgh/go-spew/spew",
 			"Rev": "2df174808ee097f90d259e432cc04442cf60be21"
 			"Rev": "2df174808ee097f90d259e432cc04442cf60be21"
 		},
 		},
+		{
+			"ImportPath": "github.com/go-ini/ini",
+			"Comment": "v0-48-g060d7da",
+			"Rev": "060d7da055ba6ec5ea7a31f116332fe5efa04ce0"
+		},
 		{
 		{
 			"ImportPath": "github.com/go-ldap/ldap",
 			"ImportPath": "github.com/go-ldap/ldap",
 			"Comment": "v1-19-g83e6542",
 			"Comment": "v1-19-g83e6542",
@@ -90,6 +100,11 @@
 			"ImportPath": "github.com/gosimple/slug",
 			"ImportPath": "github.com/gosimple/slug",
 			"Rev": "8d258463b4459f161f51d6a357edacd3eef9d663"
 			"Rev": "8d258463b4459f161f51d6a357edacd3eef9d663"
 		},
 		},
+		{
+			"ImportPath": "github.com/jmespath/go-jmespath",
+			"Comment": "0.2.2",
+			"Rev": "3433f3ea46d9f8019119e7dd41274e112a2359a9"
+		},
 		{
 		{
 			"ImportPath": "github.com/jtolds/gls",
 			"ImportPath": "github.com/jtolds/gls",
 			"Rev": "f1ac7f4f24f50328e6bc838ca4437d1612a0243c"
 			"Rev": "f1ac7f4f24f50328e6bc838ca4437d1612a0243c"
@@ -124,10 +139,6 @@
 			"ImportPath": "github.com/streadway/amqp",
 			"ImportPath": "github.com/streadway/amqp",
 			"Rev": "150b7f24d6ad507e6026c13d85ce1f1391ac7400"
 			"Rev": "150b7f24d6ad507e6026c13d85ce1f1391ac7400"
 		},
 		},
-		{
-			"ImportPath": "github.com/vaughan0/go-ini",
-			"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
-		},
 		{
 		{
 			"ImportPath": "golang.org/x/net/context",
 			"ImportPath": "golang.org/x/net/context",
 			"Rev": "972f0c5fbe4ae29e666c3f78c3ed42ae7a448b0a"
 			"Rev": "972f0c5fbe4ae29e666c3f78c3ed42ae7a448b0a"

+ 4 - 7
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy.go

@@ -57,16 +57,13 @@ func rcopy(dst, src reflect.Value, root bool) {
 			}
 			}
 		}
 		}
 	case reflect.Struct:
 	case reflect.Struct:
-		if !root {
-			dst.Set(reflect.New(src.Type()).Elem())
-		}
-
 		t := dst.Type()
 		t := dst.Type()
 		for i := 0; i < t.NumField(); i++ {
 		for i := 0; i < t.NumField(); i++ {
 			name := t.Field(i).Name
 			name := t.Field(i).Name
-			srcval := src.FieldByName(name)
-			if srcval.IsValid() {
-				rcopy(dst.FieldByName(name), srcval, false)
+			srcVal := src.FieldByName(name)
+			dstVal := dst.FieldByName(name)
+			if srcVal.IsValid() && dstVal.CanSet() {
+				rcopy(dstVal, srcVal, false)
 			}
 			}
 		}
 		}
 	case reflect.Slice:
 	case reflect.Slice:

+ 32 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go

@@ -77,6 +77,28 @@ func TestCopy(t *testing.T) {
 	assert.NotEqual(t, f2.C, f1.C)
 	assert.NotEqual(t, f2.C, f1.C)
 }
 }
 
 
+func TestCopyNestedWithUnexported(t *testing.T) {
+	type Bar struct {
+		a int
+		B int
+	}
+	type Foo struct {
+		A string
+		B Bar
+	}
+
+	f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}}
+
+	var f2 Foo
+	awsutil.Copy(&f2, f1)
+
+	// Values match
+	assert.Equal(t, f2.A, f1.A)
+	assert.NotEqual(t, f2.B, f1.B)
+	assert.NotEqual(t, f2.B.a, f1.B.a)
+	assert.Equal(t, f2.B.B, f2.B.B)
+}
+
 func TestCopyIgnoreNilMembers(t *testing.T) {
 func TestCopyIgnoreNilMembers(t *testing.T) {
 	type Foo struct {
 	type Foo struct {
 		A *string
 		A *string
@@ -136,6 +158,8 @@ func TestCopyDifferentStructs(t *testing.T) {
 		C                map[string]*int
 		C                map[string]*int
 		SrcUnique        string
 		SrcUnique        string
 		SameNameDiffType int
 		SameNameDiffType int
+		unexportedPtr    *int
+		ExportedPtr      *int
 	}
 	}
 	type DstFoo struct {
 	type DstFoo struct {
 		A                int
 		A                int
@@ -143,6 +167,8 @@ func TestCopyDifferentStructs(t *testing.T) {
 		C                map[string]*int
 		C                map[string]*int
 		DstUnique        int
 		DstUnique        int
 		SameNameDiffType string
 		SameNameDiffType string
+		unexportedPtr    *int
+		ExportedPtr      *int
 	}
 	}
 
 
 	// Create the initial value
 	// Create the initial value
@@ -159,6 +185,8 @@ func TestCopyDifferentStructs(t *testing.T) {
 		},
 		},
 		SrcUnique:        "unique",
 		SrcUnique:        "unique",
 		SameNameDiffType: 1,
 		SameNameDiffType: 1,
+		unexportedPtr:    &int1,
+		ExportedPtr:      &int2,
 	}
 	}
 
 
 	// Do the copy
 	// Do the copy
@@ -173,6 +201,10 @@ func TestCopyDifferentStructs(t *testing.T) {
 	assert.Equal(t, 1, f1.SameNameDiffType)
 	assert.Equal(t, 1, f1.SameNameDiffType)
 	assert.Equal(t, 0, f2.DstUnique)
 	assert.Equal(t, 0, f2.DstUnique)
 	assert.Equal(t, "", f2.SameNameDiffType)
 	assert.Equal(t, "", f2.SameNameDiffType)
+	assert.Equal(t, int1, *f1.unexportedPtr)
+	assert.Nil(t, f2.unexportedPtr)
+	assert.Equal(t, int2, *f1.ExportedPtr)
+	assert.Equal(t, int2, *f2.ExportedPtr)
 }
 }
 
 
 func ExampleCopyOf() {
 func ExampleCopyOf() {

+ 27 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal.go

@@ -0,0 +1,27 @@
+package awsutil
+
+import (
+	"reflect"
+)
+
+// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual.
+// In addition to this, this method will also dereference the input values if
+// possible so the DeepEqual performed will not fail if one parameter is a
+// pointer and the other is not.
+//
+// DeepEqual will not perform indirection of nested values of the input parameters.
+func DeepEqual(a, b interface{}) bool {
+	ra := reflect.Indirect(reflect.ValueOf(a))
+	rb := reflect.Indirect(reflect.ValueOf(b))
+
+	if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid {
+		// If the elements are both nil, and of the same type the are equal
+		// If they are of different types they are not equal
+		return reflect.TypeOf(a) == reflect.TypeOf(b)
+	} else if raValid != rbValid {
+		// Both values must be valid to be equal
+		return false
+	}
+
+	return reflect.DeepEqual(ra.Interface(), rb.Interface())
+}

+ 29 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go

@@ -0,0 +1,29 @@
+package awsutil_test
+
+import (
+	"testing"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/awsutil"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDeepEqual(t *testing.T) {
+	cases := []struct {
+		a, b  interface{}
+		equal bool
+	}{
+		{"a", "a", true},
+		{"a", "b", false},
+		{"a", aws.String(""), false},
+		{"a", nil, false},
+		{"a", aws.String("a"), true},
+		{(*bool)(nil), (*bool)(nil), true},
+		{(*bool)(nil), (*string)(nil), false},
+		{nil, nil, true},
+	}
+
+	for i, c := range cases {
+		assert.Equal(t, c.equal, awsutil.DeepEqual(c.a, c.b), "%d, a:%v b:%v, %t", i, c.a, c.b, c.equal)
+	}
+}

+ 70 - 35
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go

@@ -5,18 +5,20 @@ import (
 	"regexp"
 	"regexp"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
+
+	"github.com/jmespath/go-jmespath"
 )
 )
 
 
 var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
 var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
 
 
 // rValuesAtPath returns a slice of values found in value v. The values
 // rValuesAtPath returns a slice of values found in value v. The values
 // in v are explored recursively so all nested values are collected.
 // in v are explored recursively so all nested values are collected.
-func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool) []reflect.Value {
+func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
 	pathparts := strings.Split(path, "||")
 	pathparts := strings.Split(path, "||")
 	if len(pathparts) > 1 {
 	if len(pathparts) > 1 {
 		for _, pathpart := range pathparts {
 		for _, pathpart := range pathparts {
-			vals := rValuesAtPath(v, pathpart, create, caseSensitive)
-			if vals != nil && len(vals) > 0 {
+			vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
+			if len(vals) > 0 {
 				return vals
 				return vals
 			}
 			}
 		}
 		}
@@ -74,7 +76,16 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
 				return false
 				return false
 			})
 			})
 
 
-			if create && value.Kind() == reflect.Ptr && value.IsNil() {
+			if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
+				if !value.IsNil() {
+					value.Set(reflect.Zero(value.Type()))
+				}
+				return []reflect.Value{value}
+			}
+
+			if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
+				// TODO if the value is the terminus it should not be created
+				// if the value to be set to its position is nil.
 				value.Set(reflect.New(value.Type().Elem()))
 				value.Set(reflect.New(value.Type().Elem()))
 				value = value.Elem()
 				value = value.Elem()
 			} else {
 			} else {
@@ -82,7 +93,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
 			}
 			}
 
 
 			if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
 			if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
-				if !create && value.IsNil() {
+				if !createPath && value.IsNil() {
 					value = reflect.ValueOf(nil)
 					value = reflect.ValueOf(nil)
 				}
 				}
 			}
 			}
@@ -114,7 +125,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
 				// pull out index
 				// pull out index
 				i := int(*index)
 				i := int(*index)
 				if i >= value.Len() { // check out of bounds
 				if i >= value.Len() { // check out of bounds
-					if create {
+					if createPath {
 						// TODO resize slice
 						// TODO resize slice
 					} else {
 					} else {
 						continue
 						continue
@@ -125,7 +136,7 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
 				value = reflect.Indirect(value.Index(i))
 				value = reflect.Indirect(value.Index(i))
 
 
 				if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
 				if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
-					if !create && value.IsNil() {
+					if !createPath && value.IsNil() {
 						value = reflect.ValueOf(nil)
 						value = reflect.ValueOf(nil)
 					}
 					}
 				}
 				}
@@ -142,46 +153,70 @@ func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool)
 	return values
 	return values
 }
 }
 
 
-// ValuesAtPath returns a list of objects at the lexical path inside of a structure
-func ValuesAtPath(i interface{}, path string) []interface{} {
-	if rvals := rValuesAtPath(i, path, false, true); rvals != nil {
-		vals := make([]interface{}, len(rvals))
-		for i, rval := range rvals {
-			vals[i] = rval.Interface()
-		}
-		return vals
+// ValuesAtPath returns a list of values at the case insensitive lexical
+// path inside of a structure.
+func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
+	result, err := jmespath.Search(path, i)
+	if err != nil {
+		return nil, err
 	}
 	}
-	return nil
-}
 
 
-// ValuesAtAnyPath returns a list of objects at the case-insensitive lexical
-// path inside of a structure
-func ValuesAtAnyPath(i interface{}, path string) []interface{} {
-	if rvals := rValuesAtPath(i, path, false, false); rvals != nil {
-		vals := make([]interface{}, len(rvals))
-		for i, rval := range rvals {
-			vals[i] = rval.Interface()
+	v := reflect.ValueOf(result)
+	if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
+		return nil, nil
+	}
+	if s, ok := result.([]interface{}); ok {
+		return s, err
+	}
+	if v.Kind() == reflect.Map && v.Len() == 0 {
+		return nil, nil
+	}
+	if v.Kind() == reflect.Slice {
+		out := make([]interface{}, v.Len())
+		for i := 0; i < v.Len(); i++ {
+			out[i] = v.Index(i).Interface()
 		}
 		}
-		return vals
+		return out, nil
 	}
 	}
-	return nil
+
+	return []interface{}{result}, nil
 }
 }
 
 
-// SetValueAtPath sets an object at the lexical path inside of a structure
+// SetValueAtPath sets a value at the case insensitive lexical path inside
+// of a structure.
 func SetValueAtPath(i interface{}, path string, v interface{}) {
 func SetValueAtPath(i interface{}, path string, v interface{}) {
-	if rvals := rValuesAtPath(i, path, true, true); rvals != nil {
+	if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
 		for _, rval := range rvals {
 		for _, rval := range rvals {
-			rval.Set(reflect.ValueOf(v))
+			if rval.Kind() == reflect.Ptr && rval.IsNil() {
+				continue
+			}
+			setValue(rval, v)
 		}
 		}
 	}
 	}
 }
 }
 
 
-// SetValueAtAnyPath sets an object at the case insensitive lexical path inside
-// of a structure
-func SetValueAtAnyPath(i interface{}, path string, v interface{}) {
-	if rvals := rValuesAtPath(i, path, true, false); rvals != nil {
-		for _, rval := range rvals {
-			rval.Set(reflect.ValueOf(v))
+func setValue(dstVal reflect.Value, src interface{}) {
+	if dstVal.Kind() == reflect.Ptr {
+		dstVal = reflect.Indirect(dstVal)
+	}
+	srcVal := reflect.ValueOf(src)
+
+	if !srcVal.IsValid() { // src is literal nil
+		if dstVal.CanAddr() {
+			// Convert to pointer so that pointer's value can be nil'ed
+			//                     dstVal = dstVal.Addr()
+		}
+		dstVal.Set(reflect.Zero(dstVal.Type()))
+
+	} else if srcVal.Kind() == reflect.Ptr {
+		if srcVal.IsNil() {
+			srcVal = reflect.Zero(dstVal.Type())
+		} else {
+			srcVal = reflect.ValueOf(src).Elem()
 		}
 		}
+		dstVal.Set(srcVal)
+	} else {
+		dstVal.Set(srcVal)
 	}
 	}
+
 }
 }

+ 95 - 21
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go

@@ -13,6 +13,7 @@ type Struct struct {
 	B *Struct
 	B *Struct
 	D *Struct
 	D *Struct
 	C string
 	C string
+	E map[string]string
 }
 }
 
 
 var data = Struct{
 var data = Struct{
@@ -21,30 +22,69 @@ var data = Struct{
 	B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
 	B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
 	C: "initial",
 	C: "initial",
 }
 }
+var data2 = Struct{A: []Struct{
+	{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
+	{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
+}}
 
 
 func TestValueAtPathSuccess(t *testing.T) {
 func TestValueAtPathSuccess(t *testing.T) {
-	assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "C"))
-	assert.Equal(t, []interface{}{"value1"}, awsutil.ValuesAtPath(data, "A[0].C"))
-	assert.Equal(t, []interface{}{"value2"}, awsutil.ValuesAtPath(data, "A[1].C"))
-	assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[2].C"))
-	assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtAnyPath(data, "a[2].c"))
-	assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[-1].C"))
-	assert.Equal(t, []interface{}{"value1", "value2", "value3"}, awsutil.ValuesAtPath(data, "A[].C"))
-	assert.Equal(t, []interface{}{"terminal"}, awsutil.ValuesAtPath(data, "B . B . C"))
-	assert.Equal(t, []interface{}{"terminal", "terminal2"}, awsutil.ValuesAtPath(data, "B.*.C"))
-	assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "A.D.X || C"))
+	var testCases = []struct {
+		expect []interface{}
+		data   interface{}
+		path   string
+	}{
+		{[]interface{}{"initial"}, data, "C"},
+		{[]interface{}{"value1"}, data, "A[0].C"},
+		{[]interface{}{"value2"}, data, "A[1].C"},
+		{[]interface{}{"value3"}, data, "A[2].C"},
+		{[]interface{}{"value3"}, data, "a[2].c"},
+		{[]interface{}{"value3"}, data, "A[-1].C"},
+		{[]interface{}{"value1", "value2", "value3"}, data, "A[].C"},
+		{[]interface{}{"terminal"}, data, "B . B . C"},
+		{[]interface{}{"initial"}, data, "A.D.X || C"},
+		{[]interface{}{"initial"}, data, "A[0].B || C"},
+		{[]interface{}{
+			Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
+			Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
+		}, data2, "A"},
+	}
+	for i, c := range testCases {
+		v, err := awsutil.ValuesAtPath(c.data, c.path)
+		assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
+		assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
+	}
 }
 }
 
 
 func TestValueAtPathFailure(t *testing.T) {
 func TestValueAtPathFailure(t *testing.T) {
-	assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "C.x"))
-	assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, ".x"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "X.Y.Z"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[100].C"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[3].C"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "B.B.C.Z"))
-	assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "z[-1].C"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(nil, "A.B.C"))
-	assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(Struct{}, "A"))
+	var testCases = []struct {
+		expect      []interface{}
+		errContains string
+		data        interface{}
+		path        string
+	}{
+		{nil, "", data, "C.x"},
+		{nil, "SyntaxError: Invalid token: tDot", data, ".x"},
+		{nil, "", data, "X.Y.Z"},
+		{nil, "", data, "A[100].C"},
+		{nil, "", data, "A[3].C"},
+		{nil, "", data, "B.B.C.Z"},
+		{nil, "", data, "z[-1].C"},
+		{nil, "", nil, "A.B.C"},
+		{[]interface{}{}, "", Struct{}, "A"},
+		{nil, "", data, "A[0].B.C"},
+		{nil, "", data, "D"},
+	}
+
+	for i, c := range testCases {
+		v, err := awsutil.ValuesAtPath(c.data, c.path)
+		if c.errContains != "" {
+			assert.Contains(t, err.Error(), c.errContains, "case %d, expected error, %s", i, c.path)
+			continue
+		} else {
+			assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
+		}
+		assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
+	}
 }
 }
 
 
 func TestSetValueAtPathSuccess(t *testing.T) {
 func TestSetValueAtPathSuccess(t *testing.T) {
@@ -61,8 +101,42 @@ func TestSetValueAtPathSuccess(t *testing.T) {
 	assert.Equal(t, "test0", s.B.D.C)
 	assert.Equal(t, "test0", s.B.D.C)
 
 
 	var s2 Struct
 	var s2 Struct
-	awsutil.SetValueAtAnyPath(&s2, "b.b.c", "test0")
+	awsutil.SetValueAtPath(&s2, "b.b.c", "test0")
 	assert.Equal(t, "test0", s2.B.B.C)
 	assert.Equal(t, "test0", s2.B.B.C)
-	awsutil.SetValueAtAnyPath(&s2, "A", []Struct{{}})
+	awsutil.SetValueAtPath(&s2, "A", []Struct{{}})
 	assert.Equal(t, []Struct{{}}, s2.A)
 	assert.Equal(t, []Struct{{}}, s2.A)
+
+	str := "foo"
+
+	s3 := Struct{}
+	awsutil.SetValueAtPath(&s3, "b.b.c", str)
+	assert.Equal(t, "foo", s3.B.B.C)
+
+	s3 = Struct{B: &Struct{B: &Struct{C: str}}}
+	awsutil.SetValueAtPath(&s3, "b.b.c", nil)
+	assert.Equal(t, "", s3.B.B.C)
+
+	s3 = Struct{}
+	awsutil.SetValueAtPath(&s3, "b.b.c", nil)
+	assert.Equal(t, "", s3.B.B.C)
+
+	s3 = Struct{}
+	awsutil.SetValueAtPath(&s3, "b.b.c", &str)
+	assert.Equal(t, "foo", s3.B.B.C)
+
+	var s4 struct{ Name *string }
+	awsutil.SetValueAtPath(&s4, "Name", str)
+	assert.Equal(t, str, *s4.Name)
+
+	s4 = struct{ Name *string }{}
+	awsutil.SetValueAtPath(&s4, "Name", nil)
+	assert.Equal(t, (*string)(nil), s4.Name)
+
+	s4 = struct{ Name *string }{Name: &str}
+	awsutil.SetValueAtPath(&s4, "Name", nil)
+	assert.Equal(t, (*string)(nil), s4.Name)
+
+	s4 = struct{ Name *string }{}
+	awsutil.SetValueAtPath(&s4, "Name", &str)
+	assert.Equal(t, str, *s4.Name)
 }
 }

+ 89 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go

@@ -0,0 +1,89 @@
+package awsutil
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strings"
+)
+
+// StringValue returns the string representation of a value.
+func StringValue(i interface{}) string {
+	var buf bytes.Buffer
+	stringValue(reflect.ValueOf(i), 0, &buf)
+	return buf.String()
+}
+
+func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
+	for v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	switch v.Kind() {
+	case reflect.Struct:
+		buf.WriteString("{\n")
+
+		names := []string{}
+		for i := 0; i < v.Type().NumField(); i++ {
+			name := v.Type().Field(i).Name
+			f := v.Field(i)
+			if name[0:1] == strings.ToLower(name[0:1]) {
+				continue // ignore unexported fields
+			}
+			if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice) && f.IsNil() {
+				continue // ignore unset fields
+			}
+			names = append(names, name)
+		}
+
+		for i, n := range names {
+			val := v.FieldByName(n)
+			buf.WriteString(strings.Repeat(" ", indent+2))
+			buf.WriteString(n + ": ")
+			stringValue(val, indent+2, buf)
+
+			if i < len(names)-1 {
+				buf.WriteString(",\n")
+			}
+		}
+
+		buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
+	case reflect.Slice:
+		nl, id, id2 := "", "", ""
+		if v.Len() > 3 {
+			nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
+		}
+		buf.WriteString("[" + nl)
+		for i := 0; i < v.Len(); i++ {
+			buf.WriteString(id2)
+			stringValue(v.Index(i), indent+2, buf)
+
+			if i < v.Len()-1 {
+				buf.WriteString("," + nl)
+			}
+		}
+
+		buf.WriteString(nl + id + "]")
+	case reflect.Map:
+		buf.WriteString("{\n")
+
+		for i, k := range v.MapKeys() {
+			buf.WriteString(strings.Repeat(" ", indent+2))
+			buf.WriteString(k.String() + ": ")
+			stringValue(v.MapIndex(k), indent+2, buf)
+
+			if i < v.Len()-1 {
+				buf.WriteString(",\n")
+			}
+		}
+
+		buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
+	default:
+		format := "%v"
+		switch v.Interface().(type) {
+		case string:
+			format = "%q"
+		}
+		fmt.Fprintf(buf, format, v.Interface())
+	}
+}

+ 120 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go

@@ -0,0 +1,120 @@
+package client
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http/httputil"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
+	"github.com/aws/aws-sdk-go/aws/request"
+)
+
+// A Config provides configuration to a service client instance.
+type Config struct {
+	Config                  *aws.Config
+	Handlers                request.Handlers
+	Endpoint, SigningRegion string
+}
+
+// ConfigProvider provides a generic way for a service client to receive
+// the ClientConfig without circular dependencies.
+type ConfigProvider interface {
+	ClientConfig(serviceName string, cfgs ...*aws.Config) Config
+}
+
+// A Client implements the base client request and response handling
+// used by all service clients.
+type Client struct {
+	request.Retryer
+	metadata.ClientInfo
+
+	Config   aws.Config
+	Handlers request.Handlers
+}
+
+// New will return a pointer to a new initialized service client.
+func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
+	svc := &Client{
+		Config:     cfg,
+		ClientInfo: info,
+		Handlers:   handlers,
+	}
+
+	switch retryer, ok := cfg.Retryer.(request.Retryer); {
+	case ok:
+		svc.Retryer = retryer
+	case cfg.Retryer != nil && cfg.Logger != nil:
+		s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
+		cfg.Logger.Log(s)
+		fallthrough
+	default:
+		maxRetries := aws.IntValue(cfg.MaxRetries)
+		if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
+			maxRetries = 3
+		}
+		svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
+	}
+
+	svc.AddDebugHandlers()
+
+	for _, option := range options {
+		option(svc)
+	}
+
+	return svc
+}
+
+// NewRequest returns a new Request pointer for the service API
+// operation and parameters.
+func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
+	return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
+}
+
+// AddDebugHandlers injects debug logging handlers into the service to log request
+// debug information.
+func (c *Client) AddDebugHandlers() {
+	if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
+		return
+	}
+
+	c.Handlers.Send.PushFront(logRequest)
+	c.Handlers.Send.PushBack(logResponse)
+}
+
+const logReqMsg = `DEBUG: Request %s/%s Details:
+---[ REQUEST POST-SIGN ]-----------------------------
+%s
+-----------------------------------------------------`
+
+func logRequest(r *request.Request) {
+	logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
+	dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
+
+	if logBody {
+		// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
+		// Body as a NoOpCloser and will not be reset after read by the HTTP
+		// client reader.
+		r.Body.Seek(r.BodyStart, 0)
+		r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
+	}
+
+	r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
+}
+
+const logRespMsg = `DEBUG: Response %s/%s Details:
+---[ RESPONSE ]--------------------------------------
+%s
+-----------------------------------------------------`
+
+func logResponse(r *request.Request) {
+	var msg = "no reponse data"
+	if r.HTTPResponse != nil {
+		logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
+		dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
+		msg = string(dumpedBody)
+	} else if r.Error != nil {
+		msg = r.Error.Error()
+	}
+	r.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.ClientInfo.ServiceName, r.Operation.Name, msg))
+}

+ 4 - 8
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/default_retryer.go → Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go

@@ -1,11 +1,10 @@
-package service
+package client
 
 
 import (
 import (
 	"math"
 	"math"
 	"math/rand"
 	"math/rand"
 	"time"
 	"time"
 
 
-	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
 )
 )
 
 
@@ -22,16 +21,13 @@ import (
 //    // This implementation always has 100 max retries
 //    // This implementation always has 100 max retries
 //    func (d retryer) MaxRetries() uint { return 100 }
 //    func (d retryer) MaxRetries() uint { return 100 }
 type DefaultRetryer struct {
 type DefaultRetryer struct {
-	*Service
+	NumMaxRetries int
 }
 }
 
 
 // MaxRetries returns the number of maximum returns the service will use to make
 // MaxRetries returns the number of maximum returns the service will use to make
 // an individual API request.
 // an individual API request.
-func (d DefaultRetryer) MaxRetries() uint {
-	if aws.IntValue(d.Service.Config.MaxRetries) < 0 {
-		return d.DefaultMaxRetries
-	}
-	return uint(aws.IntValue(d.Service.Config.MaxRetries))
+func (d DefaultRetryer) MaxRetries() int {
+	return d.NumMaxRetries
 }
 }
 
 
 // RetryRules returns the delay duration before retrying this request again
 // RetryRules returns the delay duration before retrying this request again

+ 12 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go

@@ -0,0 +1,12 @@
+package metadata
+
+// ClientInfo wraps immutable data from the client.Client structure.
+type ClientInfo struct {
+	ServiceName   string
+	APIVersion    string
+	Endpoint      string
+	SigningName   string
+	SigningRegion string
+	JSONVersion   string
+	TargetPrefix  string
+}

+ 48 - 17
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go

@@ -7,15 +7,20 @@ import (
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 )
 )
 
 
-// DefaultRetries is the default number of retries for a service. The value of
-// -1 indicates that the service specific retry default will be used.
-const DefaultRetries = -1
+// UseServiceDefaultRetries instructs the config to use the service's own default
+// number of retries. This will be the default action if Config.MaxRetries
+// is nil also.
+const UseServiceDefaultRetries = -1
+
+// RequestRetryer is an alias for a type that implements the request.Retryer interface.
+type RequestRetryer interface{}
 
 
 // A Config provides service configuration for service clients. By default,
 // A Config provides service configuration for service clients. By default,
 // all clients will use the {defaults.DefaultConfig} structure.
 // all clients will use the {defaults.DefaultConfig} structure.
 type Config struct {
 type Config struct {
 	// The credentials object to use when signing requests. Defaults to
 	// The credentials object to use when signing requests. Defaults to
-	// {defaults.DefaultChainCredentials}.
+	// a chain of credential providers to search for credentials in environment
+	// variables, shared credential file, and EC2 Instance Roles.
 	Credentials *credentials.Credentials
 	Credentials *credentials.Credentials
 
 
 	// An optional endpoint URL (hostname only or fully qualified URI)
 	// An optional endpoint URL (hostname only or fully qualified URI)
@@ -57,6 +62,21 @@ type Config struct {
 	// configuration.
 	// configuration.
 	MaxRetries *int
 	MaxRetries *int
 
 
+	// Retryer guides how HTTP requests should be retried in case of recoverable failures.
+	//
+	// When nil or the value does not implement the request.Retryer interface,
+	// the request.DefaultRetryer will be used.
+	//
+	// When both Retryer and MaxRetries are non-nil, the former is used and
+	// the latter ignored.
+	//
+	// To set the Retryer field in a type-safe manner and with chaining, use
+	// the request.WithRetryer helper function:
+	//
+	//   cfg := request.WithRetryer(aws.NewConfig(), myRetryer)
+	//
+	Retryer RequestRetryer
+
 	// Disables semantic parameter validation, which validates input for missing
 	// Disables semantic parameter validation, which validates input for missing
 	// required fields and/or other semantic request input errors.
 	// required fields and/or other semantic request input errors.
 	DisableParamValidation *bool
 	DisableParamValidation *bool
@@ -171,15 +191,17 @@ func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
 	return c
 	return c
 }
 }
 
 
-// Merge returns a new Config with the other Config's attribute values merged into
-// this Config. If the other Config's attribute is nil it will not be merged into
-// the new Config to be returned.
-func (c Config) Merge(other *Config) *Config {
-	if other == nil {
-		return &c
+// MergeIn merges the passed in configs into the existing config object.
+func (c *Config) MergeIn(cfgs ...*Config) {
+	for _, other := range cfgs {
+		mergeInConfig(c, other)
 	}
 	}
+}
 
 
-	dst := c
+func mergeInConfig(dst *Config, other *Config) {
+	if other == nil {
+		return
+	}
 
 
 	if other.Credentials != nil {
 	if other.Credentials != nil {
 		dst.Credentials = other.Credentials
 		dst.Credentials = other.Credentials
@@ -213,6 +235,10 @@ func (c Config) Merge(other *Config) *Config {
 		dst.MaxRetries = other.MaxRetries
 		dst.MaxRetries = other.MaxRetries
 	}
 	}
 
 
+	if other.Retryer != nil {
+		dst.Retryer = other.Retryer
+	}
+
 	if other.DisableParamValidation != nil {
 	if other.DisableParamValidation != nil {
 		dst.DisableParamValidation = other.DisableParamValidation
 		dst.DisableParamValidation = other.DisableParamValidation
 	}
 	}
@@ -228,12 +254,17 @@ func (c Config) Merge(other *Config) *Config {
 	if other.SleepDelay != nil {
 	if other.SleepDelay != nil {
 		dst.SleepDelay = other.SleepDelay
 		dst.SleepDelay = other.SleepDelay
 	}
 	}
-
-	return &dst
 }
 }
 
 
-// Copy will return a shallow copy of the Config object.
-func (c Config) Copy() *Config {
-	dst := c
-	return &dst
+// Copy will return a shallow copy of the Config object. If any additional
+// configurations are provided they will be merged into the new config returned.
+func (c *Config) Copy(cfgs ...*Config) *Config {
+	dst := &Config{}
+	dst.MergeIn(c)
+
+	for _, cfg := range cfgs {
+		dst.MergeIn(cfg)
+	}
+
+	return dst
 }
 }

+ 8 - 2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go

@@ -18,7 +18,7 @@ var copyTestConfig = Config{
 	HTTPClient:              http.DefaultClient,
 	HTTPClient:              http.DefaultClient,
 	LogLevel:                LogLevel(LogDebug),
 	LogLevel:                LogLevel(LogDebug),
 	Logger:                  NewDefaultLogger(),
 	Logger:                  NewDefaultLogger(),
-	MaxRetries:              Int(DefaultRetries),
+	MaxRetries:              Int(3),
 	DisableParamValidation:  Bool(true),
 	DisableParamValidation:  Bool(true),
 	DisableComputeChecksums: Bool(true),
 	DisableComputeChecksums: Bool(true),
 	S3ForcePathStyle:        Bool(true),
 	S3ForcePathStyle:        Bool(true),
@@ -31,6 +31,11 @@ func TestCopy(t *testing.T) {
 		t.Errorf("Copy() = %+v", got)
 		t.Errorf("Copy() = %+v", got)
 		t.Errorf("    want %+v", want)
 		t.Errorf("    want %+v", want)
 	}
 	}
+
+	got.Region = String("other")
+	if got.Region == want.Region {
+		t.Errorf("Expect setting copy values not not reflect in source")
+	}
 }
 }
 
 
 func TestCopyReturnsNewInstance(t *testing.T) {
 func TestCopyReturnsNewInstance(t *testing.T) {
@@ -69,7 +74,8 @@ var mergeTests = []struct {
 
 
 func TestMerge(t *testing.T) {
 func TestMerge(t *testing.T) {
 	for i, tt := range mergeTests {
 	for i, tt := range mergeTests {
-		got := tt.cfg.Merge(tt.in)
+		got := tt.cfg.Copy()
+		got.MergeIn(tt.in)
 		if !reflect.DeepEqual(got, tt.want) {
 		if !reflect.DeepEqual(got, tt.want) {
 			t.Errorf("Config %d %+v", i, tt.cfg)
 			t.Errorf("Config %d %+v", i, tt.cfg)
 			t.Errorf("   Merge(%+v)", tt.in)
 			t.Errorf("   Merge(%+v)", tt.in)

+ 17 - 14
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go

@@ -8,6 +8,7 @@ import (
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
 	"regexp"
 	"regexp"
+	"runtime"
 	"strconv"
 	"strconv"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
@@ -23,7 +24,7 @@ type lener interface {
 // BuildContentLengthHandler builds the content length of a request based on the body,
 // BuildContentLengthHandler builds the content length of a request based on the body,
 // or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
 // or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
 // to determine request body length and no "Content-Length" was specified it will panic.
 // to determine request body length and no "Content-Length" was specified it will panic.
-var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) {
+var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) {
 	if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
 	if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
 		length, _ := strconv.ParseInt(slength, 10, 64)
 		length, _ := strconv.ParseInt(slength, 10, 64)
 		r.HTTPRequest.ContentLength = length
 		r.HTTPRequest.ContentLength = length
@@ -49,17 +50,19 @@ var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHan
 	r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
 	r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
 }}
 }}
 
 
-// UserAgentHandler is a request handler for injecting User agent into requests.
-var UserAgentHandler = request.NamedHandler{"core.UserAgentHandler", func(r *request.Request) {
-	r.HTTPRequest.Header.Set("User-Agent", aws.SDKName+"/"+aws.SDKVersion)
-}}
+// SDKVersionUserAgentHandler is a request handler for adding the SDK Version to the user agent.
+var SDKVersionUserAgentHandler = request.NamedHandler{
+	Name: "core.SDKVersionUserAgentHandler",
+	Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion,
+		runtime.Version(), runtime.GOOS, runtime.GOARCH),
+}
 
 
 var reStatusCode = regexp.MustCompile(`^(\d{3})`)
 var reStatusCode = regexp.MustCompile(`^(\d{3})`)
 
 
 // SendHandler is a request handler to send service request using HTTP client.
 // SendHandler is a request handler to send service request using HTTP client.
-var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Request) {
+var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) {
 	var err error
 	var err error
-	r.HTTPResponse, err = r.Service.Config.HTTPClient.Do(r.HTTPRequest)
+	r.HTTPResponse, err = r.Config.HTTPClient.Do(r.HTTPRequest)
 	if err != nil {
 	if err != nil {
 		// Capture the case where url.Error is returned for error processing
 		// Capture the case where url.Error is returned for error processing
 		// response. e.g. 301 without location header comes back as string
 		// response. e.g. 301 without location header comes back as string
@@ -92,7 +95,7 @@ var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Reque
 }}
 }}
 
 
 // ValidateResponseHandler is a request handler to validate service response.
 // ValidateResponseHandler is a request handler to validate service response.
-var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) {
+var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) {
 	if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
 	if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
 		// this may be replaced by an UnmarshalError handler
 		// this may be replaced by an UnmarshalError handler
 		r.Error = awserr.New("UnknownError", "unknown error", nil)
 		r.Error = awserr.New("UnknownError", "unknown error", nil)
@@ -101,7 +104,7 @@ var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler
 
 
 // AfterRetryHandler performs final checks to determine if the request should
 // AfterRetryHandler performs final checks to determine if the request should
 // be retried and how long to delay.
 // be retried and how long to delay.
-var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) {
+var AfterRetryHandler = request.NamedHandler{Name: "core.AfterRetryHandler", Fn: func(r *request.Request) {
 	// If one of the other handlers already set the retry state
 	// If one of the other handlers already set the retry state
 	// we don't want to override it based on the service's state
 	// we don't want to override it based on the service's state
 	if r.Retryable == nil {
 	if r.Retryable == nil {
@@ -110,13 +113,13 @@ var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *r
 
 
 	if r.WillRetry() {
 	if r.WillRetry() {
 		r.RetryDelay = r.RetryRules(r)
 		r.RetryDelay = r.RetryRules(r)
-		r.Service.Config.SleepDelay(r.RetryDelay)
+		r.Config.SleepDelay(r.RetryDelay)
 
 
 		// when the expired token exception occurs the credentials
 		// when the expired token exception occurs the credentials
 		// need to be expired locally so that the next request to
 		// need to be expired locally so that the next request to
 		// get credentials will trigger a credentials refresh.
 		// get credentials will trigger a credentials refresh.
 		if r.IsErrorExpired() {
 		if r.IsErrorExpired() {
-			r.Service.Config.Credentials.Expire()
+			r.Config.Credentials.Expire()
 		}
 		}
 
 
 		r.RetryCount++
 		r.RetryCount++
@@ -127,10 +130,10 @@ var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *r
 // ValidateEndpointHandler is a request handler to validate a request had the
 // ValidateEndpointHandler is a request handler to validate a request had the
 // appropriate Region and Endpoint set. Will set r.Error if the endpoint or
 // appropriate Region and Endpoint set. Will set r.Error if the endpoint or
 // region is not valid.
 // region is not valid.
-var ValidateEndpointHandler = request.NamedHandler{"core.ValidateEndpointHandler", func(r *request.Request) {
-	if r.Service.SigningRegion == "" && aws.StringValue(r.Service.Config.Region) == "" {
+var ValidateEndpointHandler = request.NamedHandler{Name: "core.ValidateEndpointHandler", Fn: func(r *request.Request) {
+	if r.ClientInfo.SigningRegion == "" && aws.StringValue(r.Config.Region) == "" {
 		r.Error = aws.ErrMissingRegion
 		r.Error = aws.ErrMissingRegion
-	} else if r.Service.Endpoint == "" {
+	} else if r.ClientInfo.Endpoint == "" {
 		r.Error = aws.ErrMissingEndpoint
 		r.Error = aws.ErrMissingEndpoint
 	}
 	}
 }}
 }}

+ 11 - 5
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go

@@ -13,12 +13,13 @@ import (
 	"github.com/aws/aws-sdk-go/aws/corehandlers"
 	"github.com/aws/aws-sdk-go/aws/corehandlers"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
+	"github.com/aws/aws-sdk-go/awstesting"
 )
 )
 
 
 func TestValidateEndpointHandler(t *testing.T) {
 func TestValidateEndpointHandler(t *testing.T) {
 	os.Clearenv()
 	os.Clearenv()
-	svc := service.New(aws.NewConfig().WithRegion("us-west-2"))
+
+	svc := awstesting.NewClient(aws.NewConfig().WithRegion("us-west-2"))
 	svc.Handlers.Clear()
 	svc.Handlers.Clear()
 	svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
 	svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
 
 
@@ -30,7 +31,8 @@ func TestValidateEndpointHandler(t *testing.T) {
 
 
 func TestValidateEndpointHandlerErrorRegion(t *testing.T) {
 func TestValidateEndpointHandlerErrorRegion(t *testing.T) {
 	os.Clearenv()
 	os.Clearenv()
-	svc := service.New(nil)
+
+	svc := awstesting.NewClient()
 	svc.Handlers.Clear()
 	svc.Handlers.Clear()
 	svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
 	svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
 
 
@@ -58,7 +60,11 @@ func (m *mockCredsProvider) IsExpired() bool {
 func TestAfterRetryRefreshCreds(t *testing.T) {
 func TestAfterRetryRefreshCreds(t *testing.T) {
 	os.Clearenv()
 	os.Clearenv()
 	credProvider := &mockCredsProvider{}
 	credProvider := &mockCredsProvider{}
-	svc := service.New(&aws.Config{Credentials: credentials.NewCredentials(credProvider), MaxRetries: aws.Int(1)})
+
+	svc := awstesting.NewClient(&aws.Config{
+		Credentials: credentials.NewCredentials(credProvider),
+		MaxRetries:  aws.Int(1),
+	})
 
 
 	svc.Handlers.Clear()
 	svc.Handlers.Clear()
 	svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) {
 	svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) {
@@ -91,7 +97,7 @@ func (t *testSendHandlerTransport) RoundTrip(r *http.Request) (*http.Response, e
 }
 }
 
 
 func TestSendHandlerError(t *testing.T) {
 func TestSendHandlerError(t *testing.T) {
-	svc := service.New(&aws.Config{
+	svc := awstesting.NewClient(&aws.Config{
 		HTTPClient: &http.Client{
 		HTTPClient: &http.Client{
 			Transport: &testSendHandlerTransport{},
 			Transport: &testSendHandlerTransport{},
 		},
 		},

+ 1 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go

@@ -12,7 +12,7 @@ import (
 
 
 // ValidateParametersHandler is a request handler to validate the input parameters.
 // ValidateParametersHandler is a request handler to validate the input parameters.
 // Validating parameters only has meaning if done prior to the request being sent.
 // Validating parameters only has meaning if done prior to the request being sent.
-var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) {
+var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) {
 	if r.ParamsFilled() {
 	if r.ParamsFilled() {
 		v := validator{errors: []string{}}
 		v := validator{errors: []string{}}
 		v.validateAny(reflect.ValueOf(r.Params), "")
 		v.validateAny(reflect.ValueOf(r.Params), "")

+ 6 - 6
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go

@@ -7,17 +7,17 @@ import (
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/corehandlers"
 	"github.com/aws/aws-sdk-go/aws/corehandlers"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
 	"github.com/stretchr/testify/require"
 	"github.com/stretchr/testify/require"
 )
 )
 
 
-var testSvc = func() *service.Service {
-	s := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      &aws.Config{},
+var testSvc = func() *client.Client {
+	s := &client.Client{
+		Config: aws.Config{},
+		ClientInfo: metadata.ClientInfo{
 			ServiceName: "mock-service",
 			ServiceName: "mock-service",
 			APIVersion:  "2015-01-01",
 			APIVersion:  "2015-01-01",
 		},
 		},

+ 34 - 29
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go

@@ -9,6 +9,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/aws/client"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 )
 )
@@ -25,9 +26,6 @@ import (
 //         Client: &http.Client{
 //         Client: &http.Client{
 //             Timeout: 10 * time.Second,
 //             Timeout: 10 * time.Second,
 //         },
 //         },
-//         // Use default EC2 Role metadata endpoint, Alternate endpoints can be
-//         // specified setting Endpoint to something else.
-//         Endpoint: "",
 //         // Do not use early expiry of credentials. If a non zero value is
 //         // Do not use early expiry of credentials. If a non zero value is
 //         // specified the credentials will be expired early
 //         // specified the credentials will be expired early
 //         ExpiryWindow: 0,
 //         ExpiryWindow: 0,
@@ -35,8 +33,8 @@ import (
 type EC2RoleProvider struct {
 type EC2RoleProvider struct {
 	credentials.Expiry
 	credentials.Expiry
 
 
-	// EC2Metadata client to use when connecting to EC2 metadata service
-	Client *ec2metadata.Client
+	// Required EC2Metadata client to use when connecting to EC2 metadata service.
+	Client *ec2metadata.EC2Metadata
 
 
 	// ExpiryWindow will allow the credentials to trigger refreshing prior to
 	// ExpiryWindow will allow the credentials to trigger refreshing prior to
 	// the credentials actually expiring. This is beneficial so race conditions
 	// the credentials actually expiring. This is beneficial so race conditions
@@ -50,33 +48,40 @@ type EC2RoleProvider struct {
 	ExpiryWindow time.Duration
 	ExpiryWindow time.Duration
 }
 }
 
 
-// NewCredentials returns a pointer to a new Credentials object
-// wrapping the EC2RoleProvider.
-//
-// Takes a custom http.Client which can be configured for custom handling of
-// things such as timeout.
-//
-// Endpoint is the URL that the EC2RoleProvider will connect to when retrieving
-// role and credentials.
-//
-// Window is the expiry window that will be subtracted from the expiry returned
-// by the role credential request. This is done so that the credentials will
-// expire sooner than their actual lifespan.
-func NewCredentials(client *ec2metadata.Client, window time.Duration) *credentials.Credentials {
-	return credentials.NewCredentials(&EC2RoleProvider{
-		Client:       client,
-		ExpiryWindow: window,
-	})
+// NewCredentials returns a pointer to a new Credentials object wrapping
+// the EC2RoleProvider. Takes a ConfigProvider to create a EC2Metadata client.
+// The ConfigProvider is satisfied by the session.Session type.
+func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials {
+	p := &EC2RoleProvider{
+		Client: ec2metadata.New(c),
+	}
+
+	for _, option := range options {
+		option(p)
+	}
+
+	return credentials.NewCredentials(p)
+}
+
+// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping
+// the EC2RoleProvider. Takes a EC2Metadata client to use when connecting to EC2
+// metadata service.
+func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*EC2RoleProvider)) *credentials.Credentials {
+	p := &EC2RoleProvider{
+		Client: client,
+	}
+
+	for _, option := range options {
+		option(p)
+	}
+
+	return credentials.NewCredentials(p)
 }
 }
 
 
 // Retrieve retrieves credentials from the EC2 service.
 // Retrieve retrieves credentials from the EC2 service.
 // Error will be returned if the request fails, or unable to extract
 // Error will be returned if the request fails, or unable to extract
 // the desired credentials.
 // the desired credentials.
 func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
 func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
-	if m.Client == nil {
-		m.Client = ec2metadata.New(nil)
-	}
-
 	credsList, err := requestCredList(m.Client)
 	credsList, err := requestCredList(m.Client)
 	if err != nil {
 	if err != nil {
 		return credentials.Value{}, err
 		return credentials.Value{}, err
@@ -101,7 +106,7 @@ func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
 	}, nil
 	}, nil
 }
 }
 
 
-// A ec2RoleCredRespBody provides the shape for deserializing credential
+// A ec2RoleCredRespBody provides the shape for unmarshalling credential
 // request responses.
 // request responses.
 type ec2RoleCredRespBody struct {
 type ec2RoleCredRespBody struct {
 	// Success State
 	// Success State
@@ -119,7 +124,7 @@ const iamSecurityCredsPath = "/iam/security-credentials"
 
 
 // requestCredList requests a list of credentials from the EC2 service.
 // requestCredList requests a list of credentials from the EC2 service.
 // If there are no credentials, or there is an error making or receiving the request
 // If there are no credentials, or there is an error making or receiving the request
-func requestCredList(client *ec2metadata.Client) ([]string, error) {
+func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) {
 	resp, err := client.GetMetadata(iamSecurityCredsPath)
 	resp, err := client.GetMetadata(iamSecurityCredsPath)
 	if err != nil {
 	if err != nil {
 		return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err)
 		return nil, awserr.New("EC2RoleRequestError", "failed to list EC2 Roles", err)
@@ -142,7 +147,7 @@ func requestCredList(client *ec2metadata.Client) ([]string, error) {
 //
 //
 // If the credentials cannot be found, or there is an error reading the response
 // If the credentials cannot be found, or there is an error reading the response
 // and error will be returned.
 // and error will be returned.
-func requestCred(client *ec2metadata.Client, credsName string) (ec2RoleCredRespBody, error) {
+func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
 	resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
 	resp, err := client.GetMetadata(path.Join(iamSecurityCredsPath, credsName))
 	if err != nil {
 	if err != nil {
 		return ec2RoleCredRespBody{},
 		return ec2RoleCredRespBody{},

+ 14 - 16
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go

@@ -13,6 +13,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
+	"github.com/aws/aws-sdk-go/aws/session"
 )
 )
 
 
 const credsRespTmpl = `{
 const credsRespTmpl = `{
@@ -54,11 +55,11 @@ func TestEC2RoleProvider(t *testing.T) {
 	defer server.Close()
 	defer server.Close()
 
 
 	p := &ec2rolecreds.EC2RoleProvider{
 	p := &ec2rolecreds.EC2RoleProvider{
-		Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}),
+		Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
 	}
 	}
 
 
 	creds, err := p.Retrieve()
 	creds, err := p.Retrieve()
-	assert.Nil(t, err, "Expect no error")
+	assert.Nil(t, err, "Expect no error, %v", err)
 
 
 	assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
 	assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
 	assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
 	assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
@@ -70,7 +71,7 @@ func TestEC2RoleProviderFailAssume(t *testing.T) {
 	defer server.Close()
 	defer server.Close()
 
 
 	p := &ec2rolecreds.EC2RoleProvider{
 	p := &ec2rolecreds.EC2RoleProvider{
-		Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}),
+		Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
 	}
 	}
 
 
 	creds, err := p.Retrieve()
 	creds, err := p.Retrieve()
@@ -91,7 +92,7 @@ func TestEC2RoleProviderIsExpired(t *testing.T) {
 	defer server.Close()
 	defer server.Close()
 
 
 	p := &ec2rolecreds.EC2RoleProvider{
 	p := &ec2rolecreds.EC2RoleProvider{
-		Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}),
+		Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
 	}
 	}
 	p.CurrentTime = func() time.Time {
 	p.CurrentTime = func() time.Time {
 		return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
 		return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC)
@@ -100,7 +101,7 @@ func TestEC2RoleProviderIsExpired(t *testing.T) {
 	assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
 	assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
 
 
 	_, err := p.Retrieve()
 	_, err := p.Retrieve()
-	assert.Nil(t, err, "Expect no error")
+	assert.Nil(t, err, "Expect no error, %v", err)
 
 
 	assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
 	assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
 
 
@@ -116,7 +117,7 @@ func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) {
 	defer server.Close()
 	defer server.Close()
 
 
 	p := &ec2rolecreds.EC2RoleProvider{
 	p := &ec2rolecreds.EC2RoleProvider{
-		Client:       ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}),
+		Client:       ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
 		ExpiryWindow: time.Hour * 1,
 		ExpiryWindow: time.Hour * 1,
 	}
 	}
 	p.CurrentTime = func() time.Time {
 	p.CurrentTime = func() time.Time {
@@ -126,7 +127,7 @@ func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) {
 	assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
 	assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.")
 
 
 	_, err := p.Retrieve()
 	_, err := p.Retrieve()
-	assert.Nil(t, err, "Expect no error")
+	assert.Nil(t, err, "Expect no error, %v", err)
 
 
 	assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
 	assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.")
 
 
@@ -137,12 +138,12 @@ func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) {
 	assert.True(t, p.IsExpired(), "Expect creds to be expired.")
 	assert.True(t, p.IsExpired(), "Expect creds to be expired.")
 }
 }
 
 
-func BenchmarkEC2RoleProvider(b *testing.B) {
+func BenchmarkEC3RoleProvider(b *testing.B) {
 	server := initTestServer("2014-12-16T01:51:37Z", false)
 	server := initTestServer("2014-12-16T01:51:37Z", false)
 	defer server.Close()
 	defer server.Close()
 
 
 	p := &ec2rolecreds.EC2RoleProvider{
 	p := &ec2rolecreds.EC2RoleProvider{
-		Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}),
+		Client: ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")}),
 	}
 	}
 	_, err := p.Retrieve()
 	_, err := p.Retrieve()
 	if err != nil {
 	if err != nil {
@@ -150,12 +151,9 @@ func BenchmarkEC2RoleProvider(b *testing.B) {
 	}
 	}
 
 
 	b.ResetTimer()
 	b.ResetTimer()
-	b.RunParallel(func(pb *testing.PB) {
-		for pb.Next() {
-			_, err := p.Retrieve()
-			if err != nil {
-				b.Fatal(err)
-			}
+	for i := 0; i < b.N; i++ {
+		if _, err := p.Retrieve(); err != nil {
+			b.Fatal(err)
 		}
 		}
-	})
+	}
 }
 }

+ 4 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/example.ini

@@ -6,3 +6,7 @@ aws_session_token = token
 [no_token]
 [no_token]
 aws_access_key_id = accessKey
 aws_access_key_id = accessKey
 aws_secret_access_key = secret
 aws_secret_access_key = secret
+
+[with_colon]
+aws_access_key_id: accessKey
+aws_secret_access_key: secret

+ 16 - 12
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go

@@ -5,7 +5,7 @@ import (
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
 
 
-	"github.com/vaughan0/go-ini"
+	"github.com/go-ini/ini"
 
 
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 )
 )
@@ -76,32 +76,36 @@ func (p *SharedCredentialsProvider) IsExpired() bool {
 // The credentials retrieved from the profile will be returned or error. Error will be
 // The credentials retrieved from the profile will be returned or error. Error will be
 // returned if it fails to read from the file, or the data is invalid.
 // returned if it fails to read from the file, or the data is invalid.
 func loadProfile(filename, profile string) (Value, error) {
 func loadProfile(filename, profile string) (Value, error) {
-	config, err := ini.LoadFile(filename)
+	config, err := ini.Load(filename)
 	if err != nil {
 	if err != nil {
 		return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
 		return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
 	}
 	}
-	iniProfile := config.Section(profile)
+	iniProfile, err := config.GetSection(profile)
+	if err != nil {
+		return Value{}, awserr.New("SharedCredsLoad", "failed to get profile", err)
+	}
 
 
-	id, ok := iniProfile["aws_access_key_id"]
-	if !ok {
+	id, err := iniProfile.GetKey("aws_access_key_id")
+	if err != nil {
 		return Value{}, awserr.New("SharedCredsAccessKey",
 		return Value{}, awserr.New("SharedCredsAccessKey",
 			fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
 			fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
-			nil)
+			err)
 	}
 	}
 
 
-	secret, ok := iniProfile["aws_secret_access_key"]
-	if !ok {
+	secret, err := iniProfile.GetKey("aws_secret_access_key")
+	if err != nil {
 		return Value{}, awserr.New("SharedCredsSecret",
 		return Value{}, awserr.New("SharedCredsSecret",
 			fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
 			fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
 			nil)
 			nil)
 	}
 	}
 
 
-	token := iniProfile["aws_session_token"]
+	// Default to empty string if not found
+	token := iniProfile.Key("aws_session_token")
 
 
 	return Value{
 	return Value{
-		AccessKeyID:     id,
-		SecretAccessKey: secret,
-		SessionToken:    token,
+		AccessKeyID:     id.String(),
+		SecretAccessKey: secret.String(),
+		SessionToken:    token.String(),
 	}, nil
 	}, nil
 }
 }
 
 

+ 12 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go

@@ -69,6 +69,18 @@ func TestSharedCredentialsProviderWithoutTokenFromProfile(t *testing.T) {
 	assert.Empty(t, creds.SessionToken, "Expect no token")
 	assert.Empty(t, creds.SessionToken, "Expect no token")
 }
 }
 
 
+func TestSharedCredentialsProviderColonInCredFile(t *testing.T) {
+	os.Clearenv()
+
+	p := SharedCredentialsProvider{Filename: "example.ini", Profile: "with_colon"}
+	creds, err := p.Retrieve()
+	assert.Nil(t, err, "Expect no error")
+
+	assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match")
+	assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match")
+	assert.Empty(t, creds.SessionToken, "Expect no token")
+}
+
 func BenchmarkSharedCredentialsProvider(b *testing.B) {
 func BenchmarkSharedCredentialsProvider(b *testing.B) {
 	os.Clearenv()
 	os.Clearenv()
 
 

+ 40 - 35
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go

@@ -9,6 +9,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/client"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/service/sts"
 	"github.com/aws/aws-sdk-go/service/sts"
 )
 )
@@ -18,31 +19,17 @@ type AssumeRoler interface {
 	AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
 	AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
 }
 }
 
 
+// DefaultDuration is the default amount of time in minutes that the credentials
+// will be valid for.
+var DefaultDuration = time.Duration(15) * time.Minute
+
 // AssumeRoleProvider retrieves temporary credentials from the STS service, and
 // AssumeRoleProvider retrieves temporary credentials from the STS service, and
 // keeps track of their expiration time. This provider must be used explicitly,
 // keeps track of their expiration time. This provider must be used explicitly,
 // as it is not included in the credentials chain.
 // as it is not included in the credentials chain.
-//
-// Example how to configure a service to use this provider:
-//
-//		config := &aws.Config{
-//			Credentials: stscreds.NewCredentials(nil, "arn-of-the-role-to-assume", 10*time.Second),
-//		})
-//		// Use config for creating your AWS service.
-//
-// Example how to obtain customised credentials:
-//
-//		provider := &stscreds.Provider{
-//			// Extend the duration to 1 hour.
-//			Duration: time.Hour,
-//			// Custom role name.
-//			RoleSessionName: "custom-session-name",
-//		}
-//		creds := credentials.NewCredentials(provider)
-//
 type AssumeRoleProvider struct {
 type AssumeRoleProvider struct {
 	credentials.Expiry
 	credentials.Expiry
 
 
-	// Custom STS client. If not set the default STS client will be used.
+	// STS client to make assume role request with.
 	Client AssumeRoler
 	Client AssumeRoler
 
 
 	// Role to be assumed.
 	// Role to be assumed.
@@ -70,37 +57,55 @@ type AssumeRoleProvider struct {
 }
 }
 
 
 // NewCredentials returns a pointer to a new Credentials object wrapping the
 // NewCredentials returns a pointer to a new Credentials object wrapping the
-// AssumeRoleProvider.  The credentials will expire every 15 minutes and the
+// AssumeRoleProvider. The credentials will expire every 15 minutes and the
 // role will be named after a nanosecond timestamp of this operation.
 // role will be named after a nanosecond timestamp of this operation.
 //
 //
-// The sts and roleARN parameters are used for building the "AssumeRole" call.
-// Pass nil as sts to use the default client.
+// Takes a Config provider to create the STS client. The ConfigProvider is
+// satisfied by the session.Session type.
+func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
+	p := &AssumeRoleProvider{
+		Client:   sts.New(c),
+		RoleARN:  roleARN,
+		Duration: DefaultDuration,
+	}
+
+	for _, option := range options {
+		option(p)
+	}
+
+	return credentials.NewCredentials(p)
+}
+
+// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping the
+// AssumeRoleProvider. The credentials will expire every 15 minutes and the
+// role will be named after a nanosecond timestamp of this operation.
 //
 //
-// Window is the expiry window that will be subtracted from the expiry returned
-// by the role credential request. This is done so that the credentials will
-// expire sooner than their actual lifespan.
-func NewCredentials(client AssumeRoler, roleARN string, window time.Duration) *credentials.Credentials {
-	return credentials.NewCredentials(&AssumeRoleProvider{
-		Client:       client,
-		RoleARN:      roleARN,
-		ExpiryWindow: window,
-	})
+// Takes an AssumeRoler which can be satisfiede by the STS client.
+func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
+	p := &AssumeRoleProvider{
+		Client:   svc,
+		RoleARN:  roleARN,
+		Duration: DefaultDuration,
+	}
+
+	for _, option := range options {
+		option(p)
+	}
+
+	return credentials.NewCredentials(p)
 }
 }
 
 
 // Retrieve generates a new set of temporary credentials using STS.
 // Retrieve generates a new set of temporary credentials using STS.
 func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
 func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
 
 
 	// Apply defaults where parameters are not set.
 	// Apply defaults where parameters are not set.
-	if p.Client == nil {
-		p.Client = sts.New(nil)
-	}
 	if p.RoleSessionName == "" {
 	if p.RoleSessionName == "" {
 		// Try to work out a role name that will hopefully end up unique.
 		// Try to work out a role name that will hopefully end up unique.
 		p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
 		p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
 	}
 	}
 	if p.Duration == 0 {
 	if p.Duration == 0 {
 		// Expire as often as AWS permits.
 		// Expire as often as AWS permits.
-		p.Duration = 15 * time.Minute
+		p.Duration = DefaultDuration
 	}
 	}
 
 
 	roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{
 	roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{

+ 4 - 7
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go

@@ -48,12 +48,9 @@ func BenchmarkAssumeRoleProvider(b *testing.B) {
 	}
 	}
 
 
 	b.ResetTimer()
 	b.ResetTimer()
-	b.RunParallel(func(pb *testing.PB) {
-		for pb.Next() {
-			_, err := p.Retrieve()
-			if err != nil {
-				b.Fatal(err)
-			}
+	for i := 0; i < b.N; i++ {
+		if _, err := p.Retrieve(); err != nil {
+			b.Fatal(err)
 		}
 		}
-	})
+	}
 }
 }

+ 64 - 27
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go

@@ -1,3 +1,5 @@
+// Package defaults is a collection of helpers to retrieve the SDK's default
+// configuration and handlers.
 package defaults
 package defaults
 
 
 import (
 import (
@@ -6,34 +8,69 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/corehandlers"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
 	"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
+	"github.com/aws/aws-sdk-go/aws/ec2metadata"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/private/endpoints"
 )
 )
 
 
-// DefaultChainCredentials is a Credentials which will find the first available
-// credentials Value from the list of Providers.
-//
-// This should be used in the default case. Once the type of credentials are
-// known switching to the specific Credentials will be more efficient.
-var DefaultChainCredentials = credentials.NewChainCredentials(
-	[]credentials.Provider{
-		&credentials.EnvProvider{},
-		&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
-		&ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute},
-	})
-
-// DefaultConfig is the default all service configuration will be based off of.
-// By default, all clients use this structure for initialization options unless
-// a custom configuration object is passed in.
-//
-// You may modify this global structure to change all default configuration
-// in the SDK. Note that configuration options are copied by value, so any
-// modifications must happen before constructing a client.
-var DefaultConfig = aws.NewConfig().
-	WithCredentials(DefaultChainCredentials).
-	WithRegion(os.Getenv("AWS_REGION")).
-	WithHTTPClient(http.DefaultClient).
-	WithMaxRetries(aws.DefaultRetries).
-	WithLogger(aws.NewDefaultLogger()).
-	WithLogLevel(aws.LogOff).
-	WithSleepDelay(time.Sleep)
+// A Defaults provides a collection of default values for SDK clients.
+type Defaults struct {
+	Config   *aws.Config
+	Handlers request.Handlers
+}
+
+// Get returns the SDK's default values with Config and handlers pre-configured.
+func Get() Defaults {
+	cfg := Config()
+	handlers := Handlers()
+	cfg.Credentials = CredChain(cfg, handlers)
+
+	return Defaults{
+		Config:   cfg,
+		Handlers: handlers,
+	}
+}
+
+// Config returns the default configuration.
+func Config() *aws.Config {
+	return aws.NewConfig().
+		WithCredentials(credentials.AnonymousCredentials).
+		WithRegion(os.Getenv("AWS_REGION")).
+		WithHTTPClient(http.DefaultClient).
+		WithMaxRetries(aws.UseServiceDefaultRetries).
+		WithLogger(aws.NewDefaultLogger()).
+		WithLogLevel(aws.LogOff).
+		WithSleepDelay(time.Sleep)
+}
+
+// Handlers returns the default request handlers.
+func Handlers() request.Handlers {
+	var handlers request.Handlers
+
+	handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
+	handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
+	handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
+	handlers.Send.PushBackNamed(corehandlers.SendHandler)
+	handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
+	handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
+
+	return handlers
+}
+
+// CredChain returns the default credential chain.
+func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
+	endpoint, signingRegion := endpoints.EndpointForRegion(ec2metadata.ServiceName, *cfg.Region, true)
+
+	return credentials.NewChainCredentials(
+		[]credentials.Provider{
+			&credentials.EnvProvider{},
+			&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
+			&ec2rolecreds.EC2RoleProvider{
+				Client:       ec2metadata.NewClient(*cfg, handlers, endpoint, signingRegion),
+				ExpiryWindow: 5 * time.Minute,
+			},
+		})
+}

+ 4 - 4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go

@@ -7,7 +7,7 @@ import (
 )
 )
 
 
 // GetMetadata uses the path provided to request
 // GetMetadata uses the path provided to request
-func (c *Client) GetMetadata(p string) (string, error) {
+func (c *EC2Metadata) GetMetadata(p string) (string, error) {
 	op := &request.Operation{
 	op := &request.Operation{
 		Name:       "GetMetadata",
 		Name:       "GetMetadata",
 		HTTPMethod: "GET",
 		HTTPMethod: "GET",
@@ -15,13 +15,13 @@ func (c *Client) GetMetadata(p string) (string, error) {
 	}
 	}
 
 
 	output := &metadataOutput{}
 	output := &metadataOutput{}
-	req := request.New(c.Service.ServiceInfo, c.Service.Handlers, c.Service.Retryer, op, nil, output)
+	req := c.NewRequest(op, nil, output)
 
 
 	return output.Content, req.Send()
 	return output.Content, req.Send()
 }
 }
 
 
 // Region returns the region the instance is running in.
 // Region returns the region the instance is running in.
-func (c *Client) Region() (string, error) {
+func (c *EC2Metadata) Region() (string, error) {
 	resp, err := c.GetMetadata("placement/availability-zone")
 	resp, err := c.GetMetadata("placement/availability-zone")
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
@@ -34,7 +34,7 @@ func (c *Client) Region() (string, error) {
 // Available returns if the application has access to the EC2 Metadata service.
 // Available returns if the application has access to the EC2 Metadata service.
 // Can be used to determine if application is running within an EC2 Instance and
 // Can be used to determine if application is running within an EC2 Instance and
 // the metadata service is available.
 // the metadata service is available.
-func (c *Client) Available() bool {
+func (c *EC2Metadata) Available() bool {
 	if _, err := c.GetMetadata("instance-id"); err != nil {
 	if _, err := c.GetMetadata("instance-id"); err != nil {
 		return false
 		return false
 	}
 	}

+ 8 - 7
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go

@@ -14,6 +14,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 	"github.com/aws/aws-sdk-go/aws/ec2metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/aws/session"
 )
 )
 
 
 func initTestServer(path string, resp string) *httptest.Server {
 func initTestServer(path string, resp string) *httptest.Server {
@@ -28,15 +29,15 @@ func initTestServer(path string, resp string) *httptest.Server {
 }
 }
 
 
 func TestEndpoint(t *testing.T) {
 func TestEndpoint(t *testing.T) {
-	c := ec2metadata.New(&ec2metadata.Config{})
+	c := ec2metadata.New(session.New())
 	op := &request.Operation{
 	op := &request.Operation{
 		Name:       "GetMetadata",
 		Name:       "GetMetadata",
 		HTTPMethod: "GET",
 		HTTPMethod: "GET",
 		HTTPPath:   path.Join("/", "meta-data", "testpath"),
 		HTTPPath:   path.Join("/", "meta-data", "testpath"),
 	}
 	}
 
 
-	req := c.Service.NewRequest(op, nil, nil)
-	assert.Equal(t, "http://169.254.169.254/latest", req.Service.Endpoint)
+	req := c.NewRequest(op, nil, nil)
+	assert.Equal(t, "http://169.254.169.254/latest", req.ClientInfo.Endpoint)
 	assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String())
 	assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String())
 }
 }
 
 
@@ -46,7 +47,7 @@ func TestGetMetadata(t *testing.T) {
 		"success", // real response includes suffix
 		"success", // real response includes suffix
 	)
 	)
 	defer server.Close()
 	defer server.Close()
-	c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")})
+	c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
 
 
 	resp, err := c.GetMetadata("some/path")
 	resp, err := c.GetMetadata("some/path")
 
 
@@ -60,7 +61,7 @@ func TestGetRegion(t *testing.T) {
 		"us-west-2a", // real response includes suffix
 		"us-west-2a", // real response includes suffix
 	)
 	)
 	defer server.Close()
 	defer server.Close()
-	c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")})
+	c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
 
 
 	region, err := c.Region()
 	region, err := c.Region()
 
 
@@ -74,7 +75,7 @@ func TestMetadataAvailable(t *testing.T) {
 		"instance-id",
 		"instance-id",
 	)
 	)
 	defer server.Close()
 	defer server.Close()
-	c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")})
+	c := ec2metadata.New(session.New(), &aws.Config{Endpoint: aws.String(server.URL + "/latest")})
 
 
 	available := c.Available()
 	available := c.Available()
 
 
@@ -82,7 +83,7 @@ func TestMetadataAvailable(t *testing.T) {
 }
 }
 
 
 func TestMetadataNotAvailable(t *testing.T) {
 func TestMetadataNotAvailable(t *testing.T) {
-	c := ec2metadata.New(nil)
+	c := ec2metadata.New(session.New())
 	c.Handlers.Send.Clear()
 	c.Handlers.Send.Clear()
 	c.Handlers.Send.PushBack(func(r *request.Request) {
 	c.Handlers.Send.PushBack(func(r *request.Request) {
 		r.HTTPResponse = &http.Response{
 		r.HTTPResponse = &http.Response{

+ 49 - 82
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go

@@ -1,3 +1,5 @@
+// Package ec2metadata provides the client for making API calls to the
+// EC2 Metadata service.
 package ec2metadata
 package ec2metadata
 
 
 import (
 import (
@@ -8,89 +10,41 @@ import (
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
-	"github.com/aws/aws-sdk-go/aws/credentials"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
 )
 )
 
 
-// DefaultRetries states the default number of times the service client will
-// attempt to retry a failed request before failing.
-const DefaultRetries = 3
-
-// A Config provides the configuration for the EC2 Metadata service.
-type Config struct {
-	// An optional endpoint URL (hostname only or fully qualified URI)
-	// that overrides the default service endpoint for a client. Set this
-	// to nil, or `""` to use the default service endpoint.
-	Endpoint *string
-
-	// The HTTP client to use when sending requests. Defaults to
-	// `http.DefaultClient`.
-	HTTPClient *http.Client
-
-	// An integer value representing the logging level. The default log level
-	// is zero (LogOff), which represents no logging. To enable logging set
-	// to a LogLevel Value.
-	Logger aws.Logger
-
-	// The logger writer interface to write logging messages to. Defaults to
-	// standard out.
-	LogLevel *aws.LogLevelType
-
-	// The maximum number of times that a request will be retried for failures.
-	// Defaults to DefaultRetries for the number of retries to be performed
-	// per request.
-	MaxRetries *int
-}
+// ServiceName is the name of the service.
+const ServiceName = "ec2metadata"
 
 
-// A Client is an EC2 Metadata service Client.
-type Client struct {
-	*service.Service
+// A EC2Metadata is an EC2 Metadata service Client.
+type EC2Metadata struct {
+	*client.Client
 }
 }
 
 
-// New creates a new instance of the EC2 Metadata service client.
+// New creates a new instance of the EC2Metadata client with a session.
+// This client is safe to use across multiple goroutines.
 //
 //
-// In the general use case the configuration for this service client should not
-// be needed and `nil` can be provided. Configuration is only needed if the
-// `ec2metadata.Config` defaults need to be overridden. Eg. Setting LogLevel.
+// Example:
+//     // Create a EC2Metadata client from just a session.
+//     svc := ec2metadata.New(mySession)
 //
 //
-// @note This configuration will NOT be merged with the default AWS service
-// client configuration `defaults.DefaultConfig`. Due to circular dependencies
-// with the defaults package and credentials EC2 Role Provider.
-func New(config *Config) *Client {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      copyConfig(config),
-			ServiceName: "Client",
-			Endpoint:    "http://169.254.169.254/latest",
-			APIVersion:  "latest",
-		},
-	}
-	service.Initialize()
-	service.Handlers.Unmarshal.PushBack(unmarshalHandler)
-	service.Handlers.UnmarshalError.PushBack(unmarshalError)
-	service.Handlers.Validate.Clear()
-	service.Handlers.Validate.PushBack(validateEndpointHandler)
-
-	return &Client{service}
+//     // Create a EC2Metadata client with additional configuration
+//     svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody))
+func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata {
+	c := p.ClientConfig(ServiceName, cfgs...)
+	return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
 }
 }
 
 
-func copyConfig(config *Config) *aws.Config {
-	if config == nil {
-		config = &Config{}
-	}
-	c := &aws.Config{
-		Credentials: credentials.AnonymousCredentials,
-		Endpoint:    config.Endpoint,
-		HTTPClient:  config.HTTPClient,
-		Logger:      config.Logger,
-		LogLevel:    config.LogLevel,
-		MaxRetries:  config.MaxRetries,
-	}
-
-	if c.HTTPClient == nil {
-		c.HTTPClient = &http.Client{
+// NewClient returns a new EC2Metadata client. Should be used to create
+// a client when not using a session. Generally using just New with a session
+// is preferred.
+func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata {
+	// If the default http client is provided, replace it with a custom
+	// client using default timeouts.
+	if cfg.HTTPClient == http.DefaultClient {
+		cfg.HTTPClient = &http.Client{
 			Transport: &http.Transport{
 			Transport: &http.Transport{
 				Proxy: http.ProxyFromEnvironment,
 				Proxy: http.ProxyFromEnvironment,
 				Dial: (&net.Dialer{
 				Dial: (&net.Dialer{
@@ -104,17 +58,30 @@ func copyConfig(config *Config) *aws.Config {
 			},
 			},
 		}
 		}
 	}
 	}
-	if c.Logger == nil {
-		c.Logger = aws.NewDefaultLogger()
-	}
-	if c.LogLevel == nil {
-		c.LogLevel = aws.LogLevel(aws.LogOff)
+
+	svc := &EC2Metadata{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName: ServiceName,
+				Endpoint:    endpoint,
+				APIVersion:  "latest",
+			},
+			handlers,
+		),
 	}
 	}
-	if c.MaxRetries == nil {
-		c.MaxRetries = aws.Int(DefaultRetries)
+
+	svc.Handlers.Unmarshal.PushBack(unmarshalHandler)
+	svc.Handlers.UnmarshalError.PushBack(unmarshalError)
+	svc.Handlers.Validate.Clear()
+	svc.Handlers.Validate.PushBack(validateEndpointHandler)
+
+	// Add additional options to the service config
+	for _, option := range opts {
+		option(svc.Client)
 	}
 	}
 
 
-	return c
+	return svc
 }
 }
 
 
 type metadataOutput struct {
 type metadataOutput struct {
@@ -143,7 +110,7 @@ func unmarshalError(r *request.Request) {
 }
 }
 
 
 func validateEndpointHandler(r *request.Request) {
 func validateEndpointHandler(r *request.Request) {
-	if r.Service.Endpoint == "" {
+	if r.ClientInfo.Endpoint == "" {
 		r.Error = aws.ErrMissingEndpoint
 		r.Error = aws.ErrMissingEndpoint
 	}
 	}
 }
 }

+ 2 - 2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/errors.go

@@ -7,11 +7,11 @@ var (
 	// not found.
 	// not found.
 	//
 	//
 	// @readonly
 	// @readonly
-	ErrMissingRegion error = awserr.New("MissingRegion", "could not find region configuration", nil)
+	ErrMissingRegion = awserr.New("MissingRegion", "could not find region configuration", nil)
 
 
 	// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
 	// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
 	// resolved for a service.
 	// resolved for a service.
 	//
 	//
 	// @readonly
 	// @readonly
-	ErrMissingEndpoint error = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
+	ErrMissingEndpoint = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
 )
 )

+ 28 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers.go

@@ -1,5 +1,10 @@
 package request
 package request
 
 
+import (
+	"fmt"
+	"strings"
+)
+
 // A Handlers provides a collection of request handlers for various
 // A Handlers provides a collection of request handlers for various
 // stages of handling requests.
 // stages of handling requests.
 type Handlers struct {
 type Handlers struct {
@@ -110,3 +115,26 @@ func (l *HandlerList) Run(r *Request) {
 		f.Fn(r)
 		f.Fn(r)
 	}
 	}
 }
 }
+
+// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request
+// header. If the extra parameters are provided they will be added as metadata to the
+// name/version pair resulting in the following format.
+// "name/version (extra0; extra1; ...)"
+// The user agent part will be concatenated with this current request's user agent string.
+func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) {
+	ua := fmt.Sprintf("%s/%s", name, version)
+	if len(extra) > 0 {
+		ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; "))
+	}
+	return func(r *Request) {
+		AddToUserAgent(r, ua)
+	}
+}
+
+// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header.
+// The input string will be concatenated with the current request's user agent string.
+func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) {
+	return func(r *Request) {
+		AddToUserAgent(r, s)
+	}
+}

+ 2 - 2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go

@@ -35,8 +35,8 @@ func TestMultipleHandlers(t *testing.T) {
 
 
 func TestNamedHandlers(t *testing.T) {
 func TestNamedHandlers(t *testing.T) {
 	l := request.HandlerList{}
 	l := request.HandlerList{}
-	named := request.NamedHandler{"Name", func(r *request.Request) {}}
-	named2 := request.NamedHandler{"NotName", func(r *request.Request) {}}
+	named := request.NamedHandler{Name: "Name", Fn: func(r *request.Request) {}}
+	named2 := request.NamedHandler{Name: "NotName", Fn: func(r *request.Request) {}}
 	l.PushBackNamed(named)
 	l.PushBackNamed(named)
 	l.PushBackNamed(named)
 	l.PushBackNamed(named)
 	l.PushBackNamed(named2)
 	l.PushBackNamed(named2)

+ 26 - 95
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request.go

@@ -12,15 +12,16 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/awsutil"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 )
 )
 
 
 // A Request is the service request to be made.
 // A Request is the service request to be made.
 type Request struct {
 type Request struct {
+	Config     aws.Config
+	ClientInfo metadata.ClientInfo
+	Handlers   Handlers
+
 	Retryer
 	Retryer
-	Service      serviceinfo.ServiceInfo
-	Handlers     Handlers
 	Time         time.Time
 	Time         time.Time
 	ExpireTime   time.Duration
 	ExpireTime   time.Duration
 	Operation    *Operation
 	Operation    *Operation
@@ -32,7 +33,7 @@ type Request struct {
 	Error        error
 	Error        error
 	Data         interface{}
 	Data         interface{}
 	RequestID    string
 	RequestID    string
-	RetryCount   uint
+	RetryCount   int
 	Retryable    *bool
 	Retryable    *bool
 	RetryDelay   time.Duration
 	RetryDelay   time.Duration
 
 
@@ -61,7 +62,9 @@ type Paginator struct {
 // Params is any value of input parameters to be the request payload.
 // Params is any value of input parameters to be the request payload.
 // Data is pointer value to an object which the request's response
 // Data is pointer value to an object which the request's response
 // payload will be deserialized to.
 // payload will be deserialized to.
-func New(service serviceinfo.ServiceInfo, handlers Handlers, retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
+func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
+	retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
+
 	method := operation.HTTPMethod
 	method := operation.HTTPMethod
 	if method == "" {
 	if method == "" {
 		method = "POST"
 		method = "POST"
@@ -72,12 +75,14 @@ func New(service serviceinfo.ServiceInfo, handlers Handlers, retryer Retryer, op
 	}
 	}
 
 
 	httpReq, _ := http.NewRequest(method, "", nil)
 	httpReq, _ := http.NewRequest(method, "", nil)
-	httpReq.URL, _ = url.Parse(service.Endpoint + p)
+	httpReq.URL, _ = url.Parse(clientInfo.Endpoint + p)
 
 
 	r := &Request{
 	r := &Request{
+		Config:     cfg,
+		ClientInfo: clientInfo,
+		Handlers:   handlers.Copy(),
+
 		Retryer:     retryer,
 		Retryer:     retryer,
-		Service:     service,
-		Handlers:    handlers.Copy(),
 		Time:        time.Now(),
 		Time:        time.Now(),
 		ExpireTime:  0,
 		ExpireTime:  0,
 		Operation:   operation,
 		Operation:   operation,
@@ -140,7 +145,7 @@ func (r *Request) Presign(expireTime time.Duration) (string, error) {
 }
 }
 
 
 func debugLogReqError(r *Request, stage string, retrying bool, err error) {
 func debugLogReqError(r *Request, stage string, retrying bool, err error) {
-	if !r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
+	if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
 		return
 		return
 	}
 	}
 
 
@@ -149,8 +154,8 @@ func debugLogReqError(r *Request, stage string, retrying bool, err error) {
 		retryStr = "will retry"
 		retryStr = "will retry"
 	}
 	}
 
 
-	r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
-		stage, r.Service.ServiceName, r.Operation.Name, retryStr, err))
+	r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
+		stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err))
 }
 }
 
 
 // Build will build the request's object so it can be signed and sent
 // Build will build the request's object so it can be signed and sent
@@ -205,9 +210,9 @@ func (r *Request) Send() error {
 		}
 		}
 
 
 		if aws.BoolValue(r.Retryable) {
 		if aws.BoolValue(r.Retryable) {
-			if r.Service.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
-				r.Service.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
-					r.Service.ServiceName, r.Operation.Name, r.RetryCount))
+			if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
+				r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
+					r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
 			}
 			}
 
 
 			// Re-seek the body back to the original point in for a retry so that
 			// Re-seek the body back to the original point in for a retry so that
@@ -264,85 +269,11 @@ func (r *Request) Send() error {
 	return nil
 	return nil
 }
 }
 
 
-// HasNextPage returns true if this request has more pages of data available.
-func (r *Request) HasNextPage() bool {
-	return r.nextPageTokens() != nil
-}
-
-// nextPageTokens returns the tokens to use when asking for the next page of
-// data.
-func (r *Request) nextPageTokens() []interface{} {
-	if r.Operation.Paginator == nil {
-		return nil
-	}
-
-	if r.Operation.TruncationToken != "" {
-		tr := awsutil.ValuesAtAnyPath(r.Data, r.Operation.TruncationToken)
-		if tr == nil || len(tr) == 0 {
-			return nil
-		}
-		switch v := tr[0].(type) {
-		case bool:
-			if v == false {
-				return nil
-			}
-		}
-	}
-
-	found := false
-	tokens := make([]interface{}, len(r.Operation.OutputTokens))
-
-	for i, outtok := range r.Operation.OutputTokens {
-		v := awsutil.ValuesAtAnyPath(r.Data, outtok)
-		if v != nil && len(v) > 0 {
-			found = true
-			tokens[i] = v[0]
-		}
-	}
-
-	if found {
-		return tokens
-	}
-	return nil
-}
-
-// NextPage returns a new Request that can be executed to return the next
-// page of result data. Call .Send() on this request to execute it.
-func (r *Request) NextPage() *Request {
-	tokens := r.nextPageTokens()
-	if tokens == nil {
-		return nil
-	}
-
-	data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
-	nr := New(r.Service, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
-	for i, intok := range nr.Operation.InputTokens {
-		awsutil.SetValueAtAnyPath(nr.Params, intok, tokens[i])
+// AddToUserAgent adds the string to the end of the request's current user agent.
+func AddToUserAgent(r *Request, s string) {
+	curUA := r.HTTPRequest.Header.Get("User-Agent")
+	if len(curUA) > 0 {
+		s = curUA + " " + s
 	}
 	}
-	return nr
-}
-
-// EachPage iterates over each page of a paginated request object. The fn
-// parameter should be a function with the following sample signature:
-//
-//   func(page *T, lastPage bool) bool {
-//       return true // return false to stop iterating
-//   }
-//
-// Where "T" is the structure type matching the output structure of the given
-// operation. For example, a request object generated by
-// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
-// as the structure "T". The lastPage value represents whether the page is
-// the last page of data or not. The return value of this function should
-// return true to keep iterating or false to stop.
-func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
-	for page := r; page != nil; page = page.NextPage() {
-		page.Send()
-		shouldContinue := fn(page.Data, !page.HasNextPage())
-		if page.Error != nil || !shouldContinue {
-			return page.Error
-		}
-	}
-
-	return nil
+	r.HTTPRequest.Header.Set("User-Agent", s)
 }
 }

+ 104 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination.go

@@ -0,0 +1,104 @@
+package request
+
+import (
+	"reflect"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/awsutil"
+)
+
+//type Paginater interface {
+//	HasNextPage() bool
+//	NextPage() *Request
+//	EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error
+//}
+
+// HasNextPage returns true if this request has more pages of data available.
+func (r *Request) HasNextPage() bool {
+	return len(r.nextPageTokens()) > 0
+}
+
+// nextPageTokens returns the tokens to use when asking for the next page of
+// data.
+func (r *Request) nextPageTokens() []interface{} {
+	if r.Operation.Paginator == nil {
+		return nil
+	}
+
+	if r.Operation.TruncationToken != "" {
+		tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken)
+		if len(tr) == 0 {
+			return nil
+		}
+
+		switch v := tr[0].(type) {
+		case *bool:
+			if !aws.BoolValue(v) {
+				return nil
+			}
+		case bool:
+			if v == false {
+				return nil
+			}
+		}
+	}
+
+	tokens := []interface{}{}
+	tokenAdded := false
+	for _, outToken := range r.Operation.OutputTokens {
+		v, _ := awsutil.ValuesAtPath(r.Data, outToken)
+		if len(v) > 0 {
+			tokens = append(tokens, v[0])
+			tokenAdded = true
+		} else {
+			tokens = append(tokens, nil)
+		}
+	}
+	if !tokenAdded {
+		return nil
+	}
+
+	return tokens
+}
+
+// NextPage returns a new Request that can be executed to return the next
+// page of result data. Call .Send() on this request to execute it.
+func (r *Request) NextPage() *Request {
+	tokens := r.nextPageTokens()
+	if len(tokens) == 0 {
+		return nil
+	}
+
+	data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
+	nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
+	for i, intok := range nr.Operation.InputTokens {
+		awsutil.SetValueAtPath(nr.Params, intok, tokens[i])
+	}
+	return nr
+}
+
+// EachPage iterates over each page of a paginated request object. The fn
+// parameter should be a function with the following sample signature:
+//
+//   func(page *T, lastPage bool) bool {
+//       return true // return false to stop iterating
+//   }
+//
+// Where "T" is the structure type matching the output structure of the given
+// operation. For example, a request object generated by
+// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
+// as the structure "T". The lastPage value represents whether the page is
+// the last page of data or not. The return value of this function should
+// return true to keep iterating or false to stop.
+func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
+	for page := r; page != nil; page = page.NextPage() {
+		if err := page.Send(); err != nil {
+			return err
+		}
+		if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage {
+			return page.Error
+		}
+	}
+
+	return nil
+}

+ 160 - 12
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_pagination_test.go

@@ -9,14 +9,101 @@ import (
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/awstesting/unit"
 	"github.com/aws/aws-sdk-go/awstesting/unit"
 	"github.com/aws/aws-sdk-go/service/dynamodb"
 	"github.com/aws/aws-sdk-go/service/dynamodb"
+	"github.com/aws/aws-sdk-go/service/route53"
 	"github.com/aws/aws-sdk-go/service/s3"
 	"github.com/aws/aws-sdk-go/service/s3"
 )
 )
 
 
-var _ = unit.Imported
+// Use DynamoDB methods for simplicity
+func TestPaginationQueryPage(t *testing.T) {
+	db := dynamodb.New(unit.Session)
+	tokens, pages, numPages, gotToEnd := []map[string]*dynamodb.AttributeValue{}, []map[string]*dynamodb.AttributeValue{}, 0, false
+
+	reqNum := 0
+	resps := []*dynamodb.QueryOutput{
+		{
+			LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}},
+			Count:            aws.Int64(1),
+			Items: []map[string]*dynamodb.AttributeValue{
+				map[string]*dynamodb.AttributeValue{
+					"key": {S: aws.String("key1")},
+				},
+			},
+		},
+		{
+			LastEvaluatedKey: map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}},
+			Count:            aws.Int64(1),
+			Items: []map[string]*dynamodb.AttributeValue{
+				map[string]*dynamodb.AttributeValue{
+					"key": {S: aws.String("key2")},
+				},
+			},
+		},
+		{
+			LastEvaluatedKey: map[string]*dynamodb.AttributeValue{},
+			Count:            aws.Int64(1),
+			Items: []map[string]*dynamodb.AttributeValue{
+				map[string]*dynamodb.AttributeValue{
+					"key": {S: aws.String("key3")},
+				},
+			},
+		},
+	}
+
+	db.Handlers.Send.Clear() // mock sending
+	db.Handlers.Unmarshal.Clear()
+	db.Handlers.UnmarshalMeta.Clear()
+	db.Handlers.ValidateResponse.Clear()
+	db.Handlers.Build.PushBack(func(r *request.Request) {
+		in := r.Params.(*dynamodb.QueryInput)
+		if in == nil {
+			tokens = append(tokens, nil)
+		} else if len(in.ExclusiveStartKey) != 0 {
+			tokens = append(tokens, in.ExclusiveStartKey)
+		}
+	})
+	db.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	params := &dynamodb.QueryInput{
+		Limit:     aws.Int64(2),
+		TableName: aws.String("tablename"),
+	}
+	err := db.QueryPages(params, func(p *dynamodb.QueryOutput, last bool) bool {
+		numPages++
+		for _, item := range p.Items {
+			pages = append(pages, item)
+		}
+		if last {
+			if gotToEnd {
+				assert.Fail(t, "last=true happened twice")
+			}
+			gotToEnd = true
+		}
+		return true
+	})
+	assert.Nil(t, err)
+
+	assert.Equal(t,
+		[]map[string]*dynamodb.AttributeValue{
+			map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}},
+			map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}},
+		}, tokens)
+	assert.Equal(t,
+		[]map[string]*dynamodb.AttributeValue{
+			map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key1")}},
+			map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key2")}},
+			map[string]*dynamodb.AttributeValue{"key": {S: aws.String("key3")}},
+		}, pages)
+	assert.Equal(t, 3, numPages)
+	assert.True(t, gotToEnd)
+	assert.Nil(t, params.ExclusiveStartKey)
+}
 
 
 // Use DynamoDB methods for simplicity
 // Use DynamoDB methods for simplicity
 func TestPagination(t *testing.T) {
 func TestPagination(t *testing.T) {
-	db := dynamodb.New(nil)
+	db := dynamodb.New(unit.Session)
 	tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
 	tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
 
 
 	reqNum := 0
 	reqNum := 0
@@ -68,7 +155,7 @@ func TestPagination(t *testing.T) {
 
 
 // Use DynamoDB methods for simplicity
 // Use DynamoDB methods for simplicity
 func TestPaginationEachPage(t *testing.T) {
 func TestPaginationEachPage(t *testing.T) {
-	db := dynamodb.New(nil)
+	db := dynamodb.New(unit.Session)
 	tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
 	tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false
 
 
 	reqNum := 0
 	reqNum := 0
@@ -121,7 +208,7 @@ func TestPaginationEachPage(t *testing.T) {
 
 
 // Use DynamoDB methods for simplicity
 // Use DynamoDB methods for simplicity
 func TestPaginationEarlyExit(t *testing.T) {
 func TestPaginationEarlyExit(t *testing.T) {
-	db := dynamodb.New(nil)
+	db := dynamodb.New(unit.Session)
 	numPages, gotToEnd := 0, false
 	numPages, gotToEnd := 0, false
 
 
 	reqNum := 0
 	reqNum := 0
@@ -161,7 +248,7 @@ func TestPaginationEarlyExit(t *testing.T) {
 }
 }
 
 
 func TestSkipPagination(t *testing.T) {
 func TestSkipPagination(t *testing.T) {
-	client := s3.New(nil)
+	client := s3.New(unit.Session)
 	client.Handlers.Send.Clear() // mock sending
 	client.Handlers.Send.Clear() // mock sending
 	client.Handlers.Unmarshal.Clear()
 	client.Handlers.Unmarshal.Clear()
 	client.Handlers.UnmarshalMeta.Clear()
 	client.Handlers.UnmarshalMeta.Clear()
@@ -186,10 +273,9 @@ func TestSkipPagination(t *testing.T) {
 
 
 // Use S3 for simplicity
 // Use S3 for simplicity
 func TestPaginationTruncation(t *testing.T) {
 func TestPaginationTruncation(t *testing.T) {
-	count := 0
-	client := s3.New(nil)
+	client := s3.New(unit.Session)
 
 
-	reqNum := &count
+	reqNum := 0
 	resps := []*s3.ListObjectsOutput{
 	resps := []*s3.ListObjectsOutput{
 		{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}},
 		{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}},
 		{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}},
 		{IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}},
@@ -202,8 +288,8 @@ func TestPaginationTruncation(t *testing.T) {
 	client.Handlers.UnmarshalMeta.Clear()
 	client.Handlers.UnmarshalMeta.Clear()
 	client.Handlers.ValidateResponse.Clear()
 	client.Handlers.ValidateResponse.Clear()
 	client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
 	client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
-		r.Data = resps[*reqNum]
-		*reqNum++
+		r.Data = resps[reqNum]
+		reqNum++
 	})
 	})
 
 
 	params := &s3.ListObjectsInput{Bucket: aws.String("bucket")}
 	params := &s3.ListObjectsInput{Bucket: aws.String("bucket")}
@@ -218,7 +304,7 @@ func TestPaginationTruncation(t *testing.T) {
 	assert.Nil(t, err)
 	assert.Nil(t, err)
 
 
 	// Try again without truncation token at all
 	// Try again without truncation token at all
-	count = 0
+	reqNum = 0
 	resps[1].IsTruncated = nil
 	resps[1].IsTruncated = nil
 	resps[2].IsTruncated = aws.Bool(true)
 	resps[2].IsTruncated = aws.Bool(true)
 	results = []string{}
 	results = []string{}
@@ -229,7 +315,69 @@ func TestPaginationTruncation(t *testing.T) {
 
 
 	assert.Equal(t, []string{"Key1", "Key2"}, results)
 	assert.Equal(t, []string{"Key1", "Key2"}, results)
 	assert.Nil(t, err)
 	assert.Nil(t, err)
+}
+
+func TestPaginationNilToken(t *testing.T) {
+	client := route53.New(unit.Session)
+
+	reqNum := 0
+	resps := []*route53.ListResourceRecordSetsOutput{
+		{
+			ResourceRecordSets: []*route53.ResourceRecordSet{
+				{Name: aws.String("first.example.com.")},
+			},
+			IsTruncated:          aws.Bool(true),
+			NextRecordName:       aws.String("second.example.com."),
+			NextRecordType:       aws.String("MX"),
+			NextRecordIdentifier: aws.String("second"),
+			MaxItems:             aws.String("1"),
+		},
+		{
+			ResourceRecordSets: []*route53.ResourceRecordSet{
+				{Name: aws.String("second.example.com.")},
+			},
+			IsTruncated:    aws.Bool(true),
+			NextRecordName: aws.String("third.example.com."),
+			NextRecordType: aws.String("MX"),
+			MaxItems:       aws.String("1"),
+		},
+		{
+			ResourceRecordSets: []*route53.ResourceRecordSet{
+				{Name: aws.String("third.example.com.")},
+			},
+			IsTruncated: aws.Bool(false),
+			MaxItems:    aws.String("1"),
+		},
+	}
+	client.Handlers.Send.Clear() // mock sending
+	client.Handlers.Unmarshal.Clear()
+	client.Handlers.UnmarshalMeta.Clear()
+	client.Handlers.ValidateResponse.Clear()
+
+	idents := []string{}
+	client.Handlers.Build.PushBack(func(r *request.Request) {
+		p := r.Params.(*route53.ListResourceRecordSetsInput)
+		idents = append(idents, aws.StringValue(p.StartRecordIdentifier))
+
+	})
+	client.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	params := &route53.ListResourceRecordSetsInput{
+		HostedZoneId: aws.String("id-zone"),
+	}
+
+	results := []string{}
+	err := client.ListResourceRecordSetsPages(params, func(p *route53.ListResourceRecordSetsOutput, last bool) bool {
+		results = append(results, *p.ResourceRecordSets[0].Name)
+		return true
+	})
 
 
+	assert.NoError(t, err)
+	assert.Equal(t, []string{"", "second", ""}, idents)
+	assert.Equal(t, []string{"first.example.com.", "second.example.com.", "third.example.com."}, results)
 }
 }
 
 
 // Benchmarks
 // Benchmarks
@@ -251,7 +399,7 @@ var benchResps = []*dynamodb.ListTablesOutput{
 }
 }
 
 
 var benchDb = func() *dynamodb.DynamoDB {
 var benchDb = func() *dynamodb.DynamoDB {
-	db := dynamodb.New(nil)
+	db := dynamodb.New(unit.Session)
 	db.Handlers.Send.Clear() // mock sending
 	db.Handlers.Send.Clear() // mock sending
 	db.Handlers.Unmarshal.Clear()
 	db.Handlers.Unmarshal.Clear()
 	db.Handlers.UnmarshalMeta.Clear()
 	db.Handlers.UnmarshalMeta.Clear()

+ 42 - 9
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/request_test.go

@@ -7,15 +7,17 @@ import (
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
 	"net/http"
 	"net/http"
+	"runtime"
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	"github.com/stretchr/testify/assert"
+
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/stretchr/testify/assert"
+	"github.com/aws/aws-sdk-go/awstesting"
 )
 )
 
 
 type testData struct {
 type testData struct {
@@ -74,7 +76,7 @@ func TestRequestRecoverRetry5xx(t *testing.T) {
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 	}
 	}
 
 
-	s := service.New(aws.NewConfig().WithMaxRetries(10))
+	s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
 	s.Handlers.Validate.Clear()
 	s.Handlers.Validate.Clear()
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
@@ -100,7 +102,7 @@ func TestRequestRecoverRetry4xxRetryable(t *testing.T) {
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 	}
 	}
 
 
-	s := service.New(aws.NewConfig().WithMaxRetries(10))
+	s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
 	s.Handlers.Validate.Clear()
 	s.Handlers.Validate.Clear()
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
@@ -119,7 +121,7 @@ func TestRequestRecoverRetry4xxRetryable(t *testing.T) {
 
 
 // test that retries don't occur for 4xx status codes with a response type that can't be retried
 // test that retries don't occur for 4xx status codes with a response type that can't be retried
 func TestRequest4xxUnretryable(t *testing.T) {
 func TestRequest4xxUnretryable(t *testing.T) {
-	s := service.New(aws.NewConfig().WithMaxRetries(10))
+	s := awstesting.NewClient(aws.NewConfig().WithMaxRetries(10))
 	s.Handlers.Validate.Clear()
 	s.Handlers.Validate.Clear()
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
@@ -155,7 +157,7 @@ func TestRequestExhaustRetries(t *testing.T) {
 		{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
 		{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)},
 	}
 	}
 
 
-	s := service.New(aws.NewConfig().WithMaxRetries(aws.DefaultRetries).WithSleepDelay(sleepDelay))
+	s := awstesting.NewClient(aws.NewConfig().WithSleepDelay(sleepDelay))
 	s.Handlers.Validate.Clear()
 	s.Handlers.Validate.Clear()
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
@@ -193,7 +195,7 @@ func TestRequestRecoverExpiredCreds(t *testing.T) {
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 		{StatusCode: 200, Body: body(`{"data":"valid"}`)},
 	}
 	}
 
 
-	s := service.New(&aws.Config{MaxRetries: aws.Int(10), Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")})
+	s := awstesting.NewClient(&aws.Config{MaxRetries: aws.Int(10), Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")})
 	s.Handlers.Validate.Clear()
 	s.Handlers.Validate.Clear()
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.Unmarshal.PushBack(unmarshal)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
 	s.Handlers.UnmarshalError.PushBack(unmarshalError)
@@ -202,12 +204,12 @@ func TestRequestRecoverExpiredCreds(t *testing.T) {
 	credExpiredAfterRetry := false
 	credExpiredAfterRetry := false
 
 
 	s.Handlers.AfterRetry.PushBack(func(r *request.Request) {
 	s.Handlers.AfterRetry.PushBack(func(r *request.Request) {
-		credExpiredAfterRetry = r.Service.Config.Credentials.IsExpired()
+		credExpiredAfterRetry = r.Config.Credentials.IsExpired()
 	})
 	})
 
 
 	s.Handlers.Sign.Clear()
 	s.Handlers.Sign.Clear()
 	s.Handlers.Sign.PushBack(func(r *request.Request) {
 	s.Handlers.Sign.PushBack(func(r *request.Request) {
-		r.Service.Config.Credentials.Get()
+		r.Config.Credentials.Get()
 	})
 	})
 	s.Handlers.Send.Clear() // mock sending
 	s.Handlers.Send.Clear() // mock sending
 	s.Handlers.Send.PushBack(func(r *request.Request) {
 	s.Handlers.Send.PushBack(func(r *request.Request) {
@@ -226,3 +228,34 @@ func TestRequestRecoverExpiredCreds(t *testing.T) {
 	assert.Equal(t, 1, int(r.RetryCount))
 	assert.Equal(t, 1, int(r.RetryCount))
 	assert.Equal(t, "valid", out.Data)
 	assert.Equal(t, "valid", out.Data)
 }
 }
+
+func TestMakeAddtoUserAgentHandler(t *testing.T) {
+	fn := request.MakeAddToUserAgentHandler("name", "version", "extra1", "extra2")
+	r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}}
+	r.HTTPRequest.Header.Set("User-Agent", "foo/bar")
+	fn(r)
+
+	assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"))
+}
+
+func TestMakeAddtoUserAgentFreeFormHandler(t *testing.T) {
+	fn := request.MakeAddToUserAgentFreeFormHandler("name/version (extra1; extra2)")
+	r := &request.Request{HTTPRequest: &http.Request{Header: http.Header{}}}
+	r.HTTPRequest.Header.Set("User-Agent", "foo/bar")
+	fn(r)
+
+	assert.Equal(t, "foo/bar name/version (extra1; extra2)", r.HTTPRequest.Header.Get("User-Agent"))
+}
+
+func TestRequestUserAgent(t *testing.T) {
+	s := awstesting.NewClient(&aws.Config{Region: aws.String("us-east-1")})
+	//	s.Handlers.Validate.Clear()
+
+	req := s.NewRequest(&request.Operation{Name: "Operation"}, nil, &testData{})
+	req.HTTPRequest.Header.Set("User-Agent", "foo/bar")
+	assert.NoError(t, req.Build())
+
+	expectUA := fmt.Sprintf("foo/bar %s/%s (%s; %s; %s)",
+		aws.SDKName, aws.SDKVersion, runtime.Version(), runtime.GOOS, runtime.GOARCH)
+	assert.Equal(t, expectUA, req.HTTPRequest.Header.Get("User-Agent"))
+}

+ 10 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/retryer.go

@@ -3,6 +3,7 @@ package request
 import (
 import (
 	"time"
 	"time"
 
 
+	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/awserr"
 )
 )
 
 
@@ -12,13 +13,21 @@ import (
 type Retryer interface {
 type Retryer interface {
 	RetryRules(*Request) time.Duration
 	RetryRules(*Request) time.Duration
 	ShouldRetry(*Request) bool
 	ShouldRetry(*Request) bool
-	MaxRetries() uint
+	MaxRetries() int
+}
+
+// WithRetryer sets a config Retryer value to the given Config returning it
+// for chaining.
+func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
+	cfg.Retryer = retryer
+	return cfg
 }
 }
 
 
 // retryableCodes is a collection of service response codes which are retry-able
 // retryableCodes is a collection of service response codes which are retry-able
 // without any further action.
 // without any further action.
 var retryableCodes = map[string]struct{}{
 var retryableCodes = map[string]struct{}{
 	"RequestError":                           {},
 	"RequestError":                           {},
+	"RequestTimeout":                         {},
 	"ProvisionedThroughputExceededException": {},
 	"ProvisionedThroughputExceededException": {},
 	"Throttling":                             {},
 	"Throttling":                             {},
 	"ThrottlingException":                    {},
 	"ThrottlingException":                    {},

+ 0 - 133
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/service.go

@@ -1,133 +0,0 @@
-package service
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/http/httputil"
-	"regexp"
-	"time"
-
-	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/corehandlers"
-	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
-	"github.com/aws/aws-sdk-go/private/endpoints"
-)
-
-// A Service implements the base service request and response handling
-// used by all services.
-type Service struct {
-	serviceinfo.ServiceInfo
-	request.Retryer
-	DefaultMaxRetries uint
-	Handlers          request.Handlers
-}
-
-var schemeRE = regexp.MustCompile("^([^:]+)://")
-
-// New will return a pointer to a new Server object initialized.
-func New(config *aws.Config) *Service {
-	svc := &Service{ServiceInfo: serviceinfo.ServiceInfo{Config: config}}
-	svc.Initialize()
-	return svc
-}
-
-// Initialize initializes the service.
-func (s *Service) Initialize() {
-	if s.Config == nil {
-		s.Config = &aws.Config{}
-	}
-	if s.Config.HTTPClient == nil {
-		s.Config.HTTPClient = http.DefaultClient
-	}
-	if s.Config.SleepDelay == nil {
-		s.Config.SleepDelay = time.Sleep
-	}
-
-	s.Retryer = DefaultRetryer{s}
-	s.DefaultMaxRetries = 3
-	s.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
-	s.Handlers.Build.PushBackNamed(corehandlers.UserAgentHandler)
-	s.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
-	s.Handlers.Send.PushBackNamed(corehandlers.SendHandler)
-	s.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
-	s.Handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
-	if !aws.BoolValue(s.Config.DisableParamValidation) {
-		s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
-	}
-	s.AddDebugHandlers()
-	s.buildEndpoint()
-}
-
-// NewRequest returns a new Request pointer for the service API
-// operation and parameters.
-func (s *Service) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
-	return request.New(s.ServiceInfo, s.Handlers, s.Retryer, operation, params, data)
-}
-
-// buildEndpoint builds the endpoint values the service will use to make requests with.
-func (s *Service) buildEndpoint() {
-	if aws.StringValue(s.Config.Endpoint) != "" {
-		s.Endpoint = *s.Config.Endpoint
-	} else if s.Endpoint == "" {
-		s.Endpoint, s.SigningRegion =
-			endpoints.EndpointForRegion(s.ServiceName, aws.StringValue(s.Config.Region))
-	}
-
-	if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) {
-		scheme := "https"
-		if aws.BoolValue(s.Config.DisableSSL) {
-			scheme = "http"
-		}
-		s.Endpoint = scheme + "://" + s.Endpoint
-	}
-}
-
-// AddDebugHandlers injects debug logging handlers into the service to log request
-// debug information.
-func (s *Service) AddDebugHandlers() {
-	if !s.Config.LogLevel.AtLeast(aws.LogDebug) {
-		return
-	}
-
-	s.Handlers.Send.PushFront(logRequest)
-	s.Handlers.Send.PushBack(logResponse)
-}
-
-const logReqMsg = `DEBUG: Request %s/%s Details:
----[ REQUEST POST-SIGN ]-----------------------------
-%s
------------------------------------------------------`
-
-func logRequest(r *request.Request) {
-	logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
-	dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
-
-	if logBody {
-		// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
-		// Body as a NoOpCloser and will not be reset after read by the HTTP
-		// client reader.
-		r.Body.Seek(r.BodyStart, 0)
-		r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
-	}
-
-	r.Service.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.Service.ServiceName, r.Operation.Name, string(dumpedBody)))
-}
-
-const logRespMsg = `DEBUG: Response %s/%s Details:
----[ RESPONSE ]--------------------------------------
-%s
------------------------------------------------------`
-
-func logResponse(r *request.Request) {
-	var msg = "no reponse data"
-	if r.HTTPResponse != nil {
-		logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
-		dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
-		msg = string(dumpedBody)
-	} else if r.Error != nil {
-		msg = r.Error.Error()
-	}
-	r.Service.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.Service.ServiceName, r.Operation.Name, msg))
-}

+ 0 - 15
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go

@@ -1,15 +0,0 @@
-package serviceinfo
-
-import "github.com/aws/aws-sdk-go/aws"
-
-// ServiceInfo wraps immutable data from the service.Service structure.
-type ServiceInfo struct {
-	Config        *aws.Config
-	ServiceName   string
-	APIVersion    string
-	Endpoint      string
-	SigningName   string
-	SigningRegion string
-	JSONVersion   string
-	TargetPrefix  string
-}

+ 105 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session.go

@@ -0,0 +1,105 @@
+// Package session provides a way to create service clients with shared configuration
+// and handlers.
+package session
+
+import (
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/corehandlers"
+	"github.com/aws/aws-sdk-go/aws/defaults"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/private/endpoints"
+)
+
+// A Session provides a central location to create service clients from and
+// store configurations and request handlers for those services.
+//
+// Sessions are safe to create service clients concurrently, but it is not safe
+// to mutate the session concurrently.
+type Session struct {
+	Config   *aws.Config
+	Handlers request.Handlers
+}
+
+// New creates a new instance of the handlers merging in the provided Configs
+// on top of the SDK's default configurations. Once the session is created it
+// can be mutated to modify Configs or Handlers. The session is safe to be read
+// concurrently, but it should not be written to concurrently.
+//
+// Example:
+//     // Create a session with the default config and request handlers.
+//     sess := session.New()
+//
+//     // Create a session with a custom region
+//     sess := session.New(&aws.Config{Region: aws.String("us-east-1")})
+//
+//     // Create a session, and add additional handlers for all service
+//     // clients created with the session to inherit. Adds logging handler.
+//     sess := session.New()
+//     sess.Handlers.Send.PushFront(func(r *request.Request) {
+//          // Log every request made and its payload
+//          logger.Println("Request: %s/%s, Payload: %s", r.ClientInfo.ServiceName, r.Operation, r.Params)
+//     })
+//
+//     // Create a S3 client instance from a session
+//     sess := session.New()
+//     svc := s3.New(sess)
+func New(cfgs ...*aws.Config) *Session {
+	def := defaults.Get()
+	s := &Session{
+		Config:   def.Config,
+		Handlers: def.Handlers,
+	}
+	s.Config.MergeIn(cfgs...)
+
+	initHandlers(s)
+
+	return s
+}
+
+func initHandlers(s *Session) {
+	// Add the Validate parameter handler if it is not disabled.
+	s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
+	if !aws.BoolValue(s.Config.DisableParamValidation) {
+		s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
+	}
+}
+
+// Copy creates and returns a copy of the current session, coping the config
+// and handlers. If any additional configs are provided they will be merged
+// on top of the session's copied config.
+//
+// Example:
+//     // Create a copy of the current session, configured for the us-west-2 region.
+//     sess.Copy(&aws.Config{Region: aws.String("us-west-2"})
+func (s *Session) Copy(cfgs ...*aws.Config) *Session {
+	newSession := &Session{
+		Config:   s.Config.Copy(cfgs...),
+		Handlers: s.Handlers.Copy(),
+	}
+
+	initHandlers(newSession)
+
+	return newSession
+}
+
+// ClientConfig satisfies the client.ConfigProvider interface and is used to
+// configure the service client instances. Passing the Session to the service
+// client's constructor (New) will use this method to configure the client.
+//
+// Example:
+//     sess := session.New()
+//     s3.New(sess)
+func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
+	s = s.Copy(cfgs...)
+	endpoint, signingRegion := endpoints.NormalizeEndpoint(
+		aws.StringValue(s.Config.Endpoint), serviceName,
+		aws.StringValue(s.Config.Region), aws.BoolValue(s.Config.DisableSSL))
+
+	return client.Config{
+		Config:        s.Config,
+		Handlers:      s.Handlers,
+		Endpoint:      endpoint,
+		SigningRegion: signingRegion,
+	}
+}

+ 20 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/session/session_test.go

@@ -0,0 +1,20 @@
+package session_test
+
+import (
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/session"
+)
+
+func TestNewDefaultSession(t *testing.T) {
+	s := session.New(&aws.Config{Region: aws.String("region")})
+
+	assert.Equal(t, "region", *s.Config.Region)
+	assert.Equal(t, http.DefaultClient, s.Config.HTTPClient)
+	assert.NotNil(t, s.Config.Logger)
+	assert.Equal(t, aws.LogOff, *s.Config.LogLevel)
+}

+ 1 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types.go

@@ -5,7 +5,7 @@ import (
 	"sync"
 	"sync"
 )
 )
 
 
-// ReadSeekCloser wraps a io.Reader returning a ReaderSeakerCloser
+// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser
 func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
 func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
 	return ReaderSeekerCloser{r}
 	return ReaderSeekerCloser{r}
 }
 }

+ 1 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go

@@ -5,4 +5,4 @@ package aws
 const SDKName = "aws-sdk-go"
 const SDKName = "aws-sdk-go"
 
 
 // SDKVersion is the version of this SDK
 // SDKVersion is the version of this SDK
-const SDKVersion = "0.9.16"
+const SDKVersion = "1.0.0"

+ 38 - 4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints.go

@@ -4,11 +4,27 @@ package endpoints
 //go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go
 //go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go
 //go:generate gofmt -s -w endpoints_map.go
 //go:generate gofmt -s -w endpoints_map.go
 
 
-import "strings"
+import (
+	"fmt"
+	"regexp"
+	"strings"
+)
+
+// NormalizeEndpoint takes and endpoint and service API information to return a
+// normalized endpoint and signing region.  If the endpoint is not an empty string
+// the service name and region will be used to look up the service's API endpoint.
+// If the endpoint is provided the scheme will be added if it is not present.
+func NormalizeEndpoint(endpoint, serviceName, region string, disableSSL bool) (normEndpoint, signingRegion string) {
+	if endpoint == "" {
+		return EndpointForRegion(serviceName, region, disableSSL)
+	}
+
+	return AddScheme(endpoint, disableSSL), ""
+}
 
 
 // EndpointForRegion returns an endpoint and its signing region for a service and region.
 // EndpointForRegion returns an endpoint and its signing region for a service and region.
 // if the service and region pair are not found endpoint and signingRegion will be empty.
 // if the service and region pair are not found endpoint and signingRegion will be empty.
-func EndpointForRegion(svcName, region string) (endpoint, signingRegion string) {
+func EndpointForRegion(svcName, region string, disableSSL bool) (endpoint, signingRegion string) {
 	derivedKeys := []string{
 	derivedKeys := []string{
 		region + "/" + svcName,
 		region + "/" + svcName,
 		region + "/*",
 		region + "/*",
@@ -24,8 +40,26 @@ func EndpointForRegion(svcName, region string) (endpoint, signingRegion string)
 
 
 			endpoint = ep
 			endpoint = ep
 			signingRegion = val.SigningRegion
 			signingRegion = val.SigningRegion
-			return
+			break
 		}
 		}
 	}
 	}
-	return
+
+	return AddScheme(endpoint, disableSSL), signingRegion
+}
+
+// Regular expression to determine if the endpoint string is prefixed with a scheme.
+var schemeRE = regexp.MustCompile("^([^:]+)://")
+
+// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
+// scheme. If disableSSL is true HTTP will be added instead of the default HTTPS.
+func AddScheme(endpoint string, disableSSL bool) string {
+	if endpoint != "" && !schemeRE.MatchString(endpoint) {
+		scheme := "https"
+		if disableSSL {
+			scheme = "http"
+		}
+		endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
+	}
+
+	return endpoint
 }
 }

+ 8 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints.json

@@ -29,6 +29,10 @@
       "endpoint": "",
       "endpoint": "",
       "signingRegion": "us-east-1"
       "signingRegion": "us-east-1"
     },
     },
+    "*/ec2metadata": {
+      "endpoint": "http://169.254.169.254/latest",
+      "signingRegion": "us-east-1"
+    },
     "*/iam": {
     "*/iam": {
       "endpoint": "iam.amazonaws.com",
       "endpoint": "iam.amazonaws.com",
       "signingRegion": "us-east-1"
       "signingRegion": "us-east-1"
@@ -45,6 +49,10 @@
       "endpoint": "sts.amazonaws.com",
       "endpoint": "sts.amazonaws.com",
       "signingRegion": "us-east-1"
       "signingRegion": "us-east-1"
     },
     },
+    "*/waf": {
+      "endpoint": "waf.amazonaws.com",
+      "signingRegion": "us-east-1"
+    },
     "us-east-1/sdb": {
     "us-east-1/sdb": {
       "endpoint": "sdb.amazonaws.com",
       "endpoint": "sdb.amazonaws.com",
       "signingRegion": "us-east-1"
       "signingRegion": "us-east-1"

+ 8 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_map.go

@@ -30,6 +30,10 @@ var endpointsMap = endpointStruct{
 			Endpoint:      "",
 			Endpoint:      "",
 			SigningRegion: "us-east-1",
 			SigningRegion: "us-east-1",
 		},
 		},
+		"*/ec2metadata": {
+			Endpoint:      "http://169.254.169.254/latest",
+			SigningRegion: "us-east-1",
+		},
 		"*/iam": {
 		"*/iam": {
 			Endpoint:      "iam.amazonaws.com",
 			Endpoint:      "iam.amazonaws.com",
 			SigningRegion: "us-east-1",
 			SigningRegion: "us-east-1",
@@ -46,6 +50,10 @@ var endpointsMap = endpointStruct{
 			Endpoint:      "sts.amazonaws.com",
 			Endpoint:      "sts.amazonaws.com",
 			SigningRegion: "us-east-1",
 			SigningRegion: "us-east-1",
 		},
 		},
+		"*/waf": {
+			Endpoint:      "waf.amazonaws.com",
+			SigningRegion: "us-east-1",
+		},
 		"ap-northeast-1/s3": {
 		"ap-northeast-1/s3": {
 			Endpoint: "s3-{region}.amazonaws.com",
 			Endpoint: "s3-{region}.amazonaws.com",
 		},
 		},

+ 20 - 7
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/endpoints/endpoints_test.go

@@ -1,28 +1,41 @@
-package endpoints
+package endpoints_test
 
 
 import (
 import (
+	"fmt"
 	"testing"
 	"testing"
 
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
+
+	"github.com/aws/aws-sdk-go/private/endpoints"
 )
 )
 
 
+func TestGenericEndpoint(t *testing.T) {
+	name := "service"
+	region := "mock-region-1"
+
+	ep, sr := endpoints.EndpointForRegion(name, region, false)
+	assert.Equal(t, fmt.Sprintf("https://%s.%s.amazonaws.com", name, region), ep)
+	assert.Empty(t, sr)
+}
+
 func TestGlobalEndpoints(t *testing.T) {
 func TestGlobalEndpoints(t *testing.T) {
 	region := "mock-region-1"
 	region := "mock-region-1"
-	svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts"}
+	svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "waf"}
 
 
 	for _, name := range svcs {
 	for _, name := range svcs {
-		ep, sr := EndpointForRegion(name, region)
-		assert.Equal(t, name+".amazonaws.com", ep)
+		ep, sr := endpoints.EndpointForRegion(name, region, false)
+		assert.Equal(t, fmt.Sprintf("https://%s.amazonaws.com", name), ep)
 		assert.Equal(t, "us-east-1", sr)
 		assert.Equal(t, "us-east-1", sr)
 	}
 	}
 }
 }
 
 
 func TestServicesInCN(t *testing.T) {
 func TestServicesInCN(t *testing.T) {
 	region := "cn-north-1"
 	region := "cn-north-1"
-	svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3"}
+	svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3", "waf"}
 
 
 	for _, name := range svcs {
 	for _, name := range svcs {
-		ep, _ := EndpointForRegion(name, region)
-		assert.Equal(t, name+"."+region+".amazonaws.com.cn", ep)
+		ep, sr := endpoints.EndpointForRegion(name, region, false)
+		assert.Equal(t, fmt.Sprintf("https://%s.%s.amazonaws.com.cn", name, region), ep)
+		assert.Empty(t, sr)
 	}
 	}
 }
 }

+ 1 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build.go

@@ -15,7 +15,7 @@ import (
 func Build(r *request.Request) {
 func Build(r *request.Request) {
 	body := url.Values{
 	body := url.Values{
 		"Action":  {r.Operation.Name},
 		"Action":  {r.Operation.Name},
-		"Version": {r.Service.APIVersion},
+		"Version": {r.ClientInfo.APIVersion},
 	}
 	}
 	if err := queryutil.Parse(body, r.Params, true); err != nil {
 	if err := queryutil.Parse(body, r.Params, true); err != nil {
 		r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err)
 		r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err)

+ 2 - 2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_bench_test.go

@@ -7,7 +7,7 @@ import (
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
+	"github.com/aws/aws-sdk-go/awstesting"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/service/ec2"
 	"github.com/aws/aws-sdk-go/service/ec2"
 )
 )
@@ -67,7 +67,7 @@ func BenchmarkEC2QueryBuild_Simple_ec2AttachNetworkInterface(b *testing.B) {
 }
 }
 
 
 func benchEC2QueryBuild(b *testing.B, opName string, params interface{}) {
 func benchEC2QueryBuild(b *testing.B, opName string, params interface{}) {
-	svc := service.New(nil)
+	svc := awstesting.NewClient()
 	svc.ServiceName = "ec2"
 	svc.ServiceName = "ec2"
 	svc.APIVersion = "2015-04-15"
 	svc.APIVersion = "2015-04-15"
 
 

+ 316 - 147
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/build_test.go

@@ -12,10 +12,10 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/defaults"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
+	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/awstesting"
 	"github.com/aws/aws-sdk-go/awstesting"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
 	"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
@@ -35,30 +35,52 @@ var _ = ioutil.Discard
 var _ = util.Trim("")
 var _ = util.Trim("")
 var _ = url.Values{}
 var _ = url.Values{}
 var _ = io.EOF
 var _ = io.EOF
+var _ = aws.String
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService1ProtocolTest struct {
 type InputService1ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService1ProtocolTest client.
-func NewInputService1ProtocolTest(config *aws.Config) *InputService1ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice1protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService1ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService1ProtocolTest client from just a session.
+//     svc := inputservice1protocoltest.New(mySession)
+//
+//     // Create a InputService1ProtocolTest client with additional configuration
+//     svc := inputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService1ProtocolTest {
+	c := p.ClientConfig("inputservice1protocoltest", cfgs...)
+	return newInputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService1ProtocolTest {
+	svc := &InputService1ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice1protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService1ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService1ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService1ProtocolTest operation and runs any
@@ -113,29 +135,50 @@ type metadataInputService1TestShapeInputService1TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService2ProtocolTest struct {
 type InputService2ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService2ProtocolTest client.
-func NewInputService2ProtocolTest(config *aws.Config) *InputService2ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice2protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService2ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService2ProtocolTest client from just a session.
+//     svc := inputservice2protocoltest.New(mySession)
+//
+//     // Create a InputService2ProtocolTest client with additional configuration
+//     svc := inputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService2ProtocolTest {
+	c := p.ClientConfig("inputservice2protocoltest", cfgs...)
+	return newInputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService2ProtocolTest {
+	svc := &InputService2ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice2protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService2ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService2ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService2ProtocolTest operation and runs any
@@ -192,29 +235,50 @@ type metadataInputService2TestShapeInputService2TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService3ProtocolTest struct {
 type InputService3ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService3ProtocolTest client.
-func NewInputService3ProtocolTest(config *aws.Config) *InputService3ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice3protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService3ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService3ProtocolTest client from just a session.
+//     svc := inputservice3protocoltest.New(mySession)
+//
+//     // Create a InputService3ProtocolTest client with additional configuration
+//     svc := inputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService3ProtocolTest {
+	c := p.ClientConfig("inputservice3protocoltest", cfgs...)
+	return newInputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService3ProtocolTest {
+	svc := &InputService3ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice3protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService3ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService3ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService3ProtocolTest operation and runs any
@@ -277,29 +341,50 @@ type metadataInputService3TestShapeStructType struct {
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService4ProtocolTest struct {
 type InputService4ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService4ProtocolTest client.
-func NewInputService4ProtocolTest(config *aws.Config) *InputService4ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice4protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService4ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService4ProtocolTest client from just a session.
+//     svc := inputservice4protocoltest.New(mySession)
+//
+//     // Create a InputService4ProtocolTest client with additional configuration
+//     svc := inputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService4ProtocolTest {
+	c := p.ClientConfig("inputservice4protocoltest", cfgs...)
+	return newInputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService4ProtocolTest {
+	svc := &InputService4ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice4protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService4ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService4ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService4ProtocolTest operation and runs any
@@ -352,29 +437,50 @@ type metadataInputService4TestShapeInputService4TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService5ProtocolTest struct {
 type InputService5ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService5ProtocolTest client.
-func NewInputService5ProtocolTest(config *aws.Config) *InputService5ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice5protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService5ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService5ProtocolTest client from just a session.
+//     svc := inputservice5protocoltest.New(mySession)
+//
+//     // Create a InputService5ProtocolTest client with additional configuration
+//     svc := inputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService5ProtocolTest {
+	c := p.ClientConfig("inputservice5protocoltest", cfgs...)
+	return newInputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService5ProtocolTest {
+	svc := &InputService5ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice5protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService5ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService5ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService5ProtocolTest operation and runs any
@@ -427,29 +533,50 @@ type metadataInputService5TestShapeInputService5TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService6ProtocolTest struct {
 type InputService6ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService6ProtocolTest client.
-func NewInputService6ProtocolTest(config *aws.Config) *InputService6ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice6protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService6ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService6ProtocolTest client from just a session.
+//     svc := inputservice6protocoltest.New(mySession)
+//
+//     // Create a InputService6ProtocolTest client with additional configuration
+//     svc := inputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService6ProtocolTest {
+	c := p.ClientConfig("inputservice6protocoltest", cfgs...)
+	return newInputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService6ProtocolTest {
+	svc := &InputService6ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice6protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService6ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService6ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService6ProtocolTest operation and runs any
@@ -502,29 +629,50 @@ type metadataInputService6TestShapeInputService6TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService7ProtocolTest struct {
 type InputService7ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService7ProtocolTest client.
-func NewInputService7ProtocolTest(config *aws.Config) *InputService7ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice7protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService7ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService7ProtocolTest client from just a session.
+//     svc := inputservice7protocoltest.New(mySession)
+//
+//     // Create a InputService7ProtocolTest client with additional configuration
+//     svc := inputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService7ProtocolTest {
+	c := p.ClientConfig("inputservice7protocoltest", cfgs...)
+	return newInputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService7ProtocolTest {
+	svc := &InputService7ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice7protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService7ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService7ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService7ProtocolTest operation and runs any
@@ -577,29 +725,50 @@ type metadataInputService7TestShapeInputService7TestCaseOperation1Output struct
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type InputService8ProtocolTest struct {
 type InputService8ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new InputService8ProtocolTest client.
-func NewInputService8ProtocolTest(config *aws.Config) *InputService8ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "inputservice8protocoltest",
-			APIVersion:  "2014-01-01",
-		},
+// New creates a new instance of the InputService8ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a InputService8ProtocolTest client from just a session.
+//     svc := inputservice8protocoltest.New(mySession)
+//
+//     // Create a InputService8ProtocolTest client with additional configuration
+//     svc := inputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewInputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *InputService8ProtocolTest {
+	c := p.ClientConfig("inputservice8protocoltest", cfgs...)
+	return newInputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newInputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *InputService8ProtocolTest {
+	svc := &InputService8ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "inputservice8protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2014-01-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &InputService8ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a InputService8ProtocolTest operation and runs any
 // newRequest creates a new request for a InputService8ProtocolTest operation and runs any
@@ -657,8 +826,8 @@ type metadataInputService8TestShapeInputService8TestCaseOperation1Output struct
 //
 //
 
 
 func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) {
 func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) {
-	svc := NewInputService1ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService1TestShapeInputService1TestCaseOperation1Input{
 	input := &InputService1TestShapeInputService1TestCaseOperation1Input{
 		Bar: aws.String("val2"),
 		Bar: aws.String("val2"),
@@ -684,8 +853,8 @@ func TestInputService1ProtocolTestScalarMembersCase1(t *testing.T) {
 }
 }
 
 
 func TestInputService2ProtocolTestStructureWithLocationNameAndQueryNameAppliedToMembersCase1(t *testing.T) {
 func TestInputService2ProtocolTestStructureWithLocationNameAndQueryNameAppliedToMembersCase1(t *testing.T) {
-	svc := NewInputService2ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService2TestShapeInputService2TestCaseOperation1Input{
 	input := &InputService2TestShapeInputService2TestCaseOperation1Input{
 		Bar:  aws.String("val2"),
 		Bar:  aws.String("val2"),
@@ -712,8 +881,8 @@ func TestInputService2ProtocolTestStructureWithLocationNameAndQueryNameAppliedTo
 }
 }
 
 
 func TestInputService3ProtocolTestNestedStructureMembersCase1(t *testing.T) {
 func TestInputService3ProtocolTestNestedStructureMembersCase1(t *testing.T) {
-	svc := NewInputService3ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService3TestShapeInputService3TestCaseOperation1Input{
 	input := &InputService3TestShapeInputService3TestCaseOperation1Input{
 		StructArg: &InputService3TestShapeStructType{
 		StructArg: &InputService3TestShapeStructType{
@@ -740,8 +909,8 @@ func TestInputService3ProtocolTestNestedStructureMembersCase1(t *testing.T) {
 }
 }
 
 
 func TestInputService4ProtocolTestListTypesCase1(t *testing.T) {
 func TestInputService4ProtocolTestListTypesCase1(t *testing.T) {
-	svc := NewInputService4ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService4TestShapeInputService4TestCaseOperation1Input{
 	input := &InputService4TestShapeInputService4TestCaseOperation1Input{
 		ListArg: []*string{
 		ListArg: []*string{
@@ -770,8 +939,8 @@ func TestInputService4ProtocolTestListTypesCase1(t *testing.T) {
 }
 }
 
 
 func TestInputService5ProtocolTestListWithLocationNameAppliedToMemberCase1(t *testing.T) {
 func TestInputService5ProtocolTestListWithLocationNameAppliedToMemberCase1(t *testing.T) {
-	svc := NewInputService5ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService5TestShapeInputService5TestCaseOperation1Input{
 	input := &InputService5TestShapeInputService5TestCaseOperation1Input{
 		ListArg: []*string{
 		ListArg: []*string{
@@ -800,8 +969,8 @@ func TestInputService5ProtocolTestListWithLocationNameAppliedToMemberCase1(t *te
 }
 }
 
 
 func TestInputService6ProtocolTestListWithLocationNameAndQueryNameCase1(t *testing.T) {
 func TestInputService6ProtocolTestListWithLocationNameAndQueryNameCase1(t *testing.T) {
-	svc := NewInputService6ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService6TestShapeInputService6TestCaseOperation1Input{
 	input := &InputService6TestShapeInputService6TestCaseOperation1Input{
 		ListArg: []*string{
 		ListArg: []*string{
@@ -830,8 +999,8 @@ func TestInputService6ProtocolTestListWithLocationNameAndQueryNameCase1(t *testi
 }
 }
 
 
 func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) {
 func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) {
-	svc := NewInputService7ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService7TestShapeInputService7TestCaseOperation1Input{
 	input := &InputService7TestShapeInputService7TestCaseOperation1Input{
 		BlobArg: []byte("foo"),
 		BlobArg: []byte("foo"),
@@ -856,8 +1025,8 @@ func TestInputService7ProtocolTestBase64EncodedBlobsCase1(t *testing.T) {
 }
 }
 
 
 func TestInputService8ProtocolTestTimestampValuesCase1(t *testing.T) {
 func TestInputService8ProtocolTestTimestampValuesCase1(t *testing.T) {
-	svc := NewInputService8ProtocolTest(nil)
-	svc.Endpoint = "https://test"
+	sess := session.New()
+	svc := NewInputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	input := &InputService8TestShapeInputService8TestCaseOperation1Input{
 	input := &InputService8TestShapeInputService8TestCaseOperation1Input{
 		TimeArg: aws.Time(time.Unix(1422172800, 0)),
 		TimeArg: aws.Time(time.Unix(1422172800, 0)),

+ 433 - 139
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/ec2query/unmarshal_test.go

@@ -12,10 +12,10 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/defaults"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
+	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/awstesting"
 	"github.com/aws/aws-sdk-go/awstesting"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
 	"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
@@ -35,30 +35,52 @@ var _ = ioutil.Discard
 var _ = util.Trim("")
 var _ = util.Trim("")
 var _ = url.Values{}
 var _ = url.Values{}
 var _ = io.EOF
 var _ = io.EOF
+var _ = aws.String
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService1ProtocolTest struct {
 type OutputService1ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService1ProtocolTest client.
-func NewOutputService1ProtocolTest(config *aws.Config) *OutputService1ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice1protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService1ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService1ProtocolTest client from just a session.
+//     svc := outputservice1protocoltest.New(mySession)
+//
+//     // Create a OutputService1ProtocolTest client with additional configuration
+//     svc := outputservice1protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService1ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService1ProtocolTest {
+	c := p.ClientConfig("outputservice1protocoltest", cfgs...)
+	return newOutputService1ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService1ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService1ProtocolTest {
+	svc := &OutputService1ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice1protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService1ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService1ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService1ProtocolTest operation and runs any
@@ -125,29 +147,50 @@ type metadataOutputService1TestShapeOutputService1TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService2ProtocolTest struct {
 type OutputService2ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService2ProtocolTest client.
-func NewOutputService2ProtocolTest(config *aws.Config) *OutputService2ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice2protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService2ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService2ProtocolTest client from just a session.
+//     svc := outputservice2protocoltest.New(mySession)
+//
+//     // Create a OutputService2ProtocolTest client with additional configuration
+//     svc := outputservice2protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService2ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService2ProtocolTest {
+	c := p.ClientConfig("outputservice2protocoltest", cfgs...)
+	return newOutputService2ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService2ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService2ProtocolTest {
+	svc := &OutputService2ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice2protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService2ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService2ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService2ProtocolTest operation and runs any
@@ -200,29 +243,50 @@ type metadataOutputService2TestShapeOutputService2TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService3ProtocolTest struct {
 type OutputService3ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService3ProtocolTest client.
-func NewOutputService3ProtocolTest(config *aws.Config) *OutputService3ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice3protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService3ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService3ProtocolTest client from just a session.
+//     svc := outputservice3protocoltest.New(mySession)
+//
+//     // Create a OutputService3ProtocolTest client with additional configuration
+//     svc := outputservice3protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService3ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService3ProtocolTest {
+	c := p.ClientConfig("outputservice3protocoltest", cfgs...)
+	return newOutputService3ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService3ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService3ProtocolTest {
+	svc := &OutputService3ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice3protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService3ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService3ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService3ProtocolTest operation and runs any
@@ -275,29 +339,50 @@ type metadataOutputService3TestShapeOutputService3TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService4ProtocolTest struct {
 type OutputService4ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService4ProtocolTest client.
-func NewOutputService4ProtocolTest(config *aws.Config) *OutputService4ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice4protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService4ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService4ProtocolTest client from just a session.
+//     svc := outputservice4protocoltest.New(mySession)
+//
+//     // Create a OutputService4ProtocolTest client with additional configuration
+//     svc := outputservice4protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService4ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService4ProtocolTest {
+	c := p.ClientConfig("outputservice4protocoltest", cfgs...)
+	return newOutputService4ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService4ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService4ProtocolTest {
+	svc := &OutputService4ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice4protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService4ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService4ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService4ProtocolTest operation and runs any
@@ -350,29 +435,50 @@ type metadataOutputService4TestShapeOutputService4TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService5ProtocolTest struct {
 type OutputService5ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService5ProtocolTest client.
-func NewOutputService5ProtocolTest(config *aws.Config) *OutputService5ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice5protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService5ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService5ProtocolTest client from just a session.
+//     svc := outputservice5protocoltest.New(mySession)
+//
+//     // Create a OutputService5ProtocolTest client with additional configuration
+//     svc := outputservice5protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService5ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService5ProtocolTest {
+	c := p.ClientConfig("outputservice5protocoltest", cfgs...)
+	return newOutputService5ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService5ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService5ProtocolTest {
+	svc := &OutputService5ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice5protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService5ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService5ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService5ProtocolTest operation and runs any
@@ -425,29 +531,50 @@ type metadataOutputService5TestShapeOutputService5TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService6ProtocolTest struct {
 type OutputService6ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService6ProtocolTest client.
-func NewOutputService6ProtocolTest(config *aws.Config) *OutputService6ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice6protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService6ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService6ProtocolTest client from just a session.
+//     svc := outputservice6protocoltest.New(mySession)
+//
+//     // Create a OutputService6ProtocolTest client with additional configuration
+//     svc := outputservice6protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService6ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService6ProtocolTest {
+	c := p.ClientConfig("outputservice6protocoltest", cfgs...)
+	return newOutputService6ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService6ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService6ProtocolTest {
+	svc := &OutputService6ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice6protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService6ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService6ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService6ProtocolTest operation and runs any
@@ -510,29 +637,50 @@ type metadataOutputService6TestShapeStructureType struct {
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService7ProtocolTest struct {
 type OutputService7ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService7ProtocolTest client.
-func NewOutputService7ProtocolTest(config *aws.Config) *OutputService7ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice7protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService7ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService7ProtocolTest client from just a session.
+//     svc := outputservice7protocoltest.New(mySession)
+//
+//     // Create a OutputService7ProtocolTest client with additional configuration
+//     svc := outputservice7protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService7ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService7ProtocolTest {
+	c := p.ClientConfig("outputservice7protocoltest", cfgs...)
+	return newOutputService7ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService7ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService7ProtocolTest {
+	svc := &OutputService7ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice7protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService7ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService7ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService7ProtocolTest operation and runs any
@@ -585,29 +733,50 @@ type metadataOutputService7TestShapeOutputService7TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type OutputService8ProtocolTest struct {
 type OutputService8ProtocolTest struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// New returns a new OutputService8ProtocolTest client.
-func NewOutputService8ProtocolTest(config *aws.Config) *OutputService8ProtocolTest {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "outputservice8protocoltest",
-			APIVersion:  "",
-		},
+// New creates a new instance of the OutputService8ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService8ProtocolTest client from just a session.
+//     svc := outputservice8protocoltest.New(mySession)
+//
+//     // Create a OutputService8ProtocolTest client with additional configuration
+//     svc := outputservice8protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService8ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService8ProtocolTest {
+	c := p.ClientConfig("outputservice8protocoltest", cfgs...)
+	return newOutputService8ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService8ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService8ProtocolTest {
+	svc := &OutputService8ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice8protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	return &OutputService8ProtocolTest{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a OutputService8ProtocolTest operation and runs any
 // newRequest creates a new request for a OutputService8ProtocolTest operation and runs any
@@ -660,12 +829,109 @@ type metadataOutputService8TestShapeOutputService8TestCaseOperation1Output struc
 	SDKShapeTraits bool `type:"structure"`
 	SDKShapeTraits bool `type:"structure"`
 }
 }
 
 
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
+type OutputService9ProtocolTest struct {
+	*client.Client
+}
+
+// New creates a new instance of the OutputService9ProtocolTest client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a OutputService9ProtocolTest client from just a session.
+//     svc := outputservice9protocoltest.New(mySession)
+//
+//     // Create a OutputService9ProtocolTest client with additional configuration
+//     svc := outputservice9protocoltest.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func NewOutputService9ProtocolTest(p client.ConfigProvider, cfgs ...*aws.Config) *OutputService9ProtocolTest {
+	c := p.ClientConfig("outputservice9protocoltest", cfgs...)
+	return newOutputService9ProtocolTestClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newOutputService9ProtocolTestClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *OutputService9ProtocolTest {
+	svc := &OutputService9ProtocolTest{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   "outputservice9protocoltest",
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "",
+			},
+			handlers,
+		),
+	}
+
+	// Handlers
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+
+	return svc
+}
+
+// newRequest creates a new request for a OutputService9ProtocolTest operation and runs any
+// custom request initialization.
+func (c *OutputService9ProtocolTest) newRequest(op *request.Operation, params, data interface{}) *request.Request {
+	req := c.NewRequest(op, params, data)
+
+	return req
+}
+
+const opOutputService9TestCaseOperation1 = "OperationName"
+
+// OutputService9TestCaseOperation1Request generates a request for the OutputService9TestCaseOperation1 operation.
+func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1Request(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (req *request.Request, output *OutputService9TestShapeOutputService9TestCaseOperation1Output) {
+	op := &request.Operation{
+		Name: opOutputService9TestCaseOperation1,
+	}
+
+	if input == nil {
+		input = &OutputService9TestShapeOutputService9TestCaseOperation1Input{}
+	}
+
+	req = c.newRequest(op, input, output)
+	output = &OutputService9TestShapeOutputService9TestCaseOperation1Output{}
+	req.Data = output
+	return
+}
+
+func (c *OutputService9ProtocolTest) OutputService9TestCaseOperation1(input *OutputService9TestShapeOutputService9TestCaseOperation1Input) (*OutputService9TestShapeOutputService9TestCaseOperation1Output, error) {
+	req, out := c.OutputService9TestCaseOperation1Request(input)
+	err := req.Send()
+	return out, err
+}
+
+type OutputService9TestShapeOutputService9TestCaseOperation1Input struct {
+	metadataOutputService9TestShapeOutputService9TestCaseOperation1Input `json:"-" xml:"-"`
+}
+
+type metadataOutputService9TestShapeOutputService9TestCaseOperation1Input struct {
+	SDKShapeTraits bool `type:"structure"`
+}
+
+type OutputService9TestShapeOutputService9TestCaseOperation1Output struct {
+	Foo *string `type:"string"`
+
+	metadataOutputService9TestShapeOutputService9TestCaseOperation1Output `json:"-" xml:"-"`
+}
+
+type metadataOutputService9TestShapeOutputService9TestCaseOperation1Output struct {
+	SDKShapeTraits bool `type:"structure"`
+}
+
 //
 //
 // Tests begin here
 // Tests begin here
 //
 //
 
 
 func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) {
 func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) {
-	svc := NewOutputService1ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService1ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Str>myname</Str><FooNum>123</FooNum><FalseBool>false</FalseBool><TrueBool>true</TrueBool><Float>1.2</Float><Double>1.3</Double><Long>200</Long><Char>a</Char><RequestId>request-id</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Str>myname</Str><FooNum>123</FooNum><FalseBool>false</FalseBool><TrueBool>true</TrueBool><Float>1.2</Float><Double>1.3</Double><Long>200</Long><Char>a</Char><RequestId>request-id</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService1TestCaseOperation1Request(nil)
 	req, out := svc.OutputService1TestCaseOperation1Request(nil)
@@ -692,7 +958,8 @@ func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService2ProtocolTestBlobCase1(t *testing.T) {
 func TestOutputService2ProtocolTestBlobCase1(t *testing.T) {
-	svc := NewOutputService2ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService2ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Blob>dmFsdWU=</Blob><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Blob>dmFsdWU=</Blob><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService2TestCaseOperation1Request(nil)
 	req, out := svc.OutputService2TestCaseOperation1Request(nil)
@@ -712,7 +979,8 @@ func TestOutputService2ProtocolTestBlobCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService3ProtocolTestListsCase1(t *testing.T) {
 func TestOutputService3ProtocolTestListsCase1(t *testing.T) {
-	svc := NewOutputService3ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService3ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember><member>abc</member><member>123</member></ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember><member>abc</member><member>123</member></ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService3TestCaseOperation1Request(nil)
 	req, out := svc.OutputService3TestCaseOperation1Request(nil)
@@ -733,7 +1001,8 @@ func TestOutputService3ProtocolTestListsCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService4ProtocolTestListWithCustomMemberNameCase1(t *testing.T) {
 func TestOutputService4ProtocolTestListWithCustomMemberNameCase1(t *testing.T) {
-	svc := NewOutputService4ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService4ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember><item>abc</item><item>123</item></ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember><item>abc</item><item>123</item></ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService4TestCaseOperation1Request(nil)
 	req, out := svc.OutputService4TestCaseOperation1Request(nil)
@@ -754,7 +1023,8 @@ func TestOutputService4ProtocolTestListWithCustomMemberNameCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService5ProtocolTestFlattenedListCase1(t *testing.T) {
 func TestOutputService5ProtocolTestFlattenedListCase1(t *testing.T) {
-	svc := NewOutputService5ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService5ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember>abc</ListMember><ListMember>123</ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><ListMember>abc</ListMember><ListMember>123</ListMember><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService5TestCaseOperation1Request(nil)
 	req, out := svc.OutputService5TestCaseOperation1Request(nil)
@@ -775,7 +1045,8 @@ func TestOutputService5ProtocolTestFlattenedListCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService6ProtocolTestNormalMapCase1(t *testing.T) {
 func TestOutputService6ProtocolTestNormalMapCase1(t *testing.T) {
-	svc := NewOutputService6ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService6ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><entry><key>qux</key><value><foo>bar</foo></value></entry><entry><key>baz</key><value><foo>bam</foo></value></entry></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><entry><key>qux</key><value><foo>bar</foo></value></entry><entry><key>baz</key><value><foo>bam</foo></value></entry></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService6TestCaseOperation1Request(nil)
 	req, out := svc.OutputService6TestCaseOperation1Request(nil)
@@ -796,7 +1067,8 @@ func TestOutputService6ProtocolTestNormalMapCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService7ProtocolTestFlattenedMapCase1(t *testing.T) {
 func TestOutputService7ProtocolTestFlattenedMapCase1(t *testing.T) {
-	svc := NewOutputService7ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService7ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><key>qux</key><value>bar</value></Map><Map><key>baz</key><value>bam</value></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><key>qux</key><value>bar</value></Map><Map><key>baz</key><value>bam</value></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService7TestCaseOperation1Request(nil)
 	req, out := svc.OutputService7TestCaseOperation1Request(nil)
@@ -817,7 +1089,8 @@ func TestOutputService7ProtocolTestFlattenedMapCase1(t *testing.T) {
 }
 }
 
 
 func TestOutputService8ProtocolTestNamedMapCase1(t *testing.T) {
 func TestOutputService8ProtocolTestNamedMapCase1(t *testing.T) {
-	svc := NewOutputService8ProtocolTest(nil)
+	sess := session.New()
+	svc := NewOutputService8ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
 
 
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><foo>qux</foo><bar>bar</bar></Map><Map><foo>baz</foo><bar>bam</bar></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	buf := bytes.NewReader([]byte("<OperationNameResponse><Map><foo>qux</foo><bar>bar</bar></Map><Map><foo>baz</foo><bar>bam</bar></Map><RequestId>requestid</RequestId></OperationNameResponse>"))
 	req, out := svc.OutputService8TestCaseOperation1Request(nil)
 	req, out := svc.OutputService8TestCaseOperation1Request(nil)
@@ -836,3 +1109,24 @@ func TestOutputService8ProtocolTestNamedMapCase1(t *testing.T) {
 	assert.Equal(t, "bar", *out.Map["qux"])
 	assert.Equal(t, "bar", *out.Map["qux"])
 
 
 }
 }
+
+func TestOutputService9ProtocolTestEmptyStringCase1(t *testing.T) {
+	sess := session.New()
+	svc := NewOutputService9ProtocolTest(sess, &aws.Config{Endpoint: aws.String("https://test")})
+
+	buf := bytes.NewReader([]byte("<OperationNameResponse><Foo/><RequestId>requestid</RequestId></OperationNameResponse>"))
+	req, out := svc.OutputService9TestCaseOperation1Request(nil)
+	req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}}
+
+	// set headers
+
+	// unmarshal response
+	ec2query.UnmarshalMeta(req)
+	ec2query.Unmarshal(req)
+	assert.NoError(t, req.Error)
+
+	// assert response
+	assert.NotNil(t, out) // ensure out variable is used
+	assert.Equal(t, "", *out.Foo)
+
+}

+ 1 - 1
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build.go

@@ -15,7 +15,7 @@ import (
 func Build(r *request.Request) {
 func Build(r *request.Request) {
 	body := url.Values{
 	body := url.Values{
 		"Action":  {r.Operation.Name},
 		"Action":  {r.Operation.Name},
-		"Version": {r.Service.APIVersion},
+		"Version": {r.ClientInfo.APIVersion},
 	}
 	}
 	if err := queryutil.Parse(body, r.Params, false); err != nil {
 	if err := queryutil.Parse(body, r.Params, false); err != nil {
 		r.Error = awserr.New("SerializationError", "failed encoding Query request", err)
 		r.Error = awserr.New("SerializationError", "failed encoding Query request", err)

Dosya farkı çok büyük olduğundan ihmal edildi
+ 539 - 196
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/build_test.go


+ 2 - 2
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go

@@ -72,7 +72,7 @@ func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix stri
 			continue // ignore unexported fields
 			continue // ignore unexported fields
 		}
 		}
 
 
-		value := elemOf(value.Field(i))
+		elemValue := elemOf(value.Field(i))
 		field := t.Field(i)
 		field := t.Field(i)
 		var name string
 		var name string
 
 
@@ -97,7 +97,7 @@ func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix stri
 			name = prefix + "." + name
 			name = prefix + "." + name
 		}
 		}
 
 
-		if err := q.parseValue(v, value, name, field.Tag); err != nil {
+		if err := q.parseValue(v, elemValue, name, field.Tag); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 620 - 228
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_test.go


+ 3 - 4
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/functional_test.go

@@ -5,16 +5,15 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	"github.com/stretchr/testify/assert"
+
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/awstesting/unit"
 	"github.com/aws/aws-sdk-go/awstesting/unit"
 	"github.com/aws/aws-sdk-go/service/s3"
 	"github.com/aws/aws-sdk-go/service/s3"
-	"github.com/stretchr/testify/assert"
 )
 )
 
 
-var _ = unit.Imported
-
 func TestPresignHandler(t *testing.T) {
 func TestPresignHandler(t *testing.T) {
-	svc := s3.New(nil)
+	svc := s3.New(unit.Session)
 	req, _ := svc.PutObjectRequest(&s3.PutObjectInput{
 	req, _ := svc.PutObjectRequest(&s3.PutObjectInput{
 		Bucket:             aws.String("bucket"),
 		Bucket:             aws.String("bucket"),
 		Key:                aws.String("key"),
 		Key:                aws.String("key"),

+ 8 - 8
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4.go

@@ -67,18 +67,18 @@ type signer struct {
 func Sign(req *request.Request) {
 func Sign(req *request.Request) {
 	// If the request does not need to be signed ignore the signing of the
 	// If the request does not need to be signed ignore the signing of the
 	// request if the AnonymousCredentials object is used.
 	// request if the AnonymousCredentials object is used.
-	if req.Service.Config.Credentials == credentials.AnonymousCredentials {
+	if req.Config.Credentials == credentials.AnonymousCredentials {
 		return
 		return
 	}
 	}
 
 
-	region := req.Service.SigningRegion
+	region := req.ClientInfo.SigningRegion
 	if region == "" {
 	if region == "" {
-		region = aws.StringValue(req.Service.Config.Region)
+		region = aws.StringValue(req.Config.Region)
 	}
 	}
 
 
-	name := req.Service.SigningName
+	name := req.ClientInfo.SigningName
 	if name == "" {
 	if name == "" {
-		name = req.Service.ServiceName
+		name = req.ClientInfo.ServiceName
 	}
 	}
 
 
 	s := signer{
 	s := signer{
@@ -89,9 +89,9 @@ func Sign(req *request.Request) {
 		Body:        req.Body,
 		Body:        req.Body,
 		ServiceName: name,
 		ServiceName: name,
 		Region:      region,
 		Region:      region,
-		Credentials: req.Service.Config.Credentials,
-		Debug:       req.Service.Config.LogLevel.Value(),
-		Logger:      req.Service.Config.Logger,
+		Credentials: req.Config.Credentials,
+		Debug:       req.Config.LogLevel.Value(),
+		Logger:      req.Config.Logger,
 	}
 	}
 
 
 	req.Error = s.sign()
 	req.Error = s.sign()

+ 13 - 8
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/signer/v4/v4_test.go

@@ -6,11 +6,12 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	"github.com/stretchr/testify/assert"
+
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/credentials"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/stretchr/testify/assert"
+	"github.com/aws/aws-sdk-go/awstesting"
 )
 )
 
 
 func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer {
 func buildSigner(serviceName string, region string, signTime time.Time, expireTime time.Duration, body string) signer {
@@ -118,7 +119,7 @@ func TestSignPrecomputedBodyChecksum(t *testing.T) {
 }
 }
 
 
 func TestAnonymousCredentials(t *testing.T) {
 func TestAnonymousCredentials(t *testing.T) {
-	svc := service.New(&aws.Config{Credentials: credentials.AnonymousCredentials})
+	svc := awstesting.NewClient(&aws.Config{Credentials: credentials.AnonymousCredentials})
 	r := svc.NewRequest(
 	r := svc.NewRequest(
 		&request.Operation{
 		&request.Operation{
 			Name:       "BatchGetItem",
 			Name:       "BatchGetItem",
@@ -142,7 +143,7 @@ func TestAnonymousCredentials(t *testing.T) {
 }
 }
 
 
 func TestIgnoreResignRequestWithValidCreds(t *testing.T) {
 func TestIgnoreResignRequestWithValidCreds(t *testing.T) {
-	svc := service.New(&aws.Config{
+	svc := awstesting.NewClient(&aws.Config{
 		Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
 		Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
 		Region:      aws.String("us-west-2"),
 		Region:      aws.String("us-west-2"),
 	})
 	})
@@ -164,7 +165,7 @@ func TestIgnoreResignRequestWithValidCreds(t *testing.T) {
 }
 }
 
 
 func TestIgnorePreResignRequestWithValidCreds(t *testing.T) {
 func TestIgnorePreResignRequestWithValidCreds(t *testing.T) {
-	svc := service.New(&aws.Config{
+	svc := awstesting.NewClient(&aws.Config{
 		Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
 		Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "SESSION"),
 		Region:      aws.String("us-west-2"),
 		Region:      aws.String("us-west-2"),
 	})
 	})
@@ -188,7 +189,7 @@ func TestIgnorePreResignRequestWithValidCreds(t *testing.T) {
 
 
 func TestResignRequestExpiredCreds(t *testing.T) {
 func TestResignRequestExpiredCreds(t *testing.T) {
 	creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
 	creds := credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
-	svc := service.New(&aws.Config{Credentials: creds})
+	svc := awstesting.NewClient(&aws.Config{Credentials: creds})
 	r := svc.NewRequest(
 	r := svc.NewRequest(
 		&request.Operation{
 		&request.Operation{
 			Name:       "BatchGetItem",
 			Name:       "BatchGetItem",
@@ -208,9 +209,13 @@ func TestResignRequestExpiredCreds(t *testing.T) {
 }
 }
 
 
 func TestPreResignRequestExpiredCreds(t *testing.T) {
 func TestPreResignRequestExpiredCreds(t *testing.T) {
-	provider := &credentials.StaticProvider{credentials.Value{"AKID", "SECRET", "SESSION"}}
+	provider := &credentials.StaticProvider{Value: credentials.Value{
+		AccessKeyID:     "AKID",
+		SecretAccessKey: "SECRET",
+		SessionToken:    "SESSION",
+	}}
 	creds := credentials.NewCredentials(provider)
 	creds := credentials.NewCredentials(provider)
-	svc := service.New(&aws.Config{Credentials: creds})
+	svc := awstesting.NewClient(&aws.Config{Credentials: creds})
 	r := svc.NewRequest(
 	r := svc.NewRequest(
 		&request.Operation{
 		&request.Operation{
 			Name:       "BatchGetItem",
 			Name:       "BatchGetItem",

+ 136 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter.go

@@ -0,0 +1,136 @@
+package waiter
+
+import (
+	"fmt"
+	"reflect"
+	"time"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/aws/awsutil"
+	"github.com/aws/aws-sdk-go/aws/request"
+)
+
+// A Config provides a collection of configuration values to setup a generated
+// waiter code with.
+type Config struct {
+	Name        string
+	Delay       int
+	MaxAttempts int
+	Operation   string
+	Acceptors   []WaitAcceptor
+}
+
+// A WaitAcceptor provides the information needed to wait for an API operation
+// to complete.
+type WaitAcceptor struct {
+	Expected interface{}
+	Matcher  string
+	State    string
+	Argument string
+}
+
+// A Waiter provides waiting for an operation to complete.
+type Waiter struct {
+	Config
+	Client interface{}
+	Input  interface{}
+}
+
+// Wait waits for an operation to complete, expire max attempts, or fail. Error
+// is returned if the operation fails.
+func (w *Waiter) Wait() error {
+	client := reflect.ValueOf(w.Client)
+	in := reflect.ValueOf(w.Input)
+	method := client.MethodByName(w.Config.Operation + "Request")
+
+	for i := 0; i < w.MaxAttempts; i++ {
+		res := method.Call([]reflect.Value{in})
+		req := res[0].Interface().(*request.Request)
+		req.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Waiter"))
+
+		err := req.Send()
+		for _, a := range w.Acceptors {
+			if err != nil && a.Matcher != "error" {
+				// Only matcher error is valid if there is a request error
+				continue
+			}
+
+			result := false
+			var vals []interface{}
+			switch a.Matcher {
+			case "pathAll", "path":
+				// Require all matches to be equal for result to match
+				vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
+				result = true
+				for _, val := range vals {
+					if !awsutil.DeepEqual(val, a.Expected) {
+						result = false
+						break
+					}
+				}
+			case "pathAny":
+				// Only a single match needs to equal for the result to match
+				vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
+				for _, val := range vals {
+					if awsutil.DeepEqual(val, a.Expected) {
+						result = true
+						break
+					}
+				}
+			case "status":
+				s := a.Expected.(int)
+				result = s == req.HTTPResponse.StatusCode
+			case "error":
+				if aerr, ok := err.(awserr.Error); ok {
+					result = aerr.Code() == a.Expected.(string)
+				}
+			case "pathList":
+				// ignored matcher
+			default:
+				logf(client, "WARNING: Waiter for %s encountered unexpected matcher: %s",
+					w.Config.Operation, a.Matcher)
+			}
+
+			if !result {
+				// If there was no matching result found there is nothing more to do
+				// for this response, retry the request.
+				continue
+			}
+
+			switch a.State {
+			case "success":
+				// waiter completed
+				return nil
+			case "failure":
+				// Waiter failure state triggered
+				return awserr.New("ResourceNotReady",
+					fmt.Sprintf("failed waiting for successful resource state"), err)
+			case "retry":
+				// clear the error and retry the operation
+				err = nil
+			default:
+				logf(client, "WARNING: Waiter for %s encountered unexpected state: %s",
+					w.Config.Operation, a.State)
+			}
+		}
+		if err != nil {
+			return err
+		}
+
+		time.Sleep(time.Second * time.Duration(w.Delay))
+	}
+
+	return awserr.New("ResourceNotReady",
+		fmt.Sprintf("exceeded %d wait attempts", w.MaxAttempts), nil)
+}
+
+func logf(client reflect.Value, msg string, args ...interface{}) {
+	cfgVal := client.FieldByName("Config")
+	if !cfgVal.IsValid() {
+		return
+	}
+	if cfg, ok := cfgVal.Interface().(*aws.Config); ok && cfg.Logger != nil {
+		cfg.Logger.Log(fmt.Sprintf(msg, args...))
+	}
+}

+ 391 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/private/waiter/waiter_test.go

@@ -0,0 +1,391 @@
+package waiter_test
+
+import (
+	"bytes"
+	"io/ioutil"
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/awstesting"
+	"github.com/aws/aws-sdk-go/private/waiter"
+)
+
+type mockClient struct {
+	*client.Client
+}
+type MockInput struct{}
+type MockOutput struct {
+	States []*MockState
+}
+type MockState struct {
+	State *string
+}
+
+func (c *mockClient) MockRequest(input *MockInput) (*request.Request, *MockOutput) {
+	op := &request.Operation{
+		Name:       "Mock",
+		HTTPMethod: "POST",
+		HTTPPath:   "/",
+	}
+
+	if input == nil {
+		input = &MockInput{}
+	}
+
+	output := &MockOutput{}
+	req := c.NewRequest(op, input, output)
+	req.Data = output
+	return req, output
+}
+
+func TestWaiterPathAll(t *testing.T) {
+	svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
+		Region: aws.String("mock-region"),
+	})}
+	svc.Handlers.Send.Clear() // mock sending
+	svc.Handlers.Unmarshal.Clear()
+	svc.Handlers.UnmarshalMeta.Clear()
+	svc.Handlers.ValidateResponse.Clear()
+
+	reqNum := 0
+	resps := []*MockOutput{
+		{ // Request 1
+			States: []*MockState{
+				{State: aws.String("pending")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 2
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 3
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("running")},
+			},
+		},
+	}
+
+	numBuiltReq := 0
+	svc.Handlers.Build.PushBack(func(r *request.Request) {
+		numBuiltReq++
+	})
+	svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		if reqNum >= len(resps) {
+			assert.Fail(t, "too many polling requests made")
+			return
+		}
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	waiterCfg := waiter.Config{
+		Operation:   "Mock",
+		Delay:       0,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "States[].State",
+				Expected: "running",
+			},
+		},
+	}
+	w := waiter.Waiter{
+		Client: svc,
+		Input:  &MockInput{},
+		Config: waiterCfg,
+	}
+
+	err := w.Wait()
+	assert.NoError(t, err)
+	assert.Equal(t, 3, numBuiltReq)
+	assert.Equal(t, 3, reqNum)
+}
+
+func TestWaiterPath(t *testing.T) {
+	svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
+		Region: aws.String("mock-region"),
+	})}
+	svc.Handlers.Send.Clear() // mock sending
+	svc.Handlers.Unmarshal.Clear()
+	svc.Handlers.UnmarshalMeta.Clear()
+	svc.Handlers.ValidateResponse.Clear()
+
+	reqNum := 0
+	resps := []*MockOutput{
+		{ // Request 1
+			States: []*MockState{
+				{State: aws.String("pending")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 2
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 3
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("running")},
+			},
+		},
+	}
+
+	numBuiltReq := 0
+	svc.Handlers.Build.PushBack(func(r *request.Request) {
+		numBuiltReq++
+	})
+	svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		if reqNum >= len(resps) {
+			assert.Fail(t, "too many polling requests made")
+			return
+		}
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	waiterCfg := waiter.Config{
+		Operation:   "Mock",
+		Delay:       0,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "path",
+				Argument: "States[].State",
+				Expected: "running",
+			},
+		},
+	}
+	w := waiter.Waiter{
+		Client: svc,
+		Input:  &MockInput{},
+		Config: waiterCfg,
+	}
+
+	err := w.Wait()
+	assert.NoError(t, err)
+	assert.Equal(t, 3, numBuiltReq)
+	assert.Equal(t, 3, reqNum)
+}
+
+func TestWaiterFailure(t *testing.T) {
+	svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
+		Region: aws.String("mock-region"),
+	})}
+	svc.Handlers.Send.Clear() // mock sending
+	svc.Handlers.Unmarshal.Clear()
+	svc.Handlers.UnmarshalMeta.Clear()
+	svc.Handlers.ValidateResponse.Clear()
+
+	reqNum := 0
+	resps := []*MockOutput{
+		{ // Request 1
+			States: []*MockState{
+				{State: aws.String("pending")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 2
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 3
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("stopping")},
+			},
+		},
+	}
+
+	numBuiltReq := 0
+	svc.Handlers.Build.PushBack(func(r *request.Request) {
+		numBuiltReq++
+	})
+	svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		if reqNum >= len(resps) {
+			assert.Fail(t, "too many polling requests made")
+			return
+		}
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	waiterCfg := waiter.Config{
+		Operation:   "Mock",
+		Delay:       0,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "States[].State",
+				Expected: "running",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "States[].State",
+				Expected: "stopping",
+			},
+		},
+	}
+	w := waiter.Waiter{
+		Client: svc,
+		Input:  &MockInput{},
+		Config: waiterCfg,
+	}
+
+	err := w.Wait().(awserr.Error)
+	assert.Error(t, err)
+	assert.Equal(t, "ResourceNotReady", err.Code())
+	assert.Equal(t, "failed waiting for successful resource state", err.Message())
+	assert.Equal(t, 3, numBuiltReq)
+	assert.Equal(t, 3, reqNum)
+}
+
+func TestWaiterError(t *testing.T) {
+	svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
+		Region: aws.String("mock-region"),
+	})}
+	svc.Handlers.Send.Clear() // mock sending
+	svc.Handlers.Unmarshal.Clear()
+	svc.Handlers.UnmarshalMeta.Clear()
+	svc.Handlers.ValidateResponse.Clear()
+
+	reqNum := 0
+	resps := []*MockOutput{
+		{ // Request 1
+			States: []*MockState{
+				{State: aws.String("pending")},
+				{State: aws.String("pending")},
+			},
+		},
+		{ // Request 2, error case
+		},
+		{ // Request 3
+			States: []*MockState{
+				{State: aws.String("running")},
+				{State: aws.String("running")},
+			},
+		},
+	}
+
+	numBuiltReq := 0
+	svc.Handlers.Build.PushBack(func(r *request.Request) {
+		numBuiltReq++
+	})
+	svc.Handlers.Send.PushBack(func(r *request.Request) {
+		if reqNum == 1 {
+			r.Error = awserr.New("MockException", "mock exception message", nil)
+			r.HTTPResponse = &http.Response{
+				StatusCode: 400,
+				Status:     http.StatusText(400),
+				Body:       ioutil.NopCloser(bytes.NewReader([]byte{})),
+			}
+			reqNum++
+		}
+	})
+	svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
+		if reqNum >= len(resps) {
+			assert.Fail(t, "too many polling requests made")
+			return
+		}
+		r.Data = resps[reqNum]
+		reqNum++
+	})
+
+	waiterCfg := waiter.Config{
+		Operation:   "Mock",
+		Delay:       0,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "States[].State",
+				Expected: "running",
+			},
+			{
+				State:    "retry",
+				Matcher:  "error",
+				Argument: "",
+				Expected: "MockException",
+			},
+		},
+	}
+	w := waiter.Waiter{
+		Client: svc,
+		Input:  &MockInput{},
+		Config: waiterCfg,
+	}
+
+	err := w.Wait()
+	assert.NoError(t, err)
+	assert.Equal(t, 3, numBuiltReq)
+	assert.Equal(t, 3, reqNum)
+}
+
+func TestWaiterStatus(t *testing.T) {
+	svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
+		Region: aws.String("mock-region"),
+	})}
+	svc.Handlers.Send.Clear() // mock sending
+	svc.Handlers.Unmarshal.Clear()
+	svc.Handlers.UnmarshalMeta.Clear()
+	svc.Handlers.ValidateResponse.Clear()
+
+	reqNum := 0
+	svc.Handlers.Build.PushBack(func(r *request.Request) {
+		reqNum++
+	})
+	svc.Handlers.Send.PushBack(func(r *request.Request) {
+		code := 200
+		if reqNum == 3 {
+			code = 404
+		}
+		r.HTTPResponse = &http.Response{
+			StatusCode: code,
+			Status:     http.StatusText(code),
+			Body:       ioutil.NopCloser(bytes.NewReader([]byte{})),
+		}
+	})
+
+	waiterCfg := waiter.Config{
+		Operation:   "Mock",
+		Delay:       0,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "status",
+				Argument: "",
+				Expected: 404,
+			},
+		},
+	}
+	w := waiter.Waiter{
+		Client: svc,
+		Input:  &MockInput{},
+		Config: waiterCfg,
+	}
+
+	err := w.Wait()
+	assert.NoError(t, err)
+	assert.Equal(t, 3, reqNum)
+}

+ 3 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/api.go

@@ -74,6 +74,7 @@ func (c *CloudWatch) DescribeAlarmHistory(input *DescribeAlarmHistoryInput) (*De
 
 
 func (c *CloudWatch) DescribeAlarmHistoryPages(input *DescribeAlarmHistoryInput, fn func(p *DescribeAlarmHistoryOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *CloudWatch) DescribeAlarmHistoryPages(input *DescribeAlarmHistoryInput, fn func(p *DescribeAlarmHistoryOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeAlarmHistoryRequest(input)
 	page, _ := c.DescribeAlarmHistoryRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeAlarmHistoryOutput), lastPage)
 		return fn(p.(*DescribeAlarmHistoryOutput), lastPage)
 	})
 	})
@@ -116,6 +117,7 @@ func (c *CloudWatch) DescribeAlarms(input *DescribeAlarmsInput) (*DescribeAlarms
 
 
 func (c *CloudWatch) DescribeAlarmsPages(input *DescribeAlarmsInput, fn func(p *DescribeAlarmsOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *CloudWatch) DescribeAlarmsPages(input *DescribeAlarmsInput, fn func(p *DescribeAlarmsOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeAlarmsRequest(input)
 	page, _ := c.DescribeAlarmsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeAlarmsOutput), lastPage)
 		return fn(p.(*DescribeAlarmsOutput), lastPage)
 	})
 	})
@@ -293,6 +295,7 @@ func (c *CloudWatch) ListMetrics(input *ListMetricsInput) (*ListMetricsOutput, e
 
 
 func (c *CloudWatch) ListMetricsPages(input *ListMetricsInput, fn func(p *ListMetricsOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *CloudWatch) ListMetricsPages(input *ListMetricsInput, fn func(p *ListMetricsOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.ListMetricsRequest(input)
 	page, _ := c.ListMetricsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*ListMetricsOutput), lastPage)
 		return fn(p.(*ListMetricsOutput), lastPage)
 	})
 	})

+ 2 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface/interface.go

@@ -60,3 +60,5 @@ type CloudWatchAPI interface {
 
 
 	SetAlarmState(*cloudwatch.SetAlarmStateInput) (*cloudwatch.SetAlarmStateOutput, error)
 	SetAlarmState(*cloudwatch.SetAlarmStateInput) (*cloudwatch.SetAlarmStateOutput, error)
 }
 }
+
+var _ CloudWatchAPI = (*cloudwatch.CloudWatch)(nil)

+ 0 - 15
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface/interface_test.go

@@ -1,15 +0,0 @@
-// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
-
-package cloudwatchiface_test
-
-import (
-	"testing"
-
-	"github.com/aws/aws-sdk-go/service/cloudwatch"
-	"github.com/aws/aws-sdk-go/service/cloudwatch/cloudwatchiface"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestInterface(t *testing.T) {
-	assert.Implements(t, (*cloudwatchiface.CloudWatchAPI)(nil), cloudwatch.New(nil))
-}

+ 12 - 11
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/examples_test.go

@@ -8,6 +8,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
 	"github.com/aws/aws-sdk-go/service/cloudwatch"
 )
 )
 
 
@@ -15,7 +16,7 @@ var _ time.Duration
 var _ bytes.Buffer
 var _ bytes.Buffer
 
 
 func ExampleCloudWatch_DeleteAlarms() {
 func ExampleCloudWatch_DeleteAlarms() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.DeleteAlarmsInput{
 	params := &cloudwatch.DeleteAlarmsInput{
 		AlarmNames: []*string{ // Required
 		AlarmNames: []*string{ // Required
@@ -37,7 +38,7 @@ func ExampleCloudWatch_DeleteAlarms() {
 }
 }
 
 
 func ExampleCloudWatch_DescribeAlarmHistory() {
 func ExampleCloudWatch_DescribeAlarmHistory() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.DescribeAlarmHistoryInput{
 	params := &cloudwatch.DescribeAlarmHistoryInput{
 		AlarmName:       aws.String("AlarmName"),
 		AlarmName:       aws.String("AlarmName"),
@@ -61,7 +62,7 @@ func ExampleCloudWatch_DescribeAlarmHistory() {
 }
 }
 
 
 func ExampleCloudWatch_DescribeAlarms() {
 func ExampleCloudWatch_DescribeAlarms() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.DescribeAlarmsInput{
 	params := &cloudwatch.DescribeAlarmsInput{
 		ActionPrefix:    aws.String("ActionPrefix"),
 		ActionPrefix:    aws.String("ActionPrefix"),
@@ -88,7 +89,7 @@ func ExampleCloudWatch_DescribeAlarms() {
 }
 }
 
 
 func ExampleCloudWatch_DescribeAlarmsForMetric() {
 func ExampleCloudWatch_DescribeAlarmsForMetric() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.DescribeAlarmsForMetricInput{
 	params := &cloudwatch.DescribeAlarmsForMetricInput{
 		MetricName: aws.String("MetricName"), // Required
 		MetricName: aws.String("MetricName"), // Required
@@ -118,7 +119,7 @@ func ExampleCloudWatch_DescribeAlarmsForMetric() {
 }
 }
 
 
 func ExampleCloudWatch_DisableAlarmActions() {
 func ExampleCloudWatch_DisableAlarmActions() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.DisableAlarmActionsInput{
 	params := &cloudwatch.DisableAlarmActionsInput{
 		AlarmNames: []*string{ // Required
 		AlarmNames: []*string{ // Required
@@ -140,7 +141,7 @@ func ExampleCloudWatch_DisableAlarmActions() {
 }
 }
 
 
 func ExampleCloudWatch_EnableAlarmActions() {
 func ExampleCloudWatch_EnableAlarmActions() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.EnableAlarmActionsInput{
 	params := &cloudwatch.EnableAlarmActionsInput{
 		AlarmNames: []*string{ // Required
 		AlarmNames: []*string{ // Required
@@ -162,7 +163,7 @@ func ExampleCloudWatch_EnableAlarmActions() {
 }
 }
 
 
 func ExampleCloudWatch_GetMetricStatistics() {
 func ExampleCloudWatch_GetMetricStatistics() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.GetMetricStatisticsInput{
 	params := &cloudwatch.GetMetricStatisticsInput{
 		EndTime:    aws.Time(time.Now()),     // Required
 		EndTime:    aws.Time(time.Now()),     // Required
@@ -197,7 +198,7 @@ func ExampleCloudWatch_GetMetricStatistics() {
 }
 }
 
 
 func ExampleCloudWatch_ListMetrics() {
 func ExampleCloudWatch_ListMetrics() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.ListMetricsInput{
 	params := &cloudwatch.ListMetricsInput{
 		Dimensions: []*cloudwatch.DimensionFilter{
 		Dimensions: []*cloudwatch.DimensionFilter{
@@ -225,7 +226,7 @@ func ExampleCloudWatch_ListMetrics() {
 }
 }
 
 
 func ExampleCloudWatch_PutMetricAlarm() {
 func ExampleCloudWatch_PutMetricAlarm() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.PutMetricAlarmInput{
 	params := &cloudwatch.PutMetricAlarmInput{
 		AlarmName:          aws.String("AlarmName"),          // Required
 		AlarmName:          aws.String("AlarmName"),          // Required
@@ -273,7 +274,7 @@ func ExampleCloudWatch_PutMetricAlarm() {
 }
 }
 
 
 func ExampleCloudWatch_PutMetricData() {
 func ExampleCloudWatch_PutMetricData() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.PutMetricDataInput{
 	params := &cloudwatch.PutMetricDataInput{
 		MetricData: []*cloudwatch.MetricDatum{ // Required
 		MetricData: []*cloudwatch.MetricDatum{ // Required
@@ -314,7 +315,7 @@ func ExampleCloudWatch_PutMetricData() {
 }
 }
 
 
 func ExampleCloudWatch_SetAlarmState() {
 func ExampleCloudWatch_SetAlarmState() {
-	svc := cloudwatch.New(nil)
+	svc := cloudwatch.New(session.New())
 
 
 	params := &cloudwatch.SetAlarmStateInput{
 	params := &cloudwatch.SetAlarmStateInput{
 		AlarmName:       aws.String("AlarmName"),   // Required
 		AlarmName:       aws.String("AlarmName"),   // Required

+ 47 - 24
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/cloudwatch/service.go

@@ -4,10 +4,9 @@ package cloudwatch
 
 
 import (
 import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/defaults"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
 	"github.com/aws/aws-sdk-go/private/protocol/query"
 	"github.com/aws/aws-sdk-go/private/protocol/query"
 	"github.com/aws/aws-sdk-go/private/signer/v4"
 	"github.com/aws/aws-sdk-go/private/signer/v4"
 )
 )
@@ -52,40 +51,64 @@ import (
 // Center (http://aws.amazon.com/php/) AWS Python Developer Center (http://aws.amazon.com/python/)
 // Center (http://aws.amazon.com/php/) AWS Python Developer Center (http://aws.amazon.com/python/)
 // AWS Ruby Developer Center (http://aws.amazon.com/ruby/) AWS Windows and .NET
 // AWS Ruby Developer Center (http://aws.amazon.com/ruby/) AWS Windows and .NET
 // Developer Center (http://aws.amazon.com/net/)
 // Developer Center (http://aws.amazon.com/net/)
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type CloudWatch struct {
 type CloudWatch struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// Used for custom service initialization logic
-var initService func(*service.Service)
+// Used for custom client initialization logic
+var initClient func(*client.Client)
 
 
 // Used for custom request initialization logic
 // Used for custom request initialization logic
 var initRequest func(*request.Request)
 var initRequest func(*request.Request)
 
 
-// New returns a new CloudWatch client.
-func New(config *aws.Config) *CloudWatch {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "monitoring",
-			APIVersion:  "2010-08-01",
-		},
+// A ServiceName is the name of the service the client will make API calls to.
+const ServiceName = "monitoring"
+
+// New creates a new instance of the CloudWatch client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a CloudWatch client from just a session.
+//     svc := cloudwatch.New(mySession)
+//
+//     // Create a CloudWatch client with additional configuration
+//     svc := cloudwatch.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func New(p client.ConfigProvider, cfgs ...*aws.Config) *CloudWatch {
+	c := p.ClientConfig(ServiceName, cfgs...)
+	return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *CloudWatch {
+	svc := &CloudWatch{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   ServiceName,
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2010-08-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(query.Build)
-	service.Handlers.Unmarshal.PushBack(query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(query.Build)
+	svc.Handlers.Unmarshal.PushBack(query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(query.UnmarshalError)
 
 
-	// Run custom service initialization if present
-	if initService != nil {
-		initService(service)
+	// Run custom client initialization if present
+	if initClient != nil {
+		initClient(svc.Client)
 	}
 	}
 
 
-	return &CloudWatch{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a CloudWatch operation and runs any
 // newRequest creates a new request for a CloudWatch operation and runs any

+ 58 - 24
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/api.go

@@ -871,7 +871,7 @@ func (c *EC2) CreateCustomerGatewayRequest(input *CreateCustomerGatewayInput) (r
 // gateway is the appliance at your end of the VPN connection. (The device on
 // gateway is the appliance at your end of the VPN connection. (The device on
 // the AWS side of the VPN connection is the virtual private gateway.) You must
 // the AWS side of the VPN connection is the virtual private gateway.) You must
 // provide the Internet-routable IP address of the customer gateway's external
 // provide the Internet-routable IP address of the customer gateway's external
-// interface. The IP address must be static and can't be behind a device performing
+// interface. The IP address must be static and may be behind a device performing
 // network address translation (NAT).
 // network address translation (NAT).
 //
 //
 // For devices that use Border Gateway Protocol (BGP), you can also provide
 // For devices that use Border Gateway Protocol (BGP), you can also provide
@@ -1598,6 +1598,9 @@ func (c *EC2) CreateTagsRequest(input *CreateTagsInput) (req *request.Request, o
 // of a key and optional value. Tag keys must be unique per resource.
 // of a key and optional value. Tag keys must be unique per resource.
 //
 //
 // For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html)
 // For more information about tags, see Tagging Your Resources (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html)
+// in the Amazon Elastic Compute Cloud User Guide. For more information about
+// creating IAM policies that control users' access to resources based on tags,
+// see Supported Resource-Level Permissions for Amazon EC2 API Actions (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-supported-iam-actions-resources.html)
 // in the Amazon Elastic Compute Cloud User Guide.
 // in the Amazon Elastic Compute Cloud User Guide.
 func (c *EC2) CreateTags(input *CreateTagsInput) (*CreateTagsOutput, error) {
 func (c *EC2) CreateTags(input *CreateTagsInput) (*CreateTagsOutput, error) {
 	req, out := c.CreateTagsRequest(input)
 	req, out := c.CreateTagsRequest(input)
@@ -3100,6 +3103,7 @@ func (c *EC2) DescribeInstanceStatus(input *DescribeInstanceStatusInput) (*Descr
 
 
 func (c *EC2) DescribeInstanceStatusPages(input *DescribeInstanceStatusInput, fn func(p *DescribeInstanceStatusOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeInstanceStatusPages(input *DescribeInstanceStatusInput, fn func(p *DescribeInstanceStatusOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeInstanceStatusRequest(input)
 	page, _ := c.DescribeInstanceStatusRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeInstanceStatusOutput), lastPage)
 		return fn(p.(*DescribeInstanceStatusOutput), lastPage)
 	})
 	})
@@ -3149,6 +3153,7 @@ func (c *EC2) DescribeInstances(input *DescribeInstancesInput) (*DescribeInstanc
 
 
 func (c *EC2) DescribeInstancesPages(input *DescribeInstancesInput, fn func(p *DescribeInstancesOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeInstancesPages(input *DescribeInstancesInput, fn func(p *DescribeInstancesOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeInstancesRequest(input)
 	page, _ := c.DescribeInstancesRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeInstancesOutput), lastPage)
 		return fn(p.(*DescribeInstancesOutput), lastPage)
 	})
 	})
@@ -3534,6 +3539,7 @@ func (c *EC2) DescribeReservedInstancesModifications(input *DescribeReservedInst
 
 
 func (c *EC2) DescribeReservedInstancesModificationsPages(input *DescribeReservedInstancesModificationsInput, fn func(p *DescribeReservedInstancesModificationsOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeReservedInstancesModificationsPages(input *DescribeReservedInstancesModificationsInput, fn func(p *DescribeReservedInstancesModificationsOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeReservedInstancesModificationsRequest(input)
 	page, _ := c.DescribeReservedInstancesModificationsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeReservedInstancesModificationsOutput), lastPage)
 		return fn(p.(*DescribeReservedInstancesModificationsOutput), lastPage)
 	})
 	})
@@ -3581,6 +3587,7 @@ func (c *EC2) DescribeReservedInstancesOfferings(input *DescribeReservedInstance
 
 
 func (c *EC2) DescribeReservedInstancesOfferingsPages(input *DescribeReservedInstancesOfferingsInput, fn func(p *DescribeReservedInstancesOfferingsOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeReservedInstancesOfferingsPages(input *DescribeReservedInstancesOfferingsInput, fn func(p *DescribeReservedInstancesOfferingsOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeReservedInstancesOfferingsRequest(input)
 	page, _ := c.DescribeReservedInstancesOfferingsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeReservedInstancesOfferingsOutput), lastPage)
 		return fn(p.(*DescribeReservedInstancesOfferingsOutput), lastPage)
 	})
 	})
@@ -3697,7 +3704,7 @@ func (c *EC2) DescribeSnapshotsRequest(input *DescribeSnapshotsInput) (req *requ
 		Paginator: &request.Paginator{
 		Paginator: &request.Paginator{
 			InputTokens:     []string{"NextToken"},
 			InputTokens:     []string{"NextToken"},
 			OutputTokens:    []string{"NextToken"},
 			OutputTokens:    []string{"NextToken"},
-			LimitToken:      "",
+			LimitToken:      "MaxResults",
 			TruncationToken: "",
 			TruncationToken: "",
 		},
 		},
 	}
 	}
@@ -3760,6 +3767,7 @@ func (c *EC2) DescribeSnapshots(input *DescribeSnapshotsInput) (*DescribeSnapsho
 
 
 func (c *EC2) DescribeSnapshotsPages(input *DescribeSnapshotsInput, fn func(p *DescribeSnapshotsOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeSnapshotsPages(input *DescribeSnapshotsInput, fn func(p *DescribeSnapshotsOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeSnapshotsRequest(input)
 	page, _ := c.DescribeSnapshotsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeSnapshotsOutput), lastPage)
 		return fn(p.(*DescribeSnapshotsOutput), lastPage)
 	})
 	})
@@ -3961,6 +3969,7 @@ func (c *EC2) DescribeSpotPriceHistory(input *DescribeSpotPriceHistoryInput) (*D
 
 
 func (c *EC2) DescribeSpotPriceHistoryPages(input *DescribeSpotPriceHistoryInput, fn func(p *DescribeSpotPriceHistoryOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeSpotPriceHistoryPages(input *DescribeSpotPriceHistoryInput, fn func(p *DescribeSpotPriceHistoryOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeSpotPriceHistoryRequest(input)
 	page, _ := c.DescribeSpotPriceHistoryRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeSpotPriceHistoryOutput), lastPage)
 		return fn(p.(*DescribeSpotPriceHistoryOutput), lastPage)
 	})
 	})
@@ -4004,6 +4013,12 @@ func (c *EC2) DescribeTagsRequest(input *DescribeTagsInput) (req *request.Reques
 		Name:       opDescribeTags,
 		Name:       opDescribeTags,
 		HTTPMethod: "POST",
 		HTTPMethod: "POST",
 		HTTPPath:   "/",
 		HTTPPath:   "/",
+		Paginator: &request.Paginator{
+			InputTokens:     []string{"NextToken"},
+			OutputTokens:    []string{"NextToken"},
+			LimitToken:      "MaxResults",
+			TruncationToken: "",
+		},
 	}
 	}
 
 
 	if input == nil {
 	if input == nil {
@@ -4026,6 +4041,14 @@ func (c *EC2) DescribeTags(input *DescribeTagsInput) (*DescribeTagsOutput, error
 	return out, err
 	return out, err
 }
 }
 
 
+func (c *EC2) DescribeTagsPages(input *DescribeTagsInput, fn func(p *DescribeTagsOutput, lastPage bool) (shouldContinue bool)) error {
+	page, _ := c.DescribeTagsRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
+	return page.EachPage(func(p interface{}, lastPage bool) bool {
+		return fn(p.(*DescribeTagsOutput), lastPage)
+	})
+}
+
 const opDescribeVolumeAttribute = "DescribeVolumeAttribute"
 const opDescribeVolumeAttribute = "DescribeVolumeAttribute"
 
 
 // DescribeVolumeAttributeRequest generates a request for the DescribeVolumeAttribute operation.
 // DescribeVolumeAttributeRequest generates a request for the DescribeVolumeAttribute operation.
@@ -4126,6 +4149,7 @@ func (c *EC2) DescribeVolumeStatus(input *DescribeVolumeStatusInput) (*DescribeV
 
 
 func (c *EC2) DescribeVolumeStatusPages(input *DescribeVolumeStatusInput, fn func(p *DescribeVolumeStatusOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeVolumeStatusPages(input *DescribeVolumeStatusInput, fn func(p *DescribeVolumeStatusOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeVolumeStatusRequest(input)
 	page, _ := c.DescribeVolumeStatusRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeVolumeStatusOutput), lastPage)
 		return fn(p.(*DescribeVolumeStatusOutput), lastPage)
 	})
 	})
@@ -4176,6 +4200,7 @@ func (c *EC2) DescribeVolumes(input *DescribeVolumesInput) (*DescribeVolumesOutp
 
 
 func (c *EC2) DescribeVolumesPages(input *DescribeVolumesInput, fn func(p *DescribeVolumesOutput, lastPage bool) (shouldContinue bool)) error {
 func (c *EC2) DescribeVolumesPages(input *DescribeVolumesInput, fn func(p *DescribeVolumesOutput, lastPage bool) (shouldContinue bool)) error {
 	page, _ := c.DescribeVolumesRequest(input)
 	page, _ := c.DescribeVolumesRequest(input)
+	page.Handlers.Build.PushBack(request.MakeAddToUserAgentFreeFormHandler("Paginator"))
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 	return page.EachPage(func(p interface{}, lastPage bool) bool {
 		return fn(p.(*DescribeVolumesOutput), lastPage)
 		return fn(p.(*DescribeVolumesOutput), lastPage)
 	})
 	})
@@ -9206,7 +9231,8 @@ func (s CreateSpotDatafeedSubscriptionOutput) GoString() string {
 type CreateSubnetInput struct {
 type CreateSubnetInput struct {
 	// The Availability Zone for the subnet.
 	// The Availability Zone for the subnet.
 	//
 	//
-	// Default: Amazon EC2 selects one for you (recommended).
+	// Default: AWS selects one for you. If you create more than one subnet in
+	// your VPC, we may not necessarily select a different zone for each subnet.
 	AvailabilityZone *string `type:"string"`
 	AvailabilityZone *string `type:"string"`
 
 
 	// The network range for the subnet, in CIDR notation. For example, 10.0.0.0/24.
 	// The network range for the subnet, in CIDR notation. For example, 10.0.0.0/24.
@@ -12262,7 +12288,7 @@ type DescribeInstancesInput struct {
 	//
 	//
 	//   network-interface.vpc-id - The ID of the VPC for the network interface.
 	//   network-interface.vpc-id - The ID of the VPC for the network interface.
 	//
 	//
-	//   network-interface.network-interface.id - The ID of the network interface.
+	//   network-interface.network-interface-id - The ID of the network interface.
 	//
 	//
 	//   network-interface.owner-id - The ID of the owner of the network interface.
 	//   network-interface.owner-id - The ID of the owner of the network interface.
 	//
 	//
@@ -14153,7 +14179,7 @@ type DescribeSpotInstanceRequestsInput struct {
 	//
 	//
 	//   launch.image-id - The ID of the AMI.
 	//   launch.image-id - The ID of the AMI.
 	//
 	//
-	//   launch.instance-type - The type of instance (for example, m1.small).
+	//   launch.instance-type - The type of instance (for example, m3.medium).
 	//
 	//
 	//   launch.kernel-id - The kernel ID.
 	//   launch.kernel-id - The kernel ID.
 	//
 	//
@@ -14291,7 +14317,7 @@ type DescribeSpotPriceHistoryInput struct {
 	//
 	//
 	//   availability-zone - The Availability Zone for which prices should be returned.
 	//   availability-zone - The Availability Zone for which prices should be returned.
 	//
 	//
-	//   instance-type - The type of instance (for example, m1.small).
+	//   instance-type - The type of instance (for example, m3.medium).
 	//
 	//
 	//   product-description - The product description for the Spot price (Linux/UNIX
 	//   product-description - The product description for the Spot price (Linux/UNIX
 	// | SUSE Linux | Windows | Linux/UNIX (Amazon VPC) | SUSE Linux (Amazon VPC)
 	// | SUSE Linux | Windows | Linux/UNIX (Amazon VPC) | SUSE Linux (Amazon VPC)
@@ -17491,7 +17517,7 @@ type Instance struct {
 	// Any block device mapping entries for the instance.
 	// Any block device mapping entries for the instance.
 	BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"`
 	BlockDeviceMappings []*InstanceBlockDeviceMapping `locationName:"blockDeviceMapping" locationNameList:"item" type:"list"`
 
 
-	// The idempotency token you provided when you launched the instance.
+	// The idempotency token you provided when you launched the instance, if applicable.
 	ClientToken *string `locationName:"clientToken" type:"string"`
 	ClientToken *string `locationName:"clientToken" type:"string"`
 
 
 	// Indicates whether the instance is optimized for EBS I/O. This optimization
 	// Indicates whether the instance is optimized for EBS I/O. This optimization
@@ -17504,7 +17530,7 @@ type Instance struct {
 	// The hypervisor type of the instance.
 	// The hypervisor type of the instance.
 	Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"`
 	Hypervisor *string `locationName:"hypervisor" type:"string" enum:"HypervisorType"`
 
 
-	// The IAM instance profile associated with the instance.
+	// The IAM instance profile associated with the instance, if applicable.
 	IamInstanceProfile *IamInstanceProfile `locationName:"iamInstanceProfile" type:"structure"`
 	IamInstanceProfile *IamInstanceProfile `locationName:"iamInstanceProfile" type:"structure"`
 
 
 	// The ID of the AMI used to launch the instance.
 	// The ID of the AMI used to launch the instance.
@@ -17519,7 +17545,7 @@ type Instance struct {
 	// The instance type.
 	// The instance type.
 	InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"`
 	InstanceType *string `locationName:"instanceType" type:"string" enum:"InstanceType"`
 
 
-	// The kernel associated with this instance.
+	// The kernel associated with this instance, if applicable.
 	KernelId *string `locationName:"kernelId" type:"string"`
 	KernelId *string `locationName:"kernelId" type:"string"`
 
 
 	// The name of the key pair, if this instance was launched with an associated
 	// The name of the key pair, if this instance was launched with an associated
@@ -17535,7 +17561,7 @@ type Instance struct {
 	// [EC2-VPC] One or more network interfaces for the instance.
 	// [EC2-VPC] One or more network interfaces for the instance.
 	NetworkInterfaces []*InstanceNetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"`
 	NetworkInterfaces []*InstanceNetworkInterface `locationName:"networkInterfaceSet" locationNameList:"item" type:"list"`
 
 
-	// The location where the instance launched.
+	// The location where the instance launched, if applicable.
 	Placement *Placement `locationName:"placement" type:"structure"`
 	Placement *Placement `locationName:"placement" type:"structure"`
 
 
 	// The value is Windows for Windows instances; otherwise blank.
 	// The value is Windows for Windows instances; otherwise blank.
@@ -17543,23 +17569,25 @@ type Instance struct {
 
 
 	// The private DNS name assigned to the instance. This DNS name can only be
 	// The private DNS name assigned to the instance. This DNS name can only be
 	// used inside the Amazon EC2 network. This name is not available until the
 	// used inside the Amazon EC2 network. This name is not available until the
-	// instance enters the running state.
+	// instance enters the running state. For EC2-VPC, this name is only available
+	// if you've enabled DNS hostnames for your VPC.
 	PrivateDnsName *string `locationName:"privateDnsName" type:"string"`
 	PrivateDnsName *string `locationName:"privateDnsName" type:"string"`
 
 
 	// The private IP address assigned to the instance.
 	// The private IP address assigned to the instance.
 	PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"`
 	PrivateIpAddress *string `locationName:"privateIpAddress" type:"string"`
 
 
-	// The product codes attached to this instance.
+	// The product codes attached to this instance, if applicable.
 	ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"`
 	ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"`
 
 
 	// The public DNS name assigned to the instance. This name is not available
 	// The public DNS name assigned to the instance. This name is not available
-	// until the instance enters the running state.
+	// until the instance enters the running state. For EC2-VPC, this name is only
+	// available if you've enabled DNS hostnames for your VPC.
 	PublicDnsName *string `locationName:"dnsName" type:"string"`
 	PublicDnsName *string `locationName:"dnsName" type:"string"`
 
 
-	// The public IP address assigned to the instance.
+	// The public IP address assigned to the instance, if applicable.
 	PublicIpAddress *string `locationName:"ipAddress" type:"string"`
 	PublicIpAddress *string `locationName:"ipAddress" type:"string"`
 
 
-	// The RAM disk associated with this instance.
+	// The RAM disk associated with this instance, if applicable.
 	RamdiskId *string `locationName:"ramdiskId" type:"string"`
 	RamdiskId *string `locationName:"ramdiskId" type:"string"`
 
 
 	// The root device name (for example, /dev/sda1 or /dev/xvda).
 	// The root device name (for example, /dev/sda1 or /dev/xvda).
@@ -17580,7 +17608,7 @@ type Instance struct {
 	// in the Amazon Virtual Private Cloud User Guide.
 	// in the Amazon Virtual Private Cloud User Guide.
 	SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"`
 	SourceDestCheck *bool `locationName:"sourceDestCheck" type:"boolean"`
 
 
-	// The ID of the Spot Instance request.
+	// If the request is a Spot instance request, the ID of the request.
 	SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"`
 	SpotInstanceRequestId *string `locationName:"spotInstanceRequestId" type:"string"`
 
 
 	// Specifies whether enhanced networking is enabled.
 	// Specifies whether enhanced networking is enabled.
@@ -17595,7 +17623,7 @@ type Instance struct {
 	// The reason for the most recent state transition. This might be an empty string.
 	// The reason for the most recent state transition. This might be an empty string.
 	StateTransitionReason *string `locationName:"reason" type:"string"`
 	StateTransitionReason *string `locationName:"reason" type:"string"`
 
 
-	// The ID of the subnet in which the instance is running.
+	// [EC2-VPC] The ID of the subnet in which the instance is running.
 	SubnetId *string `locationName:"subnetId" type:"string"`
 	SubnetId *string `locationName:"subnetId" type:"string"`
 
 
 	// Any tags assigned to the instance.
 	// Any tags assigned to the instance.
@@ -17604,7 +17632,7 @@ type Instance struct {
 	// The virtualization type of the instance.
 	// The virtualization type of the instance.
 	VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"`
 	VirtualizationType *string `locationName:"virtualizationType" type:"string" enum:"VirtualizationType"`
 
 
-	// The ID of the VPC in which the instance is running.
+	// [EC2-VPC] The ID of the VPC in which the instance is running.
 	VpcId *string `locationName:"vpcId" type:"string"`
 	VpcId *string `locationName:"vpcId" type:"string"`
 
 
 	metadataInstance `json:"-" xml:"-"`
 	metadataInstance `json:"-" xml:"-"`
@@ -18960,7 +18988,9 @@ type ModifyVpcAttributeInput struct {
 	// Indicates whether the instances launched in the VPC get DNS hostnames. If
 	// Indicates whether the instances launched in the VPC get DNS hostnames. If
 	// enabled, instances in the VPC get DNS hostnames; otherwise, they do not.
 	// enabled, instances in the VPC get DNS hostnames; otherwise, they do not.
 	//
 	//
-	// You can only enable DNS hostnames if you also enable DNS support.
+	// You cannot modify the DNS resolution and DNS hostnames attributes in the
+	// same request. Use separate requests for each attribute. You can only enable
+	// DNS hostnames if you've enabled DNS support.
 	EnableDnsHostnames *AttributeBooleanValue `type:"structure"`
 	EnableDnsHostnames *AttributeBooleanValue `type:"structure"`
 
 
 	// Indicates whether the DNS resolution is supported for the VPC. If enabled,
 	// Indicates whether the DNS resolution is supported for the VPC. If enabled,
@@ -18968,6 +18998,9 @@ type ModifyVpcAttributeInput struct {
 	// or the reserved IP address at the base of the VPC network range "plus two"
 	// or the reserved IP address at the base of the VPC network range "plus two"
 	// will succeed. If disabled, the Amazon provided DNS service in the VPC that
 	// will succeed. If disabled, the Amazon provided DNS service in the VPC that
 	// resolves public DNS hostnames to IP addresses is not enabled.
 	// resolves public DNS hostnames to IP addresses is not enabled.
+	//
+	// You cannot modify the DNS resolution and DNS hostnames attributes in the
+	// same request. Use separate requests for each attribute.
 	EnableDnsSupport *AttributeBooleanValue `type:"structure"`
 	EnableDnsSupport *AttributeBooleanValue `type:"structure"`
 
 
 	// The ID of the VPC.
 	// The ID of the VPC.
@@ -20589,7 +20622,7 @@ type RequestSpotInstancesInput struct {
 	// the instance a two-minute warning before it terminates.
 	// the instance a two-minute warning before it terminates.
 	//
 	//
 	// Note that you can't specify an Availability Zone group or a launch group
 	// Note that you can't specify an Availability Zone group or a launch group
-	// if you specify a required duration.
+	// if you specify a duration.
 	BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"`
 	BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"`
 
 
 	// Unique, case-sensitive identifier that you provide to ensure the idempotency
 	// Unique, case-sensitive identifier that you provide to ensure the idempotency
@@ -22348,8 +22381,8 @@ func (s SpotFleetRequestConfigData) GoString() string {
 
 
 // Describes a Spot instance request.
 // Describes a Spot instance request.
 type SpotInstanceRequest struct {
 type SpotInstanceRequest struct {
-	// If you specified a required duration and your request was fulfilled, this
-	// is the fixed hourly price in effect for the Spot instance while it runs.
+	// If you specified a duration and your Spot instance request was fulfilled,
+	// this is the fixed hourly price in effect for the Spot instance while it runs.
 	ActualBlockHourlyPrice *string `locationName:"actualBlockHourlyPrice" type:"string"`
 	ActualBlockHourlyPrice *string `locationName:"actualBlockHourlyPrice" type:"string"`
 
 
 	// The Availability Zone group. If you specify the same Availability Zone group
 	// The Availability Zone group. If you specify the same Availability Zone group
@@ -22357,7 +22390,7 @@ type SpotInstanceRequest struct {
 	// Availability Zone.
 	// Availability Zone.
 	AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"`
 	AvailabilityZoneGroup *string `locationName:"availabilityZoneGroup" type:"string"`
 
 
-	// The required duration for the Spot instance, in minutes.
+	// The duration for the Spot instance, in minutes.
 	BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"`
 	BlockDurationMinutes *int64 `locationName:"blockDurationMinutes" type:"integer"`
 
 
 	// The date and time when the Spot instance request was created, in UTC format
 	// The date and time when the Spot instance request was created, in UTC format
@@ -22460,7 +22493,8 @@ func (s SpotInstanceStateFault) GoString() string {
 
 
 // Describes the status of a Spot instance request.
 // Describes the status of a Spot instance request.
 type SpotInstanceStatus struct {
 type SpotInstanceStatus struct {
-	// The status code.
+	// The status code. For a list of status codes, see Spot Bid Status Codes (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-bid-status.html#spot-instance-bid-status-understand)
+	// in the Amazon Elastic Compute Cloud User Guide.
 	Code *string `locationName:"code" type:"string"`
 	Code *string `locationName:"code" type:"string"`
 
 
 	// The description for the status code.
 	// The description for the status code.

+ 18 - 20
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations.go

@@ -3,8 +3,10 @@ package ec2
 import (
 import (
 	"time"
 	"time"
 
 
+	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/awsutil"
 	"github.com/aws/aws-sdk-go/aws/awsutil"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/private/endpoints"
 )
 )
 
 
 func init() {
 func init() {
@@ -20,38 +22,34 @@ func fillPresignedURL(r *request.Request) {
 		return
 		return
 	}
 	}
 
 
-	params := r.Params.(*CopySnapshotInput)
+	origParams := r.Params.(*CopySnapshotInput)
 
 
 	// Stop if PresignedURL/DestinationRegion is set
 	// Stop if PresignedURL/DestinationRegion is set
-	if params.PresignedUrl != nil || params.DestinationRegion != nil {
+	if origParams.PresignedUrl != nil || origParams.DestinationRegion != nil {
 		return
 		return
 	}
 	}
 
 
-	// First generate a copy of parameters
-	r.Params = awsutil.CopyOf(r.Params)
-	params = r.Params.(*CopySnapshotInput)
+	origParams.DestinationRegion = r.Config.Region
+	newParams := awsutil.CopyOf(r.Params).(*CopySnapshotInput)
 
 
-	// Set destination region. Avoids infinite handler loop.
-	// Also needed to sign sub-request.
-	params.DestinationRegion = r.Service.Config.Region
-
-	// Create a new client pointing at source region.
-	// We will use this to presign the CopySnapshot request against
-	// the source region
-	config := r.Service.Config.Copy().
+	// Create a new request based on the existing request. We will use this to
+	// presign the CopySnapshot request against the source region.
+	cfg := r.Config.Copy(aws.NewConfig().
 		WithEndpoint("").
 		WithEndpoint("").
-		WithRegion(*params.SourceRegion)
+		WithRegion(aws.StringValue(origParams.SourceRegion)))
 
 
-	client := New(config)
+	clientInfo := r.ClientInfo
+	clientInfo.Endpoint, clientInfo.SigningRegion = endpoints.EndpointForRegion(
+		clientInfo.ServiceName, aws.StringValue(cfg.Region), aws.BoolValue(cfg.DisableSSL))
 
 
 	// Presign a CopySnapshot request with modified params
 	// Presign a CopySnapshot request with modified params
-	req, _ := client.CopySnapshotRequest(params)
-	url, err := req.Presign(300 * time.Second) // 5 minutes should be enough.
-
-	if err != nil { // bubble error back up to original request
+	req := request.New(*cfg, clientInfo, r.Handlers, r.Retryer, r.Operation, newParams, r.Data)
+	url, err := req.Presign(5 * time.Minute) // 5 minutes should be enough.
+	if err != nil {                          // bubble error back up to original request
 		r.Error = err
 		r.Error = err
+		return
 	}
 	}
 
 
 	// We have our URL, set it on params
 	// We have our URL, set it on params
-	params.PresignedUrl = &url
+	origParams.PresignedUrl = &url
 }
 }

+ 4 - 5
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go

@@ -11,10 +11,8 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/assert"
 )
 )
 
 
-var _ = unit.Imported
-
 func TestCopySnapshotPresignedURL(t *testing.T) {
 func TestCopySnapshotPresignedURL(t *testing.T) {
-	svc := ec2.New(&aws.Config{Region: aws.String("us-west-2")})
+	svc := ec2.New(unit.Session, &aws.Config{Region: aws.String("us-west-2")})
 
 
 	assert.NotPanics(t, func() {
 	assert.NotPanics(t, func() {
 		// Doesn't panic on nil input
 		// Doesn't panic on nil input
@@ -30,7 +28,8 @@ func TestCopySnapshotPresignedURL(t *testing.T) {
 
 
 	b, _ := ioutil.ReadAll(req.HTTPRequest.Body)
 	b, _ := ioutil.ReadAll(req.HTTPRequest.Body)
 	q, _ := url.ParseQuery(string(b))
 	q, _ := url.ParseQuery(string(b))
-	url, _ := url.QueryUnescape(q.Get("PresignedUrl"))
+	u, _ := url.QueryUnescape(q.Get("PresignedUrl"))
 	assert.Equal(t, "us-west-2", q.Get("DestinationRegion"))
 	assert.Equal(t, "us-west-2", q.Get("DestinationRegion"))
-	assert.Regexp(t, `^https://ec2\.us-west-1\.amazon.+&DestinationRegion=us-west-2`, url)
+	assert.Equal(t, "us-west-1", q.Get("SourceRegion"))
+	assert.Regexp(t, `^https://ec2\.us-west-1\.amazonaws\.com/.+&DestinationRegion=us-west-2`, u)
 }
 }

+ 4 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface.go

@@ -486,6 +486,8 @@ type EC2API interface {
 
 
 	DescribeTags(*ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error)
 	DescribeTags(*ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error)
 
 
+	DescribeTagsPages(*ec2.DescribeTagsInput, func(*ec2.DescribeTagsOutput, bool) bool) error
+
 	DescribeVolumeAttributeRequest(*ec2.DescribeVolumeAttributeInput) (*request.Request, *ec2.DescribeVolumeAttributeOutput)
 	DescribeVolumeAttributeRequest(*ec2.DescribeVolumeAttributeInput) (*request.Request, *ec2.DescribeVolumeAttributeOutput)
 
 
 	DescribeVolumeAttribute(*ec2.DescribeVolumeAttributeInput) (*ec2.DescribeVolumeAttributeOutput, error)
 	DescribeVolumeAttribute(*ec2.DescribeVolumeAttributeInput) (*ec2.DescribeVolumeAttributeOutput, error)
@@ -758,3 +760,5 @@ type EC2API interface {
 
 
 	UnmonitorInstances(*ec2.UnmonitorInstancesInput) (*ec2.UnmonitorInstancesOutput, error)
 	UnmonitorInstances(*ec2.UnmonitorInstancesInput) (*ec2.UnmonitorInstancesOutput, error)
 }
 }
+
+var _ EC2API = (*ec2.EC2)(nil)

+ 0 - 15
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface_test.go

@@ -1,15 +0,0 @@
-// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
-
-package ec2iface_test
-
-import (
-	"testing"
-
-	"github.com/aws/aws-sdk-go/service/ec2"
-	"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestInterface(t *testing.T) {
-	assert.Implements(t, (*ec2iface.EC2API)(nil), ec2.New(nil))
-}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 112 - 111
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/examples_test.go


+ 47 - 24
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/service.go

@@ -4,10 +4,9 @@ package ec2
 
 
 import (
 import (
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/defaults"
+	"github.com/aws/aws-sdk-go/aws/client"
+	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 	"github.com/aws/aws-sdk-go/aws/request"
-	"github.com/aws/aws-sdk-go/aws/service"
-	"github.com/aws/aws-sdk-go/aws/service/serviceinfo"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 	"github.com/aws/aws-sdk-go/private/signer/v4"
 	"github.com/aws/aws-sdk-go/private/signer/v4"
 )
 )
@@ -16,40 +15,64 @@ import (
 // in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your
 // in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your
 // need to invest in hardware up front, so you can develop and deploy applications
 // need to invest in hardware up front, so you can develop and deploy applications
 // faster.
 // faster.
+//The service client's operations are safe to be used concurrently.
+// It is not safe to mutate any of the client's properties though.
 type EC2 struct {
 type EC2 struct {
-	*service.Service
+	*client.Client
 }
 }
 
 
-// Used for custom service initialization logic
-var initService func(*service.Service)
+// Used for custom client initialization logic
+var initClient func(*client.Client)
 
 
 // Used for custom request initialization logic
 // Used for custom request initialization logic
 var initRequest func(*request.Request)
 var initRequest func(*request.Request)
 
 
-// New returns a new EC2 client.
-func New(config *aws.Config) *EC2 {
-	service := &service.Service{
-		ServiceInfo: serviceinfo.ServiceInfo{
-			Config:      defaults.DefaultConfig.Merge(config),
-			ServiceName: "ec2",
-			APIVersion:  "2015-10-01",
-		},
+// A ServiceName is the name of the service the client will make API calls to.
+const ServiceName = "ec2"
+
+// New creates a new instance of the EC2 client with a session.
+// If additional configuration is needed for the client instance use the optional
+// aws.Config parameter to add your extra config.
+//
+// Example:
+//     // Create a EC2 client from just a session.
+//     svc := ec2.New(mySession)
+//
+//     // Create a EC2 client with additional configuration
+//     svc := ec2.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
+func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2 {
+	c := p.ClientConfig(ServiceName, cfgs...)
+	return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
+}
+
+// newClient creates, initializes and returns a new service client instance.
+func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string) *EC2 {
+	svc := &EC2{
+		Client: client.New(
+			cfg,
+			metadata.ClientInfo{
+				ServiceName:   ServiceName,
+				SigningRegion: signingRegion,
+				Endpoint:      endpoint,
+				APIVersion:    "2015-10-01",
+			},
+			handlers,
+		),
 	}
 	}
-	service.Initialize()
 
 
 	// Handlers
 	// Handlers
-	service.Handlers.Sign.PushBack(v4.Sign)
-	service.Handlers.Build.PushBack(ec2query.Build)
-	service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
-	service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
-	service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
+	svc.Handlers.Sign.PushBack(v4.Sign)
+	svc.Handlers.Build.PushBack(ec2query.Build)
+	svc.Handlers.Unmarshal.PushBack(ec2query.Unmarshal)
+	svc.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta)
+	svc.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError)
 
 
-	// Run custom service initialization if present
-	if initService != nil {
-		initService(service)
+	// Run custom client initialization if present
+	if initClient != nil {
+		initClient(svc.Client)
 	}
 	}
 
 
-	return &EC2{service}
+	return svc
 }
 }
 
 
 // newRequest creates a new request for a EC2 operation and runs any
 // newRequest creates a new request for a EC2 operation and runs any

+ 761 - 0
Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/waiters.go

@@ -0,0 +1,761 @@
+// THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
+
+package ec2
+
+import (
+	"github.com/aws/aws-sdk-go/private/waiter"
+)
+
+func (c *EC2) WaitUntilBundleTaskComplete(input *DescribeBundleTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeBundleTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "BundleTasks[].State",
+				Expected: "complete",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "BundleTasks[].State",
+				Expected: "failed",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilConversionTaskCancelled(input *DescribeConversionTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeConversionTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "ConversionTasks[].State",
+				Expected: "cancelled",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilConversionTaskCompleted(input *DescribeConversionTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeConversionTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "ConversionTasks[].State",
+				Expected: "completed",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "ConversionTasks[].State",
+				Expected: "cancelled",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "ConversionTasks[].State",
+				Expected: "cancelling",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilConversionTaskDeleted(input *DescribeConversionTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeConversionTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "ConversionTasks[].State",
+				Expected: "deleted",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilCustomerGatewayAvailable(input *DescribeCustomerGatewaysInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeCustomerGateways",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "CustomerGateways[].State",
+				Expected: "available",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "CustomerGateways[].State",
+				Expected: "deleted",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "CustomerGateways[].State",
+				Expected: "deleting",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilExportTaskCancelled(input *DescribeExportTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeExportTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "ExportTasks[].State",
+				Expected: "cancelled",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilExportTaskCompleted(input *DescribeExportTasksInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeExportTasks",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "ExportTasks[].State",
+				Expected: "completed",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilImageAvailable(input *DescribeImagesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeImages",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Images[].State",
+				Expected: "available",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Images[].State",
+				Expected: "failed",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilInstanceExists(input *DescribeInstancesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstances",
+		Delay:       5,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "status",
+				Argument: "",
+				Expected: 200,
+			},
+			{
+				State:    "retry",
+				Matcher:  "error",
+				Argument: "",
+				Expected: "InvalidInstanceIDNotFound",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilInstanceRunning(input *DescribeInstancesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstances",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "running",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "shutting-down",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "terminated",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "stopping",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilInstanceStatusOk(input *DescribeInstanceStatusInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstanceStatus",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "InstanceStatuses[].InstanceStatus.Status",
+				Expected: "ok",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilInstanceStopped(input *DescribeInstancesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstances",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "stopped",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "pending",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "terminated",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilInstanceTerminated(input *DescribeInstancesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstances",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "terminated",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "pending",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Reservations[].Instances[].State.Name",
+				Expected: "stopping",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilKeyPairExists(input *DescribeKeyPairsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeKeyPairs",
+		Delay:       5,
+		MaxAttempts: 6,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "length(KeyPairs[].KeyName) > `0`",
+				Expected: true,
+			},
+			{
+				State:    "retry",
+				Matcher:  "error",
+				Argument: "",
+				Expected: "InvalidKeyPairNotFound",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilNetworkInterfaceAvailable(input *DescribeNetworkInterfacesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeNetworkInterfaces",
+		Delay:       20,
+		MaxAttempts: 10,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "NetworkInterfaces[].Status",
+				Expected: "available",
+			},
+			{
+				State:    "failure",
+				Matcher:  "error",
+				Argument: "",
+				Expected: "InvalidNetworkInterfaceIDNotFound",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilPasswordDataAvailable(input *GetPasswordDataInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "GetPasswordData",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "path",
+				Argument: "length(PasswordData) > `0`",
+				Expected: true,
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilSnapshotCompleted(input *DescribeSnapshotsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeSnapshots",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Snapshots[].State",
+				Expected: "completed",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilSpotInstanceRequestFulfilled(input *DescribeSpotInstanceRequestsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeSpotInstanceRequests",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "SpotInstanceRequests[].Status.Code",
+				Expected: "fulfilled",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "SpotInstanceRequests[].Status.Code",
+				Expected: "schedule-expired",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "SpotInstanceRequests[].Status.Code",
+				Expected: "canceled-before-fulfillment",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "SpotInstanceRequests[].Status.Code",
+				Expected: "bad-parameters",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "SpotInstanceRequests[].Status.Code",
+				Expected: "system-error",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilSubnetAvailable(input *DescribeSubnetsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeSubnets",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Subnets[].State",
+				Expected: "available",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilSystemStatusOk(input *DescribeInstanceStatusInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeInstanceStatus",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "InstanceStatuses[].SystemStatus.Status",
+				Expected: "ok",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVolumeAvailable(input *DescribeVolumesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVolumes",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Volumes[].State",
+				Expected: "available",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Volumes[].State",
+				Expected: "deleted",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVolumeDeleted(input *DescribeVolumesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVolumes",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Volumes[].State",
+				Expected: "deleted",
+			},
+			{
+				State:    "success",
+				Matcher:  "error",
+				Argument: "",
+				Expected: "InvalidVolumeNotFound",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVolumeInUse(input *DescribeVolumesInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVolumes",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Volumes[].State",
+				Expected: "in-use",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "Volumes[].State",
+				Expected: "deleted",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVpcAvailable(input *DescribeVpcsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVpcs",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "Vpcs[].State",
+				Expected: "available",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVpnConnectionAvailable(input *DescribeVpnConnectionsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVpnConnections",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "VpnConnections[].State",
+				Expected: "available",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "VpnConnections[].State",
+				Expected: "deleting",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "VpnConnections[].State",
+				Expected: "deleted",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}
+
+func (c *EC2) WaitUntilVpnConnectionDeleted(input *DescribeVpnConnectionsInput) error {
+	waiterCfg := waiter.Config{
+		Operation:   "DescribeVpnConnections",
+		Delay:       15,
+		MaxAttempts: 40,
+		Acceptors: []waiter.WaitAcceptor{
+			{
+				State:    "success",
+				Matcher:  "pathAll",
+				Argument: "VpnConnections[].State",
+				Expected: "deleted",
+			},
+			{
+				State:    "failure",
+				Matcher:  "pathAny",
+				Argument: "VpnConnections[].State",
+				Expected: "pending",
+			},
+		},
+	}
+
+	w := waiter.Waiter{
+		Client: c,
+		Input:  input,
+		Config: waiterCfg,
+	}
+	return w.Wait()
+}

+ 4 - 0
Godeps/_workspace/src/github.com/go-ini/ini/.gitignore

@@ -0,0 +1,4 @@
+testdata/conf_out.ini
+ini.sublime-project
+ini.sublime-workspace
+testdata/conf_reflect.ini

+ 191 - 0
Godeps/_workspace/src/github.com/go-ini/ini/LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "[]" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 560 - 0
Godeps/_workspace/src/github.com/go-ini/ini/README.md

@@ -0,0 +1,560 @@
+ini [![Build Status](https://drone.io/github.com/go-ini/ini/status.png)](https://drone.io/github.com/go-ini/ini/latest) [![](http://gocover.io/_badge/github.com/go-ini/ini)](http://gocover.io/github.com/go-ini/ini)
+===
+
+![](https://avatars0.githubusercontent.com/u/10216035?v=3&s=200)
+
+Package ini provides INI file read and write functionality in Go.
+
+[简体中文](README_ZH.md)
+
+## Feature
+
+- Load multiple data sources(`[]byte` or file) with overwrites.
+- Read with recursion values.
+- Read with parent-child sections.
+- Read with auto-increment key names.
+- Read with multiple-line values.
+- Read with tons of helper methods.
+- Read and convert values to Go types.
+- Read and **WRITE** comments of sections and keys.
+- Manipulate sections, keys and comments with ease.
+- Keep sections and keys in order as you parse and save.
+
+## Installation
+
+	go get gopkg.in/ini.v1
+
+## Getting Started
+
+### Loading from data sources
+
+A **Data Source** is either raw data in type `[]byte` or a file name with type `string` and you can load **as many as** data sources you want. Passing other types will simply return an error.
+
+```go
+cfg, err := ini.Load([]byte("raw data"), "filename")
+```
+
+Or start with an empty object:
+
+```go
+cfg := ini.Empty()
+```
+
+When you cannot decide how many data sources to load at the beginning, you still able to **Append()** them later.
+
+```go
+err := cfg.Append("other file", []byte("other raw data"))
+```
+
+### Working with sections
+
+To get a section, you would need to:
+
+```go
+section, err := cfg.GetSection("section name")
+```
+
+For a shortcut for default section, just give an empty string as name:
+
+```go
+section, err := cfg.GetSection("")
+```
+
+When you're pretty sure the section exists, following code could make your life easier:
+
+```go
+section := cfg.Section("")
+```
+
+What happens when the section somehow does not exist? Don't panic, it automatically creates and returns a new section to you.
+
+To create a new section:
+
+```go
+err := cfg.NewSection("new section")
+```
+
+To get a list of sections or section names:
+
+```go
+sections := cfg.Sections()
+names := cfg.SectionStrings()
+```
+
+### Working with keys
+
+To get a key under a section:
+
+```go
+key, err := cfg.Section("").GetKey("key name")
+```
+
+Same rule applies to key operations:
+
+```go
+key := cfg.Section("").Key("key name")
+```
+
+To create a new key:
+
+```go
+err := cfg.Section("").NewKey("name", "value")
+```
+
+To get a list of keys or key names:
+
+```go
+keys := cfg.Section("").Keys()
+names := cfg.Section("").KeyStrings()
+```
+
+To get a clone hash of keys and corresponding values:
+
+```go
+hash := cfg.GetSection("").KeysHash()
+```
+
+### Working with values
+
+To get a string value:
+
+```go
+val := cfg.Section("").Key("key name").String()
+```
+
+To validate key value on the fly:
+
+```go
+val := cfg.Section("").Key("key name").Validate(func(in string) string {
+	if len(in) == 0 {
+		return "default"
+	}
+	return in
+})
+```
+
+To get value with types:
+
+```go
+// For boolean values:
+// true when value is: 1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On
+// false when value is: 0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off
+v, err = cfg.Section("").Key("BOOL").Bool()
+v, err = cfg.Section("").Key("FLOAT64").Float64()
+v, err = cfg.Section("").Key("INT").Int()
+v, err = cfg.Section("").Key("INT64").Int64()
+v, err = cfg.Section("").Key("UINT").Uint()
+v, err = cfg.Section("").Key("UINT64").Uint64()
+v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
+v, err = cfg.Section("").Key("TIME").Time() // RFC3339
+
+v = cfg.Section("").Key("BOOL").MustBool()
+v = cfg.Section("").Key("FLOAT64").MustFloat64()
+v = cfg.Section("").Key("INT").MustInt()
+v = cfg.Section("").Key("INT64").MustInt64()
+v = cfg.Section("").Key("UINT").MustUint()
+v = cfg.Section("").Key("UINT64").MustUint64()
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
+v = cfg.Section("").Key("TIME").MustTime() // RFC3339
+
+// Methods start with Must also accept one argument for default value
+// when key not found or fail to parse value to given type.
+// Except method MustString, which you have to pass a default value.
+
+v = cfg.Section("").Key("String").MustString("default")
+v = cfg.Section("").Key("BOOL").MustBool(true)
+v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
+v = cfg.Section("").Key("INT").MustInt(10)
+v = cfg.Section("").Key("INT64").MustInt64(99)
+v = cfg.Section("").Key("UINT").MustUint(3)
+v = cfg.Section("").Key("UINT64").MustUint64(6)
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
+v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
+```
+
+What if my value is three-line long?
+
+```ini
+[advance]
+ADDRESS = """404 road,
+NotFound, State, 5000
+Earth"""
+```
+
+Not a problem!
+
+```go
+cfg.Section("advance").Key("ADDRESS").String()
+
+/* --- start ---
+404 road,
+NotFound, State, 5000
+Earth
+------  end  --- */
+```
+
+That's cool, how about continuation lines?
+
+```ini
+[advance]
+two_lines = how about \
+	continuation lines?
+lots_of_lines = 1 \
+	2 \
+	3 \
+	4
+```
+
+Piece of cake!
+
+```go
+cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
+cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
+```
+
+Note that single quotes around values will be stripped:
+
+```ini
+foo = "some value" // foo: some value
+bar = 'some value' // bar: some value
+```
+
+That's all? Hmm, no.
+
+#### Helper methods of working with values
+
+To get value with given candidates:
+
+```go
+v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
+v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
+v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
+v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
+v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
+v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
+v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
+v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
+```
+
+Default value will be presented if value of key is not in candidates you given, and default value does not need be one of candidates.
+
+To validate value in a given range:
+
+```go
+vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
+vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
+vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
+vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
+vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
+vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
+vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
+```
+
+To auto-split value into slice:
+
+```go
+vals = cfg.Section("").Key("STRINGS").Strings(",")
+vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
+vals = cfg.Section("").Key("INTS").Ints(",")
+vals = cfg.Section("").Key("INT64S").Int64s(",")
+vals = cfg.Section("").Key("UINTS").Uints(",")
+vals = cfg.Section("").Key("UINT64S").Uint64s(",")
+vals = cfg.Section("").Key("TIMES").Times(",")
+```
+
+### Save your configuration
+
+Finally, it's time to save your configuration to somewhere.
+
+A typical way to save configuration is writing it to a file:
+
+```go
+// ...
+err = cfg.SaveTo("my.ini")
+err = cfg.SaveToIndent("my.ini", "\t")
+```
+
+Another way to save is writing to a `io.Writer` interface:
+
+```go
+// ...
+cfg.WriteTo(writer)
+cfg.WriteToIndent(writer, "\t")
+```
+
+## Advanced Usage
+
+### Recursive Values
+
+For all value of keys, there is a special syntax `%(<name>)s`, where `<name>` is the key name in same section or default section, and `%(<name>)s` will be replaced by corresponding value(empty string if key not found). You can use this syntax at most 99 level of recursions.
+
+```ini
+NAME = ini
+
+[author]
+NAME = Unknwon
+GITHUB = https://github.com/%(NAME)s
+
+[package]
+FULL_NAME = github.com/go-ini/%(NAME)s
+```
+
+```go
+cfg.Section("author").Key("GITHUB").String()		// https://github.com/Unknwon
+cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
+```
+
+### Parent-child Sections
+
+You can use `.` in section name to indicate parent-child relationship between two or more sections. If the key not found in the child section, library will try again on its parent section until there is no parent section.
+
+```ini
+NAME = ini
+VERSION = v1
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+[package]
+CLONE_URL = https://%(IMPORT_PATH)s
+
+[package.sub]
+```
+
+```go
+cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
+```
+
+### Auto-increment Key Names
+
+If key name is `-` in data source, then it would be seen as special syntax for auto-increment key name start from 1, and every section is independent on counter.
+
+```ini
+[features]
+-: Support read/write comments of keys and sections
+-: Support auto-increment of key names
+-: Support load multiple files to overwrite key values
+```
+
+```go
+cfg.Section("features").KeyStrings()	// []{"#1", "#2", "#3"}
+```
+
+### Map To Struct
+
+Want more objective way to play with INI? Cool.
+
+```ini
+Name = Unknwon
+age = 21
+Male = true
+Born = 1993-01-01T20:17:05Z
+
+[Note]
+Content = Hi is a good man!
+Cities = HangZhou, Boston
+```
+
+```go
+type Note struct {
+	Content string
+	Cities  []string
+}
+
+type Person struct {
+	Name string
+	Age  int `ini:"age"`
+	Male bool
+	Born time.Time
+	Note
+	Created time.Time `ini:"-"`
+}
+
+func main() {
+	cfg, err := ini.Load("path/to/ini")
+	// ...
+	p := new(Person)
+	err = cfg.MapTo(p)
+	// ...
+
+	// Things can be simpler.
+	err = ini.MapTo(p, "path/to/ini")
+	// ...
+
+	// Just map a section? Fine.
+	n := new(Note)
+	err = cfg.Section("Note").MapTo(n)
+	// ...
+}
+```
+
+Can I have default value for field? Absolutely.
+
+Assign it before you map to struct. It will keep the value as it is if the key is not presented or got wrong type.
+
+```go
+// ...
+p := &Person{
+	Name: "Joe",
+}
+// ...
+```
+
+It's really cool, but what's the point if you can't give me my file back from struct?
+
+### Reflect From Struct
+
+Why not?
+
+```go
+type Embeded struct {
+	Dates  []time.Time `delim:"|"`
+	Places []string
+	None   []int
+}
+
+type Author struct {
+	Name      string `ini:"NAME"`
+	Male      bool
+	Age       int
+	GPA       float64
+	NeverMind string `ini:"-"`
+	*Embeded
+}
+
+func main() {
+	a := &Author{"Unknwon", true, 21, 2.8, "",
+		&Embeded{
+			[]time.Time{time.Now(), time.Now()},
+			[]string{"HangZhou", "Boston"},
+			[]int{},
+		}}
+	cfg := ini.Empty()
+	err = ini.ReflectFrom(cfg, a)
+	// ...
+}
+```
+
+So, what do I get?
+
+```ini
+NAME = Unknwon
+Male = true
+Age = 21
+GPA = 2.8
+
+[Embeded]
+Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
+Places = HangZhou,Boston
+None =
+```
+
+#### Name Mapper
+
+To save your time and make your code cleaner, this library supports [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) between struct field and actual section and key name.
+
+There are 2 built-in name mappers:
+
+- `AllCapsUnderscore`: it converts to format `ALL_CAPS_UNDERSCORE` then match section or key.
+- `TitleUnderscore`: it converts to format `title_underscore` then match section or key.
+
+To use them:
+
+```go
+type Info struct {
+	PackageName string
+}
+
+func main() {
+	err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
+	// ...
+
+	cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
+	// ...
+	info := new(Info)
+	cfg.NameMapper = ini.AllCapsUnderscore
+	err = cfg.MapTo(info)
+	// ...
+}
+```
+
+Same rules of name mapper apply to `ini.ReflectFromWithMapper` function.
+
+#### Other Notes On Map/Reflect
+
+Any embedded struct is treated as a section by default, and there is no automatic parent-child relations in map/reflect feature:
+
+```go
+type Child struct {
+	Age string
+}
+
+type Parent struct {
+	Name string
+	Child
+}
+
+type Config struct {
+	City string
+	Parent
+}
+```
+
+Example configuration:
+
+```ini
+City = Boston
+
+[Parent]
+Name = Unknwon
+
+[Child]
+Age = 21
+```
+
+What if, yes, I'm paranoid, I want embedded struct to be in the same section. Well, all roads lead to Rome.
+
+```go
+type Child struct {
+	Age string
+}
+
+type Parent struct {
+	Name string
+	Child `ini:"Parent"`
+}
+
+type Config struct {
+	City string
+	Parent
+}
+```
+
+Example configuration:
+
+```ini
+City = Boston
+
+[Parent]
+Name = Unknwon
+Age = 21
+```
+
+## Getting Help
+
+- [API Documentation](https://gowalker.org/gopkg.in/ini.v1)
+- [File An Issue](https://github.com/go-ini/ini/issues/new)
+
+## FAQs
+
+### What does `BlockMode` field do?
+
+By default, library lets you read and write values so we need a locker to make sure your data is safe. But in cases that you are very sure about only reading data through the library, you can set `cfg.BlockMode = false` to speed up read operations about **50-70%** faster.
+
+### Why another INI library?
+
+Many people are using my another INI library [goconfig](https://github.com/Unknwon/goconfig), so the reason for this one is I would like to make more Go style code. Also when you set `cfg.BlockMode = false`, this one is about **10-30%** faster.
+
+To make those changes I have to confirm API broken, so it's safer to keep it in another place and start using `gopkg.in` to version my package at this time.(PS: shorter import path)
+
+## License
+
+This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.

+ 547 - 0
Godeps/_workspace/src/github.com/go-ini/ini/README_ZH.md

@@ -0,0 +1,547 @@
+本包提供了 Go 语言中读写 INI 文件的功能。
+
+## 功能特性
+
+- 支持覆盖加载多个数据源(`[]byte` 或文件)
+- 支持递归读取键值
+- 支持读取父子分区
+- 支持读取自增键名
+- 支持读取多行的键值
+- 支持大量辅助方法
+- 支持在读取时直接转换为 Go 语言类型
+- 支持读取和 **写入** 分区和键的注释
+- 轻松操作分区、键值和注释
+- 在保存文件时分区和键值会保持原有的顺序
+
+## 下载安装
+
+    go get gopkg.in/ini.v1
+
+## 开始使用
+
+### 从数据源加载
+
+一个 **数据源** 可以是 `[]byte` 类型的原始数据,或 `string` 类型的文件路径。您可以加载 **任意多个** 数据源。如果您传递其它类型的数据源,则会直接返回错误。
+
+```go
+cfg, err := ini.Load([]byte("raw data"), "filename")
+```
+
+或者从一个空白的文件开始:
+
+```go
+cfg := ini.Empty()
+```
+
+当您在一开始无法决定需要加载哪些数据源时,仍可以使用 **Append()** 在需要的时候加载它们。
+
+```go
+err := cfg.Append("other file", []byte("other raw data"))
+```
+
+### 操作分区(Section)
+
+获取指定分区:
+
+```go
+section, err := cfg.GetSection("section name")
+```
+
+如果您想要获取默认分区,则可以用空字符串代替分区名:
+
+```go
+section, err := cfg.GetSection("")
+```
+
+当您非常确定某个分区是存在的,可以使用以下简便方法:
+
+```go
+section := cfg.Section("")
+```
+
+如果不小心判断错了,要获取的分区其实是不存在的,那会发生什么呢?没事的,它会自动创建并返回一个对应的分区对象给您。
+
+创建一个分区:
+
+```go
+err := cfg.NewSection("new section")
+```
+
+获取所有分区对象或名称:
+
+```go
+sections := cfg.Sections()
+names := cfg.SectionStrings()
+```
+
+### 操作键(Key)
+
+获取某个分区下的键:
+
+```go
+key, err := cfg.Section("").GetKey("key name")
+```
+
+和分区一样,您也可以直接获取键而忽略错误处理:
+
+```go
+key := cfg.Section("").Key("key name")
+```
+
+创建一个新的键:
+
+```go
+err := cfg.Section("").NewKey("name", "value")
+```
+
+获取分区下的所有键或键名:
+
+```go
+keys := cfg.Section("").Keys()
+names := cfg.Section("").KeyStrings()
+```
+
+获取分区下的所有键值对的克隆:
+
+```go
+hash := cfg.GetSection("").KeysHash()
+```
+
+### 操作键值(Value)
+
+获取一个类型为字符串(string)的值:
+
+```go
+val := cfg.Section("").Key("key name").String()
+```
+
+获取值的同时通过自定义函数进行处理验证:
+
+```go
+val := cfg.Section("").Key("key name").Validate(func(in string) string {
+	if len(in) == 0 {
+		return "default"
+	}
+	return in
+})
+```
+
+获取其它类型的值:
+
+```go
+// 布尔值的规则:
+// true 当值为:1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On
+// false 当值为:0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off
+v, err = cfg.Section("").Key("BOOL").Bool()
+v, err = cfg.Section("").Key("FLOAT64").Float64()
+v, err = cfg.Section("").Key("INT").Int()
+v, err = cfg.Section("").Key("INT64").Int64()
+v, err = cfg.Section("").Key("UINT").Uint()
+v, err = cfg.Section("").Key("UINT64").Uint64()
+v, err = cfg.Section("").Key("TIME").TimeFormat(time.RFC3339)
+v, err = cfg.Section("").Key("TIME").Time() // RFC3339
+
+v = cfg.Section("").Key("BOOL").MustBool()
+v = cfg.Section("").Key("FLOAT64").MustFloat64()
+v = cfg.Section("").Key("INT").MustInt()
+v = cfg.Section("").Key("INT64").MustInt64()
+v = cfg.Section("").Key("UINT").MustUint()
+v = cfg.Section("").Key("UINT64").MustUint64()
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339)
+v = cfg.Section("").Key("TIME").MustTime() // RFC3339
+
+// 由 Must 开头的方法名允许接收一个相同类型的参数来作为默认值,
+// 当键不存在或者转换失败时,则会直接返回该默认值。
+// 但是,MustString 方法必须传递一个默认值。
+
+v = cfg.Seciont("").Key("String").MustString("default")
+v = cfg.Section("").Key("BOOL").MustBool(true)
+v = cfg.Section("").Key("FLOAT64").MustFloat64(1.25)
+v = cfg.Section("").Key("INT").MustInt(10)
+v = cfg.Section("").Key("INT64").MustInt64(99)
+v = cfg.Section("").Key("UINT").MustUint(3)
+v = cfg.Section("").Key("UINT64").MustUint64(6)
+v = cfg.Section("").Key("TIME").MustTimeFormat(time.RFC3339, time.Now())
+v = cfg.Section("").Key("TIME").MustTime(time.Now()) // RFC3339
+```
+
+如果我的值有好多行怎么办?
+
+```ini
+[advance]
+ADDRESS = """404 road,
+NotFound, State, 5000
+Earth"""
+```
+
+嗯哼?小 case!
+
+```go
+cfg.Section("advance").Key("ADDRESS").String()
+
+/* --- start ---
+404 road,
+NotFound, State, 5000
+Earth
+------  end  --- */
+```
+
+赞爆了!那要是我属于一行的内容写不下想要写到第二行怎么办?
+
+```ini
+[advance]
+two_lines = how about \
+	continuation lines?
+lots_of_lines = 1 \
+	2 \
+	3 \
+	4
+```
+
+简直是小菜一碟!
+
+```go
+cfg.Section("advance").Key("two_lines").String() // how about continuation lines?
+cfg.Section("advance").Key("lots_of_lines").String() // 1 2 3 4
+```
+
+需要注意的是,值两侧的单引号会被自动剔除:
+
+```ini
+foo = "some value" // foo: some value
+bar = 'some value' // bar: some value
+```
+
+这就是全部了?哈哈,当然不是。
+
+#### 操作键值的辅助方法
+
+获取键值时设定候选值:
+
+```go
+v = cfg.Section("").Key("STRING").In("default", []string{"str", "arr", "types"})
+v = cfg.Section("").Key("FLOAT64").InFloat64(1.1, []float64{1.25, 2.5, 3.75})
+v = cfg.Section("").Key("INT").InInt(5, []int{10, 20, 30})
+v = cfg.Section("").Key("INT64").InInt64(10, []int64{10, 20, 30})
+v = cfg.Section("").Key("UINT").InUint(4, []int{3, 6, 9})
+v = cfg.Section("").Key("UINT64").InUint64(8, []int64{3, 6, 9})
+v = cfg.Section("").Key("TIME").InTimeFormat(time.RFC3339, time.Now(), []time.Time{time1, time2, time3})
+v = cfg.Section("").Key("TIME").InTime(time.Now(), []time.Time{time1, time2, time3}) // RFC3339
+```
+
+如果获取到的值不是候选值的任意一个,则会返回默认值,而默认值不需要是候选值中的一员。
+
+验证获取的值是否在指定范围内:
+
+```go
+vals = cfg.Section("").Key("FLOAT64").RangeFloat64(0.0, 1.1, 2.2)
+vals = cfg.Section("").Key("INT").RangeInt(0, 10, 20)
+vals = cfg.Section("").Key("INT64").RangeInt64(0, 10, 20)
+vals = cfg.Section("").Key("UINT").RangeUint(0, 3, 9)
+vals = cfg.Section("").Key("UINT64").RangeUint64(0, 3, 9)
+vals = cfg.Section("").Key("TIME").RangeTimeFormat(time.RFC3339, time.Now(), minTime, maxTime)
+vals = cfg.Section("").Key("TIME").RangeTime(time.Now(), minTime, maxTime) // RFC3339
+```
+
+自动分割键值为切片(slice):
+
+```go
+vals = cfg.Section("").Key("STRINGS").Strings(",")
+vals = cfg.Section("").Key("FLOAT64S").Float64s(",")
+vals = cfg.Section("").Key("INTS").Ints(",")
+vals = cfg.Section("").Key("INT64S").Int64s(",")
+vals = cfg.Section("").Key("UINTS").Uints(",")
+vals = cfg.Section("").Key("UINT64S").Uint64s(",")
+vals = cfg.Section("").Key("TIMES").Times(",")
+```
+
+### 保存配置
+
+终于到了这个时刻,是时候保存一下配置了。
+
+比较原始的做法是输出配置到某个文件:
+
+```go
+// ...
+err = cfg.SaveTo("my.ini")
+err = cfg.SaveToIndent("my.ini", "\t")
+```
+
+另一个比较高级的做法是写入到任何实现 `io.Writer` 接口的对象中:
+
+```go
+// ...
+cfg.WriteTo(writer)
+cfg.WriteToIndent(writer, "\t")
+```
+
+### 高级用法
+
+#### 递归读取键值
+
+在获取所有键值的过程中,特殊语法 `%(<name>)s` 会被应用,其中 `<name>` 可以是相同分区或者默认分区下的键名。字符串 `%(<name>)s` 会被相应的键值所替代,如果指定的键不存在,则会用空字符串替代。您可以最多使用 99 层的递归嵌套。
+
+```ini
+NAME = ini
+
+[author]
+NAME = Unknwon
+GITHUB = https://github.com/%(NAME)s
+
+[package]
+FULL_NAME = github.com/go-ini/%(NAME)s
+```
+
+```go
+cfg.Section("author").Key("GITHUB").String()		// https://github.com/Unknwon
+cfg.Section("package").Key("FULL_NAME").String()	// github.com/go-ini/ini
+```
+
+#### 读取父子分区
+
+您可以在分区名称中使用 `.` 来表示两个或多个分区之间的父子关系。如果某个键在子分区中不存在,则会去它的父分区中再次寻找,直到没有父分区为止。
+
+```ini
+NAME = ini
+VERSION = v1
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+[package]
+CLONE_URL = https://%(IMPORT_PATH)s
+
+[package.sub]
+```
+
+```go
+cfg.Section("package.sub").Key("CLONE_URL").String()	// https://gopkg.in/ini.v1
+```
+
+#### 读取自增键名
+
+如果数据源中的键名为 `-`,则认为该键使用了自增键名的特殊语法。计数器从 1 开始,并且分区之间是相互独立的。
+
+```ini
+[features]
+-: Support read/write comments of keys and sections
+-: Support auto-increment of key names
+-: Support load multiple files to overwrite key values
+```
+
+```go
+cfg.Section("features").KeyStrings()	// []{"#1", "#2", "#3"}
+```
+
+### 映射到结构
+
+想要使用更加面向对象的方式玩转 INI 吗?好主意。
+
+```ini
+Name = Unknwon
+age = 21
+Male = true
+Born = 1993-01-01T20:17:05Z
+
+[Note]
+Content = Hi is a good man!
+Cities = HangZhou, Boston
+```
+
+```go
+type Note struct {
+	Content string
+	Cities  []string
+}
+
+type Person struct {
+	Name string
+	Age  int `ini:"age"`
+	Male bool
+	Born time.Time
+	Note
+	Created time.Time `ini:"-"`
+}
+
+func main() {
+	cfg, err := ini.Load("path/to/ini")
+	// ...
+	p := new(Person)
+	err = cfg.MapTo(p)
+	// ...
+
+	// 一切竟可以如此的简单。
+	err = ini.MapTo(p, "path/to/ini")
+	// ...
+
+	// 嗯哼?只需要映射一个分区吗?
+	n := new(Note)
+	err = cfg.Section("Note").MapTo(n)
+	// ...
+}
+```
+
+结构的字段怎么设置默认值呢?很简单,只要在映射之前对指定字段进行赋值就可以了。如果键未找到或者类型错误,该值不会发生改变。
+
+```go
+// ...
+p := &Person{
+	Name: "Joe",
+}
+// ...
+```
+
+这样玩 INI 真的好酷啊!然而,如果不能还给我原来的配置文件,有什么卵用?
+
+### 从结构反射
+
+可是,我有说不能吗?
+
+```go
+type Embeded struct {
+	Dates  []time.Time `delim:"|"`
+	Places []string
+	None   []int
+}
+
+type Author struct {
+	Name      string `ini:"NAME"`
+	Male      bool
+	Age       int
+	GPA       float64
+	NeverMind string `ini:"-"`
+	*Embeded
+}
+
+func main() {
+	a := &Author{"Unknwon", true, 21, 2.8, "",
+		&Embeded{
+			[]time.Time{time.Now(), time.Now()},
+			[]string{"HangZhou", "Boston"},
+			[]int{},
+		}}
+	cfg := ini.Empty()
+	err = ini.ReflectFrom(cfg, a)
+	// ...
+}
+```
+
+瞧瞧,奇迹发生了。
+
+```ini
+NAME = Unknwon
+Male = true
+Age = 21
+GPA = 2.8
+
+[Embeded]
+Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
+Places = HangZhou,Boston
+None =
+```
+
+#### 名称映射器(Name Mapper)
+
+为了节省您的时间并简化代码,本库支持类型为 [`NameMapper`](https://gowalker.org/gopkg.in/ini.v1#NameMapper) 的名称映射器,该映射器负责结构字段名与分区名和键名之间的映射。
+
+目前有 2 款内置的映射器:
+
+- `AllCapsUnderscore`:该映射器将字段名转换至格式 `ALL_CAPS_UNDERSCORE` 后再去匹配分区名和键名。
+- `TitleUnderscore`:该映射器将字段名转换至格式 `title_underscore` 后再去匹配分区名和键名。
+
+使用方法:
+
+```go
+type Info struct{
+	PackageName string
+}
+
+func main() {
+	err = ini.MapToWithMapper(&Info{}, ini.TitleUnderscore, []byte("packag_name=ini"))
+	// ...
+
+	cfg, err := ini.Load([]byte("PACKAGE_NAME=ini"))
+	// ...
+	info := new(Info)
+	cfg.NameMapper = ini.AllCapsUnderscore
+	err = cfg.MapTo(info)
+	// ...
+}
+```
+
+使用函数 `ini.ReflectFromWithMapper` 时也可应用相同的规则。
+
+#### 映射/反射的其它说明
+
+任何嵌入的结构都会被默认认作一个不同的分区,并且不会自动产生所谓的父子分区关联:
+
+```go
+type Child struct {
+	Age string
+}
+
+type Parent struct {
+	Name string
+	Child
+}
+
+type Config struct {
+	City string
+	Parent
+}
+```
+
+示例配置文件:
+
+```ini
+City = Boston
+
+[Parent]
+Name = Unknwon
+
+[Child]
+Age = 21
+```
+
+很好,但是,我就是要嵌入结构也在同一个分区。好吧,你爹是李刚!
+
+```go
+type Child struct {
+	Age string
+}
+
+type Parent struct {
+	Name string
+	Child `ini:"Parent"`
+}
+
+type Config struct {
+	City string
+	Parent
+}
+```
+
+示例配置文件:
+
+```ini
+City = Boston
+
+[Parent]
+Name = Unknwon
+Age = 21
+```
+
+## 获取帮助
+
+- [API 文档](https://gowalker.org/gopkg.in/ini.v1)
+- [创建工单](https://github.com/go-ini/ini/issues/new)
+
+## 常见问题
+
+### 字段 `BlockMode` 是什么?
+
+默认情况下,本库会在您进行读写操作时采用锁机制来确保数据时间。但在某些情况下,您非常确定只进行读操作。此时,您可以通过设置 `cfg.BlockMode = false` 来将读操作提升大约 **50-70%** 的性能。
+
+### 为什么要写另一个 INI 解析库?
+
+许多人都在使用我的 [goconfig](https://github.com/Unknwon/goconfig) 来完成对 INI 文件的操作,但我希望使用更加 Go 风格的代码。并且当您设置 `cfg.BlockMode = false` 时,会有大约 **10-30%** 的性能提升。
+
+为了做出这些改变,我必须对 API 进行破坏,所以新开一个仓库是最安全的做法。除此之外,本库直接使用 `gopkg.in` 来进行版本化发布。(其实真相是导入路径更短了)

+ 1226 - 0
Godeps/_workspace/src/github.com/go-ini/ini/ini.go

@@ -0,0 +1,1226 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// Package ini provides INI file read and write functionality in Go.
+package ini
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io"
+	"os"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+const (
+	DEFAULT_SECTION = "DEFAULT"
+	// Maximum allowed depth when recursively substituing variable names.
+	_DEPTH_VALUES = 99
+
+	_VERSION = "1.6.0"
+)
+
+func Version() string {
+	return _VERSION
+}
+
+var (
+	LineBreak = "\n"
+
+	// Variable regexp pattern: %(variable)s
+	varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`)
+
+	// Write spaces around "=" to look better.
+	PrettyFormat = true
+)
+
+func init() {
+	if runtime.GOOS == "windows" {
+		LineBreak = "\r\n"
+	}
+}
+
+func inSlice(str string, s []string) bool {
+	for _, v := range s {
+		if str == v {
+			return true
+		}
+	}
+	return false
+}
+
+// dataSource is a interface that returns file content.
+type dataSource interface {
+	ReadCloser() (io.ReadCloser, error)
+}
+
+type sourceFile struct {
+	name string
+}
+
+func (s sourceFile) ReadCloser() (_ io.ReadCloser, err error) {
+	return os.Open(s.name)
+}
+
+type bytesReadCloser struct {
+	reader io.Reader
+}
+
+func (rc *bytesReadCloser) Read(p []byte) (n int, err error) {
+	return rc.reader.Read(p)
+}
+
+func (rc *bytesReadCloser) Close() error {
+	return nil
+}
+
+type sourceData struct {
+	data []byte
+}
+
+func (s *sourceData) ReadCloser() (io.ReadCloser, error) {
+	return &bytesReadCloser{bytes.NewReader(s.data)}, nil
+}
+
+//  ____  __.
+// |    |/ _|____ ___.__.
+// |      <_/ __ <   |  |
+// |    |  \  ___/\___  |
+// |____|__ \___  > ____|
+//         \/   \/\/
+
+// Key represents a key under a section.
+type Key struct {
+	s          *Section
+	Comment    string
+	name       string
+	value      string
+	isAutoIncr bool
+}
+
+// Name returns name of key.
+func (k *Key) Name() string {
+	return k.name
+}
+
+// Value returns raw value of key for performance purpose.
+func (k *Key) Value() string {
+	return k.value
+}
+
+// String returns string representation of value.
+func (k *Key) String() string {
+	val := k.value
+	if strings.Index(val, "%") == -1 {
+		return val
+	}
+
+	for i := 0; i < _DEPTH_VALUES; i++ {
+		vr := varPattern.FindString(val)
+		if len(vr) == 0 {
+			break
+		}
+
+		// Take off leading '%(' and trailing ')s'.
+		noption := strings.TrimLeft(vr, "%(")
+		noption = strings.TrimRight(noption, ")s")
+
+		// Search in the same section.
+		nk, err := k.s.GetKey(noption)
+		if err != nil {
+			// Search again in default section.
+			nk, _ = k.s.f.Section("").GetKey(noption)
+		}
+
+		// Substitute by new value and take off leading '%(' and trailing ')s'.
+		val = strings.Replace(val, vr, nk.value, -1)
+	}
+	return val
+}
+
+// Validate accepts a validate function which can
+// return modifed result as key value.
+func (k *Key) Validate(fn func(string) string) string {
+	return fn(k.String())
+}
+
+// parseBool returns the boolean value represented by the string.
+//
+// It accepts 1, t, T, TRUE, true, True, YES, yes, Yes, ON, on, On,
+// 0, f, F, FALSE, false, False, NO, no, No, OFF, off, Off.
+// Any other value returns an error.
+func parseBool(str string) (value bool, err error) {
+	switch str {
+	case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "ON", "on", "On":
+		return true, nil
+	case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "OFF", "off", "Off":
+		return false, nil
+	}
+	return false, fmt.Errorf("parsing \"%s\": invalid syntax", str)
+}
+
+// Bool returns bool type value.
+func (k *Key) Bool() (bool, error) {
+	return parseBool(k.String())
+}
+
+// Float64 returns float64 type value.
+func (k *Key) Float64() (float64, error) {
+	return strconv.ParseFloat(k.String(), 64)
+}
+
+// Int returns int type value.
+func (k *Key) Int() (int, error) {
+	return strconv.Atoi(k.String())
+}
+
+// Int64 returns int64 type value.
+func (k *Key) Int64() (int64, error) {
+	return strconv.ParseInt(k.String(), 10, 64)
+}
+
+// Uint returns uint type valued.
+func (k *Key) Uint() (uint, error) {
+	u, e := strconv.ParseUint(k.String(), 10, 64)
+	return uint(u), e
+}
+
+// Uint64 returns uint64 type value.
+func (k *Key) Uint64() (uint64, error) {
+	return strconv.ParseUint(k.String(), 10, 64)
+}
+
+// Duration returns time.Duration type value.
+func (k *Key) Duration() (time.Duration, error) {
+	return time.ParseDuration(k.String())
+}
+
+// TimeFormat parses with given format and returns time.Time type value.
+func (k *Key) TimeFormat(format string) (time.Time, error) {
+	return time.Parse(format, k.String())
+}
+
+// Time parses with RFC3339 format and returns time.Time type value.
+func (k *Key) Time() (time.Time, error) {
+	return k.TimeFormat(time.RFC3339)
+}
+
+// MustString returns default value if key value is empty.
+func (k *Key) MustString(defaultVal string) string {
+	val := k.String()
+	if len(val) == 0 {
+		return defaultVal
+	}
+	return val
+}
+
+// MustBool always returns value without error,
+// it returns false if error occurs.
+func (k *Key) MustBool(defaultVal ...bool) bool {
+	val, err := k.Bool()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustFloat64 always returns value without error,
+// it returns 0.0 if error occurs.
+func (k *Key) MustFloat64(defaultVal ...float64) float64 {
+	val, err := k.Float64()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustInt always returns value without error,
+// it returns 0 if error occurs.
+func (k *Key) MustInt(defaultVal ...int) int {
+	val, err := k.Int()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustInt64 always returns value without error,
+// it returns 0 if error occurs.
+func (k *Key) MustInt64(defaultVal ...int64) int64 {
+	val, err := k.Int64()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustUint always returns value without error,
+// it returns 0 if error occurs.
+func (k *Key) MustUint(defaultVal ...uint) uint {
+	val, err := k.Uint()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustUint64 always returns value without error,
+// it returns 0 if error occurs.
+func (k *Key) MustUint64(defaultVal ...uint64) uint64 {
+	val, err := k.Uint64()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustDuration always returns value without error,
+// it returns zero value if error occurs.
+func (k *Key) MustDuration(defaultVal ...time.Duration) time.Duration {
+	val, err := k.Duration()
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustTimeFormat always parses with given format and returns value without error,
+// it returns zero value if error occurs.
+func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time {
+	val, err := k.TimeFormat(format)
+	if len(defaultVal) > 0 && err != nil {
+		return defaultVal[0]
+	}
+	return val
+}
+
+// MustTime always parses with RFC3339 format and returns value without error,
+// it returns zero value if error occurs.
+func (k *Key) MustTime(defaultVal ...time.Time) time.Time {
+	return k.MustTimeFormat(time.RFC3339, defaultVal...)
+}
+
+// In always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) In(defaultVal string, candidates []string) string {
+	val := k.String()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InFloat64 always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 {
+	val := k.MustFloat64()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InInt always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InInt(defaultVal int, candidates []int) int {
+	val := k.MustInt()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InInt64 always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 {
+	val := k.MustInt64()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InUint always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InUint(defaultVal uint, candidates []uint) uint {
+	val := k.MustUint()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InUint64 always returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InUint64(defaultVal uint64, candidates []uint64) uint64 {
+	val := k.MustUint64()
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InTimeFormat always parses with given format and returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time {
+	val := k.MustTimeFormat(format)
+	for _, cand := range candidates {
+		if val == cand {
+			return val
+		}
+	}
+	return defaultVal
+}
+
+// InTime always parses with RFC3339 format and returns value without error,
+// it returns default value if error occurs or doesn't fit into candidates.
+func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time {
+	return k.InTimeFormat(time.RFC3339, defaultVal, candidates)
+}
+
+// RangeFloat64 checks if value is in given range inclusively,
+// and returns default value if it's not.
+func (k *Key) RangeFloat64(defaultVal, min, max float64) float64 {
+	val := k.MustFloat64()
+	if val < min || val > max {
+		return defaultVal
+	}
+	return val
+}
+
+// RangeInt checks if value is in given range inclusively,
+// and returns default value if it's not.
+func (k *Key) RangeInt(defaultVal, min, max int) int {
+	val := k.MustInt()
+	if val < min || val > max {
+		return defaultVal
+	}
+	return val
+}
+
+// RangeInt64 checks if value is in given range inclusively,
+// and returns default value if it's not.
+func (k *Key) RangeInt64(defaultVal, min, max int64) int64 {
+	val := k.MustInt64()
+	if val < min || val > max {
+		return defaultVal
+	}
+	return val
+}
+
+// RangeTimeFormat checks if value with given format is in given range inclusively,
+// and returns default value if it's not.
+func (k *Key) RangeTimeFormat(format string, defaultVal, min, max time.Time) time.Time {
+	val := k.MustTimeFormat(format)
+	if val.Unix() < min.Unix() || val.Unix() > max.Unix() {
+		return defaultVal
+	}
+	return val
+}
+
+// RangeTime checks if value with RFC3339 format is in given range inclusively,
+// and returns default value if it's not.
+func (k *Key) RangeTime(defaultVal, min, max time.Time) time.Time {
+	return k.RangeTimeFormat(time.RFC3339, defaultVal, min, max)
+}
+
+// Strings returns list of string devide by given delimiter.
+func (k *Key) Strings(delim string) []string {
+	str := k.String()
+	if len(str) == 0 {
+		return []string{}
+	}
+
+	vals := strings.Split(str, delim)
+	for i := range vals {
+		vals[i] = strings.TrimSpace(vals[i])
+	}
+	return vals
+}
+
+// Float64s returns list of float64 devide by given delimiter.
+func (k *Key) Float64s(delim string) []float64 {
+	strs := k.Strings(delim)
+	vals := make([]float64, len(strs))
+	for i := range strs {
+		vals[i], _ = strconv.ParseFloat(strs[i], 64)
+	}
+	return vals
+}
+
+// Ints returns list of int devide by given delimiter.
+func (k *Key) Ints(delim string) []int {
+	strs := k.Strings(delim)
+	vals := make([]int, len(strs))
+	for i := range strs {
+		vals[i], _ = strconv.Atoi(strs[i])
+	}
+	return vals
+}
+
+// Int64s returns list of int64 devide by given delimiter.
+func (k *Key) Int64s(delim string) []int64 {
+	strs := k.Strings(delim)
+	vals := make([]int64, len(strs))
+	for i := range strs {
+		vals[i], _ = strconv.ParseInt(strs[i], 10, 64)
+	}
+	return vals
+}
+
+// Uints returns list of uint devide by given delimiter.
+func (k *Key) Uints(delim string) []uint {
+	strs := k.Strings(delim)
+	vals := make([]uint, len(strs))
+	for i := range strs {
+		u, _ := strconv.ParseUint(strs[i], 10, 64)
+		vals[i] = uint(u)
+	}
+	return vals
+}
+
+// Uint64s returns list of uint64 devide by given delimiter.
+func (k *Key) Uint64s(delim string) []uint64 {
+	strs := k.Strings(delim)
+	vals := make([]uint64, len(strs))
+	for i := range strs {
+		vals[i], _ = strconv.ParseUint(strs[i], 10, 64)
+	}
+	return vals
+}
+
+// TimesFormat parses with given format and returns list of time.Time devide by given delimiter.
+func (k *Key) TimesFormat(format, delim string) []time.Time {
+	strs := k.Strings(delim)
+	vals := make([]time.Time, len(strs))
+	for i := range strs {
+		vals[i], _ = time.Parse(format, strs[i])
+	}
+	return vals
+}
+
+// Times parses with RFC3339 format and returns list of time.Time devide by given delimiter.
+func (k *Key) Times(delim string) []time.Time {
+	return k.TimesFormat(time.RFC3339, delim)
+}
+
+// SetValue changes key value.
+func (k *Key) SetValue(v string) {
+	k.value = v
+}
+
+//   _________              __  .__
+//  /   _____/ ____   _____/  |_|__| ____   ____
+//  \_____  \_/ __ \_/ ___\   __\  |/  _ \ /    \
+//  /        \  ___/\  \___|  | |  (  <_> )   |  \
+// /_______  /\___  >\___  >__| |__|\____/|___|  /
+//         \/     \/     \/                    \/
+
+// Section represents a config section.
+type Section struct {
+	f        *File
+	Comment  string
+	name     string
+	keys     map[string]*Key
+	keyList  []string
+	keysHash map[string]string
+}
+
+func newSection(f *File, name string) *Section {
+	return &Section{f, "", name, make(map[string]*Key), make([]string, 0, 10), make(map[string]string)}
+}
+
+// Name returns name of Section.
+func (s *Section) Name() string {
+	return s.name
+}
+
+// NewKey creates a new key to given section.
+func (s *Section) NewKey(name, val string) (*Key, error) {
+	if len(name) == 0 {
+		return nil, errors.New("error creating new key: empty key name")
+	}
+
+	if s.f.BlockMode {
+		s.f.lock.Lock()
+		defer s.f.lock.Unlock()
+	}
+
+	if inSlice(name, s.keyList) {
+		s.keys[name].value = val
+		return s.keys[name], nil
+	}
+
+	s.keyList = append(s.keyList, name)
+	s.keys[name] = &Key{s, "", name, val, false}
+	s.keysHash[name] = val
+	return s.keys[name], nil
+}
+
+// GetKey returns key in section by given name.
+func (s *Section) GetKey(name string) (*Key, error) {
+	// FIXME: change to section level lock?
+	if s.f.BlockMode {
+		s.f.lock.RLock()
+	}
+	key := s.keys[name]
+	if s.f.BlockMode {
+		s.f.lock.RUnlock()
+	}
+
+	if key == nil {
+		// Check if it is a child-section.
+		sname := s.name
+		for {
+			if i := strings.LastIndex(sname, "."); i > -1 {
+				sname = sname[:i]
+				sec, err := s.f.GetSection(sname)
+				if err != nil {
+					continue
+				}
+				return sec.GetKey(name)
+			} else {
+				break
+			}
+		}
+		return nil, fmt.Errorf("error when getting key of section '%s': key '%s' not exists", s.name, name)
+	}
+	return key, nil
+}
+
+// Key assumes named Key exists in section and returns a zero-value when not.
+func (s *Section) Key(name string) *Key {
+	key, err := s.GetKey(name)
+	if err != nil {
+		// It's OK here because the only possible error is empty key name,
+		// but if it's empty, this piece of code won't be executed.
+		key, _ = s.NewKey(name, "")
+		return key
+	}
+	return key
+}
+
+// Keys returns list of keys of section.
+func (s *Section) Keys() []*Key {
+	keys := make([]*Key, len(s.keyList))
+	for i := range s.keyList {
+		keys[i] = s.Key(s.keyList[i])
+	}
+	return keys
+}
+
+// KeyStrings returns list of key names of section.
+func (s *Section) KeyStrings() []string {
+	list := make([]string, len(s.keyList))
+	copy(list, s.keyList)
+	return list
+}
+
+// KeysHash returns keys hash consisting of names and values.
+func (s *Section) KeysHash() map[string]string {
+	if s.f.BlockMode {
+		s.f.lock.RLock()
+		defer s.f.lock.RUnlock()
+	}
+
+	hash := map[string]string{}
+	for key, value := range s.keysHash {
+		hash[key] = value
+	}
+	return hash
+}
+
+// DeleteKey deletes a key from section.
+func (s *Section) DeleteKey(name string) {
+	if s.f.BlockMode {
+		s.f.lock.Lock()
+		defer s.f.lock.Unlock()
+	}
+
+	for i, k := range s.keyList {
+		if k == name {
+			s.keyList = append(s.keyList[:i], s.keyList[i+1:]...)
+			delete(s.keys, name)
+			return
+		}
+	}
+}
+
+// ___________.__.__
+// \_   _____/|__|  |   ____
+//  |    __)  |  |  | _/ __ \
+//  |     \   |  |  |_\  ___/
+//  \___  /   |__|____/\___  >
+//      \/                 \/
+
+// File represents a combination of a or more INI file(s) in memory.
+type File struct {
+	// Should make things safe, but sometimes doesn't matter.
+	BlockMode bool
+	// Make sure data is safe in multiple goroutines.
+	lock sync.RWMutex
+
+	// Allow combination of multiple data sources.
+	dataSources []dataSource
+	// Actual data is stored here.
+	sections map[string]*Section
+
+	// To keep data in order.
+	sectionList []string
+
+	NameMapper
+}
+
+// newFile initializes File object with given data sources.
+func newFile(dataSources []dataSource) *File {
+	return &File{
+		BlockMode:   true,
+		dataSources: dataSources,
+		sections:    make(map[string]*Section),
+		sectionList: make([]string, 0, 10),
+	}
+}
+
+func parseDataSource(source interface{}) (dataSource, error) {
+	switch s := source.(type) {
+	case string:
+		return sourceFile{s}, nil
+	case []byte:
+		return &sourceData{s}, nil
+	default:
+		return nil, fmt.Errorf("error parsing data source: unknown type '%s'", s)
+	}
+}
+
+// Load loads and parses from INI data sources.
+// Arguments can be mixed of file name with string type, or raw data in []byte.
+func Load(source interface{}, others ...interface{}) (_ *File, err error) {
+	sources := make([]dataSource, len(others)+1)
+	sources[0], err = parseDataSource(source)
+	if err != nil {
+		return nil, err
+	}
+	for i := range others {
+		sources[i+1], err = parseDataSource(others[i])
+		if err != nil {
+			return nil, err
+		}
+	}
+	f := newFile(sources)
+	return f, f.Reload()
+}
+
+// Empty returns an empty file object.
+func Empty() *File {
+	// Ignore error here, we sure our data is good.
+	f, _ := Load([]byte(""))
+	return f
+}
+
+// NewSection creates a new section.
+func (f *File) NewSection(name string) (*Section, error) {
+	if len(name) == 0 {
+		return nil, errors.New("error creating new section: empty section name")
+	}
+
+	if f.BlockMode {
+		f.lock.Lock()
+		defer f.lock.Unlock()
+	}
+
+	if inSlice(name, f.sectionList) {
+		return f.sections[name], nil
+	}
+
+	f.sectionList = append(f.sectionList, name)
+	f.sections[name] = newSection(f, name)
+	return f.sections[name], nil
+}
+
+// NewSections creates a list of sections.
+func (f *File) NewSections(names ...string) (err error) {
+	for _, name := range names {
+		if _, err = f.NewSection(name); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// GetSection returns section by given name.
+func (f *File) GetSection(name string) (*Section, error) {
+	if len(name) == 0 {
+		name = DEFAULT_SECTION
+	}
+
+	if f.BlockMode {
+		f.lock.RLock()
+		defer f.lock.RUnlock()
+	}
+
+	sec := f.sections[name]
+	if sec == nil {
+		return nil, fmt.Errorf("error when getting section: section '%s' not exists", name)
+	}
+	return sec, nil
+}
+
+// Section assumes named section exists and returns a zero-value when not.
+func (f *File) Section(name string) *Section {
+	sec, err := f.GetSection(name)
+	if err != nil {
+		// Note: It's OK here because the only possible error is empty section name,
+		// but if it's empty, this piece of code won't be executed.
+		sec, _ = f.NewSection(name)
+		return sec
+	}
+	return sec
+}
+
+// Section returns list of Section.
+func (f *File) Sections() []*Section {
+	sections := make([]*Section, len(f.sectionList))
+	for i := range f.sectionList {
+		sections[i] = f.Section(f.sectionList[i])
+	}
+	return sections
+}
+
+// SectionStrings returns list of section names.
+func (f *File) SectionStrings() []string {
+	list := make([]string, len(f.sectionList))
+	copy(list, f.sectionList)
+	return list
+}
+
+// DeleteSection deletes a section.
+func (f *File) DeleteSection(name string) {
+	if f.BlockMode {
+		f.lock.Lock()
+		defer f.lock.Unlock()
+	}
+
+	if len(name) == 0 {
+		name = DEFAULT_SECTION
+	}
+
+	for i, s := range f.sectionList {
+		if s == name {
+			f.sectionList = append(f.sectionList[:i], f.sectionList[i+1:]...)
+			delete(f.sections, name)
+			return
+		}
+	}
+}
+
+func cutComment(str string) string {
+	i := strings.Index(str, "#")
+	if i == -1 {
+		return str
+	}
+	return str[:i]
+}
+
+func checkMultipleLines(buf *bufio.Reader, line, val, valQuote string) (string, error) {
+	isEnd := false
+	for {
+		next, err := buf.ReadString('\n')
+		if err != nil {
+			if err != io.EOF {
+				return "", err
+			}
+			isEnd = true
+		}
+		pos := strings.LastIndex(next, valQuote)
+		if pos > -1 {
+			val += next[:pos]
+			break
+		}
+		val += next
+		if isEnd {
+			return "", fmt.Errorf("error parsing line: missing closing key quote from '%s' to '%s'", line, next)
+		}
+	}
+	return val, nil
+}
+
+func checkContinuationLines(buf *bufio.Reader, val string) (string, bool, error) {
+	isEnd := false
+	for {
+		valLen := len(val)
+		if valLen == 0 || val[valLen-1] != '\\' {
+			break
+		}
+		val = val[:valLen-1]
+
+		next, err := buf.ReadString('\n')
+		if err != nil {
+			if err != io.EOF {
+				return "", isEnd, err
+			}
+			isEnd = true
+		}
+
+		next = strings.TrimSpace(next)
+		if len(next) == 0 {
+			break
+		}
+		val += next
+	}
+	return val, isEnd, nil
+}
+
+// parse parses data through an io.Reader.
+func (f *File) parse(reader io.Reader) error {
+	buf := bufio.NewReader(reader)
+
+	// Handle BOM-UTF8.
+	// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
+	mask, err := buf.Peek(3)
+	if err == nil && len(mask) >= 3 && mask[0] == 239 && mask[1] == 187 && mask[2] == 191 {
+		buf.Read(mask)
+	}
+
+	count := 1
+	comments := ""
+	isEnd := false
+
+	section, err := f.NewSection(DEFAULT_SECTION)
+	if err != nil {
+		return err
+	}
+
+	for {
+		line, err := buf.ReadString('\n')
+		line = strings.TrimSpace(line)
+		length := len(line)
+
+		// Check error and ignore io.EOF just for a moment.
+		if err != nil {
+			if err != io.EOF {
+				return fmt.Errorf("error reading next line: %v", err)
+			}
+			// The last line of file could be an empty line.
+			if length == 0 {
+				break
+			}
+			isEnd = true
+		}
+
+		// Skip empty lines.
+		if length == 0 {
+			continue
+		}
+
+		switch {
+		case line[0] == '#' || line[0] == ';': // Comments.
+			if len(comments) == 0 {
+				comments = line
+			} else {
+				comments += LineBreak + line
+			}
+			continue
+		case line[0] == '[' && line[length-1] == ']': // New sction.
+			section, err = f.NewSection(strings.TrimSpace(line[1 : length-1]))
+			if err != nil {
+				return err
+			}
+
+			if len(comments) > 0 {
+				section.Comment = comments
+				comments = ""
+			}
+			// Reset counter.
+			count = 1
+			continue
+		}
+
+		// Other possibilities.
+		var (
+			i        int
+			keyQuote string
+			kname    string
+			valQuote string
+			val      string
+		)
+
+		// Key name surrounded by quotes.
+		if line[0] == '"' {
+			if length > 6 && line[0:3] == `"""` {
+				keyQuote = `"""`
+			} else {
+				keyQuote = `"`
+			}
+		} else if line[0] == '`' {
+			keyQuote = "`"
+		}
+		if len(keyQuote) > 0 {
+			qLen := len(keyQuote)
+			pos := strings.Index(line[qLen:], keyQuote)
+			if pos == -1 {
+				return fmt.Errorf("error parsing line: missing closing key quote: %s", line)
+			}
+			pos = pos + qLen
+			i = strings.IndexAny(line[pos:], "=:")
+			if i < 0 {
+				return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line)
+			} else if i == pos {
+				return fmt.Errorf("error parsing line: key is empty: %s", line)
+			}
+			i = i + pos
+			kname = line[qLen:pos] // Just keep spaces inside quotes.
+		} else {
+			i = strings.IndexAny(line, "=:")
+			if i < 0 {
+				return fmt.Errorf("error parsing line: key-value delimiter not found: %s", line)
+			} else if i == 0 {
+				return fmt.Errorf("error parsing line: key is empty: %s", line)
+			}
+			kname = strings.TrimSpace(line[0:i])
+		}
+
+		isAutoIncr := false
+		// Auto increment.
+		if kname == "-" {
+			isAutoIncr = true
+			kname = "#" + fmt.Sprint(count)
+			count++
+		}
+
+		lineRight := strings.TrimSpace(line[i+1:])
+		lineRightLength := len(lineRight)
+		firstChar := ""
+		if lineRightLength >= 2 {
+			firstChar = lineRight[0:1]
+		}
+		if firstChar == "`" {
+			valQuote = "`"
+		} else if firstChar == `"` {
+			if lineRightLength >= 3 && lineRight[0:3] == `"""` {
+				valQuote = `"""`
+			} else {
+				valQuote = `"`
+			}
+		} else if firstChar == `'` {
+			valQuote = `'`
+		}
+
+		if len(valQuote) > 0 {
+			qLen := len(valQuote)
+			pos := strings.LastIndex(lineRight[qLen:], valQuote)
+			// For multiple-line value check.
+			if pos == -1 {
+				if valQuote == `"` || valQuote == `'` {
+					return fmt.Errorf("error parsing line: single quote does not allow multiple-line value: %s", line)
+				}
+
+				val = lineRight[qLen:] + "\n"
+				val, err = checkMultipleLines(buf, line, val, valQuote)
+				if err != nil {
+					return err
+				}
+			} else {
+				val = lineRight[qLen : pos+qLen]
+			}
+		} else {
+			val = strings.TrimSpace(cutComment(lineRight))
+			val, isEnd, err = checkContinuationLines(buf, val)
+			if err != nil {
+				return err
+			}
+		}
+
+		k, err := section.NewKey(kname, val)
+		if err != nil {
+			return err
+		}
+		k.isAutoIncr = isAutoIncr
+		if len(comments) > 0 {
+			k.Comment = comments
+			comments = ""
+		}
+
+		if isEnd {
+			break
+		}
+	}
+	return nil
+}
+
+func (f *File) reload(s dataSource) error {
+	r, err := s.ReadCloser()
+	if err != nil {
+		return err
+	}
+	defer r.Close()
+
+	return f.parse(r)
+}
+
+// Reload reloads and parses all data sources.
+func (f *File) Reload() (err error) {
+	for _, s := range f.dataSources {
+		if err = f.reload(s); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Append appends one or more data sources and reloads automatically.
+func (f *File) Append(source interface{}, others ...interface{}) error {
+	ds, err := parseDataSource(source)
+	if err != nil {
+		return err
+	}
+	f.dataSources = append(f.dataSources, ds)
+	for _, s := range others {
+		ds, err = parseDataSource(s)
+		if err != nil {
+			return err
+		}
+		f.dataSources = append(f.dataSources, ds)
+	}
+	return f.Reload()
+}
+
+// WriteToIndent writes file content into io.Writer with given value indention.
+func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
+	equalSign := "="
+	if PrettyFormat {
+		equalSign = " = "
+	}
+
+	// Use buffer to make sure target is safe until finish encoding.
+	buf := bytes.NewBuffer(nil)
+	for i, sname := range f.sectionList {
+		sec := f.Section(sname)
+		if len(sec.Comment) > 0 {
+			if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
+				sec.Comment = "; " + sec.Comment
+			}
+			if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil {
+				return 0, err
+			}
+		}
+
+		if i > 0 {
+			if _, err = buf.WriteString("[" + sname + "]" + LineBreak); err != nil {
+				return 0, err
+			}
+		} else {
+			// Write nothing if default section is empty.
+			if len(sec.keyList) == 0 {
+				continue
+			}
+		}
+
+		for _, kname := range sec.keyList {
+			key := sec.Key(kname)
+			if len(key.Comment) > 0 {
+				if len(indent) > 0 && sname != DEFAULT_SECTION {
+					buf.WriteString(indent)
+				}
+				if key.Comment[0] != '#' && key.Comment[0] != ';' {
+					key.Comment = "; " + key.Comment
+				}
+				if _, err = buf.WriteString(key.Comment + LineBreak); err != nil {
+					return 0, err
+				}
+			}
+
+			if len(indent) > 0 && sname != DEFAULT_SECTION {
+				buf.WriteString(indent)
+			}
+
+			switch {
+			case key.isAutoIncr:
+				kname = "-"
+			case strings.Contains(kname, "`") || strings.Contains(kname, `"`):
+				kname = `"""` + kname + `"""`
+			case strings.Contains(kname, `=`) || strings.Contains(kname, `:`):
+				kname = "`" + kname + "`"
+			}
+
+			val := key.value
+			// In case key value contains "\n", "`" or "\"".
+			if strings.Contains(val, "\n") || strings.Contains(val, "`") || strings.Contains(val, `"`) ||
+				strings.Contains(val, "#") {
+				val = `"""` + val + `"""`
+			}
+			if _, err = buf.WriteString(kname + equalSign + val + LineBreak); err != nil {
+				return 0, err
+			}
+		}
+
+		// Put a line between sections.
+		if _, err = buf.WriteString(LineBreak); err != nil {
+			return 0, err
+		}
+	}
+
+	return buf.WriteTo(w)
+}
+
+// WriteTo writes file content into io.Writer.
+func (f *File) WriteTo(w io.Writer) (int64, error) {
+	return f.WriteToIndent(w, "")
+}
+
+// SaveToIndent writes content to file system with given value indention.
+func (f *File) SaveToIndent(filename, indent string) error {
+	// Note: Because we are truncating with os.Create,
+	// 	so it's safer to save to a temporary file location and rename afte done.
+	tmpPath := filename + "." + strconv.Itoa(time.Now().Nanosecond()) + ".tmp"
+	defer os.Remove(tmpPath)
+
+	fw, err := os.Create(tmpPath)
+	if err != nil {
+		return err
+	}
+
+	if _, err = f.WriteToIndent(fw, indent); err != nil {
+		fw.Close()
+		return err
+	}
+	fw.Close()
+
+	// Remove old file and rename the new one.
+	os.Remove(filename)
+	return os.Rename(tmpPath, filename)
+}
+
+// SaveTo writes content to file system.
+func (f *File) SaveTo(filename string) error {
+	return f.SaveToIndent(filename, "")
+}

+ 512 - 0
Godeps/_workspace/src/github.com/go-ini/ini/ini_test.go

@@ -0,0 +1,512 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+func Test_Version(t *testing.T) {
+	Convey("Get version", t, func() {
+		So(Version(), ShouldEqual, _VERSION)
+	})
+}
+
+const _CONF_DATA = `
+; Package name
+NAME = ini
+; Package version
+VERSION = v1
+; Package import path
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+# Information about package author
+# Bio can be written in multiple lines.
+[author]
+NAME = Unknwon  # Succeeding comment
+E-MAIL = fake@localhost
+GITHUB = https://github.com/%(NAME)s
+BIO = """Gopher.
+Coding addict.
+Good man.
+"""  # Succeeding comment
+
+[package]
+CLONE_URL = https://%(IMPORT_PATH)s
+
+[package.sub]
+UNUSED_KEY = should be deleted
+
+[features]
+-: Support read/write comments of keys and sections
+-: Support auto-increment of key names
+-: Support load multiple files to overwrite key values
+
+[types]
+STRING = str
+BOOL = true
+BOOL_FALSE = false
+FLOAT64 = 1.25
+INT = 10
+TIME = 2015-01-01T20:17:05Z
+DURATION = 2h45m
+UINT = 3
+
+[array]
+STRINGS = en, zh, de
+FLOAT64S = 1.1, 2.2, 3.3
+INTS = 1, 2, 3
+UINTS = 1, 2, 3
+TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
+
+[note]
+empty_lines = next line is empty\
+
+[advance]
+value with quotes = "some value"
+value quote2 again = 'some value'
+true = """"2+3=5""""
+"1+1=2" = true
+"""6+1=7""" = true
+"""` + "`" + `5+5` + "`" + `""" = 10
+""""6+6"""" = 12
+` + "`" + `7-2=4` + "`" + ` = false
+ADDRESS = ` + "`" + `404 road,
+NotFound, State, 50000` + "`" + `
+
+two_lines = how about \
+	continuation lines?
+lots_of_lines = 1 \
+	2 \
+	3 \
+	4 \
+`
+
+func Test_Load(t *testing.T) {
+	Convey("Load from data sources", t, func() {
+
+		Convey("Load with empty data", func() {
+			So(Empty(), ShouldNotBeNil)
+		})
+
+		Convey("Load with multiple data sources", func() {
+			cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+			So(err, ShouldBeNil)
+			So(cfg, ShouldNotBeNil)
+		})
+	})
+
+	Convey("Bad load process", t, func() {
+
+		Convey("Load from invalid data sources", func() {
+			_, err := Load(_CONF_DATA)
+			So(err, ShouldNotBeNil)
+
+			_, err = Load("testdata/404.ini")
+			So(err, ShouldNotBeNil)
+
+			_, err = Load(1)
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(""), 1)
+			So(err, ShouldNotBeNil)
+		})
+
+		Convey("Load with empty section name", func() {
+			_, err := Load([]byte("[]"))
+			So(err, ShouldNotBeNil)
+		})
+
+		Convey("Load with bad keys", func() {
+			_, err := Load([]byte(`"""name`))
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(`"""name"""`))
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(`""=1`))
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(`=`))
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(`name`))
+			So(err, ShouldNotBeNil)
+		})
+
+		Convey("Load with bad values", func() {
+			_, err := Load([]byte(`name="""Unknwon`))
+			So(err, ShouldNotBeNil)
+
+			_, err = Load([]byte(`key = "value`))
+			So(err, ShouldNotBeNil)
+		})
+	})
+}
+
+func Test_Values(t *testing.T) {
+	Convey("Test getting and setting values", t, func() {
+		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		Convey("Get values in default section", func() {
+			sec := cfg.Section("")
+			So(sec, ShouldNotBeNil)
+			So(sec.Key("NAME").Value(), ShouldEqual, "ini")
+			So(sec.Key("NAME").String(), ShouldEqual, "ini")
+			So(sec.Key("NAME").Validate(func(in string) string {
+				return in
+			}), ShouldEqual, "ini")
+			So(sec.Key("NAME").Comment, ShouldEqual, "; Package name")
+			So(sec.Key("IMPORT_PATH").String(), ShouldEqual, "gopkg.in/ini.v1")
+		})
+
+		Convey("Get values in non-default section", func() {
+			sec := cfg.Section("author")
+			So(sec, ShouldNotBeNil)
+			So(sec.Key("NAME").String(), ShouldEqual, "Unknwon")
+			So(sec.Key("GITHUB").String(), ShouldEqual, "https://github.com/Unknwon")
+
+			sec = cfg.Section("package")
+			So(sec, ShouldNotBeNil)
+			So(sec.Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
+		})
+
+		Convey("Get auto-increment key names", func() {
+			keys := cfg.Section("features").Keys()
+			for i, k := range keys {
+				So(k.Name(), ShouldEqual, fmt.Sprintf("#%d", i+1))
+			}
+		})
+
+		Convey("Get overwrite value", func() {
+			So(cfg.Section("author").Key("E-MAIL").String(), ShouldEqual, "u@gogs.io")
+		})
+
+		Convey("Get sections", func() {
+			sections := cfg.Sections()
+			for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "advance"} {
+				So(sections[i].Name(), ShouldEqual, name)
+			}
+		})
+
+		Convey("Get parent section value", func() {
+			So(cfg.Section("package.sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
+		})
+
+		Convey("Get multiple line value", func() {
+			So(cfg.Section("author").Key("BIO").String(), ShouldEqual, "Gopher.\nCoding addict.\nGood man.\n")
+		})
+
+		Convey("Get values with type", func() {
+			sec := cfg.Section("types")
+			v1, err := sec.Key("BOOL").Bool()
+			So(err, ShouldBeNil)
+			So(v1, ShouldBeTrue)
+
+			v1, err = sec.Key("BOOL_FALSE").Bool()
+			So(err, ShouldBeNil)
+			So(v1, ShouldBeFalse)
+
+			v2, err := sec.Key("FLOAT64").Float64()
+			So(err, ShouldBeNil)
+			So(v2, ShouldEqual, 1.25)
+
+			v3, err := sec.Key("INT").Int()
+			So(err, ShouldBeNil)
+			So(v3, ShouldEqual, 10)
+
+			v4, err := sec.Key("INT").Int64()
+			So(err, ShouldBeNil)
+			So(v4, ShouldEqual, 10)
+
+			v5, err := sec.Key("UINT").Uint()
+			So(err, ShouldBeNil)
+			So(v5, ShouldEqual, 3)
+
+			v6, err := sec.Key("UINT").Uint64()
+			So(err, ShouldBeNil)
+			So(v6, ShouldEqual, 3)
+
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			v7, err := sec.Key("TIME").Time()
+			So(err, ShouldBeNil)
+			So(v7.String(), ShouldEqual, t.String())
+
+			Convey("Must get values with type", func() {
+				So(sec.Key("STRING").MustString("404"), ShouldEqual, "str")
+				So(sec.Key("BOOL").MustBool(), ShouldBeTrue)
+				So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25)
+				So(sec.Key("INT").MustInt(), ShouldEqual, 10)
+				So(sec.Key("INT").MustInt64(), ShouldEqual, 10)
+				So(sec.Key("UINT").MustUint(), ShouldEqual, 3)
+				So(sec.Key("UINT").MustUint64(), ShouldEqual, 3)
+				So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String())
+
+				dur, err := time.ParseDuration("2h45m")
+				So(err, ShouldBeNil)
+				So(sec.Key("DURATION").MustDuration().Seconds(), ShouldEqual, dur.Seconds())
+
+				Convey("Must get values with default value", func() {
+					So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404")
+					So(sec.Key("BOOL_404").MustBool(true), ShouldBeTrue)
+					So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5)
+					So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15)
+					So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15)
+					So(sec.Key("UINT_404").MustUint(6), ShouldEqual, 6)
+					So(sec.Key("UINT_404").MustUint64(6), ShouldEqual, 6)
+
+					t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z")
+					So(err, ShouldBeNil)
+					So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String())
+
+					So(sec.Key("DURATION_404").MustDuration(dur).Seconds(), ShouldEqual, dur.Seconds())
+				})
+			})
+		})
+
+		Convey("Get value with candidates", func() {
+			sec := cfg.Section("types")
+			So(sec.Key("STRING").In("", []string{"str", "arr", "types"}), ShouldEqual, "str")
+			So(sec.Key("FLOAT64").InFloat64(0, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
+			So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10)
+			So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10)
+			So(sec.Key("UINT").InUint(0, []uint{3, 6, 9}), ShouldEqual, 3)
+			So(sec.Key("UINT").InUint64(0, []uint64{3, 6, 9}), ShouldEqual, 3)
+
+			zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
+			So(err, ShouldBeNil)
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
+
+			Convey("Get value with candidates and default value", func() {
+				So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str")
+				So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25)
+				So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10)
+				So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10)
+				So(sec.Key("UINT_404").InUint(3, []uint{3, 6, 9}), ShouldEqual, 3)
+				So(sec.Key("UINT_404").InUint64(3, []uint64{3, 6, 9}), ShouldEqual, 3)
+				So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String())
+			})
+		})
+
+		Convey("Get values in range", func() {
+			sec := cfg.Section("types")
+			So(sec.Key("FLOAT64").RangeFloat64(0, 1, 2), ShouldEqual, 1.25)
+			So(sec.Key("INT").RangeInt(0, 10, 20), ShouldEqual, 10)
+			So(sec.Key("INT").RangeInt64(0, 10, 20), ShouldEqual, 10)
+
+			minT, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z")
+			So(err, ShouldBeNil)
+			midT, err := time.Parse(time.RFC3339, "2013-01-01T01:00:00Z")
+			So(err, ShouldBeNil)
+			maxT, err := time.Parse(time.RFC3339, "9999-01-01T01:00:00Z")
+			So(err, ShouldBeNil)
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			So(sec.Key("TIME").RangeTime(t, minT, maxT).String(), ShouldEqual, t.String())
+
+			Convey("Get value in range with default value", func() {
+				So(sec.Key("FLOAT64").RangeFloat64(5, 0, 1), ShouldEqual, 5)
+				So(sec.Key("INT").RangeInt(7, 0, 5), ShouldEqual, 7)
+				So(sec.Key("INT").RangeInt64(7, 0, 5), ShouldEqual, 7)
+				So(sec.Key("TIME").RangeTime(t, minT, midT).String(), ShouldEqual, t.String())
+			})
+		})
+
+		Convey("Get values into slice", func() {
+			sec := cfg.Section("array")
+			So(strings.Join(sec.Key("STRINGS").Strings(","), ","), ShouldEqual, "en,zh,de")
+			So(len(sec.Key("STRINGS_404").Strings(",")), ShouldEqual, 0)
+
+			vals1 := sec.Key("FLOAT64S").Float64s(",")
+			for i, v := range []float64{1.1, 2.2, 3.3} {
+				So(vals1[i], ShouldEqual, v)
+			}
+
+			vals2 := sec.Key("INTS").Ints(",")
+			for i, v := range []int{1, 2, 3} {
+				So(vals2[i], ShouldEqual, v)
+			}
+
+			vals3 := sec.Key("INTS").Int64s(",")
+			for i, v := range []int64{1, 2, 3} {
+				So(vals3[i], ShouldEqual, v)
+			}
+
+			vals4 := sec.Key("UINTS").Uints(",")
+			for i, v := range []uint{1, 2, 3} {
+				So(vals4[i], ShouldEqual, v)
+			}
+
+			vals5 := sec.Key("UINTS").Uint64s(",")
+			for i, v := range []uint64{1, 2, 3} {
+				So(vals5[i], ShouldEqual, v)
+			}
+
+			t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z")
+			So(err, ShouldBeNil)
+			vals6 := sec.Key("TIMES").Times(",")
+			for i, v := range []time.Time{t, t, t} {
+				So(vals6[i].String(), ShouldEqual, v.String())
+			}
+		})
+
+		Convey("Get key hash", func() {
+			cfg.Section("").KeysHash()
+		})
+
+		Convey("Set key value", func() {
+			k := cfg.Section("author").Key("NAME")
+			k.SetValue("无闻")
+			So(k.String(), ShouldEqual, "无闻")
+		})
+
+		Convey("Get key strings", func() {
+			So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,BOOL_FALSE,FLOAT64,INT,TIME,DURATION,UINT")
+		})
+
+		Convey("Delete a key", func() {
+			cfg.Section("package.sub").DeleteKey("UNUSED_KEY")
+			_, err := cfg.Section("package.sub").GetKey("UNUSED_KEY")
+			So(err, ShouldNotBeNil)
+		})
+
+		Convey("Get section strings", func() {
+			So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,advance")
+		})
+
+		Convey("Delete a section", func() {
+			cfg.DeleteSection("")
+			So(cfg.SectionStrings()[0], ShouldNotEqual, DEFAULT_SECTION)
+		})
+
+		Convey("Create new sections", func() {
+			cfg.NewSections("test", "test2")
+			_, err := cfg.GetSection("test")
+			So(err, ShouldBeNil)
+			_, err = cfg.GetSection("test2")
+			So(err, ShouldBeNil)
+		})
+	})
+
+	Convey("Test getting and setting bad values", t, func() {
+		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		Convey("Create new key with empty name", func() {
+			k, err := cfg.Section("").NewKey("", "")
+			So(err, ShouldNotBeNil)
+			So(k, ShouldBeNil)
+		})
+
+		Convey("Create new section with empty name", func() {
+			s, err := cfg.NewSection("")
+			So(err, ShouldNotBeNil)
+			So(s, ShouldBeNil)
+		})
+
+		Convey("Create new sections with empty name", func() {
+			So(cfg.NewSections(""), ShouldNotBeNil)
+		})
+
+		Convey("Get section that not exists", func() {
+			s, err := cfg.GetSection("404")
+			So(err, ShouldNotBeNil)
+			So(s, ShouldBeNil)
+
+			s = cfg.Section("404")
+			So(s, ShouldNotBeNil)
+		})
+	})
+}
+
+func Test_File_Append(t *testing.T) {
+	Convey("Append data sources", t, func() {
+		cfg, err := Load([]byte(""))
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		So(cfg.Append([]byte(""), []byte("")), ShouldBeNil)
+
+		Convey("Append bad data sources", func() {
+			So(cfg.Append(1), ShouldNotBeNil)
+			So(cfg.Append([]byte(""), 1), ShouldNotBeNil)
+		})
+	})
+}
+
+func Test_File_SaveTo(t *testing.T) {
+	Convey("Save file", t, func() {
+		cfg, err := Load([]byte(_CONF_DATA), "testdata/conf.ini")
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		cfg.Section("").Key("NAME").Comment = "Package name"
+		cfg.Section("author").Comment = `Information about package author
+# Bio can be written in multiple lines.`
+		cfg.Section("advanced").Key("val w/ pound").SetValue("my#password")
+		So(cfg.SaveTo("testdata/conf_out.ini"), ShouldBeNil)
+
+		cfg.Section("author").Key("NAME").Comment = "This is author name"
+		So(cfg.SaveToIndent("testdata/conf_out.ini", "\t"), ShouldBeNil)
+	})
+}
+
+func Benchmark_Key_Value(b *testing.B) {
+	c, _ := Load([]byte(_CONF_DATA))
+	for i := 0; i < b.N; i++ {
+		c.Section("").Key("NAME").Value()
+	}
+}
+
+func Benchmark_Key_String(b *testing.B) {
+	c, _ := Load([]byte(_CONF_DATA))
+	for i := 0; i < b.N; i++ {
+		c.Section("").Key("NAME").String()
+	}
+}
+
+func Benchmark_Key_Value_NonBlock(b *testing.B) {
+	c, _ := Load([]byte(_CONF_DATA))
+	c.BlockMode = false
+	for i := 0; i < b.N; i++ {
+		c.Section("").Key("NAME").Value()
+	}
+}
+
+func Benchmark_Key_String_NonBlock(b *testing.B) {
+	c, _ := Load([]byte(_CONF_DATA))
+	c.BlockMode = false
+	for i := 0; i < b.N; i++ {
+		c.Section("").Key("NAME").String()
+	}
+}
+
+func Benchmark_Key_SetValue(b *testing.B) {
+	c, _ := Load([]byte(_CONF_DATA))
+	for i := 0; i < b.N; i++ {
+		c.Section("").Key("NAME").SetValue("10")
+	}
+}

+ 350 - 0
Godeps/_workspace/src/github.com/go-ini/ini/struct.go

@@ -0,0 +1,350 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"reflect"
+	"time"
+	"unicode"
+)
+
+// NameMapper represents a ini tag name mapper.
+type NameMapper func(string) string
+
+// Built-in name getters.
+var (
+	// AllCapsUnderscore converts to format ALL_CAPS_UNDERSCORE.
+	AllCapsUnderscore NameMapper = func(raw string) string {
+		newstr := make([]rune, 0, len(raw))
+		for i, chr := range raw {
+			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
+				if i > 0 {
+					newstr = append(newstr, '_')
+				}
+			}
+			newstr = append(newstr, unicode.ToUpper(chr))
+		}
+		return string(newstr)
+	}
+	// TitleUnderscore converts to format title_underscore.
+	TitleUnderscore NameMapper = func(raw string) string {
+		newstr := make([]rune, 0, len(raw))
+		for i, chr := range raw {
+			if isUpper := 'A' <= chr && chr <= 'Z'; isUpper {
+				if i > 0 {
+					newstr = append(newstr, '_')
+				}
+				chr -= ('A' - 'a')
+			}
+			newstr = append(newstr, chr)
+		}
+		return string(newstr)
+	}
+)
+
+func (s *Section) parseFieldName(raw, actual string) string {
+	if len(actual) > 0 {
+		return actual
+	}
+	if s.f.NameMapper != nil {
+		return s.f.NameMapper(raw)
+	}
+	return raw
+}
+
+func parseDelim(actual string) string {
+	if len(actual) > 0 {
+		return actual
+	}
+	return ","
+}
+
+var reflectTime = reflect.TypeOf(time.Now()).Kind()
+
+// setWithProperType sets proper value to field based on its type,
+// but it does not return error for failing parsing,
+// because we want to use default value that is already assigned to strcut.
+func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
+	switch t.Kind() {
+	case reflect.String:
+		if len(key.String()) == 0 {
+			return nil
+		}
+		field.SetString(key.String())
+	case reflect.Bool:
+		boolVal, err := key.Bool()
+		if err != nil {
+			return nil
+		}
+		field.SetBool(boolVal)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		durationVal, err := key.Duration()
+		if err == nil {
+			field.Set(reflect.ValueOf(durationVal))
+			return nil
+		}
+
+		intVal, err := key.Int64()
+		if err != nil {
+			return nil
+		}
+		field.SetInt(intVal)
+	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
+	case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		durationVal, err := key.Duration()
+		if err == nil {
+			field.Set(reflect.ValueOf(durationVal))
+			return nil
+		}
+
+		uintVal, err := key.Uint64()
+		if err != nil {
+			return nil
+		}
+		field.SetUint(uintVal)
+
+	case reflect.Float64:
+		floatVal, err := key.Float64()
+		if err != nil {
+			return nil
+		}
+		field.SetFloat(floatVal)
+	case reflectTime:
+		timeVal, err := key.Time()
+		if err != nil {
+			return nil
+		}
+		field.Set(reflect.ValueOf(timeVal))
+	case reflect.Slice:
+		vals := key.Strings(delim)
+		numVals := len(vals)
+		if numVals == 0 {
+			return nil
+		}
+
+		sliceOf := field.Type().Elem().Kind()
+
+		var times []time.Time
+		if sliceOf == reflectTime {
+			times = key.Times(delim)
+		}
+
+		slice := reflect.MakeSlice(field.Type(), numVals, numVals)
+		for i := 0; i < numVals; i++ {
+			switch sliceOf {
+			case reflectTime:
+				slice.Index(i).Set(reflect.ValueOf(times[i]))
+			default:
+				slice.Index(i).Set(reflect.ValueOf(vals[i]))
+			}
+		}
+		field.Set(slice)
+	default:
+		return fmt.Errorf("unsupported type '%s'", t)
+	}
+	return nil
+}
+
+func (s *Section) mapTo(val reflect.Value) error {
+	if val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	typ := val.Type()
+
+	for i := 0; i < typ.NumField(); i++ {
+		field := val.Field(i)
+		tpField := typ.Field(i)
+
+		tag := tpField.Tag.Get("ini")
+		if tag == "-" {
+			continue
+		}
+
+		fieldName := s.parseFieldName(tpField.Name, tag)
+		if len(fieldName) == 0 || !field.CanSet() {
+			continue
+		}
+
+		isAnonymous := tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous
+		isStruct := tpField.Type.Kind() == reflect.Struct
+		if isAnonymous {
+			field.Set(reflect.New(tpField.Type.Elem()))
+		}
+
+		if isAnonymous || isStruct {
+			if sec, err := s.f.GetSection(fieldName); err == nil {
+				if err = sec.mapTo(field); err != nil {
+					return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
+				}
+				continue
+			}
+		}
+
+		if key, err := s.GetKey(fieldName); err == nil {
+			if err = setWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
+				return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
+			}
+		}
+	}
+	return nil
+}
+
+// MapTo maps section to given struct.
+func (s *Section) MapTo(v interface{}) error {
+	typ := reflect.TypeOf(v)
+	val := reflect.ValueOf(v)
+	if typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+		val = val.Elem()
+	} else {
+		return errors.New("cannot map to non-pointer struct")
+	}
+
+	return s.mapTo(val)
+}
+
+// MapTo maps file to given struct.
+func (f *File) MapTo(v interface{}) error {
+	return f.Section("").MapTo(v)
+}
+
+// MapTo maps data sources to given struct with name mapper.
+func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
+	cfg, err := Load(source, others...)
+	if err != nil {
+		return err
+	}
+	cfg.NameMapper = mapper
+	return cfg.MapTo(v)
+}
+
+// MapTo maps data sources to given struct.
+func MapTo(v, source interface{}, others ...interface{}) error {
+	return MapToWithMapper(v, nil, source, others...)
+}
+
+// reflectWithProperType does the opposite thing with setWithProperType.
+func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string) error {
+	switch t.Kind() {
+	case reflect.String:
+		key.SetValue(field.String())
+	case reflect.Bool,
+		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+		reflect.Float64,
+		reflectTime:
+		key.SetValue(fmt.Sprint(field))
+	case reflect.Slice:
+		vals := field.Slice(0, field.Len())
+		if field.Len() == 0 {
+			return nil
+		}
+
+		var buf bytes.Buffer
+		isTime := fmt.Sprint(field.Type()) == "[]time.Time"
+		for i := 0; i < field.Len(); i++ {
+			if isTime {
+				buf.WriteString(vals.Index(i).Interface().(time.Time).Format(time.RFC3339))
+			} else {
+				buf.WriteString(fmt.Sprint(vals.Index(i)))
+			}
+			buf.WriteString(delim)
+		}
+		key.SetValue(buf.String()[:buf.Len()-1])
+	default:
+		return fmt.Errorf("unsupported type '%s'", t)
+	}
+	return nil
+}
+
+func (s *Section) reflectFrom(val reflect.Value) error {
+	if val.Kind() == reflect.Ptr {
+		val = val.Elem()
+	}
+	typ := val.Type()
+
+	for i := 0; i < typ.NumField(); i++ {
+		field := val.Field(i)
+		tpField := typ.Field(i)
+
+		tag := tpField.Tag.Get("ini")
+		if tag == "-" {
+			continue
+		}
+
+		fieldName := s.parseFieldName(tpField.Name, tag)
+		if len(fieldName) == 0 || !field.CanSet() {
+			continue
+		}
+
+		if (tpField.Type.Kind() == reflect.Ptr && tpField.Anonymous) ||
+			(tpField.Type.Kind() == reflect.Struct) {
+			// Note: The only error here is section doesn't exist.
+			sec, err := s.f.GetSection(fieldName)
+			if err != nil {
+				// Note: fieldName can never be empty here, ignore error.
+				sec, _ = s.f.NewSection(fieldName)
+			}
+			if err = sec.reflectFrom(field); err != nil {
+				return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
+			}
+			continue
+		}
+
+		// Note: Same reason as secion.
+		key, err := s.GetKey(fieldName)
+		if err != nil {
+			key, _ = s.NewKey(fieldName, "")
+		}
+		if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
+			return fmt.Errorf("error reflecting field(%s): %v", fieldName, err)
+		}
+
+	}
+	return nil
+}
+
+// ReflectFrom reflects secion from given struct.
+func (s *Section) ReflectFrom(v interface{}) error {
+	typ := reflect.TypeOf(v)
+	val := reflect.ValueOf(v)
+	if typ.Kind() == reflect.Ptr {
+		typ = typ.Elem()
+		val = val.Elem()
+	} else {
+		return errors.New("cannot reflect from non-pointer struct")
+	}
+
+	return s.reflectFrom(val)
+}
+
+// ReflectFrom reflects file from given struct.
+func (f *File) ReflectFrom(v interface{}) error {
+	return f.Section("").ReflectFrom(v)
+}
+
+// ReflectFrom reflects data sources from given struct with name mapper.
+func ReflectFromWithMapper(cfg *File, v interface{}, mapper NameMapper) error {
+	cfg.NameMapper = mapper
+	return cfg.ReflectFrom(v)
+}
+
+// ReflectFrom reflects data sources from given struct.
+func ReflectFrom(cfg *File, v interface{}) error {
+	return ReflectFromWithMapper(cfg, v, nil)
+}

+ 239 - 0
Godeps/_workspace/src/github.com/go-ini/ini/struct_test.go

@@ -0,0 +1,239 @@
+// Copyright 2014 Unknwon
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package ini
+
+import (
+	"strings"
+	"testing"
+	"time"
+
+	. "github.com/smartystreets/goconvey/convey"
+)
+
+type testNested struct {
+	Cities []string `delim:"|"`
+	Visits []time.Time
+	Note   string
+	Unused int `ini:"-"`
+}
+
+type testEmbeded struct {
+	GPA float64
+}
+
+type testStruct struct {
+	Name         string `ini:"NAME"`
+	Age          int
+	Male         bool
+	Money        float64
+	Born         time.Time
+	Time         time.Duration `ini:"Duration"`
+	Others       testNested
+	*testEmbeded `ini:"grade"`
+	Unused       int `ini:"-"`
+	Unsigned     uint
+}
+
+const _CONF_DATA_STRUCT = `
+NAME = Unknwon
+Age = 21
+Male = true
+Money = 1.25
+Born = 1993-10-07T20:17:05Z
+Duration = 2h45m
+Unsigned = 3
+
+[Others]
+Cities = HangZhou|Boston
+Visits = 1993-10-07T20:17:05Z, 1993-10-07T20:17:05Z
+Note = Hello world!
+
+[grade]
+GPA = 2.8
+
+[foo.bar]
+Here = there
+When = then
+`
+
+type unsupport struct {
+	Byte byte
+}
+
+type unsupport2 struct {
+	Others struct {
+		Cities byte
+	}
+}
+
+type unsupport3 struct {
+	Cities byte
+}
+
+type unsupport4 struct {
+	*unsupport3 `ini:"Others"`
+}
+
+type defaultValue struct {
+	Name   string
+	Age    int
+	Male   bool
+	Money  float64
+	Born   time.Time
+	Cities []string
+}
+
+type fooBar struct {
+	Here, When string
+}
+
+const _INVALID_DATA_CONF_STRUCT = `
+Name = 
+Age = age
+Male = 123
+Money = money
+Born = nil
+Cities = 
+`
+
+func Test_Struct(t *testing.T) {
+	Convey("Map to struct", t, func() {
+		Convey("Map file to struct", func() {
+			ts := new(testStruct)
+			So(MapTo(ts, []byte(_CONF_DATA_STRUCT)), ShouldBeNil)
+
+			So(ts.Name, ShouldEqual, "Unknwon")
+			So(ts.Age, ShouldEqual, 21)
+			So(ts.Male, ShouldBeTrue)
+			So(ts.Money, ShouldEqual, 1.25)
+			So(ts.Unsigned, ShouldEqual, 3)
+
+			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
+			So(err, ShouldBeNil)
+			So(ts.Born.String(), ShouldEqual, t.String())
+
+			dur, err := time.ParseDuration("2h45m")
+			So(err, ShouldBeNil)
+			So(ts.Time.Seconds(), ShouldEqual, dur.Seconds())
+
+			So(strings.Join(ts.Others.Cities, ","), ShouldEqual, "HangZhou,Boston")
+			So(ts.Others.Visits[0].String(), ShouldEqual, t.String())
+			So(ts.Others.Note, ShouldEqual, "Hello world!")
+			So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
+		})
+
+		Convey("Map section to struct", func() {
+			foobar := new(fooBar)
+			f, err := Load([]byte(_CONF_DATA_STRUCT))
+			So(err, ShouldBeNil)
+
+			So(f.Section("foo.bar").MapTo(foobar), ShouldBeNil)
+			So(foobar.Here, ShouldEqual, "there")
+			So(foobar.When, ShouldEqual, "then")
+		})
+
+		Convey("Map to non-pointer struct", func() {
+			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+			So(err, ShouldBeNil)
+			So(cfg, ShouldNotBeNil)
+
+			So(cfg.MapTo(testStruct{}), ShouldNotBeNil)
+		})
+
+		Convey("Map to unsupported type", func() {
+			cfg, err := Load([]byte(_CONF_DATA_STRUCT))
+			So(err, ShouldBeNil)
+			So(cfg, ShouldNotBeNil)
+
+			cfg.NameMapper = func(raw string) string {
+				if raw == "Byte" {
+					return "NAME"
+				}
+				return raw
+			}
+			So(cfg.MapTo(&unsupport{}), ShouldNotBeNil)
+			So(cfg.MapTo(&unsupport2{}), ShouldNotBeNil)
+			So(cfg.MapTo(&unsupport4{}), ShouldNotBeNil)
+		})
+
+		Convey("Map from invalid data source", func() {
+			So(MapTo(&testStruct{}, "hi"), ShouldNotBeNil)
+		})
+
+		Convey("Map to wrong types and gain default values", func() {
+			cfg, err := Load([]byte(_INVALID_DATA_CONF_STRUCT))
+			So(err, ShouldBeNil)
+
+			t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
+			So(err, ShouldBeNil)
+			dv := &defaultValue{"Joe", 10, true, 1.25, t, []string{"HangZhou", "Boston"}}
+			So(cfg.MapTo(dv), ShouldBeNil)
+			So(dv.Name, ShouldEqual, "Joe")
+			So(dv.Age, ShouldEqual, 10)
+			So(dv.Male, ShouldBeTrue)
+			So(dv.Money, ShouldEqual, 1.25)
+			So(dv.Born.String(), ShouldEqual, t.String())
+			So(strings.Join(dv.Cities, ","), ShouldEqual, "HangZhou,Boston")
+		})
+	})
+
+	Convey("Reflect from struct", t, func() {
+		type Embeded struct {
+			Dates  []time.Time `delim:"|"`
+			Places []string
+			None   []int
+		}
+		type Author struct {
+			Name      string `ini:"NAME"`
+			Male      bool
+			Age       int
+			GPA       float64
+			NeverMind string `ini:"-"`
+			*Embeded  `ini:"infos"`
+		}
+		a := &Author{"Unknwon", true, 21, 2.8, "",
+			&Embeded{
+				[]time.Time{time.Now(), time.Now()},
+				[]string{"HangZhou", "Boston"},
+				[]int{},
+			}}
+		cfg := Empty()
+		So(ReflectFrom(cfg, a), ShouldBeNil)
+		cfg.SaveTo("testdata/conf_reflect.ini")
+
+		Convey("Reflect from non-point struct", func() {
+			So(ReflectFrom(cfg, Author{}), ShouldNotBeNil)
+		})
+	})
+}
+
+type testMapper struct {
+	PackageName string
+}
+
+func Test_NameGetter(t *testing.T) {
+	Convey("Test name mappers", t, func() {
+		So(MapToWithMapper(&testMapper{}, TitleUnderscore, []byte("packag_name=ini")), ShouldBeNil)
+
+		cfg, err := Load([]byte("PACKAGE_NAME=ini"))
+		So(err, ShouldBeNil)
+		So(cfg, ShouldNotBeNil)
+
+		cfg.NameMapper = AllCapsUnderscore
+		tg := new(testMapper)
+		So(cfg.MapTo(tg), ShouldBeNil)
+		So(tg.PackageName, ShouldEqual, "ini")
+	})
+}

+ 2 - 0
Godeps/_workspace/src/github.com/go-ini/ini/testdata/conf.ini

@@ -0,0 +1,2 @@
+[author]
+E-MAIL = u@gogs.io

+ 4 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/.gitignore

@@ -0,0 +1,4 @@
+jpgo
+jmespath-fuzz.zip
+cpu.out
+go-jmespath.test

+ 9 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/.travis.yml

@@ -0,0 +1,9 @@
+language: go
+
+sudo: false
+
+go:
+  - 1.4
+
+install: go get -v -t ./...
+script: make test

+ 13 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/LICENSE

@@ -0,0 +1,13 @@
+Copyright 2015 James Saryerwinnie
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

+ 44 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/Makefile

@@ -0,0 +1,44 @@
+
+CMD = jpgo
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  test                    to run all the tests"
+	@echo "  build                   to build the library and jp executable"
+	@echo "  generate                to run codegen"
+
+
+generate:
+	go generate ./...
+
+build:
+	rm -f $(CMD)
+	go build ./...
+	rm -f cmd/$(CMD)/$(CMD) && cd cmd/$(CMD)/ && go build ./...
+	mv cmd/$(CMD)/$(CMD) .
+
+test:
+	go test -v ./...
+
+check:
+	go vet ./...
+	@echo "golint ./..."
+	@lint=`golint ./...`; \
+	lint=`echo "$$lint" | grep -v "astnodetype_string.go" | grep -v "toktype_string.go"`; \
+	echo "$$lint"; \
+	if [ "$$lint" != "" ]; then exit 1; fi
+
+htmlc:
+	go test -coverprofile="/tmp/jpcov"  && go tool cover -html="/tmp/jpcov" && unlink /tmp/jpcov
+
+buildfuzz:
+	go-fuzz-build github.com/jmespath/go-jmespath/fuzz
+
+fuzz: buildfuzz
+	go-fuzz -bin=./jmespath-fuzz.zip -workdir=fuzz/corpus
+
+bench:
+	go test -bench . -cpuprofile cpu.out
+
+pprof-cpu:
+	go tool pprof ./go-jmespath.test ./cpu.out

+ 7 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/README.md

@@ -0,0 +1,7 @@
+# go-jmespath - A JMESPath implementation in Go
+
+[![Build Status](https://img.shields.io/travis/jmespath/go-jmespath.svg)](https://travis-ci.org/jmespath/go-jmespath)
+
+
+
+See http://jmespath.org for more info.

+ 12 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/api.go

@@ -0,0 +1,12 @@
+package jmespath
+
+// Search evaluates a JMESPath expression against input data and returns the result.
+func Search(expression string, data interface{}) (interface{}, error) {
+	intr := newInterpreter()
+	parser := NewParser()
+	ast, err := parser.Parse(expression)
+	if err != nil {
+		return nil, err
+	}
+	return intr.Execute(ast, data)
+}

+ 16 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/astnodetype_string.go

@@ -0,0 +1,16 @@
+// generated by stringer -type astNodeType; DO NOT EDIT
+
+package jmespath
+
+import "fmt"
+
+const _astNodeType_name = "ASTEmptyASTComparatorASTCurrentNodeASTExpRefASTFunctionExpressionASTFieldASTFilterProjectionASTFlattenASTIdentityASTIndexASTIndexExpressionASTKeyValPairASTLiteralASTMultiSelectHashASTMultiSelectListASTOrExpressionASTAndExpressionASTNotExpressionASTPipeASTProjectionASTSubexpressionASTSliceASTValueProjection"
+
+var _astNodeType_index = [...]uint16{0, 8, 21, 35, 44, 65, 73, 92, 102, 113, 121, 139, 152, 162, 180, 198, 213, 229, 245, 252, 265, 281, 289, 307}
+
+func (i astNodeType) String() string {
+	if i < 0 || i >= astNodeType(len(_astNodeType_index)-1) {
+		return fmt.Sprintf("astNodeType(%d)", i)
+	}
+	return _astNodeType_name[_astNodeType_index[i]:_astNodeType_index[i+1]]
+}

+ 96 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/basic.json

@@ -0,0 +1,96 @@
+[{
+    "given":
+        {"foo": {"bar": {"baz": "correct"}}},
+     "cases": [
+         {
+            "expression": "foo",
+            "result": {"bar": {"baz": "correct"}}
+         },
+         {
+            "expression": "foo.bar",
+            "result": {"baz": "correct"}
+         },
+         {
+            "expression": "foo.bar.baz",
+            "result": "correct"
+         },
+         {
+            "expression": "foo\n.\nbar\n.baz",
+            "result": "correct"
+         },
+         {
+            "expression": "foo.bar.baz.bad",
+            "result": null
+         },
+         {
+            "expression": "foo.bar.bad",
+            "result": null
+         },
+         {
+            "expression": "foo.bad",
+            "result": null
+         },
+         {
+            "expression": "bad",
+            "result": null
+         },
+         {
+            "expression": "bad.morebad.morebad",
+            "result": null
+         }
+     ]
+},
+{
+    "given":
+        {"foo": {"bar": ["one", "two", "three"]}},
+    "cases": [
+         {
+            "expression": "foo",
+            "result": {"bar": ["one", "two", "three"]}
+         },
+         {
+            "expression": "foo.bar",
+            "result": ["one", "two", "three"]
+         }
+    ]
+},
+{
+    "given": ["one", "two", "three"],
+    "cases": [
+        {
+            "expression": "one",
+            "result": null
+        },
+        {
+            "expression": "two",
+            "result": null
+        },
+        {
+            "expression": "three",
+            "result": null
+        },
+        {
+            "expression": "one.two",
+            "result": null
+        }
+    ]
+},
+{
+    "given":
+        {"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
+    "cases": [
+         {
+            "expression": "foo.\"1\"",
+            "result": ["one", "two", "three"]
+         },
+         {
+            "expression": "foo.\"1\"[0]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.\"-1\"",
+            "result": "bar"
+         }
+    ]
+}
+]

+ 257 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/boolean.json

@@ -0,0 +1,257 @@
+[
+  {
+    "given": {
+      "outer": {
+        "foo": "foo",
+        "bar": "bar",
+        "baz": "baz"
+      }
+    },
+    "cases": [
+      {
+        "expression": "outer.foo || outer.bar",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo||outer.bar",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bar || outer.baz",
+        "result": "bar"
+      },
+      {
+        "expression": "outer.bar||outer.baz",
+        "result": "bar"
+      },
+      {
+        "expression": "outer.bad || outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bad||outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo || outer.bad",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.foo||outer.bad",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.bad || outer.alsobad",
+        "result": null
+      },
+      {
+        "expression": "outer.bad||outer.alsobad",
+        "result": null
+      }
+    ]
+  },
+  {
+    "given": {
+      "outer": {
+        "foo": "foo",
+        "bool": false,
+        "empty_list": [],
+        "empty_string": ""
+      }
+    },
+    "cases": [
+      {
+        "expression": "outer.empty_string || outer.foo",
+        "result": "foo"
+      },
+      {
+        "expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
+        "result": "foo"
+      }
+    ]
+  },
+  {
+    "given": {
+      "True": true,
+      "False": false,
+      "Number": 5,
+      "EmptyList": [],
+      "Zero": 0
+    },
+    "cases": [
+      {
+        "expression": "True && False",
+        "result": false
+      },
+      {
+        "expression": "False && True",
+        "result": false
+      },
+      {
+        "expression": "True && True",
+        "result": true
+      },
+      {
+        "expression": "False && False",
+        "result": false
+      },
+      {
+        "expression": "True && Number",
+        "result": 5
+      },
+      {
+        "expression": "Number && True",
+        "result": true
+      },
+      {
+        "expression": "Number && False",
+        "result": false
+      },
+      {
+        "expression": "Number && EmptyList",
+        "result": []
+      },
+      {
+        "expression": "Number && True",
+        "result": true
+      },
+      {
+        "expression": "EmptyList && True",
+        "result": []
+      },
+      {
+        "expression": "EmptyList && False",
+        "result": []
+      },
+      {
+        "expression": "True || False",
+        "result": true
+      },
+      {
+        "expression": "True || True",
+        "result": true
+      },
+      {
+        "expression": "False || True",
+        "result": true
+      },
+      {
+        "expression": "False || False",
+        "result": false
+      },
+      {
+        "expression": "Number || EmptyList",
+        "result": 5
+      },
+      {
+        "expression": "Number || True",
+        "result": 5
+      },
+      {
+        "expression": "Number || True && False",
+        "result": 5
+      },
+      {
+        "expression": "(Number || True) && False",
+        "result": false
+      },
+      {
+        "expression": "Number || (True && False)",
+        "result": 5
+      },
+      {
+        "expression": "!True",
+        "result": false
+      },
+      {
+        "expression": "!False",
+        "result": true
+      },
+      {
+        "expression": "!Number",
+        "result": false
+      },
+      {
+        "expression": "!EmptyList",
+        "result": true
+      },
+      {
+        "expression": "True && !False",
+        "result": true
+      },
+      {
+        "expression": "True && !EmptyList",
+        "result": true
+      },
+      {
+        "expression": "!False && !EmptyList",
+        "result": true
+      },
+      {
+        "expression": "!(True && False)",
+        "result": true
+      },
+      {
+        "expression": "!Zero",
+        "result": false
+      },
+      {
+        "expression": "!!Zero",
+        "result": true
+      }
+    ]
+  },
+  {
+    "given": {
+      "one": 1,
+      "two": 2,
+      "three": 3
+    },
+    "cases": [
+      {
+        "expression": "one < two",
+        "result": true
+      },
+      {
+        "expression": "one <= two",
+        "result": true
+      },
+      {
+        "expression": "one == one",
+        "result": true
+      },
+      {
+        "expression": "one == two",
+        "result": false
+      },
+      {
+        "expression": "one > two",
+        "result": false
+      },
+      {
+        "expression": "one >= two",
+        "result": false
+      },
+      {
+        "expression": "one != two",
+        "result": true
+      },
+      {
+        "expression": "one < two && three > one",
+        "result": true
+      },
+      {
+        "expression": "one < two || three > one",
+        "result": true
+      },
+      {
+        "expression": "one < two || three < one",
+        "result": true
+      },
+      {
+        "expression": "two < one || three < one",
+        "result": false
+      }
+    ]
+  }
+]

+ 25 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/current.json

@@ -0,0 +1,25 @@
+[
+    {
+        "given": {
+            "foo": [{"name": "a"}, {"name": "b"}],
+            "bar": {"baz": "qux"}
+        },
+        "cases": [
+            {
+                "expression": "@",
+                "result": {
+                    "foo": [{"name": "a"}, {"name": "b"}],
+                    "bar": {"baz": "qux"}
+                }
+            },
+            {
+                "expression": "@.bar",
+                "result": {"baz": "qux"}
+            },
+            {
+                "expression": "@.foo[0]",
+                "result": {"name": "a"}
+            }
+        ]
+    }
+]

+ 46 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/escape.json

@@ -0,0 +1,46 @@
+[{
+    "given": {
+        "foo.bar": "dot",
+        "foo bar": "space",
+        "foo\nbar": "newline",
+        "foo\"bar": "doublequote",
+        "c:\\\\windows\\path": "windows",
+        "/unix/path": "unix",
+        "\"\"\"": "threequotes",
+        "bar": {"baz": "qux"}
+     },
+     "cases": [
+         {
+            "expression": "\"foo.bar\"",
+            "result": "dot"
+         },
+         {
+            "expression": "\"foo bar\"",
+            "result": "space"
+         },
+         {
+            "expression": "\"foo\\nbar\"",
+            "result": "newline"
+         },
+         {
+            "expression": "\"foo\\\"bar\"",
+            "result": "doublequote"
+         },
+         {
+            "expression": "\"c:\\\\\\\\windows\\\\path\"",
+            "result": "windows"
+         },
+         {
+            "expression": "\"/unix/path\"",
+            "result": "unix"
+         },
+         {
+            "expression": "\"\\\"\\\"\\\"\"",
+            "result": "threequotes"
+         },
+         {
+            "expression": "\"bar\".\"baz\"",
+            "result": "qux"
+         }
+     ]
+}]

+ 468 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/filters.json

@@ -0,0 +1,468 @@
+[
+  {
+    "given": {"foo": [{"name": "a"}, {"name": "b"}]},
+    "cases": [
+      {
+        "comment": "Matching a literal",
+        "expression": "foo[?name == 'a']",
+        "result": [{"name": "a"}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [0, 1], "bar": [2, 3]},
+    "cases": [
+      {
+        "comment": "Matching a literal",
+        "expression": "*[?[0] == `0`]",
+        "result": [[], []]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"first": "foo", "last": "bar"},
+      {"first": "foo", "last": "foo"},
+      {"first": "foo", "last": "baz"}]},
+    "cases": [
+      {
+        "comment": "Matching an expression",
+        "expression": "foo[?first == last]",
+        "result": [{"first": "foo", "last": "foo"}]
+      },
+      {
+        "comment": "Verify projection created from filter",
+        "expression": "foo[?first == last].first",
+        "result": ["foo"]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"age": 20},
+      {"age": 25},
+      {"age": 30}]},
+    "cases": [
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age > `25`]",
+        "result": [{"age": 30}]
+      },
+      {
+        "expression": "foo[?age >= `25`]",
+        "result": [{"age": 25}, {"age": 30}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age > `30`]",
+        "result": []
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age < `25`]",
+        "result": [{"age": 20}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age <= `25`]",
+        "result": [{"age": 20}, {"age": 25}]
+      },
+      {
+        "comment": "Greater than with a number",
+        "expression": "foo[?age < `20`]",
+        "result": []
+      },
+      {
+        "expression": "foo[?age == `20`]",
+        "result": [{"age": 20}]
+      },
+      {
+        "expression": "foo[?age != `20`]",
+        "result": [{"age": 25}, {"age": 30}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"top": {"name": "a"}},
+      {"top": {"name": "b"}}]},
+    "cases": [
+      {
+        "comment": "Filter with subexpression",
+        "expression": "foo[?top.name == 'a']",
+        "result": [{"top": {"name": "a"}}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"top": {"first": "foo", "last": "bar"}},
+      {"top": {"first": "foo", "last": "foo"}},
+      {"top": {"first": "foo", "last": "baz"}}]},
+    "cases": [
+      {
+        "comment": "Matching an expression",
+        "expression": "foo[?top.first == top.last]",
+        "result": [{"top": {"first": "foo", "last": "foo"}}]
+      },
+      {
+        "comment": "Matching a JSON array",
+        "expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]",
+        "result": [{"top": {"first": "foo", "last": "bar"}}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [
+      {"key": true},
+      {"key": false},
+      {"key": 0},
+      {"key": 1},
+      {"key": [0]},
+      {"key": {"bar": [0]}},
+      {"key": null},
+      {"key": [1]},
+      {"key": {"a":2}}
+    ]},
+    "cases": [
+      {
+        "expression": "foo[?key == `true`]",
+        "result": [{"key": true}]
+      },
+      {
+        "expression": "foo[?key == `false`]",
+        "result": [{"key": false}]
+      },
+      {
+        "expression": "foo[?key == `0`]",
+        "result": [{"key": 0}]
+      },
+      {
+        "expression": "foo[?key == `1`]",
+        "result": [{"key": 1}]
+      },
+      {
+        "expression": "foo[?key == `[0]`]",
+        "result": [{"key": [0]}]
+      },
+      {
+        "expression": "foo[?key == `{\"bar\": [0]}`]",
+        "result": [{"key": {"bar": [0]}}]
+      },
+      {
+        "expression": "foo[?key == `null`]",
+        "result": [{"key": null}]
+      },
+      {
+        "expression": "foo[?key == `[1]`]",
+        "result": [{"key": [1]}]
+      },
+      {
+        "expression": "foo[?key == `{\"a\":2}`]",
+        "result": [{"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`true` == key]",
+        "result": [{"key": true}]
+      },
+      {
+        "expression": "foo[?`false` == key]",
+        "result": [{"key": false}]
+      },
+      {
+        "expression": "foo[?`0` == key]",
+        "result": [{"key": 0}]
+      },
+      {
+        "expression": "foo[?`1` == key]",
+        "result": [{"key": 1}]
+      },
+      {
+        "expression": "foo[?`[0]` == key]",
+        "result": [{"key": [0]}]
+      },
+      {
+        "expression": "foo[?`{\"bar\": [0]}` == key]",
+        "result": [{"key": {"bar": [0]}}]
+      },
+      {
+        "expression": "foo[?`null` == key]",
+        "result": [{"key": null}]
+      },
+      {
+        "expression": "foo[?`[1]` == key]",
+        "result": [{"key": [1]}]
+      },
+      {
+        "expression": "foo[?`{\"a\":2}` == key]",
+        "result": [{"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `true`]",
+        "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `false`]",
+        "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `0`]",
+        "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `1`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `null`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `[1]`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?key != `{\"a\":2}`]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
+      },
+      {
+        "expression": "foo[?`true` != key]",
+        "result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`false` != key]",
+        "result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`0` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`1` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`null` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`[1]` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
+      },
+      {
+        "expression": "foo[?`{\"a\":2}` != key]",
+        "result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
+          {"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
+      }
+    ]
+  },
+  {
+    "given": {"reservations": [
+      {"instances": [
+        {"foo": 1, "bar": 2}, {"foo": 1, "bar": 3},
+        {"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]},
+    "cases": [
+      {
+        "expression": "reservations[].instances[?bar==`1`]",
+        "result": [[{"foo": 2, "bar": 1}]]
+      },
+      {
+        "expression": "reservations[*].instances[?bar==`1`]",
+        "result": [[{"foo": 2, "bar": 1}]]
+      },
+      {
+        "expression": "reservations[].instances[?bar==`1`][]",
+        "result": [{"foo": 2, "bar": 1}]
+      }
+    ]
+  },
+  {
+    "given": {
+      "baz": "other",
+      "foo": [
+        {"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2}
+      ]
+    },
+    "cases": [
+      {
+        "expression": "foo[?bar==`1`].bar[0]",
+        "result": []
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [
+        {"a": 1, "b": {"c": "x"}},
+	{"a": 1, "b": {"c": "y"}},
+	{"a": 1, "b": {"c": "z"}},
+	{"a": 2, "b": {"c": "z"}},
+	{"a": 1, "baz": 2}
+      ]
+    },
+    "cases": [
+      {
+        "expression": "foo[?a==`1`].b.c",
+        "result": ["x", "y", "z"]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]},
+    "cases": [
+      {
+        "comment": "Filter with or expression",
+        "expression": "foo[?name == 'a' || name == 'b']",
+        "result": [{"name": "a"}, {"name": "b"}]
+      },
+      {
+        "expression": "foo[?name == 'a' || name == 'e']",
+        "result": [{"name": "a"}]
+      },
+      {
+        "expression": "foo[?name == 'a' || name == 'b' || name == 'c']",
+        "result": [{"name": "a"}, {"name": "b"}, {"name": "c"}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]},
+    "cases": [
+      {
+        "comment": "Filter with and expression",
+        "expression": "foo[?a == `1` && b == `2`]",
+        "result": [{"a": 1, "b": 2}]
+      },
+      {
+        "expression": "foo[?a == `1` && b == `4`]",
+        "result": []
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
+    "cases": [
+      {
+        "comment": "Filter with Or and And expressions",
+        "expression": "foo[?c == `3` || a == `1` && b == `4`]",
+        "result": [{"a": 1, "b": 2, "c": 3}]
+      },
+      {
+        "expression": "foo[?b == `2` || a == `3` && b == `4`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && b == `4` || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?(a == `3` && b == `4`) || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?((a == `3` && b == `4`)) || b == `2`]",
+        "result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && (b == `4` || b == `2`)]",
+        "result": [{"a": 3, "b": 4}]
+      },
+      {
+        "expression": "foo[?a == `3` && ((b == `4` || b == `2`))]",
+        "result": [{"a": 3, "b": 4}]
+      }
+    ]
+  },
+  {
+    "given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
+    "cases": [
+      {
+        "comment": "Verify precedence of or/and expressions",
+        "expression": "foo[?a == `1` || b ==`2` && c == `5`]",
+        "result": [{"a": 1, "b": 2, "c": 3}]
+      },
+      {
+        "comment": "Parentheses can alter precedence",
+        "expression": "foo[?(a == `1` || b ==`2`) && c == `5`]",
+        "result": []
+      },
+      {
+        "comment": "Not expressions combined with and/or",
+        "expression": "foo[?!(a == `1` || b ==`2`)]",
+        "result": [{"a": 3, "b": 4}]
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [
+        {"key": true},
+        {"key": false},
+        {"key": []},
+        {"key": {}},
+        {"key": [0]},
+        {"key": {"a": "b"}},
+        {"key": 0},
+        {"key": 1},
+        {"key": null},
+        {"notkey": true}
+      ]
+    },
+    "cases": [
+      {
+        "comment": "Unary filter expression",
+        "expression": "foo[?key]",
+        "result": [
+          {"key": true}, {"key": [0]}, {"key": {"a": "b"}},
+          {"key": 0}, {"key": 1}
+        ]
+      },
+      {
+        "comment": "Unary not filter expression",
+        "expression": "foo[?!key]",
+        "result": [
+          {"key": false}, {"key": []}, {"key": {}},
+          {"key": null}, {"notkey": true}
+        ]
+      },
+      {
+        "comment": "Equality with null RHS",
+        "expression": "foo[?key == `null`]",
+        "result": [
+          {"key": null}, {"notkey": true}
+        ]
+      }
+    ]
+  },
+  {
+    "given": {
+      "foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+    },
+    "cases": [
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?@ < `5`]",
+        "result": [0, 1, 2, 3, 4]
+      },
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?`5` > @]",
+        "result": [0, 1, 2, 3, 4]
+      },
+      {
+        "comment": "Using @ in a filter expression",
+        "expression": "foo[?@ == @]",
+        "result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+      }
+    ]
+  }
+]

+ 825 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/functions.json

@@ -0,0 +1,825 @@
+[{
+  "given":
+  {
+    "foo": -1,
+    "zero": 0,
+    "numbers": [-1, 3, 4, 5],
+    "array": [-1, 3, 4, 5, "a", "100"],
+    "strings": ["a", "b", "c"],
+    "decimals": [1.01, 1.2, -1.5],
+    "str": "Str",
+    "false": false,
+    "empty_list": [],
+    "empty_hash": {},
+    "objects": {"foo": "bar", "bar": "baz"},
+    "null_key": null
+  },
+  "cases": [
+    {
+      "expression": "abs(foo)",
+      "result": 1
+    },
+    {
+      "expression": "abs(foo)",
+      "result": 1
+    },
+    {
+      "expression": "abs(str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "abs(array[1])",
+      "result": 3
+    },
+    {
+      "expression": "abs(array[1])",
+      "result": 3
+    },
+    {
+      "expression": "abs(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "abs(`-24`)",
+      "result": 24
+    },
+    {
+      "expression": "abs(`-24`)",
+      "result": 24
+    },
+    {
+      "expression": "abs(`1`, `2`)",
+      "error": "invalid-arity"
+    },
+    {
+      "expression": "abs()",
+      "error": "invalid-arity"
+    },
+    {
+      "expression": "unknown_function(`1`, `2`)",
+      "error": "unknown-function"
+    },
+    {
+      "expression": "avg(numbers)",
+      "result": 2.75
+    },
+    {
+      "expression": "avg(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg('abc')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(@)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "avg(strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "ceil(`1.2`)",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[0])",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[1])",
+      "result": 2
+    },
+    {
+      "expression": "ceil(decimals[2])",
+      "result": -1
+    },
+    {
+      "expression": "ceil('string')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "contains('abc', 'a')",
+      "result": true
+    },
+    {
+      "expression": "contains('abc', 'd')",
+      "result": false
+    },
+    {
+      "expression": "contains(`false`, 'd')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "contains(strings, 'a')",
+      "result": true
+    },
+    {
+      "expression": "contains(decimals, `1.2`)",
+      "result": true
+    },
+    {
+      "expression": "contains(decimals, `false`)",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, 'r')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'tr')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'Str')",
+      "result": true
+    },
+    {
+      "expression": "ends_with(str, 'SStr')",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, 'foo')",
+      "result": false
+    },
+    {
+      "expression": "ends_with(str, `0`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "floor(`1.2`)",
+      "result": 1
+    },
+    {
+      "expression": "floor('string')",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "floor(decimals[0])",
+      "result": 1
+    },
+    {
+      "expression": "floor(foo)",
+      "result": -1
+    },
+    {
+      "expression": "floor(str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length('abc')",
+      "result": 3
+    },
+    {
+      "expression": "length('✓foo')",
+      "result": 4
+    },
+    {
+      "expression": "length('')",
+      "result": 0
+    },
+    {
+      "expression": "length(@)",
+      "result": 12
+    },
+    {
+      "expression": "length(strings[0])",
+      "result": 1
+    },
+    {
+      "expression": "length(str)",
+      "result": 3
+    },
+    {
+      "expression": "length(array)",
+      "result": 6
+    },
+    {
+      "expression": "length(objects)",
+      "result": 2
+    },
+    {
+      "expression": "length(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "length(strings[0])",
+      "result": 1
+    },
+    {
+      "expression": "max(numbers)",
+      "result": 5
+    },
+    {
+      "expression": "max(decimals)",
+      "result": 1.2
+    },
+    {
+      "expression": "max(strings)",
+      "result": "c"
+    },
+    {
+      "expression": "max(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max(decimals)",
+      "result": 1.2
+    },
+    {
+      "expression": "max(empty_list)",
+      "result": null
+    },
+    {
+      "expression": "merge(`{}`)",
+      "result": {}
+    },
+    {
+      "expression": "merge(`{}`, `{}`)",
+      "result": {}
+    },
+    {
+      "expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)",
+      "result": {"a": 1, "b": 2}
+    },
+    {
+      "expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)",
+      "result": {"a": 2}
+    },
+    {
+      "expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)",
+      "result": {"a": 2, "b": 2, "c": 3, "d": 4}
+    },
+    {
+      "expression": "min(numbers)",
+      "result": -1
+    },
+    {
+      "expression": "min(decimals)",
+      "result": -1.5
+    },
+    {
+      "expression": "min(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min(empty_list)",
+      "result": null
+    },
+    {
+      "expression": "min(decimals)",
+      "result": -1.5
+    },
+    {
+      "expression": "min(strings)",
+      "result": "a"
+    },
+    {
+      "expression": "type('abc')",
+      "result": "string"
+    },
+    {
+      "expression": "type(`1.0`)",
+      "result": "number"
+    },
+    {
+      "expression": "type(`2`)",
+      "result": "number"
+    },
+    {
+      "expression": "type(`true`)",
+      "result": "boolean"
+    },
+    {
+      "expression": "type(`false`)",
+      "result": "boolean"
+    },
+    {
+      "expression": "type(`null`)",
+      "result": "null"
+    },
+    {
+      "expression": "type(`[0]`)",
+      "result": "array"
+    },
+    {
+      "expression": "type(`{\"a\": \"b\"}`)",
+      "result": "object"
+    },
+    {
+      "expression": "type(@)",
+      "result": "object"
+    },
+    {
+      "expression": "sort(keys(objects))",
+      "result": ["bar", "foo"]
+    },
+    {
+      "expression": "keys(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "keys(strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "keys(`false`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(values(objects))",
+      "result": ["bar", "baz"]
+    },
+    {
+      "expression": "keys(empty_hash)",
+      "result": []
+    },
+    {
+      "expression": "values(foo)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join(', ', strings)",
+      "result": "a, b, c"
+    },
+    {
+      "expression": "join(', ', strings)",
+      "result": "a, b, c"
+    },
+    {
+      "expression": "join(',', `[\"a\", \"b\"]`)",
+      "result": "a,b"
+    },
+    {
+      "expression": "join(',', `[\"a\", 0]`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join(', ', str)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', strings)",
+      "result": "a|b|c"
+    },
+    {
+      "expression": "join(`2`, strings)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', decimals)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "join('|', decimals[].to_string(@))",
+      "result": "1.01|1.2|-1.5"
+    },
+    {
+      "expression": "join('|', empty_list)",
+      "result": ""
+    },
+    {
+      "expression": "reverse(numbers)",
+      "result": [5, 4, 3, -1]
+    },
+    {
+      "expression": "reverse(array)",
+      "result": ["100", "a", 5, 4, 3, -1]
+    },
+    {
+      "expression": "reverse(`[]`)",
+      "result": []
+    },
+    {
+      "expression": "reverse('')",
+      "result": ""
+    },
+    {
+      "expression": "reverse('hello world')",
+      "result": "dlrow olleh"
+    },
+    {
+      "expression": "starts_with(str, 'S')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'St')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'Str')",
+      "result": true
+    },
+    {
+      "expression": "starts_with(str, 'String')",
+      "result": false
+    },
+    {
+      "expression": "starts_with(str, `0`)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sum(numbers)",
+      "result": 11
+    },
+    {
+      "expression": "sum(decimals)",
+      "result": 0.71
+    },
+    {
+      "expression": "sum(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sum(array[].to_number(@))",
+      "result": 111
+    },
+    {
+      "expression": "sum(`[]`)",
+      "result": 0
+    },
+    {
+      "expression": "to_array('foo')",
+      "result": ["foo"]
+    },
+    {
+      "expression": "to_array(`0`)",
+      "result": [0]
+    },
+    {
+      "expression": "to_array(objects)",
+      "result": [{"foo": "bar", "bar": "baz"}]
+    },
+    {
+      "expression": "to_array(`[1, 2, 3]`)",
+      "result": [1, 2, 3]
+    },
+    {
+      "expression": "to_array(false)",
+      "result": [false]
+    },
+    {
+      "expression": "to_string('foo')",
+      "result": "foo"
+    },
+    {
+      "expression": "to_string(`1.2`)",
+      "result": "1.2"
+    },
+    {
+      "expression": "to_string(`[0, 1]`)",
+      "result": "[0,1]"
+    },
+    {
+      "expression": "to_number('1.0')",
+      "result": 1.0
+    },
+    {
+      "expression": "to_number('1.1')",
+      "result": 1.1
+    },
+    {
+      "expression": "to_number('4')",
+      "result": 4
+    },
+    {
+      "expression": "to_number('notanumber')",
+      "result": null
+    },
+    {
+      "expression": "to_number(`false`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`null`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`[0]`)",
+      "result": null
+    },
+    {
+      "expression": "to_number(`{\"foo\": 0}`)",
+      "result": null
+    },
+    {
+      "expression": "\"to_string\"(`1.0`)",
+      "error": "syntax"
+    },
+    {
+      "expression": "sort(numbers)",
+      "result": [-1, 3, 4, 5]
+    },
+    {
+      "expression": "sort(strings)",
+      "result": ["a", "b", "c"]
+    },
+    {
+      "expression": "sort(decimals)",
+      "result": [-1.5, 1.01, 1.2]
+    },
+    {
+      "expression": "sort(array)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(abc)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort(empty_list)",
+      "result": []
+    },
+    {
+      "expression": "sort(@)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "not_null(unknown_key, str)",
+      "result": "Str"
+    },
+    {
+      "expression": "not_null(unknown_key, foo.bar, empty_list, str)",
+      "result": []
+    },
+    {
+      "expression": "not_null(unknown_key, null_key, empty_list, str)",
+      "result": []
+    },
+    {
+      "expression": "not_null(all, expressions, are_null)",
+      "result": null
+    },
+    {
+      "expression": "not_null()",
+      "error": "invalid-arity"
+    },
+    {
+      "description": "function projection on single arg function",
+      "expression": "numbers[].to_string(@)",
+      "result": ["-1", "3", "4", "5"]
+    },
+    {
+      "description": "function projection on single arg function",
+      "expression": "array[].to_number(@)",
+      "result": [-1, 3, 4, 5, 100]
+    }
+  ]
+}, {
+  "given":
+  {
+    "foo": [
+         {"b": "b", "a": "a"},
+         {"c": "c", "b": "b"},
+         {"d": "d", "c": "c"},
+         {"e": "e", "d": "d"},
+         {"f": "f", "e": "e"}
+    ]
+  },
+  "cases": [
+    {
+      "description": "function projection on variadic function",
+      "expression": "foo[].not_null(f, e, d, c, b, a)",
+      "result": ["b", "c", "d", "e", "f"]
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"},
+         {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    ]
+  },
+  "cases": [
+    {
+      "description": "sort by field expression",
+      "expression": "sort_by(people, &age)",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "expression": "sort_by(people, &age_str)",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "description": "sort by function expression",
+      "expression": "sort_by(people, &to_number(age_str))",
+      "result": [
+         {"age": 10, "age_str": "10", "bool": true, "name": 3},
+         {"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
+         {"age": 30, "age_str": "30", "bool": true, "name": "c"},
+         {"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
+         {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+      ]
+    },
+    {
+      "description": "function projection on sort_by function",
+      "expression": "sort_by(people, &age)[].name",
+      "result": [3, "a", "c", "b", "d"]
+    },
+    {
+      "expression": "sort_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &name)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, name)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "sort_by(people, &age)[].extra",
+      "result": ["foo", "bar"]
+    },
+    {
+      "expression": "sort_by(`[]`, &age)",
+      "result": []
+    },
+    {
+      "expression": "max_by(people, &age)",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "max_by(people, &age_str)",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "max_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "max_by(people, &to_number(age_str))",
+      "result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
+    },
+    {
+      "expression": "min_by(people, &age)",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    },
+    {
+      "expression": "min_by(people, &age_str)",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    },
+    {
+      "expression": "min_by(people, &bool)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min_by(people, &extra)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "min_by(people, &to_number(age_str))",
+      "result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"age": 10, "order": "1"},
+         {"age": 10, "order": "2"},
+         {"age": 10, "order": "3"},
+         {"age": 10, "order": "4"},
+         {"age": 10, "order": "5"},
+         {"age": 10, "order": "6"},
+         {"age": 10, "order": "7"},
+         {"age": 10, "order": "8"},
+         {"age": 10, "order": "9"},
+         {"age": 10, "order": "10"},
+         {"age": 10, "order": "11"}
+    ]
+  },
+  "cases": [
+    {
+      "description": "stable sort order",
+      "expression": "sort_by(people, &age)",
+      "result": [
+         {"age": 10, "order": "1"},
+         {"age": 10, "order": "2"},
+         {"age": 10, "order": "3"},
+         {"age": 10, "order": "4"},
+         {"age": 10, "order": "5"},
+         {"age": 10, "order": "6"},
+         {"age": 10, "order": "7"},
+         {"age": 10, "order": "8"},
+         {"age": 10, "order": "9"},
+         {"age": 10, "order": "10"},
+         {"age": 10, "order": "11"}
+      ]
+    }
+  ]
+}, {
+  "given":
+  {
+    "people": [
+         {"a": 10, "b": 1, "c": "z"},
+         {"a": 10, "b": 2, "c": null},
+         {"a": 10, "b": 3},
+         {"a": 10, "b": 4, "c": "z"},
+         {"a": 10, "b": 5, "c": null},
+         {"a": 10, "b": 6},
+         {"a": 10, "b": 7, "c": "z"},
+         {"a": 10, "b": 8, "c": null},
+         {"a": 10, "b": 9}
+    ],
+    "empty": []
+  },
+  "cases": [
+    {
+      "expression": "map(&a, people)",
+      "result": [10, 10, 10, 10, 10, 10, 10, 10, 10]
+    },
+    {
+      "expression": "map(&c, people)",
+      "result": ["z", null, null, "z", null, null, "z", null, null]
+    },
+    {
+      "expression": "map(&a, badkey)",
+      "error": "invalid-type"
+    },
+    {
+      "expression": "map(&foo, empty)",
+      "result": []
+    }
+  ]
+}, {
+  "given": {
+    "array": [
+      {
+          "foo": {"bar": "yes1"}
+      },
+      {
+          "foo": {"bar": "yes2"}
+      },
+      {
+          "foo1": {"bar": "no"}
+      }
+  ]},
+  "cases": [
+    {
+      "expression": "map(&foo.bar, array)",
+      "result": ["yes1", "yes2", null]
+    },
+    {
+      "expression": "map(&foo1.bar, array)",
+      "result": [null, null, "no"]
+    },
+    {
+      "expression": "map(&foo.bar.baz, array)",
+      "result": [null, null, null]
+    }
+  ]
+}, {
+  "given": {
+    "array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]]
+  },
+  "cases": [
+    {
+      "expression": "map(&[], array)",
+      "result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
+    }
+  ]
+}
+]

+ 1377 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/identifiers.json

@@ -0,0 +1,1377 @@
+[
+    {
+        "given": {
+            "__L": true
+        },
+        "cases": [
+            {
+                "expression": "__L",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Y_1623": true
+        },
+        "cases": [
+            {
+                "expression": "Y_1623",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "x": true
+        },
+        "cases": [
+            {
+                "expression": "x",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tF\uCebb": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tF\\uCebb\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " \t": true
+        },
+        "cases": [
+            {
+                "expression": "\" \\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " ": true
+        },
+        "cases": [
+            {
+                "expression": "\" \"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "v2": true
+        },
+        "cases": [
+            {
+                "expression": "v2",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_X": true
+        },
+        "cases": [
+            {
+                "expression": "_X",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t4\ud9da\udd15": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t4\\ud9da\\udd15\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "v24_W": true
+        },
+        "cases": [
+            {
+                "expression": "v24_W",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "H": true
+        },
+        "cases": [
+            {
+                "expression": "\"H\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "E4": true
+        },
+        "cases": [
+            {
+                "expression": "\"E4\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "tM": true
+        },
+        "cases": [
+            {
+                "expression": "tM",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            " [": true
+        },
+        "cases": [
+            {
+                "expression": "\" [\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "R!": true
+        },
+        "cases": [
+            {
+                "expression": "\"R!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_6W": true
+        },
+        "cases": [
+            {
+                "expression": "_6W",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uaBA1\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uaBA1\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "tL7": true
+        },
+        "cases": [
+            {
+                "expression": "tL7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<<U\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"<<U\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\ubBcE\ufAfB": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\ubBcE\\ufAfB\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "sNA_": true
+        },
+        "cases": [
+            {
+                "expression": "sNA_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "9": true
+        },
+        "cases": [
+            {
+                "expression": "\"9\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\b\ud8cb\udc83": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\\b\\ud8cb\\udc83\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "r": true
+        },
+        "cases": [
+            {
+                "expression": "\"r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Q": true
+        },
+        "cases": [
+            {
+                "expression": "Q",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_Q__7GL8": true
+        },
+        "cases": [
+            {
+                "expression": "_Q__7GL8",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "RR9_": true
+        },
+        "cases": [
+            {
+                "expression": "RR9_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r\f:": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\\f:\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "r7": true
+        },
+        "cases": [
+            {
+                "expression": "r7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "-": true
+        },
+        "cases": [
+            {
+                "expression": "\"-\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "p9": true
+        },
+        "cases": [
+            {
+                "expression": "p9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "__": true
+        },
+        "cases": [
+            {
+                "expression": "__",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "O_": true
+        },
+        "cases": [
+            {
+                "expression": "O_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_r_8": true
+        },
+        "cases": [
+            {
+                "expression": "_r_8",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_j": true
+        },
+        "cases": [
+            {
+                "expression": "_j",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ":": true
+        },
+        "cases": [
+            {
+                "expression": "\":\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\rB": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\rB\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Obf": true
+        },
+        "cases": [
+            {
+                "expression": "Obf",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\n": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\n\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\f\udb54\udf33": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\f\udb54\udf33\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\u4FDc": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\\u4FDc\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "m_": true
+        },
+        "cases": [
+            {
+                "expression": "m_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\r\fB ": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\r\\fB \"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "+\"\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"+\\\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Mg": true
+        },
+        "cases": [
+            {
+                "expression": "Mg",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"!\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"!\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "7\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"7\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\\udb3a\udca4S": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\\udb3a\udca4S\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Kl": true
+        },
+        "cases": [
+            {
+                "expression": "Kl",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b\b": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\\b\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ">": true
+        },
+        "cases": [
+            {
+                "expression": "\">\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "hvu": true
+        },
+        "cases": [
+            {
+                "expression": "hvu",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "; !": true
+        },
+        "cases": [
+            {
+                "expression": "\"; !\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "hU": true
+        },
+        "cases": [
+            {
+                "expression": "hU",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!I\n\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"!I\\n\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uEEbF": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uEEbF\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "U)\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"U)\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "fa0_9": true
+        },
+        "cases": [
+            {
+                "expression": "fa0_9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "/": true
+        },
+        "cases": [
+            {
+                "expression": "\"/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Gy": true
+        },
+        "cases": [
+            {
+                "expression": "Gy",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<": true
+        },
+        "cases": [
+            {
+                "expression": "\"<\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\t&\\\r": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\t&\\\\\\r\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "#": true
+        },
+        "cases": [
+            {
+                "expression": "\"#\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "B__": true
+        },
+        "cases": [
+            {
+                "expression": "B__",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\nS \n": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\nS \\n\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Bp": true
+        },
+        "cases": [
+            {
+                "expression": "Bp",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ",\t;": true
+        },
+        "cases": [
+            {
+                "expression": "\",\\t;\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "B_q": true
+        },
+        "cases": [
+            {
+                "expression": "B_q",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\/+\t\n\b!Z": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\/+\\t\\n\\b!Z\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udadd\udfc7\\ueFAc": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udadd\udfc7\\\\ueFAc\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            ":\f": true
+        },
+        "cases": [
+            {
+                "expression": "\":\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_BW_6Hg_Gl": true
+        },
+        "cases": [
+            {
+                "expression": "_BW_6Hg_Gl",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udbcf\udc02": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udbcf\udc02\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "zs1DC": true
+        },
+        "cases": [
+            {
+                "expression": "zs1DC",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "__434": true
+        },
+        "cases": [
+            {
+                "expression": "__434",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\udb94\udd41": true
+        },
+        "cases": [
+            {
+                "expression": "\"\udb94\udd41\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Z_5": true
+        },
+        "cases": [
+            {
+                "expression": "Z_5",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "z_M_": true
+        },
+        "cases": [
+            {
+                "expression": "z_M_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "YU_2": true
+        },
+        "cases": [
+            {
+                "expression": "YU_2",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_0": true
+        },
+        "cases": [
+            {
+                "expression": "_0",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b+": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b+\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "D7": true
+        },
+        "cases": [
+            {
+                "expression": "D7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_62L": true
+        },
+        "cases": [
+            {
+                "expression": "_62L",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tK\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tK\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\n\\\f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\n\\\\\\f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "I_": true
+        },
+        "cases": [
+            {
+                "expression": "I_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "W_a0_": true
+        },
+        "cases": [
+            {
+                "expression": "W_a0_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "BQ": true
+        },
+        "cases": [
+            {
+                "expression": "BQ",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\tX$\uABBb": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\tX$\\uABBb\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Z9": true
+        },
+        "cases": [
+            {
+                "expression": "Z9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\b%\"\uda38\udd0f": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\b%\\\"\uda38\udd0f\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_F": true
+        },
+        "cases": [
+            {
+                "expression": "_F",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!,": true
+        },
+        "cases": [
+            {
+                "expression": "\"!,\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\"!": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\"!\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "Hh": true
+        },
+        "cases": [
+            {
+                "expression": "Hh",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "&": true
+        },
+        "cases": [
+            {
+                "expression": "\"&\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "9\r\\R": true
+        },
+        "cases": [
+            {
+                "expression": "\"9\\r\\\\R\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "M_k": true
+        },
+        "cases": [
+            {
+                "expression": "M_k",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "!\b\n\udb06\ude52\"\"": true
+        },
+        "cases": [
+            {
+                "expression": "\"!\\b\\n\udb06\ude52\\\"\\\"\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "6": true
+        },
+        "cases": [
+            {
+                "expression": "\"6\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_7": true
+        },
+        "cases": [
+            {
+                "expression": "_7",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "0": true
+        },
+        "cases": [
+            {
+                "expression": "\"0\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\\8\\": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\\\8\\\\\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "b7eo": true
+        },
+        "cases": [
+            {
+                "expression": "b7eo",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "xIUo9": true
+        },
+        "cases": [
+            {
+                "expression": "xIUo9",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "5": true
+        },
+        "cases": [
+            {
+                "expression": "\"5\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "?": true
+        },
+        "cases": [
+            {
+                "expression": "\"?\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "sU": true
+        },
+        "cases": [
+            {
+                "expression": "sU",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "VH2&H\\\/": true
+        },
+        "cases": [
+            {
+                "expression": "\"VH2&H\\\\\\/\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_C": true
+        },
+        "cases": [
+            {
+                "expression": "_C",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "_": true
+        },
+        "cases": [
+            {
+                "expression": "_",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "<\t": true
+        },
+        "cases": [
+            {
+                "expression": "\"<\\t\"",
+                "result": true
+            }
+        ]
+    },
+    {
+        "given": {
+            "\uD834\uDD1E": true
+        },
+        "cases": [
+            {
+                "expression": "\"\\uD834\\uDD1E\"",
+                "result": true
+            }
+        ]
+    }
+]

+ 346 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/indices.json

@@ -0,0 +1,346 @@
+[{
+    "given":
+        {"foo": {"bar": ["zero", "one", "two"]}},
+     "cases": [
+         {
+            "expression": "foo.bar[0]",
+            "result": "zero"
+         },
+         {
+            "expression": "foo.bar[1]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.bar[2]",
+            "result": "two"
+         },
+         {
+            "expression": "foo.bar[3]",
+            "result": null
+         },
+         {
+            "expression": "foo.bar[-1]",
+            "result": "two"
+         },
+         {
+            "expression": "foo.bar[-2]",
+            "result": "one"
+         },
+         {
+            "expression": "foo.bar[-3]",
+            "result": "zero"
+         },
+         {
+            "expression": "foo.bar[-4]",
+            "result": null
+         }
+     ]
+},
+{
+    "given":
+        {"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
+     "cases": [
+         {
+            "expression": "foo.bar",
+            "result": null
+         },
+         {
+            "expression": "foo[0].bar",
+            "result": "one"
+         },
+         {
+            "expression": "foo[1].bar",
+            "result": "two"
+         },
+         {
+            "expression": "foo[2].bar",
+            "result": "three"
+         },
+         {
+            "expression": "foo[3].notbar",
+            "result": "four"
+         },
+         {
+            "expression": "foo[3].bar",
+            "result": null
+         },
+         {
+            "expression": "foo[0]",
+            "result": {"bar": "one"}
+         },
+         {
+            "expression": "foo[1]",
+            "result": {"bar": "two"}
+         },
+         {
+            "expression": "foo[2]",
+            "result": {"bar": "three"}
+         },
+         {
+            "expression": "foo[3]",
+            "result": {"notbar": "four"}
+         },
+         {
+            "expression": "foo[4]",
+            "result": null
+         }
+     ]
+},
+{
+    "given": [
+        "one", "two", "three"
+    ],
+     "cases": [
+         {
+            "expression": "[0]",
+            "result": "one"
+         },
+         {
+            "expression": "[1]",
+            "result": "two"
+         },
+         {
+            "expression": "[2]",
+            "result": "three"
+         },
+         {
+            "expression": "[-1]",
+            "result": "three"
+         },
+         {
+            "expression": "[-2]",
+            "result": "two"
+         },
+         {
+            "expression": "[-3]",
+            "result": "one"
+         }
+     ]
+},
+{
+    "given": {"reservations": [
+        {"instances": [{"foo": 1}, {"foo": 2}]}
+    ]},
+    "cases": [
+        {
+           "expression": "reservations[].instances[].foo",
+           "result": [1, 2]
+        },
+        {
+           "expression": "reservations[].instances[].bar",
+           "result": []
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        }
+    ]
+},
+{
+    "given": {"reservations": [{
+        "instances": [
+            {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
+            {"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
+            {"foo": "bar"},
+            {"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]},
+            {"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]},
+            {"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]},
+            {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
+        ],
+        "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
+      }, {
+        "instances": [
+            {"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
+            {"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
+            {"c": "bar"},
+            {"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]},
+            {"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
+        ],
+        "otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
+      }
+    ]},
+    "cases": [
+        {
+           "expression": "reservations[].instances[].foo[].bar",
+           "result": [1, 2, 4, 5, 6, 8]
+        },
+        {
+           "expression": "reservations[].instances[].foo[].baz",
+           "result": []
+        },
+        {
+           "expression": "reservations[].instances[].notfoo[].bar",
+           "result": [20, 21, 22, 23, 24, 25]
+        },
+        {
+           "expression": "reservations[].instances[].notfoo[].notbar",
+           "result": [[7], [7]]
+        },
+        {
+           "expression": "reservations[].notinstances[].foo",
+           "result": []
+        },
+        {
+           "expression": "reservations[].instances[].foo[].notbar",
+           "result": [3, [7]]
+        },
+        {
+           "expression": "reservations[].instances[].bar[].baz",
+           "result": [[1], [2], [3], [4]]
+        },
+        {
+           "expression": "reservations[].instances[].baz[].baz",
+           "result": [[1, 2], [], [], [3, 4]]
+        },
+        {
+           "expression": "reservations[].instances[].qux[].baz",
+           "result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []]
+        },
+        {
+           "expression": "reservations[].instances[].qux[].baz[]",
+           "result": [1, 2, 3, 4, 1, 2, 3, 4]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": [
+            [["one", "two"], ["three", "four"]],
+            [["five", "six"], ["seven", "eight"]],
+            [["nine"], ["ten"]]
+        ]
+     },
+    "cases": [
+        {
+           "expression": "foo[]",
+           "result": [["one", "two"], ["three", "four"], ["five", "six"],
+                      ["seven", "eight"], ["nine"], ["ten"]]
+        },
+        {
+           "expression": "foo[][0]",
+           "result": ["one", "three", "five", "seven", "nine", "ten"]
+        },
+        {
+           "expression": "foo[][1]",
+           "result": ["two", "four", "six", "eight"]
+        },
+        {
+           "expression": "foo[][0][0]",
+           "result": []
+        },
+         {
+            "expression": "foo[][2][2]",
+            "result": []
+         },
+         {
+            "expression": "foo[][0][0][100]",
+            "result": []
+         }
+    ]
+},
+{
+    "given": {
+      "foo": [{
+          "bar": [
+            {
+              "qux": 2,
+              "baz": 1
+            },
+            {
+              "qux": 4,
+              "baz": 3
+            }
+          ]
+        },
+        {
+          "bar": [
+            {
+              "qux": 6,
+              "baz": 5
+            },
+            {
+              "qux": 8,
+              "baz": 7
+            }
+          ]
+        }
+      ]
+    },
+    "cases": [
+        {
+           "expression": "foo",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[]",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[].bar",
+           "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
+                      [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
+        },
+        {
+           "expression": "foo[].bar[]",
+           "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
+                      {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
+        },
+        {
+           "expression": "foo[].bar[].baz",
+           "result": [1, 3, 5, 7]
+        }
+    ]
+},
+{
+    "given": {
+        "string": "string",
+        "hash": {"foo": "bar", "bar": "baz"},
+        "number": 23,
+        "nullvalue": null
+     },
+     "cases": [
+         {
+            "expression": "string[]",
+            "result": null
+         },
+         {
+            "expression": "hash[]",
+            "result": null
+         },
+         {
+            "expression": "number[]",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[]",
+            "result": null
+         },
+         {
+            "expression": "string[].foo",
+            "result": null
+         },
+         {
+            "expression": "hash[].foo",
+            "result": null
+         },
+         {
+            "expression": "number[].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[].foo",
+            "result": null
+         },
+         {
+            "expression": "nullvalue[].foo[].bar",
+            "result": null
+         }
+     ]
+}
+]

+ 185 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/literal.json

@@ -0,0 +1,185 @@
+[
+    {
+        "given": {
+            "foo": [{"name": "a"}, {"name": "b"}],
+            "bar": {"baz": "qux"}
+        },
+        "cases": [
+            {
+                "expression": "`\"foo\"`",
+                "result": "foo"
+            },
+            {
+                "comment": "Interpret escaped unicode.",
+                "expression": "`\"\\u03a6\"`",
+                "result": "Φ"
+            },
+            {
+                "expression": "`\"✓\"`",
+                "result": "✓"
+            },
+            {
+                "expression": "`[1, 2, 3]`",
+                "result": [1, 2, 3]
+            },
+            {
+                "expression": "`{\"a\": \"b\"}`",
+                "result": {"a": "b"}
+            },
+            {
+                "expression": "`true`",
+                "result": true
+            },
+            {
+                "expression": "`false`",
+                "result": false
+            },
+            {
+                "expression": "`null`",
+                "result": null
+            },
+            {
+                "expression": "`0`",
+                "result": 0
+            },
+            {
+                "expression": "`1`",
+                "result": 1
+            },
+            {
+                "expression": "`2`",
+                "result": 2
+            },
+            {
+                "expression": "`3`",
+                "result": 3
+            },
+            {
+                "expression": "`4`",
+                "result": 4
+            },
+            {
+                "expression": "`5`",
+                "result": 5
+            },
+            {
+                "expression": "`6`",
+                "result": 6
+            },
+            {
+                "expression": "`7`",
+                "result": 7
+            },
+            {
+                "expression": "`8`",
+                "result": 8
+            },
+            {
+                "expression": "`9`",
+                "result": 9
+            },
+            {
+                "comment": "Escaping a backtick in quotes",
+                "expression": "`\"foo\\`bar\"`",
+                "result": "foo`bar"
+            },
+            {
+                "comment": "Double quote in literal",
+                "expression": "`\"foo\\\"bar\"`",
+                "result": "foo\"bar"
+            },
+            {
+                "expression": "`\"1\\`\"`",
+                "result": "1`"
+            },
+            {
+                "comment": "Multiple literal expressions with escapes",
+                "expression": "`\"\\\\\"`.{a:`\"b\"`}",
+                "result": {"a": "b"}
+            },
+            {
+                "comment": "literal . identifier",
+                "expression": "`{\"a\": \"b\"}`.a",
+                "result": "b"
+            },
+            {
+                "comment": "literal . identifier . identifier",
+                "expression": "`{\"a\": {\"b\": \"c\"}}`.a.b",
+                "result": "c"
+            },
+            {
+                "comment": "literal . identifier bracket-expr",
+                "expression": "`[0, 1, 2]`[1]",
+                "result": 1
+            }
+        ]
+    },
+    {
+      "comment": "Literals",
+      "given": {"type": "object"},
+      "cases": [
+        {
+          "comment": "Literal with leading whitespace",
+          "expression": "`  {\"foo\": true}`",
+          "result": {"foo": true}
+        },
+        {
+          "comment": "Literal with trailing whitespace",
+          "expression": "`{\"foo\": true}   `",
+          "result": {"foo": true}
+        },
+        {
+          "comment": "Literal on RHS of subexpr not allowed",
+          "expression": "foo.`\"bar\"`",
+          "error": "syntax"
+        }
+      ]
+    },
+    {
+      "comment": "Raw String Literals",
+      "given": {},
+      "cases": [
+        {
+          "expression": "'foo'",
+          "result": "foo"
+        },
+        {
+          "expression": "'  foo  '",
+          "result": "  foo  "
+        },
+        {
+          "expression": "'0'",
+          "result": "0"
+        },
+        {
+          "expression": "'newline\n'",
+          "result": "newline\n"
+        },
+        {
+          "expression": "'\n'",
+          "result": "\n"
+        },
+        {
+          "expression": "'✓'",
+	  "result": "✓"
+        },
+        {
+          "expression": "'𝄞'",
+	  "result": "𝄞"
+        },
+        {
+          "expression": "'  [foo]  '",
+          "result": "  [foo]  "
+        },
+        {
+          "expression": "'[foo]'",
+          "result": "[foo]"
+        },
+        {
+          "comment": "Do not interpret escaped unicode.",
+          "expression": "'\\u03a6'",
+          "result": "\\u03a6"
+        }
+      ]
+    }
+]

+ 393 - 0
Godeps/_workspace/src/github.com/jmespath/go-jmespath/compliance/multiselect.json

@@ -0,0 +1,393 @@
+[{
+    "given": {
+      "foo": {
+        "bar": "bar",
+        "baz": "baz",
+        "qux": "qux",
+        "nested": {
+          "one": {
+            "a": "first",
+            "b": "second",
+            "c": "third"
+          },
+          "two": {
+            "a": "first",
+            "b": "second",
+            "c": "third"
+          },
+          "three": {
+            "a": "first",
+            "b": "second",
+            "c": {"inner": "third"}
+          }
+        }
+      },
+      "bar": 1,
+      "baz": 2,
+      "qux\"": 3
+    },
+     "cases": [
+         {
+            "expression": "foo.{bar: bar}",
+            "result": {"bar": "bar"}
+         },
+         {
+            "expression": "foo.{\"bar\": bar}",
+            "result": {"bar": "bar"}
+         },
+         {
+            "expression": "foo.{\"foo.bar\": bar}",
+            "result": {"foo.bar": "bar"}
+         },
+         {
+            "expression": "foo.{bar: bar, baz: baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "foo.{\"bar\": bar, \"baz\": baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}",
+            "result": {"baz": 2, "qux\"": 3}
+         },
+         {
+            "expression": "foo.{bar:bar,baz:baz}",
+            "result": {"bar": "bar", "baz": "baz"}
+         },
+         {
+            "expression": "foo.{bar: bar,qux: qux}",
+            "result": {"bar": "bar", "qux": "qux"}
+         },
+         {
+            "expression": "foo.{bar: bar, noexist: noexist}",
+            "result": {"bar": "bar", "noexist": null}
+         },
+         {
+            "expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}",
+            "result": {"noexist": null, "alsonoexist": null}
+         },
+         {
+            "expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}",
+            "result": null
+         },
+         {
+            "expression": "foo.nested.*.{a: a,b: b}",
+            "result": [{"a": "first", "b": "second"},
+                       {"a": "first", "b": "second"},
+                       {"a": "first", "b": "second"}]
+         },
+         {
+            "expression": "foo.nested.three.{a: a, cinner: c.inner}",
+            "result": {"a": "first", "cinner": "third"}
+         },
+         {
+            "expression": "foo.nested.three.{a: a, c: c.inner.bad.key}",
+            "result": {"a": "first", "c": null}
+         },
+         {
+            "expression": "foo.{a: nested.one.a, b: nested.two.b}",
+            "result": {"a": "first", "b": "second"}
+         },
+         {
+            "expression": "{bar: bar, baz: baz}",
+            "result": {"bar": 1, "baz": 2}
+         },
+         {
+            "expression": "{bar: bar}",
+            "result": {"bar": 1}
+         },
+         {
+            "expression": "{otherkey: bar}",
+            "result": {"otherkey": 1}
+         },
+         {
+            "expression": "{no: no, exist: exist}",
+            "result": {"no": null, "exist": null}
+         },
+         {
+            "expression": "foo.[bar]",
+            "result": ["bar"]
+         },
+         {
+            "expression": "foo.[bar,baz]",
+            "result": ["bar", "baz"]
+         },
+         {
+            "expression": "foo.[bar,qux]",
+            "result": ["bar", "qux"]
+         },
+         {
+            "expression": "foo.[bar,noexist]",
+            "result": ["bar", null]
+         },
+         {
+            "expression": "foo.[noexist,alsonoexist]",
+            "result": [null, null]
+         }
+     ]
+}, {
+    "given": {
+      "foo": {"bar": 1, "baz": [2, 3, 4]}
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar:bar,baz:baz}",
+            "result": {"bar": 1, "baz": [2, 3, 4]}
+         },
+         {
+            "expression": "foo.[bar,baz[0]]",
+            "result": [1, 2]
+         },
+         {
+            "expression": "foo.[bar,baz[1]]",
+            "result": [1, 3]
+         },
+         {
+            "expression": "foo.[bar,baz[2]]",
+            "result": [1, 4]
+         },
+         {
+            "expression": "foo.[bar,baz[3]]",
+            "result": [1, null]
+         },
+         {
+            "expression": "foo.[bar[0],baz[3]]",
+            "result": [null, null]
+         }
+    ]
+}, {
+    "given": {
+      "foo": {"bar": 1, "baz": 2}
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar: bar, baz: baz}",
+            "result": {"bar": 1, "baz": 2}
+         },
+         {
+            "expression": "foo.[bar,baz]",
+            "result": [1, 2]
+         }
+    ]
+}, {
+    "given": {
+      "foo": {
+          "bar": {"baz": [{"common": "first", "one": 1},
+                          {"common": "second", "two": 2}]},
+          "ignoreme": 1,
+          "includeme": true
+      }
+    },
+    "cases": [
+         {
+            "expression": "foo.{bar: bar.baz[1],includeme: includeme}",
+            "result": {"bar": {"common": "second", "two": 2}, "includeme": true}
+         },
+         {
+            "expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}",
+            "result": {"bar.baz.two": 2, "includeme": true}
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[*].common]",
+            "result": [true, ["first", "second"]]
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[*].none]",
+            "result": [true, []]
+         },
+         {
+            "expression": "foo.[includeme, bar.baz[].common]",
+            "result": [true, ["first", "second"]]
+         }
+    ]
+}, {
+    "given": {
+      "reservations": [{
+          "instances": [
+              {"id": "id1",
+               "name": "first"},
+              {"id": "id2",
+               "name": "second"}
+          ]}, {
+          "instances": [
+              {"id": "id3",
+               "name": "third"},
+              {"id": "id4",
+               "name": "fourth"}
+          ]}
+      ]},
+    "cases": [
+         {
+            "expression": "reservations[*].instances[*].{id: id, name: name}",
+            "result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}],
+                       [{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]]
+         },
+         {
+            "expression": "reservations[].instances[].{id: id, name: name}",
+            "result": [{"id": "id1", "name": "first"},
+                       {"id": "id2", "name": "second"},
+                       {"id": "id3", "name": "third"},
+                       {"id": "id4", "name": "fourth"}]
+         },
+         {
+            "expression": "reservations[].instances[].[id, name]",
+            "result": [["id1", "first"],
+                       ["id2", "second"],
+                       ["id3", "third"],
+                       ["id4", "fourth"]]
+         }
+    ]
+},
+{
+    "given": {
+      "foo": [{
+          "bar": [
+            {
+              "qux": 2,
+              "baz": 1
+            },
+            {
+              "qux": 4,
+              "baz": 3
+            }
+          ]
+        },
+        {
+          "bar": [
+            {
+              "qux": 6,
+              "baz": 5
+            },
+            {
+              "qux": 8,
+              "baz": 7
+            }
+          ]
+        }
+      ]
+    },
+    "cases": [
+        {
+           "expression": "foo",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[]",
+           "result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
+                      {"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
+        },
+        {
+           "expression": "foo[].bar",
+           "result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
+                      [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
+        },
+        {
+           "expression": "foo[].bar[]",
+           "result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
+                      {"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
+        },
+        {
+           "expression": "foo[].bar[].[baz, qux]",
+           "result": [[1, 2], [3, 4], [5, 6], [7, 8]]
+        },
+        {
+           "expression": "foo[].bar[].[baz]",
+           "result": [[1], [3], [5], [7]]
+        },
+        {
+           "expression": "foo[].bar[].[baz, qux][]",
+           "result": [1, 2, 3, 4, 5, 6, 7, 8]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "abc"
+                }, {
+                    "bar": "def"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].bar, qux[0]]",
+           "result": [["abc", "def"], "zero"]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "a",
+                    "bam": "b",
+                    "boo": "c"
+                }, {
+                    "bar": "d",
+                    "bam": "e",
+                    "boo": "f"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].[bar, boo], qux[0]]",
+           "result": [[["a", "c" ], ["d", "f" ]], "zero"]
+        }
+    ]
+},
+{
+    "given": {
+        "foo": {
+            "baz": [
+                {
+                    "bar": "a",
+                    "bam": "b",
+                    "boo": "c"
+                }, {
+                    "bar": "d",
+                    "bam": "e",
+                    "boo": "f"
+                }
+            ],
+            "qux": ["zero"]
+        }
+    },
+    "cases": [
+        {
+           "expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]",
+           "result": [["a", "d"], "zero"]
+        }
+    ]
+},
+{
+    "given": {"type": "object"},
+    "cases": [
+        {
+          "comment": "Nested multiselect",
+          "expression": "[[*],*]",
+          "result": [null, ["object"]]
+        }
+    ]
+},
+{
+    "given": [],
+    "cases": [
+        {
+          "comment": "Nested multiselect",
+          "expression": "[[*]]",
+          "result": [[]]
+        }
+    ]
+}
+]

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor