ソースを参照

Allow kube subnet manager to run outside of kubernetes

This is really useful for dev and test work

This PRs also fixes some problems in the vendoring and adds a target to
the Makefile to make it easy to run.
Tom Denham 7 年 前
コミット
c9970d0569
100 ファイル変更4539 行追加1178 行削除
  1. 19 0
      Makefile
  2. 11 0
      dist/fake-node.yaml
  3. 39 20
      glide.lock
  4. 1 2
      glide.yaml
  5. 11 8
      main.go
  6. 35 16
      subnet/kube/kube.go
  7. 0 0
      vendor/cloud.google.com/go/LICENSE
  8. 91 36
      vendor/cloud.google.com/go/compute/metadata/metadata.go
  9. 0 59
      vendor/github.com/aws/aws-sdk-go/aws/client/client.go
  10. 108 0
      vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
  11. 84 43
      vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
  12. 8 6
      vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
  13. 6 4
      vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
  14. 1 0
      vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
  15. 16 17
      vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
  16. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
  17. 27 0
      vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go
  18. 56 0
      vendor/github.com/aws/aws-sdk-go/aws/doc.go
  19. 162 18
      vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
  20. 77 35
      vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
  21. 10 7
      vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go
  22. 2 1
      vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go
  23. 2 2
      vendor/github.com/aws/aws-sdk-go/aws/logger.go
  24. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
  25. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go
  26. 31 0
      vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
  27. 32 31
      vendor/github.com/aws/aws-sdk-go/aws/request/request.go
  28. 20 2
      vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
  29. 27 3
      vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
  30. 8 1
      vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
  31. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
  32. 2 2
      vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
  33. 2 3
      vendor/github.com/aws/aws-sdk-go/aws/session/doc.go
  34. 8 28
      vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go
  35. 23 7
      vendor/github.com/aws/aws-sdk-go/aws/session/session.go
  36. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
  37. 16 16
      vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go
  38. 1 1
      vendor/github.com/aws/aws-sdk-go/aws/version.go
  39. 40 0
      vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go
  40. 0 1
      vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go
  41. 5 2
      vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go
  42. 9 4
      vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
  43. 501 8
      vendor/github.com/aws/aws-sdk-go/service/ec2/api.go
  44. 83 0
      vendor/github.com/aws/aws-sdk-go/service/ec2/doc.go
  45. 6 7
      vendor/github.com/aws/aws-sdk-go/service/ec2/service.go
  46. 3 4
      vendor/github.com/aws/aws-sdk-go/service/sts/api.go
  47. 124 0
      vendor/github.com/aws/aws-sdk-go/service/sts/doc.go
  48. 5 47
      vendor/github.com/aws/aws-sdk-go/service/sts/service.go
  49. 150 8
      vendor/github.com/coreos/go-iptables/iptables/iptables.go
  50. 140 8
      vendor/github.com/denverdino/aliyungo/common/client.go
  51. 118 0
      vendor/github.com/denverdino/aliyungo/common/endpoint.go
  52. 16 11
      vendor/github.com/denverdino/aliyungo/common/regions.go
  53. 74 0
      vendor/github.com/denverdino/aliyungo/common/types.go
  54. 38 1
      vendor/github.com/denverdino/aliyungo/ecs/client.go
  55. 104 0
      vendor/github.com/denverdino/aliyungo/ecs/forward_entry.go
  56. 39 3
      vendor/github.com/denverdino/aliyungo/ecs/images.go
  57. 31 0
      vendor/github.com/denverdino/aliyungo/ecs/instance_types.go
  58. 65 1
      vendor/github.com/denverdino/aliyungo/ecs/instances.go
  59. 202 0
      vendor/github.com/denverdino/aliyungo/ecs/nat_gateway.go
  60. 1 0
      vendor/github.com/denverdino/aliyungo/ecs/security_groups.go
  61. 95 0
      vendor/github.com/denverdino/aliyungo/ecs/snat_entry.go
  62. 144 0
      vendor/github.com/denverdino/aliyungo/ecs/ssh_key_pair.go
  63. 1 0
      vendor/github.com/denverdino/aliyungo/ecs/vpcs.go
  64. 1 0
      vendor/github.com/denverdino/aliyungo/ecs/vswitches.go
  65. 162 0
      vendor/github.com/denverdino/aliyungo/util/encoding.go
  66. 48 25
      vendor/github.com/go-ini/ini/ini.go
  67. 107 41
      vendor/github.com/go-ini/ini/key.go
  68. 15 13
      vendor/github.com/go-ini/ini/parser.go
  69. 22 6
      vendor/github.com/go-ini/ini/section.go
  70. 93 24
      vendor/github.com/go-ini/ini/struct.go
  71. 15 0
      vendor/github.com/howeyc/gopass/LICENSE.txt
  72. 91 0
      vendor/github.com/howeyc/gopass/pass.go
  73. 25 0
      vendor/github.com/howeyc/gopass/terminal.go
  74. 69 0
      vendor/github.com/howeyc/gopass/terminal_solaris.go
  75. 28 0
      vendor/github.com/imdario/mergo/LICENSE
  76. 44 0
      vendor/github.com/imdario/mergo/doc.go
  77. 146 0
      vendor/github.com/imdario/mergo/map.go
  78. 99 0
      vendor/github.com/imdario/mergo/merge.go
  79. 90 0
      vendor/github.com/imdario/mergo/mergo.go
  80. 37 0
      vendor/github.com/jmespath/go-jmespath/api.go
  81. 65 63
      vendor/github.com/jmespath/go-jmespath/functions.go
  82. 2 2
      vendor/github.com/jmespath/go-jmespath/parser.go
  83. 0 1
      vendor/github.com/joho/godotenv/.gitignore
  84. 0 127
      vendor/github.com/joho/godotenv/README.md
  85. 0 15
      vendor/github.com/joho/godotenv/autoload/autoload.go
  86. 0 54
      vendor/github.com/joho/godotenv/cmd/godotenv/cmd.go
  87. 0 2
      vendor/github.com/joho/godotenv/fixtures/equals.env
  88. 0 2
      vendor/github.com/joho/godotenv/fixtures/exported.env
  89. 0 2
      vendor/github.com/joho/godotenv/fixtures/invalid1.env
  90. 0 5
      vendor/github.com/joho/godotenv/fixtures/plain.env
  91. 0 8
      vendor/github.com/joho/godotenv/fixtures/quoted.env
  92. 0 288
      vendor/github.com/joho/godotenv/godotenv_test.go
  93. 0 1
      vendor/github.com/joho/godotenv/wercker.yml
  94. 12 3
      vendor/github.com/vishvananda/netlink/addr.go
  95. 21 5
      vendor/github.com/vishvananda/netlink/addr_linux.go
  96. 7 5
      vendor/github.com/vishvananda/netlink/bpf_linux.go
  97. 2 2
      vendor/github.com/vishvananda/netlink/filter.go
  98. 25 0
      vendor/github.com/vishvananda/netlink/handle_linux.go
  99. 218 0
      vendor/github.com/vishvananda/netlink/handle_unspecified.go
  100. 160 6
      vendor/github.com/vishvananda/netlink/link.go

+ 19 - 0
Makefile

@@ -231,3 +231,22 @@ run-etcd: stop-etcd
 
 stop-etcd:
 	@-docker rm -f flannel-etcd
+
+K8S_VERSION=v1.6.6
+run-k8s-apiserver: stop-k8s-apiserver
+	docker run --detach --net=host \
+	  --name calico-k8s-apiserver \
+  	gcr.io/google_containers/hyperkube-amd64:$(K8S_VERSION) \
+		  /hyperkube apiserver --etcd-servers=http://$(LOCAL_IP_ENV):2379 \
+		  --service-cluster-ip-range=10.101.0.0/16
+
+stop-k8s-apiserver:
+	@-docker rm -f calico-k8s-apiserver
+
+run-local-kube-flannel-with-prereqs: run-etcd run-k8s-apiserver dist/flanneld
+	while ! kubectl apply -f dist/fake-node.yaml; do sleep 1; done
+	$(MAKE) run-local-kube-flannel
+
+run-local-kube-flannel:
+	# Currently this requires the netconf to be in /etc/kube-flannel/net-conf.json
+	sudo NODE_NAME=test dist/flanneld --kube-subnet-mgr --kube-api-url http://127.0.0.1:8080

+ 11 - 0
dist/fake-node.yaml

@@ -0,0 +1,11 @@
+apiVersion: v1
+kind: Node
+metadata:
+  name: test
+  annotations:
+    flannel.alpha.coreos.com/backend-data: '{"VtepMAC":"96:59:b2:3f:04:ee"}' 
+    flannel.alpha.coreos.com/backend-type: vxlan
+    flannel.alpha.coreos.com/kube-subnet-manager: "true"
+    flannel.alpha.coreos.com/public-ip: 192.168.77.17
+spec:
+  podCIDR: 10.244.7.0/24

+ 39 - 20
glide.lock

@@ -1,8 +1,12 @@
-hash: e34384407e03d01da342b9dd4905efae99325ec4f742b6b104d60dcfa4bf197d
-updated: 2017-04-19T15:20:15.788350895-07:00
+hash: 2f18ae318a81ddf8a97889dd05c1d2cae675586788b641c8b2b1fec819177d69
+updated: 2017-06-29T10:56:36.891947592-07:00
 imports:
+- name: cloud.google.com/go
+  version: 7c205da84d8d024a8200be93ab042357c9a70177
+  subpackages:
+  - compute/metadata
 - name: github.com/aws/aws-sdk-go
-  version: 3981b48d0eca40d1ce35f20c605b3a153e64b4ad
+  version: 50762c1efc55dd2a05eac85fc170b0f65aeec28f
   subpackages:
   - aws
   - aws/awserr
@@ -20,6 +24,7 @@ imports:
   - aws/request
   - aws/session
   - aws/signer/v4
+  - internal/shareddefaults
   - private/protocol
   - private/protocol/ec2query
   - private/protocol/query
@@ -29,7 +34,7 @@ imports:
   - service/ec2
   - service/sts
 - name: github.com/coreos/etcd
-  version: e5b7ee2d03627ca33201da428b8110ef7c3e95f1
+  version: 0f4a535c2fb7a2920e13e2e19b9eaf6b2e9285e5
   subpackages:
   - client
   - clientv3
@@ -39,7 +44,7 @@ imports:
   - pkg/transport
   - pkg/types
 - name: github.com/coreos/go-iptables
-  version: fbb73372b87f6e89951c2b6b31470c2c9d5cfae3
+  version: 259c8e6a4275d497442c721fa52204d7a58bde8b
   subpackages:
   - iptables
 - name: github.com/coreos/go-systemd
@@ -58,7 +63,7 @@ imports:
   subpackages:
   - spew
 - name: github.com/denverdino/aliyungo
-  version: 33365dab57be370c8462f0101b8e61fdf69af3fc
+  version: f6cab0c35083495bd138281f0b9ca40ae2f15e19
   subpackages:
   - common
   - ecs
@@ -77,7 +82,7 @@ imports:
 - name: github.com/ghodss/yaml
   version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
 - name: github.com/go-ini/ini
-  version: e3c2d47c61e5333f9aa2974695dd94396eb69c75
+  version: 3d73f4b845efdf9989fffd4b4e562727744a34ba
 - name: github.com/go-openapi/jsonpointer
   version: 46af16f9f7b149af66e5d1bd010e3574dc06de98
 - name: github.com/go-openapi/jsonreference
@@ -101,9 +106,13 @@ imports:
 - name: github.com/google/gofuzz
   version: 44d81051d367757e1c7c6a5a86423ece9afcf63c
 - name: github.com/gorilla/mux
-  version: 392c28fe23e1c45ddba891b0320b3b5df220beea
+  version: bcd8bc72b08df0f70df986b97f95590779502d31
+- name: github.com/howeyc/gopass
+  version: 3ca23474a7c7203e0a0a070fd33508f6efdb9b3d
+- name: github.com/imdario/mergo
+  version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
 - name: github.com/jmespath/go-jmespath
-  version: 3433f3ea46d9f8019119e7dd41274e112a2359a9
+  version: bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
 - name: github.com/joho/godotenv
   version: 726cc8b906e3d31c70a9671c90a13716a8d3f50d
 - name: github.com/jonboulle/clockwork
@@ -127,11 +136,17 @@ imports:
   subpackages:
   - codec
 - name: github.com/vishvananda/netlink
-  version: e73bad418fd727ed3a02830b1af1ad0283a1de6c
+  version: fe3b5664d23a11b52ba59bece4ff29c52772a56b
   subpackages:
   - nl
 - name: github.com/vishvananda/netns
-  version: 8ba1072b58e0c2a240eb5f6120165c7776c3e7b8
+  version: 54f0e4339ce73702a0607f49922aaa1e749b418d
+- name: golang.org/x/crypto
+  version: 1351f936d976c60a0a48d728281922cf63eafb8d
+  subpackages:
+  - bcrypt
+  - blowfish
+  - ssh/terminal
 - name: golang.org/x/net
   version: f2499483f923065a842d38eb4c7f1927e6fc6e6d
   subpackages:
@@ -142,12 +157,16 @@ imports:
   - idna
   - lex/httplex
 - name: golang.org/x/oauth2
-  version: 188fb45fbef6ffd967b3a8abcfe176fd473361df
+  version: 5432cc9688e6250a0dd8f5a5f4c781d92b398be6
   subpackages:
   - google
   - internal
   - jws
   - jwt
+- name: golang.org/x/sys
+  version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
+  subpackages:
+  - unix
 - name: golang.org/x/text
   version: 2910a502d2bf9e43193af9d68ca516529614eed3
   subpackages:
@@ -162,7 +181,7 @@ imports:
   - unicode/norm
   - width
 - name: google.golang.org/api
-  version: e6294e63a06b2be522ff3d328d8cacded0b1bd31
+  version: e6586c9293b9d514c7f5d5076731ec977cff1be6
   subpackages:
   - compute/v1
   - gensupport
@@ -180,17 +199,12 @@ imports:
   - internal/remote_api
   - internal/urlfetch
   - urlfetch
-- name: google.golang.org/cloud
-  version: eb47ba841d53d93506cfbfbc03927daf9cc48f88
-  subpackages:
-  - compute/metadata
-  - internal
 - name: gopkg.in/inf.v0
   version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
 - name: gopkg.in/yaml.v2
   version: 53feefa2559fb8dfa8d81baad31be332c97d6c77
 - name: k8s.io/apimachinery
-  version: 72e51762028fdf72f1a20e59bedceece02a425c6
+  version: 85ace5365f33b16fc735c866a12e3c765b9700f2
   subpackages:
   - pkg/api/errors
   - pkg/api/meta
@@ -235,7 +249,7 @@ imports:
   - third_party/forked/golang/json
   - third_party/forked/golang/reflect
 - name: k8s.io/client-go
-  version: d257309ce8cccf0cd65b6beb32baeb0c67a7cffb
+  version: 99c1992389642cae4f41b931eca21827f9cc35b7
   subpackages:
   - discovery
   - kubernetes
@@ -306,12 +320,17 @@ imports:
   - pkg/version
   - rest
   - rest/watch
+  - tools/auth
   - tools/cache
+  - tools/clientcmd
   - tools/clientcmd/api
+  - tools/clientcmd/api/latest
+  - tools/clientcmd/api/v1
   - tools/metrics
   - transport
   - util/cert
   - util/clock
   - util/flowcontrol
+  - util/homedir
   - util/integer
 testImports: []

+ 1 - 2
glide.yaml

@@ -9,7 +9,7 @@ import:
   - aws/session
   - service/ec2
 - package: github.com/coreos/etcd
-  version: ^3.1.0
+  version: 3.1.x
   subpackages:
   - client
   - clientv3
@@ -52,7 +52,6 @@ import:
   - rest
   - tools/cache
 - package: k8s.io/apimachinery
-  version: 72e51762028fdf72f1a20e59bedceece02a425c6
   subpackages:
   - pkg/apis/meta/v1
   - pkg/runtime

+ 11 - 8
main.go

@@ -67,6 +67,8 @@ type CmdLineOpts struct {
 	help                   bool
 	version                bool
 	kubeSubnetMgr          bool
+	kubeApiUrl             string
+	kubeConfigFile         string
 	iface                  string
 	ifaceRegex             string
 	ipMasq                 bool
@@ -86,24 +88,25 @@ var (
 )
 
 func init() {
-
 	flannelFlags.StringVar(&opts.etcdEndpoints, "etcd-endpoints", "http://127.0.0.1:4001,http://127.0.0.1:2379", "a comma-delimited list of etcd endpoints")
 	flannelFlags.StringVar(&opts.etcdPrefix, "etcd-prefix", "/coreos.com/network", "etcd prefix")
 	flannelFlags.StringVar(&opts.etcdKeyfile, "etcd-keyfile", "", "SSL key file used to secure etcd communication")
 	flannelFlags.StringVar(&opts.etcdCertfile, "etcd-certfile", "", "SSL certification file used to secure etcd communication")
 	flannelFlags.StringVar(&opts.etcdCAFile, "etcd-cafile", "", "SSL Certificate Authority file used to secure etcd communication")
-	flannelFlags.StringVar(&opts.etcdUsername, "etcd-username", "", "Username for BasicAuth to etcd")
-	flannelFlags.StringVar(&opts.etcdPassword, "etcd-password", "", "Password for BasicAuth to etcd")
+	flannelFlags.StringVar(&opts.etcdUsername, "etcd-username", "", "username for BasicAuth to etcd")
+	flannelFlags.StringVar(&opts.etcdPassword, "etcd-password", "", "password for BasicAuth to etcd")
 	flannelFlags.StringVar(&opts.iface, "iface", "", "interface to use (IP or name) for inter-host communication")
 	flannelFlags.StringVar(&opts.ifaceRegex, "iface-regex", "", "regex expression to match the first interface to use (IP or name) for inter-host communication. Skipped if the iface option is also specified")
 	flannelFlags.StringVar(&opts.subnetFile, "subnet-file", "/run/flannel/subnet.env", "filename where env variables (subnet, MTU, ... ) will be written to")
 	flannelFlags.StringVar(&opts.publicIP, "public-ip", "", "IP accessible by other nodes for inter-host communication")
-	flannelFlags.IntVar(&opts.subnetLeaseRenewMargin, "subnet-lease-renew-margin", 60, "Subnet lease renewal margin, in minutes.")
+	flannelFlags.IntVar(&opts.subnetLeaseRenewMargin, "subnet-lease-renew-margin", 60, "subnet lease renewal margin, in minutes.")
 	flannelFlags.BoolVar(&opts.ipMasq, "ip-masq", false, "setup IP masquerade rule for traffic destined outside of overlay network")
-	flannelFlags.BoolVar(&opts.kubeSubnetMgr, "kube-subnet-mgr", false, "Contact the Kubernetes API for subnet assignment instead of etcd.")
+	flannelFlags.BoolVar(&opts.kubeSubnetMgr, "kube-subnet-mgr", false, "contact the Kubernetes API for subnet assignment instead of etcd.")
+	flannelFlags.StringVar(&opts.kubeApiUrl, "kube-api-url", "", "Kubernetes API server URL. Does not need to be specified if flannel is running in a pod.")
+	flannelFlags.StringVar(&opts.kubeConfigFile, "kubeconfig-file", "", "kubeconfig file location. Does not need to be specified if flannel is running in a pod.")
 	flannelFlags.BoolVar(&opts.version, "version", false, "print version and exit")
-	flannelFlags.StringVar(&opts.healthzIP, "healthz-ip", "0.0.0.0", "The IP address for healthz server to listen")
-	flannelFlags.IntVar(&opts.healthzPort, "healthz-port", 0, "The port for healthz server to listen(0 to disable)")
+	flannelFlags.StringVar(&opts.healthzIP, "healthz-ip", "0.0.0.0", "the IP address for healthz server to listen")
+	flannelFlags.IntVar(&opts.healthzPort, "healthz-port", 0, "the port for healthz server to listen(0 to disable)")
 
 	// glog will log to tmp files by default. override so all entries
 	// can flow into journald (if running under systemd)
@@ -133,7 +136,7 @@ func usage() {
 
 func newSubnetManager() (subnet.Manager, error) {
 	if opts.kubeSubnetMgr {
-		return kube.NewSubnetManager()
+		return kube.NewSubnetManager(opts.kubeApiUrl, opts.kubeConfigFile)
 	}
 
 	cfg := &etcdv2.EtcdConfig{

+ 35 - 16
subnet/kube/kube.go

@@ -40,6 +40,7 @@ import (
 	"k8s.io/client-go/pkg/api/v1"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/cache"
+	"k8s.io/client-go/tools/clientcmd"
 )
 
 var (
@@ -67,29 +68,47 @@ type kubeSubnetManager struct {
 	events         chan subnet.Event
 }
 
-func NewSubnetManager() (subnet.Manager, error) {
-	cfg, err := rest.InClusterConfig()
-	if err != nil {
-		return nil, fmt.Errorf("unable to initialize inclusterconfig: %v", err)
+func NewSubnetManager(apiUrl, kubeconfig string) (subnet.Manager, error) {
+
+	var cfg *rest.Config
+	var err error
+	// Use out of cluster config if the URL or kubeconfig have been specified. Otherwise use incluster config.
+	if apiUrl != "" || kubeconfig != "" {
+		cfg, err = clientcmd.BuildConfigFromFlags(apiUrl, kubeconfig)
+		if err != nil {
+			return nil, fmt.Errorf("unable to create k8s config: %v", err)
+		}
+	} else {
+		cfg, err = rest.InClusterConfig()
+		if err != nil {
+			return nil, fmt.Errorf("unable to initialize inclusterconfig: %v", err)
+		}
 	}
+
 	c, err := clientset.NewForConfig(cfg)
 	if err != nil {
 		return nil, fmt.Errorf("unable to initialize client: %v", err)
 	}
 
-	podName := os.Getenv("POD_NAME")
-	podNamespace := os.Getenv("POD_NAMESPACE")
-	if podName == "" || podNamespace == "" {
-		return nil, fmt.Errorf("env variables POD_NAME and POD_NAMESPACE must be set")
-	}
-
-	pod, err := c.Pods(podNamespace).Get(podName, metav1.GetOptions{})
-	if err != nil {
-		return nil, fmt.Errorf("error retrieving pod spec for '%s/%s': %v", podNamespace, podName, err)
-	}
-	nodeName := pod.Spec.NodeName
+	// The kube subnet mgr needs to know the k8s node name that it's running on so it can annotate it.
+	// If we're running as a pod then the POD_NAME and POD_NAMESPACE will be populated and can be used to find the node
+	// name. Otherwise, the environment variable NODE_NAME can be passed in.
+	nodeName := os.Getenv("NODE_NAME")
 	if nodeName == "" {
-		return nil, fmt.Errorf("node name not present in pod spec '%s/%s'", podNamespace, podName)
+		podName := os.Getenv("POD_NAME")
+		podNamespace := os.Getenv("POD_NAMESPACE")
+		if podName == "" || podNamespace == "" {
+			return nil, fmt.Errorf("env variables POD_NAME and POD_NAMESPACE must be set")
+		}
+
+		pod, err := c.Pods(podNamespace).Get(podName, metav1.GetOptions{})
+		if err != nil {
+			return nil, fmt.Errorf("error retrieving pod spec for '%s/%s': %v", podNamespace, podName, err)
+		}
+		nodeName = pod.Spec.NodeName
+		if nodeName == "" {
+			return nil, fmt.Errorf("node name not present in pod spec '%s/%s'", podNamespace, podName)
+		}
 	}
 
 	netConf, err := ioutil.ReadFile(netConfPath)

+ 0 - 0
vendor/google.golang.org/cloud/LICENSE → vendor/cloud.google.com/go/LICENSE


+ 91 - 36
vendor/google.golang.org/cloud/compute/metadata/metadata.go → vendor/cloud.google.com/go/compute/metadata/metadata.go

@@ -17,7 +17,7 @@
 //
 // This package is a wrapper around the GCE metadata service,
 // as documented at https://developers.google.com/compute/docs/metadata.
-package metadata // import "google.golang.org/cloud/compute/metadata"
+package metadata // import "cloud.google.com/go/compute/metadata"
 
 import (
 	"encoding/json"
@@ -27,18 +27,28 @@ import (
 	"net/http"
 	"net/url"
 	"os"
+	"runtime"
 	"strings"
 	"sync"
 	"time"
 
 	"golang.org/x/net/context"
 	"golang.org/x/net/context/ctxhttp"
-
-	"google.golang.org/cloud/internal"
 )
 
-// metadataIP is the documented metadata server IP address.
-const metadataIP = "169.254.169.254"
+const (
+	// metadataIP is the documented metadata server IP address.
+	metadataIP = "169.254.169.254"
+
+	// metadataHostEnv is the environment variable specifying the
+	// GCE metadata hostname.  If empty, the default value of
+	// metadataIP ("169.254.169.254") is used instead.
+	// This is variable name is not defined by any spec, as far as
+	// I know; it was made up for the Go package.
+	metadataHostEnv = "GCE_METADATA_HOST"
+
+	userAgent = "gcloud-golang/0.1"
+)
 
 type cachedValue struct {
 	k    string
@@ -55,24 +65,20 @@ var (
 
 var (
 	metaClient = &http.Client{
-		Transport: &internal.Transport{
-			Base: &http.Transport{
-				Dial: (&net.Dialer{
-					Timeout:   2 * time.Second,
-					KeepAlive: 30 * time.Second,
-				}).Dial,
-				ResponseHeaderTimeout: 2 * time.Second,
-			},
+		Transport: &http.Transport{
+			Dial: (&net.Dialer{
+				Timeout:   2 * time.Second,
+				KeepAlive: 30 * time.Second,
+			}).Dial,
+			ResponseHeaderTimeout: 2 * time.Second,
 		},
 	}
 	subscribeClient = &http.Client{
-		Transport: &internal.Transport{
-			Base: &http.Transport{
-				Dial: (&net.Dialer{
-					Timeout:   2 * time.Second,
-					KeepAlive: 30 * time.Second,
-				}).Dial,
-			},
+		Transport: &http.Transport{
+			Dial: (&net.Dialer{
+				Timeout:   2 * time.Second,
+				KeepAlive: 30 * time.Second,
+			}).Dial,
 		},
 	}
 )
@@ -110,7 +116,7 @@ func getETag(client *http.Client, suffix string) (value, etag string, err error)
 	// deployments. To enable spoofing of the metadata service, the environment
 	// variable GCE_METADATA_HOST is first inspected to decide where metadata
 	// requests shall go.
-	host := os.Getenv("GCE_METADATA_HOST")
+	host := os.Getenv(metadataHostEnv)
 	if host == "" {
 		// Using 169.254.169.254 instead of "metadata" here because Go
 		// binaries built with the "netgo" tag and without cgo won't
@@ -122,6 +128,7 @@ func getETag(client *http.Client, suffix string) (value, etag string, err error)
 	url := "http://" + host + "/computeMetadata/v1/" + suffix
 	req, _ := http.NewRequest("GET", url, nil)
 	req.Header.Set("Metadata-Flavor", "Google")
+	req.Header.Set("User-Agent", userAgent)
 	res, err := client.Do(req)
 	if err != nil {
 		return "", "", err
@@ -163,34 +170,38 @@ func (c *cachedValue) get() (v string, err error) {
 	return
 }
 
-var onGCE struct {
-	sync.Mutex
-	set bool
-	v   bool
-}
+var (
+	onGCEOnce sync.Once
+	onGCE     bool
+)
 
 // OnGCE reports whether this process is running on Google Compute Engine.
 func OnGCE() bool {
-	defer onGCE.Unlock()
-	onGCE.Lock()
-	if onGCE.set {
-		return onGCE.v
-	}
-	onGCE.set = true
-	onGCE.v = testOnGCE()
-	return onGCE.v
+	onGCEOnce.Do(initOnGCE)
+	return onGCE
+}
+
+func initOnGCE() {
+	onGCE = testOnGCE()
 }
 
 func testOnGCE() bool {
+	// The user explicitly said they're on GCE, so trust them.
+	if os.Getenv(metadataHostEnv) != "" {
+		return true
+	}
+
 	ctx, cancel := context.WithCancel(context.Background())
 	defer cancel()
 
 	resc := make(chan bool, 2)
 
 	// Try two strategies in parallel.
-	// See https://github.com/GoogleCloudPlatform/gcloud-golang/issues/194
+	// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
 	go func() {
-		res, err := ctxhttp.Get(ctx, metaClient, "http://"+metadataIP)
+		req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
+		req.Header.Set("User-Agent", userAgent)
+		res, err := ctxhttp.Do(ctx, metaClient, req)
 		if err != nil {
 			resc <- false
 			return
@@ -208,9 +219,53 @@ func testOnGCE() bool {
 		resc <- strsContains(addrs, metadataIP)
 	}()
 
+	tryHarder := systemInfoSuggestsGCE()
+	if tryHarder {
+		res := <-resc
+		if res {
+			// The first strategy succeeded, so let's use it.
+			return true
+		}
+		// Wait for either the DNS or metadata server probe to
+		// contradict the other one and say we are running on
+		// GCE. Give it a lot of time to do so, since the system
+		// info already suggests we're running on a GCE BIOS.
+		timer := time.NewTimer(5 * time.Second)
+		defer timer.Stop()
+		select {
+		case res = <-resc:
+			return res
+		case <-timer.C:
+			// Too slow. Who knows what this system is.
+			return false
+		}
+	}
+
+	// There's no hint from the system info that we're running on
+	// GCE, so use the first probe's result as truth, whether it's
+	// true or false. The goal here is to optimize for speed for
+	// users who are NOT running on GCE. We can't assume that
+	// either a DNS lookup or an HTTP request to a blackholed IP
+	// address is fast. Worst case this should return when the
+	// metaClient's Transport.ResponseHeaderTimeout or
+	// Transport.Dial.Timeout fires (in two seconds).
 	return <-resc
 }
 
+// systemInfoSuggestsGCE reports whether the local system (without
+// doing network requests) suggests that we're running on GCE. If this
+// returns true, testOnGCE tries a bit harder to reach its metadata
+// server.
+func systemInfoSuggestsGCE() bool {
+	if runtime.GOOS != "linux" {
+		// We don't have any non-Linux clues available, at least yet.
+		return false
+	}
+	slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
+	name := strings.TrimSpace(string(slurp))
+	return name == "Google" || name == "Google Compute Engine"
+}
+
 // Subscribe subscribes to a value from the metadata service.
 // The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
 // The suffix may contain query parameters.

+ 0 - 59
vendor/github.com/aws/aws-sdk-go/aws/client/client.go

@@ -2,10 +2,8 @@ package client
 
 import (
 	"fmt"
-	"net/http/httputil"
 
 	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/awserr"
 	"github.com/aws/aws-sdk-go/aws/client/metadata"
 	"github.com/aws/aws-sdk-go/aws/request"
 )
@@ -90,60 +88,3 @@ func (c *Client) AddDebugHandlers() {
 	c.Handlers.Send.PushFrontNamed(request.NamedHandler{Name: "awssdk.client.LogRequest", Fn: logRequest})
 	c.Handlers.Send.PushBackNamed(request.NamedHandler{Name: "awssdk.client.LogResponse", Fn: logResponse})
 }
-
-const logReqMsg = `DEBUG: Request %s/%s Details:
----[ REQUEST POST-SIGN ]-----------------------------
-%s
------------------------------------------------------`
-
-const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
----[ REQUEST DUMP ERROR ]-----------------------------
-%s
------------------------------------------------------`
-
-func logRequest(r *request.Request) {
-	logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
-	dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
-	if err != nil {
-		r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
-		r.Error = awserr.New(request.ErrCodeRead, "an error occurred during request body reading", err)
-		return
-	}
-
-	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.ResetBody()
-	}
-
-	r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
-}
-
-const logRespMsg = `DEBUG: Response %s/%s Details:
----[ RESPONSE ]--------------------------------------
-%s
------------------------------------------------------`
-
-const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
----[ RESPONSE DUMP ERROR ]-----------------------------
-%s
------------------------------------------------------`
-
-func logResponse(r *request.Request) {
-	var msg = "no response data"
-	if r.HTTPResponse != nil {
-		logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
-		dumpedBody, err := httputil.DumpResponse(r.HTTPResponse, logBody)
-		if err != nil {
-			r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
-			r.Error = awserr.New(request.ErrCodeRead, "an error occurred during response body reading", err)
-			return
-		}
-
-		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))
-}

+ 108 - 0
vendor/github.com/aws/aws-sdk-go/aws/client/logger.go

@@ -0,0 +1,108 @@
+package client
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http/httputil"
+
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/aws/aws-sdk-go/aws/request"
+)
+
+const logReqMsg = `DEBUG: Request %s/%s Details:
+---[ REQUEST POST-SIGN ]-----------------------------
+%s
+-----------------------------------------------------`
+
+const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
+---[ REQUEST DUMP ERROR ]-----------------------------
+%s
+------------------------------------------------------`
+
+type logWriter struct {
+	// Logger is what we will use to log the payload of a response.
+	Logger aws.Logger
+	// buf stores the contents of what has been read
+	buf *bytes.Buffer
+}
+
+func (logger *logWriter) Write(b []byte) (int, error) {
+	return logger.buf.Write(b)
+}
+
+type teeReaderCloser struct {
+	// io.Reader will be a tee reader that is used during logging.
+	// This structure will read from a body and write the contents to a logger.
+	io.Reader
+	// Source is used just to close when we are done reading.
+	Source io.ReadCloser
+}
+
+func (reader *teeReaderCloser) Close() error {
+	return reader.Source.Close()
+}
+
+func logRequest(r *request.Request) {
+	logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
+	dumpedBody, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
+	if err != nil {
+		r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg, r.ClientInfo.ServiceName, r.Operation.Name, err))
+		return
+	}
+
+	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.ResetBody()
+	}
+
+	r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
+}
+
+const logRespMsg = `DEBUG: Response %s/%s Details:
+---[ RESPONSE ]--------------------------------------
+%s
+-----------------------------------------------------`
+
+const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
+---[ RESPONSE DUMP ERROR ]-----------------------------
+%s
+-----------------------------------------------------`
+
+func logResponse(r *request.Request) {
+	lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)}
+	r.HTTPResponse.Body = &teeReaderCloser{
+		Reader: io.TeeReader(r.HTTPResponse.Body, lw),
+		Source: r.HTTPResponse.Body,
+	}
+
+	handlerFn := func(req *request.Request) {
+		body, err := httputil.DumpResponse(req.HTTPResponse, false)
+		if err != nil {
+			lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
+			return
+		}
+
+		b, err := ioutil.ReadAll(lw.buf)
+		if err != nil {
+			lw.Logger.Log(fmt.Sprintf(logRespErrMsg, req.ClientInfo.ServiceName, req.Operation.Name, err))
+			return
+		}
+		lw.Logger.Log(fmt.Sprintf(logRespMsg, req.ClientInfo.ServiceName, req.Operation.Name, string(body)))
+		if req.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) {
+			lw.Logger.Log(string(b))
+		}
+	}
+
+	const handlerName = "awsdk.client.LogResponse.ResponseBody"
+
+	r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{
+		Name: handlerName, Fn: handlerFn,
+	})
+	r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{
+		Name: handlerName, Fn: handlerFn,
+	})
+}

+ 84 - 43
vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go

@@ -27,7 +27,7 @@ type lener interface {
 // 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.
 //
-// The Content-Length will only be aded to the request if the length of the body
+// The Content-Length will only be added to the request if the length of the body
 // is greater than 0. If the body is empty or the current `Content-Length`
 // header is <= 0, the header will also be stripped.
 var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) {
@@ -71,8 +71,8 @@ var reStatusCode = regexp.MustCompile(`^(\d{3})`)
 
 // ValidateReqSigHandler is a request handler to ensure that the request's
 // signature doesn't expire before it is sent. This can happen when a request
-// is built and signed signficantly before it is sent. Or significant delays
-// occur whne retrying requests that would cause the signature to expire.
+// is built and signed significantly before it is sent. Or significant delays
+// occur when retrying requests that would cause the signature to expire.
 var ValidateReqSigHandler = request.NamedHandler{
 	Name: "core.ValidateReqSigHandler",
 	Fn: func(r *request.Request) {
@@ -98,54 +98,95 @@ var ValidateReqSigHandler = request.NamedHandler{
 }
 
 // SendHandler is a request handler to send service request using HTTP client.
-var SendHandler = request.NamedHandler{Name: "core.SendHandler", Fn: func(r *request.Request) {
-	var err error
-	r.HTTPResponse, err = r.Config.HTTPClient.Do(r.HTTPRequest)
-	if err != nil {
-		// Prevent leaking if an HTTPResponse was returned. Clean up
-		// the body.
-		if r.HTTPResponse != nil {
-			r.HTTPResponse.Body.Close()
+var SendHandler = request.NamedHandler{
+	Name: "core.SendHandler",
+	Fn: func(r *request.Request) {
+		sender := sendFollowRedirects
+		if r.DisableFollowRedirects {
+			sender = sendWithoutFollowRedirects
 		}
-		// Capture the case where url.Error is returned for error processing
-		// response. e.g. 301 without location header comes back as string
-		// error and r.HTTPResponse is nil. Other url redirect errors will
-		// comeback in a similar method.
-		if e, ok := err.(*url.Error); ok && e.Err != nil {
-			if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil {
-				code, _ := strconv.ParseInt(s[1], 10, 64)
-				r.HTTPResponse = &http.Response{
-					StatusCode: int(code),
-					Status:     http.StatusText(int(code)),
-					Body:       ioutil.NopCloser(bytes.NewReader([]byte{})),
-				}
-				return
-			}
+
+		if request.NoBody == r.HTTPRequest.Body {
+			// Strip off the request body if the NoBody reader was used as a
+			// place holder for a request body. This prevents the SDK from
+			// making requests with a request body when it would be invalid
+			// to do so.
+			//
+			// Use a shallow copy of the http.Request to ensure the race condition
+			// of transport on Body will not trigger
+			reqOrig, reqCopy := r.HTTPRequest, *r.HTTPRequest
+			reqCopy.Body = nil
+			r.HTTPRequest = &reqCopy
+			defer func() {
+				r.HTTPRequest = reqOrig
+			}()
 		}
-		if r.HTTPResponse == nil {
-			// Add a dummy request response object to ensure the HTTPResponse
-			// value is consistent.
+
+		var err error
+		r.HTTPResponse, err = sender(r)
+		if err != nil {
+			handleSendError(r, err)
+		}
+	},
+}
+
+func sendFollowRedirects(r *request.Request) (*http.Response, error) {
+	return r.Config.HTTPClient.Do(r.HTTPRequest)
+}
+
+func sendWithoutFollowRedirects(r *request.Request) (*http.Response, error) {
+	transport := r.Config.HTTPClient.Transport
+	if transport == nil {
+		transport = http.DefaultTransport
+	}
+
+	return transport.RoundTrip(r.HTTPRequest)
+}
+
+func handleSendError(r *request.Request, err error) {
+	// Prevent leaking if an HTTPResponse was returned. Clean up
+	// the body.
+	if r.HTTPResponse != nil {
+		r.HTTPResponse.Body.Close()
+	}
+	// Capture the case where url.Error is returned for error processing
+	// response. e.g. 301 without location header comes back as string
+	// error and r.HTTPResponse is nil. Other URL redirect errors will
+	// comeback in a similar method.
+	if e, ok := err.(*url.Error); ok && e.Err != nil {
+		if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil {
+			code, _ := strconv.ParseInt(s[1], 10, 64)
 			r.HTTPResponse = &http.Response{
-				StatusCode: int(0),
-				Status:     http.StatusText(int(0)),
+				StatusCode: int(code),
+				Status:     http.StatusText(int(code)),
 				Body:       ioutil.NopCloser(bytes.NewReader([]byte{})),
 			}
+			return
 		}
-		// Catch all other request errors.
-		r.Error = awserr.New("RequestError", "send request failed", err)
-		r.Retryable = aws.Bool(true) // network errors are retryable
-
-		// Override the error with a context canceled error, if that was canceled.
-		ctx := r.Context()
-		select {
-		case <-ctx.Done():
-			r.Error = awserr.New(request.CanceledErrorCode,
-				"request context canceled", ctx.Err())
-			r.Retryable = aws.Bool(false)
-		default:
+	}
+	if r.HTTPResponse == nil {
+		// Add a dummy request response object to ensure the HTTPResponse
+		// value is consistent.
+		r.HTTPResponse = &http.Response{
+			StatusCode: int(0),
+			Status:     http.StatusText(int(0)),
+			Body:       ioutil.NopCloser(bytes.NewReader([]byte{})),
 		}
 	}
-}}
+	// Catch all other request errors.
+	r.Error = awserr.New("RequestError", "send request failed", err)
+	r.Retryable = aws.Bool(true) // network errors are retryable
+
+	// Override the error with a context canceled error, if that was canceled.
+	ctx := r.Context()
+	select {
+	case <-ctx.Done():
+		r.Error = awserr.New(request.CanceledErrorCode,
+			"request context canceled", ctx.Err())
+		r.Retryable = aws.Bool(false)
+	default:
+	}
+}
 
 // ValidateResponseHandler is a request handler to validate service response.
 var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) {

+ 8 - 6
vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go

@@ -13,7 +13,7 @@ var (
 	//
 	// @readonly
 	ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders",
-		`no valid providers in chain. Deprecated. 
+		`no valid providers in chain. Deprecated.
 	For verbose messaging see aws.Config.CredentialsChainVerboseErrors`,
 		nil)
 )
@@ -39,16 +39,18 @@ var (
 // does not return any credentials ChainProvider will return the error
 // ErrNoValidProvidersFoundInChain
 //
-//     creds := NewChainCredentials(
-//         []Provider{
-//             &EnvProvider{},
-//             &EC2RoleProvider{
+//     creds := credentials.NewChainCredentials(
+//         []credentials.Provider{
+//             &credentials.EnvProvider{},
+//             &ec2rolecreds.EC2RoleProvider{
 //                 Client: ec2metadata.New(sess),
 //             },
 //         })
 //
 //     // Usage of ChainCredentials with aws.Config
-//     svc := ec2.New(&aws.Config{Credentials: creds})
+//     svc := ec2.New(session.Must(session.NewSession(&aws.Config{
+//       Credentials: creds,
+//     })))
 //
 type ChainProvider struct {
 	Providers     []Provider

+ 6 - 4
vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go

@@ -14,7 +14,7 @@
 //
 // Example of using the environment variable credentials.
 //
-//     creds := NewEnvCredentials()
+//     creds := credentials.NewEnvCredentials()
 //
 //     // Retrieve the credentials value
 //     credValue, err := creds.Get()
@@ -26,7 +26,7 @@
 // This may be helpful to proactively expire credentials and refresh them sooner
 // than they would naturally expire on their own.
 //
-//     creds := NewCredentials(&EC2RoleProvider{})
+//     creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{})
 //     creds.Expire()
 //     credsValue, err := creds.Get()
 //     // New credentials will be retrieved instead of from cache.
@@ -43,7 +43,7 @@
 //     func (m *MyProvider) Retrieve() (Value, error) {...}
 //     func (m *MyProvider) IsExpired() bool {...}
 //
-//     creds := NewCredentials(&MyProvider{})
+//     creds := credentials.NewCredentials(&MyProvider{})
 //     credValue, err := creds.Get()
 //
 package credentials
@@ -60,7 +60,9 @@ import (
 // when making service API calls. For example, when accessing public
 // s3 buckets.
 //
-//     svc := s3.New(&aws.Config{Credentials: AnonymousCredentials})
+//     svc := s3.New(session.Must(session.NewSession(&aws.Config{
+//       Credentials: credentials.AnonymousCredentials,
+//     })))
 //     // Access public S3 buckets.
 //
 // @readonly

+ 1 - 0
vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go

@@ -29,6 +29,7 @@ var (
 // Environment variables used:
 //
 // * Access Key ID:     AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
+//
 // * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
 type EnvProvider struct {
 	retrieved bool

+ 16 - 17
vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go

@@ -3,11 +3,11 @@ package credentials
 import (
 	"fmt"
 	"os"
-	"path/filepath"
 
 	"github.com/go-ini/ini"
 
 	"github.com/aws/aws-sdk-go/aws/awserr"
+	"github.com/aws/aws-sdk-go/internal/shareddefaults"
 )
 
 // SharedCredsProviderName provides a name of SharedCreds provider
@@ -15,8 +15,6 @@ const SharedCredsProviderName = "SharedCredentialsProvider"
 
 var (
 	// ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found.
-	//
-	// @readonly
 	ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil)
 )
 
@@ -117,22 +115,23 @@ func loadProfile(filename, profile string) (Value, error) {
 //
 // Will return an error if the user's home directory path cannot be found.
 func (p *SharedCredentialsProvider) filename() (string, error) {
-	if p.Filename == "" {
-		if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" {
-			return p.Filename, nil
-		}
-
-		homeDir := os.Getenv("HOME") // *nix
-		if homeDir == "" {           // Windows
-			homeDir = os.Getenv("USERPROFILE")
-		}
-		if homeDir == "" {
-			return "", ErrSharedCredentialsHomeNotFound
-		}
-
-		p.Filename = filepath.Join(homeDir, ".aws", "credentials")
+	if len(p.Filename) != 0 {
+		return p.Filename, nil
+	}
+
+	if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(p.Filename) != 0 {
+		return p.Filename, nil
 	}
 
+	if home := shareddefaults.UserHomeDir(); len(home) == 0 {
+		// Backwards compatibility of home directly not found error being returned.
+		// This error is too verbose, failure when opening the file would of been
+		// a better error to return.
+		return "", ErrSharedCredentialsHomeNotFound
+	}
+
+	p.Filename = shareddefaults.SharedCredentialsFilename()
+
 	return p.Filename, nil
 }
 

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go

@@ -12,7 +12,7 @@ between multiple Credentials, Sessions or service clients.
 Assume Role
 
 To assume an IAM role using STS with the SDK you can create a new Credentials
-with the SDKs's stscreds package. 
+with the SDKs's stscreds package.
 
 	// Initial credentials loaded from SDK's default credential chain. Such as
 	// the environment, shared credentials (~/.aws/credentials), or EC2 Instance

+ 27 - 0
vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go

@@ -0,0 +1,27 @@
+package defaults
+
+import (
+	"github.com/aws/aws-sdk-go/internal/shareddefaults"
+)
+
+// SharedCredentialsFilename returns the SDK's default file path
+// for the shared credentials file.
+//
+// Builds the shared config file path based on the OS's platform.
+//
+//   - Linux/Unix: $HOME/.aws/credentials
+//   - Windows: %USERPROFILE%\.aws\credentials
+func SharedCredentialsFilename() string {
+	return shareddefaults.SharedCredentialsFilename()
+}
+
+// SharedConfigFilename returns the SDK's default file path for
+// the shared config file.
+//
+// Builds the shared config file path based on the OS's platform.
+//
+//   - Linux/Unix: $HOME/.aws/config
+//   - Windows: %USERPROFILE%\.aws\config
+func SharedConfigFilename() string {
+	return shareddefaults.SharedConfigFilename()
+}

+ 56 - 0
vendor/github.com/aws/aws-sdk-go/aws/doc.go

@@ -0,0 +1,56 @@
+// Package aws provides the core SDK's utilities and shared types. Use this package's
+// utilities to simplify setting and reading API operations parameters.
+//
+// Value and Pointer Conversion Utilities
+//
+// This package includes a helper conversion utility for each scalar type the SDK's
+// API use. These utilities make getting a pointer of the scalar, and dereferencing
+// a pointer easier.
+//
+// Each conversion utility comes in two forms. Value to Pointer and Pointer to Value.
+// The Pointer to value will safely dereference the pointer and return its value.
+// If the pointer was nil, the scalar's zero value will be returned.
+//
+// The value to pointer functions will be named after the scalar type. So get a
+// *string from a string value use the "String" function. This makes it easy to
+// to get pointer of a literal string value, because getting the address of a
+// literal requires assigning the value to a variable first.
+//
+//    var strPtr *string
+//
+//    // Without the SDK's conversion functions
+//    str := "my string"
+//    strPtr = &str
+//
+//    // With the SDK's conversion functions
+//    strPtr = aws.String("my string")
+//
+//    // Convert *string to string value
+//    str = aws.StringValue(strPtr)
+//
+// In addition to scalars the aws package also includes conversion utilities for
+// map and slice for commonly types used in API parameters. The map and slice
+// conversion functions use similar naming pattern as the scalar conversion
+// functions.
+//
+//    var strPtrs []*string
+//    var strs []string = []string{"Go", "Gophers", "Go"}
+//
+//    // Convert []string to []*string
+//    strPtrs = aws.StringSlice(strs)
+//
+//    // Convert []*string to []string
+//    strs = aws.StringValueSlice(strPtrs)
+//
+// SDK Default HTTP Client
+//
+// The SDK will use the http.DefaultClient if a HTTP client is not provided to
+// the SDK's Session, or service client constructor. This means that if the
+// http.DefaultClient is modified by other components of your application the
+// modifications will be picked up by the SDK as well.
+//
+// In some cases this might be intended, but it is a better practice to create
+// a custom HTTP Client to share explicitly through your application. You can
+// configure the SDK to use the custom HTTP Client by setting the HTTPClient
+// value of the SDK's Config type when creating a Session or service client.
+package aws

+ 162 - 18
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go

@@ -47,6 +47,7 @@ const (
 	ApigatewayServiceID                   = "apigateway"                   // Apigateway.
 	ApplicationAutoscalingServiceID       = "application-autoscaling"      // ApplicationAutoscaling.
 	Appstream2ServiceID                   = "appstream2"                   // Appstream2.
+	AthenaServiceID                       = "athena"                       // Athena.
 	AutoscalingServiceID                  = "autoscaling"                  // Autoscaling.
 	BatchServiceID                        = "batch"                        // Batch.
 	BudgetsServiceID                      = "budgets"                      // Budgets.
@@ -60,6 +61,7 @@ const (
 	CodecommitServiceID                   = "codecommit"                   // Codecommit.
 	CodedeployServiceID                   = "codedeploy"                   // Codedeploy.
 	CodepipelineServiceID                 = "codepipeline"                 // Codepipeline.
+	CodestarServiceID                     = "codestar"                     // Codestar.
 	CognitoIdentityServiceID              = "cognito-identity"             // CognitoIdentity.
 	CognitoIdpServiceID                   = "cognito-idp"                  // CognitoIdp.
 	CognitoSyncServiceID                  = "cognito-sync"                 // CognitoSync.
@@ -83,11 +85,13 @@ const (
 	ElasticmapreduceServiceID             = "elasticmapreduce"             // Elasticmapreduce.
 	ElastictranscoderServiceID            = "elastictranscoder"            // Elastictranscoder.
 	EmailServiceID                        = "email"                        // Email.
+	EntitlementMarketplaceServiceID       = "entitlement.marketplace"      // EntitlementMarketplace.
 	EsServiceID                           = "es"                           // Es.
 	EventsServiceID                       = "events"                       // Events.
 	FirehoseServiceID                     = "firehose"                     // Firehose.
 	GameliftServiceID                     = "gamelift"                     // Gamelift.
 	GlacierServiceID                      = "glacier"                      // Glacier.
+	GreengrassServiceID                   = "greengrass"                   // Greengrass.
 	HealthServiceID                       = "health"                       // Health.
 	IamServiceID                          = "iam"                          // Iam.
 	ImportexportServiceID                 = "importexport"                 // Importexport.
@@ -103,6 +107,7 @@ const (
 	MarketplacecommerceanalyticsServiceID = "marketplacecommerceanalytics" // Marketplacecommerceanalytics.
 	MeteringMarketplaceServiceID          = "metering.marketplace"         // MeteringMarketplace.
 	MobileanalyticsServiceID              = "mobileanalytics"              // Mobileanalytics.
+	ModelsLexServiceID                    = "models.lex"                   // ModelsLex.
 	MonitoringServiceID                   = "monitoring"                   // Monitoring.
 	MturkRequesterServiceID               = "mturk-requester"              // MturkRequester.
 	OpsworksServiceID                     = "opsworks"                     // Opsworks.
@@ -142,17 +147,20 @@ const (
 // DefaultResolver returns an Endpoint resolver that will be able
 // to resolve endpoints for: AWS Standard, AWS China, and AWS GovCloud (US).
 //
-// Casting the return value of this func to a EnumPartitions will
-// allow you to get a list of the partitions in the order the endpoints
-// will be resolved in.
+// Use DefaultPartitions() to get the list of the default partitions.
+func DefaultResolver() Resolver {
+	return defaultPartitions
+}
+
+// DefaultPartitions returns a list of the partitions the SDK is bundled
+// with. The available partitions are: AWS Standard, AWS China, and AWS GovCloud (US).
 //
-//    resolver := endpoints.DefaultResolver()
-//    partitions := resolver.(endpoints.EnumPartitions).Partitions()
+//    partitions := endpoints.DefaultPartitions
 //    for _, p := range partitions {
 //        // ... inspect partitions
 //    }
-func DefaultResolver() Resolver {
-	return defaultPartitions
+func DefaultPartitions() []Partition {
+	return defaultPartitions.Partitions()
 }
 
 var defaultPartitions = partitions{
@@ -256,6 +264,7 @@ var awsPartition = partition{
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
 				"eu-west-2":      endpoint{},
+				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
 				"us-west-1":      endpoint{},
@@ -301,6 +310,14 @@ var awsPartition = partition{
 				"us-west-2":      endpoint{},
 			},
 		},
+		"athena": service{
+
+			Endpoints: endpoints{
+				"us-east-1": endpoint{},
+				"us-east-2": endpoint{},
+				"us-west-2": endpoint{},
+			},
+		},
 		"autoscaling": service{
 			Defaults: endpoint{
 				Protocols: []string{"http", "https"},
@@ -325,7 +342,10 @@ var awsPartition = partition{
 		"batch": service{
 
 			Endpoints: endpoints{
-				"us-east-1": endpoint{},
+				"ap-northeast-1": endpoint{},
+				"eu-west-1":      endpoint{},
+				"us-east-1":      endpoint{},
+				"us-west-2":      endpoint{},
 			},
 		},
 		"budgets": service{
@@ -347,6 +367,7 @@ var awsPartition = partition{
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
 				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
 				"us-west-2":      endpoint{},
@@ -450,10 +471,18 @@ var awsPartition = partition{
 		"codecommit": service{
 
 			Endpoints: endpoints{
-				"eu-west-1": endpoint{},
-				"us-east-1": endpoint{},
-				"us-east-2": endpoint{},
-				"us-west-2": endpoint{},
+				"ap-northeast-1": endpoint{},
+				"ap-northeast-2": endpoint{},
+				"ap-southeast-1": endpoint{},
+				"ap-southeast-2": endpoint{},
+				"eu-central-1":   endpoint{},
+				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
+				"sa-east-1":      endpoint{},
+				"us-east-1":      endpoint{},
+				"us-east-2":      endpoint{},
+				"us-west-1":      endpoint{},
+				"us-west-2":      endpoint{},
 			},
 		},
 		"codedeploy": service{
@@ -489,11 +518,21 @@ var awsPartition = partition{
 				"us-west-2":      endpoint{},
 			},
 		},
+		"codestar": service{
+
+			Endpoints: endpoints{
+				"eu-west-1": endpoint{},
+				"us-east-1": endpoint{},
+				"us-east-2": endpoint{},
+				"us-west-2": endpoint{},
+			},
+		},
 		"cognito-identity": service{
 
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
 				"ap-northeast-2": endpoint{},
+				"ap-south-1":     endpoint{},
 				"ap-southeast-2": endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
@@ -508,6 +547,7 @@ var awsPartition = partition{
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
 				"ap-northeast-2": endpoint{},
+				"ap-south-1":     endpoint{},
 				"ap-southeast-2": endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
@@ -522,6 +562,7 @@ var awsPartition = partition{
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
 				"ap-northeast-2": endpoint{},
+				"ap-south-1":     endpoint{},
 				"ap-southeast-2": endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
@@ -620,11 +661,15 @@ var awsPartition = partition{
 
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
+				"ap-northeast-2": endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
+				"ca-central-1":   endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
 				"us-east-1":      endpoint{},
+				"us-east-2":      endpoint{},
 				"us-west-2":      endpoint{},
 			},
 		},
@@ -836,6 +881,16 @@ var awsPartition = partition{
 				"us-west-2": endpoint{},
 			},
 		},
+		"entitlement.marketplace": service{
+			Defaults: endpoint{
+				CredentialScope: credentialScope{
+					Service: "aws-marketplace",
+				},
+			},
+			Endpoints: endpoints{
+				"us-east-1": endpoint{},
+			},
+		},
 		"es": service{
 
 			Endpoints: endpoints{
@@ -844,8 +899,10 @@ var awsPartition = partition{
 				"ap-south-1":     endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
+				"ca-central-1":   endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
 				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
@@ -913,6 +970,16 @@ var awsPartition = partition{
 				"us-west-2":      endpoint{},
 			},
 		},
+		"greengrass": service{
+			IsRegionalized: boxedTrue,
+			Defaults: endpoint{
+				Protocols: []string{"https"},
+			},
+			Endpoints: endpoints{
+				"us-east-1": endpoint{},
+				"us-west-2": endpoint{},
+			},
+		},
 		"health": service{
 
 			Endpoints: endpoints{
@@ -956,6 +1023,7 @@ var awsPartition = partition{
 				"ap-southeast-2": endpoint{},
 				"eu-west-1":      endpoint{},
 				"us-east-1":      endpoint{},
+				"us-west-1":      endpoint{},
 				"us-west-2":      endpoint{},
 			},
 		},
@@ -1032,9 +1100,11 @@ var awsPartition = partition{
 				"ap-south-1":     endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
+				"ca-central-1":   endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
 				"eu-west-2":      endpoint{},
+				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
 				"us-west-1":      endpoint{},
@@ -1044,7 +1114,16 @@ var awsPartition = partition{
 		"lightsail": service{
 
 			Endpoints: endpoints{
-				"us-east-1": endpoint{},
+				"ap-northeast-1": endpoint{},
+				"ap-south-1":     endpoint{},
+				"ap-southeast-1": endpoint{},
+				"ap-southeast-2": endpoint{},
+				"eu-central-1":   endpoint{},
+				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
+				"us-east-1":      endpoint{},
+				"us-east-2":      endpoint{},
+				"us-west-2":      endpoint{},
 			},
 		},
 		"logs": service{
@@ -1108,6 +1187,16 @@ var awsPartition = partition{
 				"us-east-1": endpoint{},
 			},
 		},
+		"models.lex": service{
+			Defaults: endpoint{
+				CredentialScope: credentialScope{
+					Service: "lex",
+				},
+			},
+			Endpoints: endpoints{
+				"us-east-1": endpoint{},
+			},
+		},
 		"monitoring": service{
 			Defaults: endpoint{
 				Protocols: []string{"http", "https"},
@@ -1447,10 +1536,13 @@ var awsPartition = partition{
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
 				"ap-northeast-2": endpoint{},
+				"ap-south-1":     endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
+				"ca-central-1":   endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
 				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
@@ -1462,6 +1554,7 @@ var awsPartition = partition{
 
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
+				"ap-southeast-2": endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
 				"us-east-1":      endpoint{},
@@ -1474,6 +1567,7 @@ var awsPartition = partition{
 			Endpoints: endpoints{
 				"ap-northeast-1": endpoint{},
 				"ap-northeast-2": endpoint{},
+				"ap-south-1":     endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
 				"ca-central-1":   endpoint{},
@@ -1489,7 +1583,7 @@ var awsPartition = partition{
 		},
 		"streams.dynamodb": service{
 			Defaults: endpoint{
-				Protocols: []string{"http", "http", "https", "https"},
+				Protocols: []string{"http", "https"},
 				CredentialScope: credentialScope{
 					Service: "dynamodb",
 				},
@@ -1544,9 +1638,33 @@ var awsPartition = partition{
 				"eu-west-2":      endpoint{},
 				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
-				"us-east-2":      endpoint{},
-				"us-west-1":      endpoint{},
-				"us-west-2":      endpoint{},
+				"us-east-1-fips": endpoint{
+					Hostname: "sts-fips.us-east-1.amazonaws.com",
+					CredentialScope: credentialScope{
+						Region: "us-east-1",
+					},
+				},
+				"us-east-2": endpoint{},
+				"us-east-2-fips": endpoint{
+					Hostname: "sts-fips.us-east-2.amazonaws.com",
+					CredentialScope: credentialScope{
+						Region: "us-east-2",
+					},
+				},
+				"us-west-1": endpoint{},
+				"us-west-1-fips": endpoint{
+					Hostname: "sts-fips.us-west-1.amazonaws.com",
+					CredentialScope: credentialScope{
+						Region: "us-west-1",
+					},
+				},
+				"us-west-2": endpoint{},
+				"us-west-2-fips": endpoint{
+					Hostname: "sts-fips.us-west-2.amazonaws.com",
+					CredentialScope: credentialScope{
+						Region: "us-west-2",
+					},
+				},
 			},
 		},
 		"support": service{
@@ -1646,8 +1764,10 @@ var awsPartition = partition{
 				"ap-south-1":     endpoint{},
 				"ap-southeast-1": endpoint{},
 				"ap-southeast-2": endpoint{},
+				"ca-central-1":   endpoint{},
 				"eu-central-1":   endpoint{},
 				"eu-west-1":      endpoint{},
+				"eu-west-2":      endpoint{},
 				"sa-east-1":      endpoint{},
 				"us-east-1":      endpoint{},
 				"us-east-2":      endpoint{},
@@ -1870,7 +1990,7 @@ var awscnPartition = partition{
 		},
 		"streams.dynamodb": service{
 			Defaults: endpoint{
-				Protocols: []string{"http", "http", "https", "https"},
+				Protocols: []string{"http", "https"},
 				CredentialScope: credentialScope{
 					Service: "dynamodb",
 				},
@@ -1952,6 +2072,12 @@ var awsusgovPartition = partition{
 				"us-gov-west-1": endpoint{},
 			},
 		},
+		"codedeploy": service{
+
+			Endpoints: endpoints{
+				"us-gov-west-1": endpoint{},
+			},
+		},
 		"config": service{
 
 			Endpoints: endpoints{
@@ -2009,6 +2135,12 @@ var awsusgovPartition = partition{
 				},
 			},
 		},
+		"events": service{
+
+			Endpoints: endpoints{
+				"us-gov-west-1": endpoint{},
+			},
+		},
 		"glacier": service{
 
 			Endpoints: endpoints{
@@ -2042,6 +2174,12 @@ var awsusgovPartition = partition{
 				"us-gov-west-1": endpoint{},
 			},
 		},
+		"lambda": service{
+
+			Endpoints: endpoints{
+				"us-gov-west-1": endpoint{},
+			},
+		},
 		"logs": service{
 
 			Endpoints: endpoints{
@@ -2066,6 +2204,12 @@ var awsusgovPartition = partition{
 				"us-gov-west-1": endpoint{},
 			},
 		},
+		"rekognition": service{
+
+			Endpoints: endpoints{
+				"us-gov-west-1": endpoint{},
+			},
+		},
 		"s3": service{
 			Defaults: endpoint{
 				SignatureVersions: []string{"s3", "s3v4"},

+ 77 - 35
vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go

@@ -124,6 +124,49 @@ type EnumPartitions interface {
 	Partitions() []Partition
 }
 
+// RegionsForService returns a map of regions for the partition and service.
+// If either the partition or service does not exist false will be returned
+// as the second parameter.
+//
+// This example shows how  to get the regions for DynamoDB in the AWS partition.
+//    rs, exists := endpoints.RegionsForService(endpoints.DefaultPartitions(), endpoints.AwsPartitionID, endpoints.DynamodbServiceID)
+//
+// This is equivalent to using the partition directly.
+//    rs := endpoints.AwsPartition().Services()[endpoints.DynamodbServiceID].Regions()
+func RegionsForService(ps []Partition, partitionID, serviceID string) (map[string]Region, bool) {
+	for _, p := range ps {
+		if p.ID() != partitionID {
+			continue
+		}
+		if _, ok := p.p.Services[serviceID]; !ok {
+			break
+		}
+
+		s := Service{
+			id: serviceID,
+			p:  p.p,
+		}
+		return s.Regions(), true
+	}
+
+	return map[string]Region{}, false
+}
+
+// PartitionForRegion returns the first partition which includes the region
+// passed in. This includes both known regions and regions which match
+// a pattern supported by the partition which may include regions that are
+// not explicitly known by the partition. Use the Regions method of the
+// returned Partition if explicit support is needed.
+func PartitionForRegion(ps []Partition, regionID string) (Partition, bool) {
+	for _, p := range ps {
+		if _, ok := p.p.Regions[regionID]; ok || p.p.RegionRegex.MatchString(regionID) {
+			return p, true
+		}
+	}
+
+	return Partition{}, false
+}
+
 // A Partition provides the ability to enumerate the partition's regions
 // and services.
 type Partition struct {
@@ -132,7 +175,7 @@ type Partition struct {
 }
 
 // ID returns the identifier of the partition.
-func (p *Partition) ID() string { return p.id }
+func (p Partition) ID() string { return p.id }
 
 // EndpointFor attempts to resolve the endpoint based on service and region.
 // See Options for information on configuring how the endpoint is resolved.
@@ -155,13 +198,13 @@ func (p *Partition) ID() string { return p.id }
 // Errors that can be returned.
 //   * UnknownServiceError
 //   * UnknownEndpointError
-func (p *Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
+func (p Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 	return p.p.EndpointFor(service, region, opts...)
 }
 
 // Regions returns a map of Regions indexed by their ID. This is useful for
 // enumerating over the regions in a partition.
-func (p *Partition) Regions() map[string]Region {
+func (p Partition) Regions() map[string]Region {
 	rs := map[string]Region{}
 	for id := range p.p.Regions {
 		rs[id] = Region{
@@ -175,7 +218,7 @@ func (p *Partition) Regions() map[string]Region {
 
 // Services returns a map of Service indexed by their ID. This is useful for
 // enumerating over the services in a partition.
-func (p *Partition) Services() map[string]Service {
+func (p Partition) Services() map[string]Service {
 	ss := map[string]Service{}
 	for id := range p.p.Services {
 		ss[id] = Service{
@@ -195,16 +238,16 @@ type Region struct {
 }
 
 // ID returns the region's identifier.
-func (r *Region) ID() string { return r.id }
+func (r Region) ID() string { return r.id }
 
 // ResolveEndpoint resolves an endpoint from the context of the region given
 // a service. See Partition.EndpointFor for usage and errors that can be returned.
-func (r *Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
+func (r Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 	return r.p.EndpointFor(service, r.id, opts...)
 }
 
 // Services returns a list of all services that are known to be in this region.
-func (r *Region) Services() map[string]Service {
+func (r Region) Services() map[string]Service {
 	ss := map[string]Service{}
 	for id, s := range r.p.Services {
 		if _, ok := s.Endpoints[r.id]; ok {
@@ -226,17 +269,38 @@ type Service struct {
 }
 
 // ID returns the identifier for the service.
-func (s *Service) ID() string { return s.id }
+func (s Service) ID() string { return s.id }
 
 // ResolveEndpoint resolves an endpoint from the context of a service given
 // a region. See Partition.EndpointFor for usage and errors that can be returned.
-func (s *Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
+func (s Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
 	return s.p.EndpointFor(s.id, region, opts...)
 }
 
+// Regions returns a map of Regions that the service is present in.
+//
+// A region is the AWS region the service exists in. Whereas a Endpoint is
+// an URL that can be resolved to a instance of a service.
+func (s Service) Regions() map[string]Region {
+	rs := map[string]Region{}
+	for id := range s.p.Services[s.id].Endpoints {
+		if _, ok := s.p.Regions[id]; ok {
+			rs[id] = Region{
+				id: id,
+				p:  s.p,
+			}
+		}
+	}
+
+	return rs
+}
+
 // Endpoints returns a map of Endpoints indexed by their ID for all known
 // endpoints for a service.
-func (s *Service) Endpoints() map[string]Endpoint {
+//
+// A region is the AWS region the service exists in. Whereas a Endpoint is
+// an URL that can be resolved to a instance of a service.
+func (s Service) Endpoints() map[string]Endpoint {
 	es := map[string]Endpoint{}
 	for id := range s.p.Services[s.id].Endpoints {
 		es[id] = Endpoint{
@@ -259,15 +323,15 @@ type Endpoint struct {
 }
 
 // ID returns the identifier for an endpoint.
-func (e *Endpoint) ID() string { return e.id }
+func (e Endpoint) ID() string { return e.id }
 
 // ServiceID returns the identifier the endpoint belongs to.
-func (e *Endpoint) ServiceID() string { return e.serviceID }
+func (e Endpoint) ServiceID() string { return e.serviceID }
 
 // ResolveEndpoint resolves an endpoint from the context of a service and
 // region the endpoint represents. See Partition.EndpointFor for usage and
 // errors that can be returned.
-func (e *Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
+func (e Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
 	return e.p.EndpointFor(e.serviceID, e.id, opts...)
 }
 
@@ -300,28 +364,6 @@ type EndpointNotFoundError struct {
 	Region    string
 }
 
-//// NewEndpointNotFoundError builds and returns NewEndpointNotFoundError.
-//func NewEndpointNotFoundError(p, s, r string) EndpointNotFoundError {
-//	return EndpointNotFoundError{
-//		awsError:  awserr.New("EndpointNotFoundError", "unable to find endpoint", nil),
-//		Partition: p,
-//		Service:   s,
-//		Region:    r,
-//	}
-//}
-//
-//// Error returns string representation of the error.
-//func (e EndpointNotFoundError) Error() string {
-//	extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
-//		e.Partition, e.Service, e.Region)
-//	return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
-//}
-//
-//// String returns the string representation of the error.
-//func (e EndpointNotFoundError) String() string {
-//	return e.Error()
-//}
-
 // A UnknownServiceError is returned when the service does not resolve to an
 // endpoint. Includes a list of all known services for the partition. Returned
 // when a partition does not support the service.

+ 10 - 7
vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go

@@ -209,17 +209,20 @@ import (
 	// DefaultResolver returns an Endpoint resolver that will be able
 	// to resolve endpoints for: {{ ListPartitionNames . }}.
 	//
-	// Casting the return value of this func to a EnumPartitions will
-	// allow you to get a list of the partitions in the order the endpoints
-	// will be resolved in.
+	// Use DefaultPartitions() to get the list of the default partitions.
+	func DefaultResolver() Resolver {
+		return defaultPartitions
+	}
+
+	// DefaultPartitions returns a list of the partitions the SDK is bundled
+	// with. The available partitions are: {{ ListPartitionNames . }}.
 	//
-	//    resolver := endpoints.DefaultResolver()
-	//    partitions := resolver.(endpoints.EnumPartitions).Partitions()
+	//    partitions := endpoints.DefaultPartitions
 	//    for _, p := range partitions {
 	//        // ... inspect partitions
 	//    }
-	func DefaultResolver() Resolver {
-		return defaultPartitions
+	func DefaultPartitions() []Partition {
+		return defaultPartitions.Partitions()
 	}
 
 	var defaultPartitions = partitions{

+ 2 - 1
vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go

@@ -4,7 +4,8 @@ package aws
 // into a json string. This type can be used just like any other map.
 //
 //	Example:
-//	values := JSONValue{
+//
+//	values := aws.JSONValue{
 //		"Foo": "Bar",
 //	}
 //	values["Baz"] = "Qux"

+ 2 - 2
vendor/github.com/aws/aws-sdk-go/aws/logger.go

@@ -26,14 +26,14 @@ func (l *LogLevelType) Value() LogLevelType {
 
 // Matches returns true if the v LogLevel is enabled by this LogLevel. Should be
 // used with logging sub levels. Is safe to use on nil value LogLevelTypes. If
-// LogLevel is nill, will default to LogOff comparison.
+// LogLevel is nil, will default to LogOff comparison.
 func (l *LogLevelType) Matches(v LogLevelType) bool {
 	c := l.Value()
 	return c&v == v
 }
 
 // AtLeast returns true if this LogLevel is at least high enough to satisfies v.
-// Is safe to use on nil value LogLevelTypes. If LogLevel is nill, will default
+// Is safe to use on nil value LogLevelTypes. If LogLevel is nil, will default
 // to LogOff comparison.
 func (l *LogLevelType) AtLeast(v LogLevelType) bool {
 	c := l.Value()

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go

@@ -1,4 +1,4 @@
-// +build !appengine
+// +build !appengine,!plan9
 
 package request
 

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go → vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_other.go

@@ -1,4 +1,4 @@
-// +build appengine
+// +build appengine plan9
 
 package request
 

+ 31 - 0
vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go

@@ -158,6 +158,37 @@ func (l *HandlerList) RemoveByName(name string) {
 	}
 }
 
+// SwapNamed will swap out any existing handlers with the same name as the
+// passed in NamedHandler returning true if handlers were swapped. False is
+// returned otherwise.
+func (l *HandlerList) SwapNamed(n NamedHandler) (swapped bool) {
+	for i := 0; i < len(l.list); i++ {
+		if l.list[i].Name == n.Name {
+			l.list[i].Fn = n.Fn
+			swapped = true
+		}
+	}
+
+	return swapped
+}
+
+// SetBackNamed will replace the named handler if it exists in the handler list.
+// If the handler does not exist the handler will be added to the end of the list.
+func (l *HandlerList) SetBackNamed(n NamedHandler) {
+	if !l.SwapNamed(n) {
+		l.PushBackNamed(n)
+	}
+}
+
+// SetFrontNamed will replace the named handler if it exists in the handler list.
+// If the handler does not exist the handler will be added to the beginning of
+// the list.
+func (l *HandlerList) SetFrontNamed(n NamedHandler) {
+	if !l.SwapNamed(n) {
+		l.PushFrontNamed(n)
+	}
+}
+
 // Run executes all handlers in the list with a given request object.
 func (l *HandlerList) Run(r *Request) {
 	for i, h := range l.list {

+ 32 - 31
vendor/github.com/aws/aws-sdk-go/aws/request/request.go

@@ -41,23 +41,24 @@ type Request struct {
 	Handlers   Handlers
 
 	Retryer
-	Time             time.Time
-	ExpireTime       time.Duration
-	Operation        *Operation
-	HTTPRequest      *http.Request
-	HTTPResponse     *http.Response
-	Body             io.ReadSeeker
-	BodyStart        int64 // offset from beginning of Body that the request body starts
-	Params           interface{}
-	Error            error
-	Data             interface{}
-	RequestID        string
-	RetryCount       int
-	Retryable        *bool
-	RetryDelay       time.Duration
-	NotHoist         bool
-	SignedHeaderVals http.Header
-	LastSignedAt     time.Time
+	Time                   time.Time
+	ExpireTime             time.Duration
+	Operation              *Operation
+	HTTPRequest            *http.Request
+	HTTPResponse           *http.Response
+	Body                   io.ReadSeeker
+	BodyStart              int64 // offset from beginning of Body that the request body starts
+	Params                 interface{}
+	Error                  error
+	Data                   interface{}
+	RequestID              string
+	RetryCount             int
+	Retryable              *bool
+	RetryDelay             time.Duration
+	NotHoist               bool
+	SignedHeaderVals       http.Header
+	LastSignedAt           time.Time
+	DisableFollowRedirects bool
 
 	context aws.Context
 
@@ -337,10 +338,7 @@ func (r *Request) Sign() error {
 	return r.Error
 }
 
-// ResetBody rewinds the request body backto its starting position, and
-// set's the HTTP Request body reference. When the body is read prior
-// to being sent in the HTTP request it will need to be rewound.
-func (r *Request) ResetBody() {
+func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
 	if r.safeBody != nil {
 		r.safeBody.Close()
 	}
@@ -362,14 +360,14 @@ func (r *Request) ResetBody() {
 	// Related golang/go#18257
 	l, err := computeBodyLength(r.Body)
 	if err != nil {
-		r.Error = awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
-		return
+		return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
 	}
 
+	var body io.ReadCloser
 	if l == 0 {
-		r.HTTPRequest.Body = noBodyReader
+		body = NoBody
 	} else if l > 0 {
-		r.HTTPRequest.Body = r.safeBody
+		body = r.safeBody
 	} else {
 		// Hack to prevent sending bodies for methods where the body
 		// should be ignored by the server. Sending bodies on these
@@ -381,11 +379,13 @@ func (r *Request) ResetBody() {
 		// a io.Reader that was not also an io.Seeker.
 		switch r.Operation.HTTPMethod {
 		case "GET", "HEAD", "DELETE":
-			r.HTTPRequest.Body = noBodyReader
+			body = NoBody
 		default:
-			r.HTTPRequest.Body = r.safeBody
+			body = r.safeBody
 		}
 	}
+
+	return body, nil
 }
 
 // Attempts to compute the length of the body of the reader using the
@@ -487,7 +487,7 @@ func (r *Request) Send() error {
 			r.Handlers.Retry.Run(r)
 			r.Handlers.AfterRetry.Run(r)
 			if r.Error != nil {
-				debugLogReqError(r, "Send Request", false, r.Error)
+				debugLogReqError(r, "Send Request", false, err)
 				return r.Error
 			}
 			debugLogReqError(r, "Send Request", true, err)
@@ -496,12 +496,13 @@ func (r *Request) Send() error {
 		r.Handlers.UnmarshalMeta.Run(r)
 		r.Handlers.ValidateResponse.Run(r)
 		if r.Error != nil {
-			err := r.Error
 			r.Handlers.UnmarshalError.Run(r)
+			err := r.Error
+
 			r.Handlers.Retry.Run(r)
 			r.Handlers.AfterRetry.Run(r)
 			if r.Error != nil {
-				debugLogReqError(r, "Validate Response", false, r.Error)
+				debugLogReqError(r, "Validate Response", false, err)
 				return r.Error
 			}
 			debugLogReqError(r, "Validate Response", true, err)
@@ -514,7 +515,7 @@ func (r *Request) Send() error {
 			r.Handlers.Retry.Run(r)
 			r.Handlers.AfterRetry.Run(r)
 			if r.Error != nil {
-				debugLogReqError(r, "Unmarshal Response", false, r.Error)
+				debugLogReqError(r, "Unmarshal Response", false, err)
 				return r.Error
 			}
 			debugLogReqError(r, "Unmarshal Response", true, err)

+ 20 - 2
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go

@@ -16,6 +16,24 @@ func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
 func (noBody) Close() error                     { return nil }
 func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
 
-// Is an empty reader that will trigger the Go HTTP client to not include
+// NoBody is an empty reader that will trigger the Go HTTP client to not include
 // and body in the HTTP request.
-var noBodyReader = noBody{}
+var NoBody = noBody{}
+
+// ResetBody rewinds the request body back to its starting position, and
+// set's the HTTP Request body reference. When the body is read prior
+// to being sent in the HTTP request it will need to be rewound.
+//
+// ResetBody will automatically be called by the SDK's build handler, but if
+// the request is being used directly ResetBody must be called before the request
+// is Sent.  SetStringBody, SetBufferBody, and SetReaderBody will automatically
+// call ResetBody.
+func (r *Request) ResetBody() {
+	body, err := r.getNextRequestBody()
+	if err != nil {
+		r.Error = err
+		return
+	}
+
+	r.HTTPRequest.Body = body
+}

+ 27 - 3
vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go

@@ -2,8 +2,32 @@
 
 package request
 
-import "net/http"
+import (
+	"net/http"
+)
 
-// Is a http.NoBody reader instructing Go HTTP client to not include
+// NoBody is a http.NoBody reader instructing Go HTTP client to not include
 // and body in the HTTP request.
-var noBodyReader = http.NoBody
+var NoBody = http.NoBody
+
+// ResetBody rewinds the request body back to its starting position, and
+// set's the HTTP Request body reference. When the body is read prior
+// to being sent in the HTTP request it will need to be rewound.
+//
+// ResetBody will automatically be called by the SDK's build handler, but if
+// the request is being used directly ResetBody must be called before the request
+// is Sent.  SetStringBody, SetBufferBody, and SetReaderBody will automatically
+// call ResetBody.
+//
+// Will also set the Go 1.8's http.Request.GetBody member to allow retrying
+// PUT/POST redirects.
+func (r *Request) ResetBody() {
+	body, err := r.getNextRequestBody()
+	if err != nil {
+		r.Error = err
+		return
+	}
+
+	r.HTTPRequest.Body = body
+	r.HTTPRequest.GetBody = r.getNextRequestBody
+}

+ 8 - 1
vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go

@@ -38,7 +38,6 @@ var throttleCodes = map[string]struct{}{
 	"ThrottlingException":                    {},
 	"RequestLimitExceeded":                   {},
 	"RequestThrottled":                       {},
-	"LimitExceededException":                 {}, // Deleting 10+ DynamoDb tables at once
 	"TooManyRequestsException":               {}, // Lambda functions
 	"PriorRequestNotComplete":                {}, // Route53
 }
@@ -75,6 +74,10 @@ var validParentCodes = map[string]struct{}{
 	ErrCodeRead:          struct{}{},
 }
 
+type temporaryError interface {
+	Temporary() bool
+}
+
 func isNestedErrorRetryable(parentErr awserr.Error) bool {
 	if parentErr == nil {
 		return false
@@ -93,6 +96,10 @@ func isNestedErrorRetryable(parentErr awserr.Error) bool {
 		return isCodeRetryable(aerr.Code())
 	}
 
+	if t, ok := err.(temporaryError); ok {
+		return t.Temporary()
+	}
+
 	return isErrConnectionReset(err)
 }
 

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/request/validation.go

@@ -220,7 +220,7 @@ type ErrParamMinLen struct {
 func NewErrParamMinLen(field string, min int) *ErrParamMinLen {
 	return &ErrParamMinLen{
 		errInvalidParam: errInvalidParam{
-			code:  ParamMinValueErrCode,
+			code:  ParamMinLenErrCode,
 			field: field,
 			msg:   fmt.Sprintf("minimum field size of %v", min),
 		},

+ 2 - 2
vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go

@@ -66,8 +66,8 @@ func WithWaiterRequestOptions(opts ...Option) WaiterOption {
 	}
 }
 
-// A Waiter provides the functionality to performing blocking call which will
-// wait for an resource state to be satisfied a service.
+// A Waiter provides the functionality to perform a blocking call which will
+// wait for a resource state to be satisfied by a service.
 //
 // This type should not be used directly. The API operations provided in the
 // service packages prefixed with "WaitUntil" should be used instead.

+ 2 - 3
vendor/github.com/aws/aws-sdk-go/aws/session/doc.go

@@ -124,9 +124,8 @@ file (~/.aws/config) and shared credentials file (~/.aws/credentials). Both
 files have the same format.
 
 If both config files are present the configuration from both files will be
-read. The Session will be created from  configuration values from the shared
-credentials file (~/.aws/credentials) over those in the shared credentials
-file (~/.aws/config).
+read. The Session will be created from configuration values from the shared
+credentials file (~/.aws/credentials) over those in the shared config file (~/.aws/config).
 
 Credentials are the values the SDK should use for authenticating requests with
 AWS Services. They arfrom a configuration file will need to include both

+ 8 - 28
vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go

@@ -2,7 +2,6 @@ package session
 
 import (
 	"os"
-	"path/filepath"
 	"strconv"
 
 	"github.com/aws/aws-sdk-go/aws/credentials"
@@ -116,6 +115,12 @@ var (
 		"AWS_PROFILE",
 		"AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set
 	}
+	sharedCredsFileEnvKey = []string{
+		"AWS_SHARED_CREDENTIALS_FILE",
+	}
+	sharedConfigFileEnvKey = []string{
+		"AWS_CONFIG_FILE",
+	}
 )
 
 // loadEnvConfig retrieves the SDK's environment configuration.
@@ -165,8 +170,8 @@ func envConfigLoad(enableSharedConfig bool) envConfig {
 	setFromEnvVal(&cfg.Region, regionKeys)
 	setFromEnvVal(&cfg.Profile, profileKeys)
 
-	cfg.SharedCredentialsFile = sharedCredentialsFilename()
-	cfg.SharedConfigFile = sharedConfigFilename()
+	setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey)
+	setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey)
 
 	cfg.CustomCABundle = os.Getenv("AWS_CA_BUNDLE")
 
@@ -181,28 +186,3 @@ func setFromEnvVal(dst *string, keys []string) {
 		}
 	}
 }
-
-func sharedCredentialsFilename() string {
-	if name := os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(name) > 0 {
-		return name
-	}
-
-	return filepath.Join(userHomeDir(), ".aws", "credentials")
-}
-
-func sharedConfigFilename() string {
-	if name := os.Getenv("AWS_CONFIG_FILE"); len(name) > 0 {
-		return name
-	}
-
-	return filepath.Join(userHomeDir(), ".aws", "config")
-}
-
-func userHomeDir() string {
-	homeDir := os.Getenv("HOME") // *nix
-	if len(homeDir) == 0 {       // windows
-		homeDir = os.Getenv("USERPROFILE")
-	}
-
-	return homeDir
-}

+ 23 - 7
vendor/github.com/aws/aws-sdk-go/aws/session/session.go

@@ -155,6 +155,10 @@ type Options struct {
 	// and enable or disable the shared config functionality.
 	SharedConfigState SharedConfigState
 
+	// Ordered list of files the session will load configuration from.
+	// It will override environment variable AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE.
+	SharedConfigFiles []string
+
 	// When the SDK's shared config is configured to assume a role with MFA
 	// this option is required in order to provide the mechanism that will
 	// retrieve the MFA token. There is no default value for this field. If
@@ -218,7 +222,7 @@ type Options struct {
 //
 //     // Force enable Shared Config support
 //     sess := session.Must(session.NewSessionWithOptions(session.Options{
-//         SharedConfigState: SharedConfigEnable,
+//         SharedConfigState: session.SharedConfigEnable,
 //     }))
 func NewSessionWithOptions(opts Options) (*Session, error) {
 	var envCfg envConfig
@@ -239,6 +243,13 @@ func NewSessionWithOptions(opts Options) (*Session, error) {
 		envCfg.EnableSharedConfig = true
 	}
 
+	if len(envCfg.SharedCredentialsFile) == 0 {
+		envCfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
+	}
+	if len(envCfg.SharedConfigFile) == 0 {
+		envCfg.SharedConfigFile = defaults.SharedConfigFilename()
+	}
+
 	// Only use AWS_CA_BUNDLE if session option is not provided.
 	if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil {
 		f, err := os.Open(envCfg.CustomCABundle)
@@ -304,13 +315,18 @@ func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session,
 	userCfg := &aws.Config{}
 	userCfg.MergeIn(cfgs...)
 
-	// Order config files will be loaded in with later files overwriting
+	// Ordered config files will be loaded in with later files overwriting
 	// previous config file values.
-	cfgFiles := []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
-	if !envCfg.EnableSharedConfig {
-		// The shared config file (~/.aws/config) is only loaded if instructed
-		// to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
-		cfgFiles = cfgFiles[1:]
+	var cfgFiles []string
+	if opts.SharedConfigFiles != nil {
+		cfgFiles = opts.SharedConfigFiles
+	} else {
+		cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
+		if !envCfg.EnableSharedConfig {
+			// The shared config file (~/.aws/config) is only loaded if instructed
+			// to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
+			cfgFiles = cfgFiles[1:]
+		}
 	}
 
 	// Load additional config from file(s)

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go

@@ -113,7 +113,7 @@ func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
 
 		f, err := ini.Load(b)
 		if err != nil {
-			return nil, SharedConfigLoadError{Filename: filename}
+			return nil, SharedConfigLoadError{Filename: filename, Err: err}
 		}
 
 		files = append(files, sharedConfigFile{

+ 16 - 16
vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go

@@ -45,7 +45,7 @@
 // If signing a request intended for HTTP2 server, and you're using Go 1.6.2
 // through 1.7.4 you should use the URL.RawPath as the pre-escaped form of the
 // request URL. https://github.com/golang/go/issues/16847 points to a bug in
-// Go pre 1.8 that failes to make HTTP2 requests using absolute URL in the HTTP
+// Go pre 1.8 that fails to make HTTP2 requests using absolute URL in the HTTP
 // message. URL.Opaque generally will force Go to make requests with absolute URL.
 // URL.RawPath does not do this, but RawPath must be a valid escaping of Path
 // or url.EscapedPath will ignore the RawPath escaping.
@@ -402,7 +402,7 @@ var SignRequestHandler = request.NamedHandler{
 }
 
 // SignSDKRequest signs an AWS request with the V4 signature. This
-// request handler is bested used only with the SDK's built in service client's
+// request handler should only be used with the SDK's built in service client's
 // API operation requests.
 //
 // This function should not be used on its on its own, but in conjunction with
@@ -604,7 +604,11 @@ func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) {
 	headerValues := make([]string, len(headers))
 	for i, k := range headers {
 		if k == "host" {
-			headerValues[i] = "host:" + ctx.Request.URL.Host
+			if ctx.Request.Host != "" {
+				headerValues[i] = "host:" + ctx.Request.Host
+			} else {
+				headerValues[i] = "host:" + ctx.Request.URL.Host
+			}
 		} else {
 			headerValues[i] = k + ":" +
 				strings.Join(ctx.SignedHeaderVals[k], ",")
@@ -724,24 +728,24 @@ func stripExcessSpaces(headerVals []string) []string {
 		trimmed := strings.TrimSpace(str)
 
 		idx := strings.Index(trimmed, doubleSpaces)
-		var buf []byte
-		for idx > -1 {
-			// Multiple adjacent spaces found
-			if buf == nil {
-				// first time create the buffer
-				buf = []byte(trimmed)
-			}
+		if idx < 0 {
+			vals[i] = trimmed
+			continue
+		}
 
+		buf := []byte(trimmed)
+		for idx > -1 {
 			stripToIdx := -1
 			for j := idx + 1; j < len(buf); j++ {
 				if buf[j] != ' ' {
 					buf = append(buf[:idx+1], buf[j:]...)
-					stripToIdx = j
+					stripToIdx = j - idx - 1
 					break
 				}
 			}
 
 			if stripToIdx >= 0 {
+				// Find next double space
 				idx = bytes.Index(buf[stripToIdx:], doubleSpaceBytes)
 				if idx >= 0 {
 					idx += stripToIdx
@@ -751,11 +755,7 @@ func stripExcessSpaces(headerVals []string) []string {
 			}
 		}
 
-		if buf != nil {
-			vals[i] = string(buf)
-		} else {
-			vals[i] = trimmed
-		}
+		vals[i] = string(buf)
 	}
 	return vals
 }

+ 1 - 1
vendor/github.com/aws/aws-sdk-go/aws/version.go

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

+ 40 - 0
vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go

@@ -0,0 +1,40 @@
+package shareddefaults
+
+import (
+	"os"
+	"path/filepath"
+	"runtime"
+)
+
+// SharedCredentialsFilename returns the SDK's default file path
+// for the shared credentials file.
+//
+// Builds the shared config file path based on the OS's platform.
+//
+//   - Linux/Unix: $HOME/.aws/credentials
+//   - Windows: %USERPROFILE%\.aws\credentials
+func SharedCredentialsFilename() string {
+	return filepath.Join(UserHomeDir(), ".aws", "credentials")
+}
+
+// SharedConfigFilename returns the SDK's default file path for
+// the shared config file.
+//
+// Builds the shared config file path based on the OS's platform.
+//
+//   - Linux/Unix: $HOME/.aws/config
+//   - Windows: %USERPROFILE%\.aws\config
+func SharedConfigFilename() string {
+	return filepath.Join(UserHomeDir(), ".aws", "config")
+}
+
+// UserHomeDir returns the home directory for the user the process is
+// running under.
+func UserHomeDir() string {
+	if runtime.GOOS == "windows" { // Windows
+		return os.Getenv("USERPROFILE")
+	}
+
+	// *nix
+	return os.Getenv("HOME")
+}

+ 0 - 1
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go

@@ -131,7 +131,6 @@ func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag refl
 			continue
 		}
 
-
 		mTag := field.Tag
 		if mTag.Get("location") != "" { // skip non-body members
 			continue

+ 5 - 2
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go

@@ -15,7 +15,10 @@ import (
 // needs to match the shape of the XML expected to be decoded.
 // If the shape doesn't match unmarshaling will fail.
 func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
-	n, _ := XMLToStruct(d, nil)
+	n, err := XMLToStruct(d, nil)
+	if err != nil {
+		return err
+	}
 	if n.Children != nil {
 		for _, root := range n.Children {
 			for _, c := range root {
@@ -23,7 +26,7 @@ func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
 					c = wrappedChild[0] // pull out wrapped element
 				}
 
-				err := parse(reflect.ValueOf(v), c, "")
+				err = parse(reflect.ValueOf(v), c, "")
 				if err != nil {
 					if err == io.EOF {
 						return nil

+ 9 - 4
vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go

@@ -40,11 +40,16 @@ func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
 	out := &XMLNode{}
 	for {
 		tok, err := d.Token()
-		if tok == nil || err == io.EOF {
-			break
-		}
 		if err != nil {
-			return out, err
+			if err == io.EOF {
+				break
+			} else {
+				return out, err
+			}
+		}
+
+		if tok == nil {
+			break
 		}
 
 		switch typed := tok.(type) {

+ 501 - 8
vendor/github.com/aws/aws-sdk-go/service/ec2/api.go

@@ -1,6 +1,5 @@
 // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
 
-// Package ec2 provides a client for Amazon Elastic Compute Cloud.
 package ec2
 
 import (
@@ -2368,7 +2367,8 @@ func (c *EC2) CopyImageRequest(input *CopyImageInput) (req *request.Request, out
 // region. You specify the destination region by using its endpoint when making
 // the request.
 //
-// For more information, see Copying AMIs (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html)
+// For more information about the prerequisites and limits when copying an AMI,
+// see Copying an AMI (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/CopyingAMIs.html)
 // in the Amazon Elastic Compute Cloud User Guide.
 //
 // Returns awserr.Error for service API and SDK errors. Use runtime type assertions
@@ -7979,6 +7979,83 @@ func (c *EC2) DescribeFlowLogsWithContext(ctx aws.Context, input *DescribeFlowLo
 	return out, req.Send()
 }
 
+const opDescribeFpgaImages = "DescribeFpgaImages"
+
+// DescribeFpgaImagesRequest generates a "aws/request.Request" representing the
+// client's request for the DescribeFpgaImages operation. The "output" return
+// value can be used to capture response data after the request's "Send" method
+// is called.
+//
+// See DescribeFpgaImages for usage and error information.
+//
+// Creating a request object using this method should be used when you want to inject
+// custom logic into the request's lifecycle using a custom handler, or if you want to
+// access properties on the request object before or after sending the request. If
+// you just want the service response, call the DescribeFpgaImages method directly
+// instead.
+//
+// Note: You must call the "Send" method on the returned request object in order
+// to execute the request.
+//
+//    // Example sending a request using the DescribeFpgaImagesRequest method.
+//    req, resp := client.DescribeFpgaImagesRequest(params)
+//
+//    err := req.Send()
+//    if err == nil { // resp is now filled
+//        fmt.Println(resp)
+//    }
+//
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/DescribeFpgaImages
+func (c *EC2) DescribeFpgaImagesRequest(input *DescribeFpgaImagesInput) (req *request.Request, output *DescribeFpgaImagesOutput) {
+	op := &request.Operation{
+		Name:       opDescribeFpgaImages,
+		HTTPMethod: "POST",
+		HTTPPath:   "/",
+	}
+
+	if input == nil {
+		input = &DescribeFpgaImagesInput{}
+	}
+
+	output = &DescribeFpgaImagesOutput{}
+	req = c.newRequest(op, input, output)
+	return
+}
+
+// DescribeFpgaImages API operation for Amazon Elastic Compute Cloud.
+//
+// Describes one or more available Amazon FPGA Images (AFIs). These include
+// public AFIs, private AFIs that you own, and AFIs owned by other AWS accounts
+// for which you have load permissions.
+//
+// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
+// with awserr.Error's Code and Message methods to get detailed information about
+// the error.
+//
+// See the AWS API reference guide for Amazon Elastic Compute Cloud's
+// API operation DescribeFpgaImages for usage and error information.
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/DescribeFpgaImages
+func (c *EC2) DescribeFpgaImages(input *DescribeFpgaImagesInput) (*DescribeFpgaImagesOutput, error) {
+	req, out := c.DescribeFpgaImagesRequest(input)
+	return out, req.Send()
+}
+
+// DescribeFpgaImagesWithContext is the same as DescribeFpgaImages with the addition of
+// the ability to pass a context and additional request options.
+//
+// See DescribeFpgaImages for details on how to use this API operation.
+//
+// The context must be non-nil and will be used for request cancellation. If
+// the context is nil a panic will occur. In the future the SDK may create
+// sub-contexts for http.Requests. See https://golang.org/pkg/context/
+// for more information on using Contexts.
+func (c *EC2) DescribeFpgaImagesWithContext(ctx aws.Context, input *DescribeFpgaImagesInput, opts ...request.Option) (*DescribeFpgaImagesOutput, error) {
+	req, out := c.DescribeFpgaImagesRequest(input)
+	req.SetContext(ctx)
+	req.ApplyOptions(opts...)
+	return out, req.Send()
+}
+
 const opDescribeHostReservationOfferings = "DescribeHostReservationOfferings"
 
 // DescribeHostReservationOfferingsRequest generates a "aws/request.Request" representing the
@@ -29314,6 +29391,164 @@ func (s *DescribeFlowLogsOutput) SetNextToken(v string) *DescribeFlowLogsOutput
 	return s
 }
 
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/DescribeFpgaImagesRequest
+type DescribeFpgaImagesInput struct {
+	_ struct{} `type:"structure"`
+
+	// Checks whether you have the required permissions for the action, without
+	// actually making the request, and provides an error response. If you have
+	// the required permissions, the error response is DryRunOperation. Otherwise,
+	// it is UnauthorizedOperation.
+	DryRun *bool `type:"boolean"`
+
+	// One or more filters.
+	//
+	//    * create-time - The creation time of the AFI.
+	//
+	//    * fpga-image-id - The FPGA image identifier (AFI ID).
+	//
+	//    * fpga-image-global-id - The global FPGA image identifier (AGFI ID).
+	//
+	//    * name - The name of the AFI.
+	//
+	//    * owner-id - The AWS account ID of the AFI owner.
+	//
+	//    * product-code - The product code.
+	//
+	//    * shell-version - The version of the AWS Shell that was used to create
+	//    the bitstream.
+	//
+	//    * state - The state of the AFI (pending | failed | available | unavailable).
+	//
+	//    * tag:key=value - The key/value combination of a tag assigned to the resource.
+	//    Specify the key of the tag in the filter name and the value of the tag
+	//    in the filter value. For example, for the tag Purpose=X, specify tag:Purpose
+	//    for the filter name and X for the filter value.
+	//
+	//    * tag-key - The key of a tag assigned to the resource. This filter is
+	//    independent of the tag-value filter. For example, if you use both the
+	//    filter "tag-key=Purpose" and the filter "tag-value=X", you get any resources
+	//    assigned both the tag key Purpose (regardless of what the tag's value
+	//    is), and the tag value X (regardless of what the tag's key is). If you
+	//    want to list only resources where Purpose is X, see the tag:key=value
+	//    filter.
+	//
+	//    * tag-value - The value of a tag assigned to the resource. This filter
+	//    is independent of the tag-key filter.
+	//
+	//    * update-time - The time of the most recent update.
+	Filters []*Filter `locationName:"Filter" locationNameList:"Filter" type:"list"`
+
+	// One or more AFI IDs.
+	FpgaImageIds []*string `locationName:"FpgaImageId" locationNameList:"item" type:"list"`
+
+	// The maximum number of results to return in a single call.
+	MaxResults *int64 `min:"5" type:"integer"`
+
+	// The token to retrieve the next page of results.
+	NextToken *string `min:"1" type:"string"`
+
+	// Filters the AFI by owner. Specify an AWS account ID, self (owner is the sender
+	// of the request), or an AWS owner alias (valid values are amazon | aws-marketplace).
+	Owners []*string `locationName:"Owner" locationNameList:"Owner" type:"list"`
+}
+
+// String returns the string representation
+func (s DescribeFpgaImagesInput) String() string {
+	return awsutil.Prettify(s)
+}
+
+// GoString returns the string representation
+func (s DescribeFpgaImagesInput) GoString() string {
+	return s.String()
+}
+
+// Validate inspects the fields of the type to determine if they are valid.
+func (s *DescribeFpgaImagesInput) Validate() error {
+	invalidParams := request.ErrInvalidParams{Context: "DescribeFpgaImagesInput"}
+	if s.MaxResults != nil && *s.MaxResults < 5 {
+		invalidParams.Add(request.NewErrParamMinValue("MaxResults", 5))
+	}
+	if s.NextToken != nil && len(*s.NextToken) < 1 {
+		invalidParams.Add(request.NewErrParamMinLen("NextToken", 1))
+	}
+
+	if invalidParams.Len() > 0 {
+		return invalidParams
+	}
+	return nil
+}
+
+// SetDryRun sets the DryRun field's value.
+func (s *DescribeFpgaImagesInput) SetDryRun(v bool) *DescribeFpgaImagesInput {
+	s.DryRun = &v
+	return s
+}
+
+// SetFilters sets the Filters field's value.
+func (s *DescribeFpgaImagesInput) SetFilters(v []*Filter) *DescribeFpgaImagesInput {
+	s.Filters = v
+	return s
+}
+
+// SetFpgaImageIds sets the FpgaImageIds field's value.
+func (s *DescribeFpgaImagesInput) SetFpgaImageIds(v []*string) *DescribeFpgaImagesInput {
+	s.FpgaImageIds = v
+	return s
+}
+
+// SetMaxResults sets the MaxResults field's value.
+func (s *DescribeFpgaImagesInput) SetMaxResults(v int64) *DescribeFpgaImagesInput {
+	s.MaxResults = &v
+	return s
+}
+
+// SetNextToken sets the NextToken field's value.
+func (s *DescribeFpgaImagesInput) SetNextToken(v string) *DescribeFpgaImagesInput {
+	s.NextToken = &v
+	return s
+}
+
+// SetOwners sets the Owners field's value.
+func (s *DescribeFpgaImagesInput) SetOwners(v []*string) *DescribeFpgaImagesInput {
+	s.Owners = v
+	return s
+}
+
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/DescribeFpgaImagesResult
+type DescribeFpgaImagesOutput struct {
+	_ struct{} `type:"structure"`
+
+	// Information about one or more FPGA images.
+	FpgaImages []*FpgaImage `locationName:"fpgaImageSet" locationNameList:"item" type:"list"`
+
+	// The token to use to retrieve the next page of results. This value is null
+	// when there are no more results to return.
+	NextToken *string `locationName:"nextToken" min:"1" type:"string"`
+}
+
+// String returns the string representation
+func (s DescribeFpgaImagesOutput) String() string {
+	return awsutil.Prettify(s)
+}
+
+// GoString returns the string representation
+func (s DescribeFpgaImagesOutput) GoString() string {
+	return s.String()
+}
+
+// SetFpgaImages sets the FpgaImages field's value.
+func (s *DescribeFpgaImagesOutput) SetFpgaImages(v []*FpgaImage) *DescribeFpgaImagesOutput {
+	s.FpgaImages = v
+	return s
+}
+
+// SetNextToken sets the NextToken field's value.
+func (s *DescribeFpgaImagesOutput) SetNextToken(v string) *DescribeFpgaImagesOutput {
+	s.NextToken = &v
+	return s
+}
+
 // Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/DescribeHostReservationOfferingsRequest
 type DescribeHostReservationOfferingsInput struct {
 	_ struct{} `type:"structure"`
@@ -38391,6 +38626,182 @@ func (s *FlowLog) SetTrafficType(v string) *FlowLog {
 	return s
 }
 
+// Describes an Amazon FPGA image (AFI).
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/FpgaImage
+type FpgaImage struct {
+	_ struct{} `type:"structure"`
+
+	// The date and time the AFI was created.
+	CreateTime *time.Time `locationName:"createTime" type:"timestamp" timestampFormat:"iso8601"`
+
+	// The description of the AFI.
+	Description *string `locationName:"description" type:"string"`
+
+	// The global FPGA image identifier (AGFI ID).
+	FpgaImageGlobalId *string `locationName:"fpgaImageGlobalId" type:"string"`
+
+	// The FPGA image identifier (AFI ID).
+	FpgaImageId *string `locationName:"fpgaImageId" type:"string"`
+
+	// The name of the AFI.
+	Name *string `locationName:"name" type:"string"`
+
+	// The alias of the AFI owner. Possible values include self, amazon, and aws-marketplace.
+	OwnerAlias *string `locationName:"ownerAlias" type:"string"`
+
+	// The AWS account ID of the AFI owner.
+	OwnerId *string `locationName:"ownerId" type:"string"`
+
+	// Information about the PCI bus.
+	PciId *PciId `locationName:"pciId" type:"structure"`
+
+	// The product codes for the AFI.
+	ProductCodes []*ProductCode `locationName:"productCodes" locationNameList:"item" type:"list"`
+
+	// The version of the AWS Shell that was used to create the bitstream.
+	ShellVersion *string `locationName:"shellVersion" type:"string"`
+
+	// Information about the state of the AFI.
+	State *FpgaImageState `locationName:"state" type:"structure"`
+
+	// Any tags assigned to the AFI.
+	Tags []*Tag `locationName:"tags" locationNameList:"item" type:"list"`
+
+	// The time of the most recent update to the AFI.
+	UpdateTime *time.Time `locationName:"updateTime" type:"timestamp" timestampFormat:"iso8601"`
+}
+
+// String returns the string representation
+func (s FpgaImage) String() string {
+	return awsutil.Prettify(s)
+}
+
+// GoString returns the string representation
+func (s FpgaImage) GoString() string {
+	return s.String()
+}
+
+// SetCreateTime sets the CreateTime field's value.
+func (s *FpgaImage) SetCreateTime(v time.Time) *FpgaImage {
+	s.CreateTime = &v
+	return s
+}
+
+// SetDescription sets the Description field's value.
+func (s *FpgaImage) SetDescription(v string) *FpgaImage {
+	s.Description = &v
+	return s
+}
+
+// SetFpgaImageGlobalId sets the FpgaImageGlobalId field's value.
+func (s *FpgaImage) SetFpgaImageGlobalId(v string) *FpgaImage {
+	s.FpgaImageGlobalId = &v
+	return s
+}
+
+// SetFpgaImageId sets the FpgaImageId field's value.
+func (s *FpgaImage) SetFpgaImageId(v string) *FpgaImage {
+	s.FpgaImageId = &v
+	return s
+}
+
+// SetName sets the Name field's value.
+func (s *FpgaImage) SetName(v string) *FpgaImage {
+	s.Name = &v
+	return s
+}
+
+// SetOwnerAlias sets the OwnerAlias field's value.
+func (s *FpgaImage) SetOwnerAlias(v string) *FpgaImage {
+	s.OwnerAlias = &v
+	return s
+}
+
+// SetOwnerId sets the OwnerId field's value.
+func (s *FpgaImage) SetOwnerId(v string) *FpgaImage {
+	s.OwnerId = &v
+	return s
+}
+
+// SetPciId sets the PciId field's value.
+func (s *FpgaImage) SetPciId(v *PciId) *FpgaImage {
+	s.PciId = v
+	return s
+}
+
+// SetProductCodes sets the ProductCodes field's value.
+func (s *FpgaImage) SetProductCodes(v []*ProductCode) *FpgaImage {
+	s.ProductCodes = v
+	return s
+}
+
+// SetShellVersion sets the ShellVersion field's value.
+func (s *FpgaImage) SetShellVersion(v string) *FpgaImage {
+	s.ShellVersion = &v
+	return s
+}
+
+// SetState sets the State field's value.
+func (s *FpgaImage) SetState(v *FpgaImageState) *FpgaImage {
+	s.State = v
+	return s
+}
+
+// SetTags sets the Tags field's value.
+func (s *FpgaImage) SetTags(v []*Tag) *FpgaImage {
+	s.Tags = v
+	return s
+}
+
+// SetUpdateTime sets the UpdateTime field's value.
+func (s *FpgaImage) SetUpdateTime(v time.Time) *FpgaImage {
+	s.UpdateTime = &v
+	return s
+}
+
+// Describes the state of the bitstream generation process for an Amazon FPGA
+// image (AFI).
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/FpgaImageState
+type FpgaImageState struct {
+	_ struct{} `type:"structure"`
+
+	// The state. The following are the possible values:
+	//
+	//    * pending - AFI bitstream generation is in progress.
+	//
+	//    * available - The AFI is available for use.
+	//
+	//    * failed - AFI bitstream generation failed.
+	//
+	//    * unavailable - The AFI is no longer available for use.
+	Code *string `locationName:"code" type:"string" enum:"FpgaImageStateCode"`
+
+	// If the state is failed, this is the error message.
+	Message *string `locationName:"message" type:"string"`
+}
+
+// String returns the string representation
+func (s FpgaImageState) String() string {
+	return awsutil.Prettify(s)
+}
+
+// GoString returns the string representation
+func (s FpgaImageState) GoString() string {
+	return s.String()
+}
+
+// SetCode sets the Code field's value.
+func (s *FpgaImageState) SetCode(v string) *FpgaImageState {
+	s.Code = &v
+	return s
+}
+
+// SetMessage sets the Message field's value.
+func (s *FpgaImageState) SetMessage(v string) *FpgaImageState {
+	s.Message = &v
+	return s
+}
+
 // Contains the parameters for GetConsoleOutput.
 // Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/GetConsoleOutputRequest
 type GetConsoleOutputInput struct {
@@ -45882,6 +46293,59 @@ func (s *NewDhcpConfiguration) SetValues(v []*string) *NewDhcpConfiguration {
 	return s
 }
 
+// Describes the data that identifies an Amazon FPGA image (AFI) on the PCI
+// bus.
+// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/PciId
+type PciId struct {
+	_ struct{} `type:"structure"`
+
+	// The ID of the device.
+	DeviceId *string `type:"string"`
+
+	// The ID of the subsystem.
+	SubsystemId *string `type:"string"`
+
+	// The ID of the vendor for the subsystem.
+	SubsystemVendorId *string `type:"string"`
+
+	// The ID of the vendor.
+	VendorId *string `type:"string"`
+}
+
+// String returns the string representation
+func (s PciId) String() string {
+	return awsutil.Prettify(s)
+}
+
+// GoString returns the string representation
+func (s PciId) GoString() string {
+	return s.String()
+}
+
+// SetDeviceId sets the DeviceId field's value.
+func (s *PciId) SetDeviceId(v string) *PciId {
+	s.DeviceId = &v
+	return s
+}
+
+// SetSubsystemId sets the SubsystemId field's value.
+func (s *PciId) SetSubsystemId(v string) *PciId {
+	s.SubsystemId = &v
+	return s
+}
+
+// SetSubsystemVendorId sets the SubsystemVendorId field's value.
+func (s *PciId) SetSubsystemVendorId(v string) *PciId {
+	s.SubsystemVendorId = &v
+	return s
+}
+
+// SetVendorId sets the VendorId field's value.
+func (s *PciId) SetVendorId(v string) *PciId {
+	s.VendorId = &v
+	return s
+}
+
 // Describes the VPC peering connection options.
 // Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/PeeringConnectionOptions
 type PeeringConnectionOptions struct {
@@ -45993,6 +46457,9 @@ type Placement struct {
 	// is not supported for the ImportInstance command.
 	HostId *string `locationName:"hostId" type:"string"`
 
+	// Reserved for future use.
+	SpreadDomain *string `locationName:"spreadDomain" type:"string"`
+
 	// The tenancy of the instance (if the instance is running in a VPC). An instance
 	// with a tenancy of dedicated runs on single-tenant hardware. The host tenancy
 	// is not supported for the ImportInstance command.
@@ -46033,6 +46500,12 @@ func (s *Placement) SetHostId(v string) *Placement {
 	return s
 }
 
+// SetSpreadDomain sets the SpreadDomain field's value.
+func (s *Placement) SetSpreadDomain(v string) *Placement {
+	s.SpreadDomain = &v
+	return s
+}
+
 // SetTenancy sets the Tenancy field's value.
 func (s *Placement) SetTenancy(v string) *Placement {
 	s.Tenancy = &v
@@ -48412,7 +48885,7 @@ type RequestSpotInstancesInput struct {
 	// Default: Instances are launched and terminated individually
 	LaunchGroup *string `locationName:"launchGroup" type:"string"`
 
-	// Describes the launch specification for an instance.
+	// The launch specification.
 	LaunchSpecification *RequestSpotLaunchSpecification `type:"structure"`
 
 	// The maximum hourly price (bid) for any Spot instance launched to fulfill
@@ -48601,7 +49074,9 @@ type RequestSpotLaunchSpecification struct {
 	// The name of the key pair.
 	KeyName *string `locationName:"keyName" type:"string"`
 
-	// Describes the monitoring of an instance.
+	// Indicates whether basic or detailed monitoring is enabled for the instance.
+	//
+	// Default: Disabled
 	Monitoring *RunInstancesMonitoringEnabled `locationName:"monitoring" type:"structure"`
 
 	// One or more network interfaces. If you specify a network interface, you must
@@ -48614,8 +49089,12 @@ type RequestSpotLaunchSpecification struct {
 	// The ID of the RAM disk.
 	RamdiskId *string `locationName:"ramdiskId" type:"string"`
 
+	// One or more security group IDs.
 	SecurityGroupIds []*string `locationName:"SecurityGroupId" locationNameList:"item" type:"list"`
 
+	// One or more security groups. When requesting instances in a VPC, you must
+	// specify the IDs of the security groups. When requesting instances in EC2-Classic,
+	// you can specify the names or the IDs of the security groups.
 	SecurityGroups []*string `locationName:"SecurityGroup" locationNameList:"item" type:"list"`
 
 	// The ID of the subnet in which to launch the instance.
@@ -56210,15 +56689,15 @@ func (s *VpcIpv6CidrBlockAssociation) SetIpv6CidrBlockState(v *VpcCidrBlockState
 type VpcPeeringConnection struct {
 	_ struct{} `type:"structure"`
 
-	// Information about the accepter VPC. CIDR block information is not returned
-	// when creating a VPC peering connection, or when describing a VPC peering
-	// connection that's in the initiating-request or pending-acceptance state.
+	// Information about the accepter VPC. CIDR block information is only returned
+	// when describing an active VPC peering connection.
 	AccepterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"accepterVpcInfo" type:"structure"`
 
 	// The time that an unaccepted VPC peering connection will expire.
 	ExpirationTime *time.Time `locationName:"expirationTime" type:"timestamp" timestampFormat:"iso8601"`
 
-	// Information about the requester VPC.
+	// Information about the requester VPC. CIDR block information is only returned
+	// when describing an active VPC peering connection.
 	RequesterVpcInfo *VpcPeeringConnectionVpcInfo `locationName:"requesterVpcInfo" type:"structure"`
 
 	// The status of the VPC peering connection.
@@ -57009,6 +57488,20 @@ const (
 	FlowLogsResourceTypeNetworkInterface = "NetworkInterface"
 )
 
+const (
+	// FpgaImageStateCodePending is a FpgaImageStateCode enum value
+	FpgaImageStateCodePending = "pending"
+
+	// FpgaImageStateCodeFailed is a FpgaImageStateCode enum value
+	FpgaImageStateCodeFailed = "failed"
+
+	// FpgaImageStateCodeAvailable is a FpgaImageStateCode enum value
+	FpgaImageStateCodeAvailable = "available"
+
+	// FpgaImageStateCodeUnavailable is a FpgaImageStateCode enum value
+	FpgaImageStateCodeUnavailable = "unavailable"
+)
+
 const (
 	// GatewayTypeIpsec1 is a GatewayType enum value
 	GatewayTypeIpsec1 = "ipsec.1"

+ 83 - 0
vendor/github.com/aws/aws-sdk-go/service/ec2/doc.go

@@ -0,0 +1,83 @@
+// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
+
+// Package ec2 provides the client and types for making API
+// requests to Amazon Elastic Compute Cloud.
+//
+// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity
+// 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
+// faster.
+//
+// See https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15 for more information on this service.
+//
+// See ec2 package documentation for more information.
+// https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/
+//
+// Using the Client
+//
+// To use the client for Amazon Elastic Compute Cloud you will first need
+// to create a new instance of it.
+//
+// When creating a client for an AWS service you'll first need to have a Session
+// already created. The Session provides configuration that can be shared
+// between multiple service clients. Additional configuration can be applied to
+// the Session and service's client when they are constructed. The aws package's
+// Config type contains several fields such as Region for the AWS Region the
+// client should make API requests too. The optional Config value can be provided
+// as the variadic argument for Sessions and client creation.
+//
+// Once the service's client is created you can use it to make API requests the
+// AWS service. These clients are safe to use concurrently.
+//
+//   // Create a session to share configuration, and load external configuration.
+//   sess := session.Must(session.NewSession())
+//
+//   // Create the service's client with the session.
+//   svc := ec2.New(sess)
+//
+// See the SDK's documentation for more information on how to use service clients.
+// https://docs.aws.amazon.com/sdk-for-go/api/
+//
+// See aws package's Config type for more information on configuration options.
+// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
+//
+// See the Amazon Elastic Compute Cloud client EC2 for more
+// information on creating the service's client.
+// https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#New
+//
+// Once the client is created you can make an API request to the service.
+// Each API method takes a input parameter, and returns the service response
+// and an error.
+//
+// The API method will document which error codes the service can be returned
+// by the operation if the service models the API operation's errors. These
+// errors will also be available as const strings prefixed with "ErrCode".
+//
+//   result, err := svc.AcceptReservedInstancesExchangeQuote(params)
+//   if err != nil {
+//       // Cast err to awserr.Error to handle specific error codes.
+//       aerr, ok := err.(awserr.Error)
+//       if ok && aerr.Code() == <error code to check for> {
+//           // Specific error code handling
+//       }
+//       return err
+//   }
+//
+//   fmt.Println("AcceptReservedInstancesExchangeQuote result:")
+//   fmt.Println(result)
+//
+// Using the Client with Context
+//
+// The service's client also provides methods to make API requests with a Context
+// value. This allows you to control the timeout, and cancellation of pending
+// requests. These methods also take request Option as variadic parameter to apply
+// additional configuration to the API request.
+//
+//   ctx := context.Background()
+//
+//   result, err := svc.AcceptReservedInstancesExchangeQuoteWithContext(ctx, params)
+//
+// See the request package documentation for more information on using Context pattern
+// with the SDK.
+// https://docs.aws.amazon.com/sdk-for-go/api/aws/request/
+package ec2

+ 6 - 7
vendor/github.com/aws/aws-sdk-go/service/ec2/service.go

@@ -11,13 +11,12 @@ import (
 	"github.com/aws/aws-sdk-go/private/protocol/ec2query"
 )
 
-// Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity
-// 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
-// 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.
-// Please also see https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15
+// EC2 provides the API operation methods for making requests to
+// Amazon Elastic Compute Cloud. See this package's package overview docs
+// for details on the service.
+//
+// EC2 methods are safe to use concurrently. It is not safe to
+// modify mutate any of the struct's properties though.
 type EC2 struct {
 	*client.Client
 }

+ 3 - 4
vendor/github.com/aws/aws-sdk-go/service/sts/api.go

@@ -1,6 +1,5 @@
 // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
 
-// Package sts provides a client for AWS Security Token Service.
 package sts
 
 import (
@@ -1086,7 +1085,7 @@ type AssumeRoleInput struct {
 	//
 	// The regex used to validated this parameter is a string of characters consisting
 	// of upper- and lower-case alphanumeric characters with no spaces. You can
-	// also include underscores or any of the following characters: =,.@:\/-
+	// also include underscores or any of the following characters: =,.@:/-
 	ExternalId *string `min:"2" type:"string"`
 
 	// An IAM policy in JSON format.
@@ -2270,9 +2269,9 @@ type GetSessionTokenInput struct {
 	// You can find the device for an IAM user by going to the AWS Management Console
 	// and viewing the user's security credentials.
 	//
-	// The regex used to validate this parameter is a string of characters consisting
+	// The regex used to validated this parameter is a string of characters consisting
 	// of upper- and lower-case alphanumeric characters with no spaces. You can
-	// also include underscores or any of the following characters: =,.@-
+	// also include underscores or any of the following characters: =,.@:/-
 	SerialNumber *string `min:"9" type:"string"`
 
 	// The value provided by the MFA device, if MFA is required. If any policy requires

+ 124 - 0
vendor/github.com/aws/aws-sdk-go/service/sts/doc.go

@@ -0,0 +1,124 @@
+// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
+
+// Package sts provides the client and types for making API
+// requests to AWS Security Token Service.
+//
+// The AWS Security Token Service (STS) is a web service that enables you to
+// request temporary, limited-privilege credentials for AWS Identity and Access
+// Management (IAM) users or for users that you authenticate (federated users).
+// This guide provides descriptions of the STS API. For more detailed information
+// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html).
+//
+// As an alternative to using the API, you can use one of the AWS SDKs, which
+// consist of libraries and sample code for various programming languages and
+// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient
+// way to create programmatic access to STS. For example, the SDKs take care
+// of cryptographically signing requests, managing errors, and retrying requests
+// automatically. For information about the AWS SDKs, including how to download
+// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/).
+//
+// For information about setting up signatures and authorization through the
+// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)
+// in the AWS General Reference. For general information about the Query API,
+// go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html)
+// in Using IAM. For information about using security tokens with other AWS
+// products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html)
+// in the IAM User Guide.
+//
+// If you're new to AWS and need additional technical information about a specific
+// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/
+// (http://aws.amazon.com/documentation/).
+//
+// Endpoints
+//
+// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com
+// that maps to the US East (N. Virginia) region. Additional regions are available
+// and are activated by default. For more information, see Activating and Deactivating
+// AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
+// in the IAM User Guide.
+//
+// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region)
+// in the AWS General Reference.
+//
+// Recording API requests
+//
+// STS supports AWS CloudTrail, which is a service that records AWS calls for
+// your AWS account and delivers log files to an Amazon S3 bucket. By using
+// information collected by CloudTrail, you can determine what requests were
+// successfully made to STS, who made the request, when it was made, and so
+// on. To learn more about CloudTrail, including how to turn it on and find
+// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html).
+//
+// See https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15 for more information on this service.
+//
+// See sts package documentation for more information.
+// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/
+//
+// Using the Client
+//
+// To use the client for AWS Security Token Service you will first need
+// to create a new instance of it.
+//
+// When creating a client for an AWS service you'll first need to have a Session
+// already created. The Session provides configuration that can be shared
+// between multiple service clients. Additional configuration can be applied to
+// the Session and service's client when they are constructed. The aws package's
+// Config type contains several fields such as Region for the AWS Region the
+// client should make API requests too. The optional Config value can be provided
+// as the variadic argument for Sessions and client creation.
+//
+// Once the service's client is created you can use it to make API requests the
+// AWS service. These clients are safe to use concurrently.
+//
+//   // Create a session to share configuration, and load external configuration.
+//   sess := session.Must(session.NewSession())
+//
+//   // Create the service's client with the session.
+//   svc := sts.New(sess)
+//
+// See the SDK's documentation for more information on how to use service clients.
+// https://docs.aws.amazon.com/sdk-for-go/api/
+//
+// See aws package's Config type for more information on configuration options.
+// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
+//
+// See the AWS Security Token Service client STS for more
+// information on creating the service's client.
+// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/#New
+//
+// Once the client is created you can make an API request to the service.
+// Each API method takes a input parameter, and returns the service response
+// and an error.
+//
+// The API method will document which error codes the service can be returned
+// by the operation if the service models the API operation's errors. These
+// errors will also be available as const strings prefixed with "ErrCode".
+//
+//   result, err := svc.AssumeRole(params)
+//   if err != nil {
+//       // Cast err to awserr.Error to handle specific error codes.
+//       aerr, ok := err.(awserr.Error)
+//       if ok && aerr.Code() == <error code to check for> {
+//           // Specific error code handling
+//       }
+//       return err
+//   }
+//
+//   fmt.Println("AssumeRole result:")
+//   fmt.Println(result)
+//
+// Using the Client with Context
+//
+// The service's client also provides methods to make API requests with a Context
+// value. This allows you to control the timeout, and cancellation of pending
+// requests. These methods also take request Option as variadic parameter to apply
+// additional configuration to the API request.
+//
+//   ctx := context.Background()
+//
+//   result, err := svc.AssumeRoleWithContext(ctx, params)
+//
+// See the request package documentation for more information on using Context pattern
+// with the SDK.
+// https://docs.aws.amazon.com/sdk-for-go/api/aws/request/
+package sts

+ 5 - 47
vendor/github.com/aws/aws-sdk-go/service/sts/service.go

@@ -11,54 +11,12 @@ import (
 	"github.com/aws/aws-sdk-go/private/protocol/query"
 )
 
-// The AWS Security Token Service (STS) is a web service that enables you to
-// request temporary, limited-privilege credentials for AWS Identity and Access
-// Management (IAM) users or for users that you authenticate (federated users).
-// This guide provides descriptions of the STS API. For more detailed information
-// about using this service, go to Temporary Security Credentials (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html).
+// STS provides the API operation methods for making requests to
+// AWS Security Token Service. See this package's package overview docs
+// for details on the service.
 //
-// As an alternative to using the API, you can use one of the AWS SDKs, which
-// consist of libraries and sample code for various programming languages and
-// platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs provide a convenient
-// way to create programmatic access to STS. For example, the SDKs take care
-// of cryptographically signing requests, managing errors, and retrying requests
-// automatically. For information about the AWS SDKs, including how to download
-// and install them, see the Tools for Amazon Web Services page (http://aws.amazon.com/tools/).
-//
-// For information about setting up signatures and authorization through the
-// API, go to Signing AWS API Requests (http://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html)
-// in the AWS General Reference. For general information about the Query API,
-// go to Making Query Requests (http://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html)
-// in Using IAM. For information about using security tokens with other AWS
-// products, go to AWS Services That Work with IAM (http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html)
-// in the IAM User Guide.
-//
-// If you're new to AWS and need additional technical information about a specific
-// AWS product, you can find the product's technical documentation at http://aws.amazon.com/documentation/
-// (http://aws.amazon.com/documentation/).
-//
-// Endpoints
-//
-// The AWS Security Token Service (STS) has a default endpoint of https://sts.amazonaws.com
-// that maps to the US East (N. Virginia) region. Additional regions are available
-// and are activated by default. For more information, see Activating and Deactivating
-// AWS STS in an AWS Region (http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
-// in the IAM User Guide.
-//
-// For information about STS endpoints, see Regions and Endpoints (http://docs.aws.amazon.com/general/latest/gr/rande.html#sts_region)
-// in the AWS General Reference.
-//
-// Recording API requests
-//
-// STS supports AWS CloudTrail, which is a service that records AWS calls for
-// your AWS account and delivers log files to an Amazon S3 bucket. By using
-// information collected by CloudTrail, you can determine what requests were
-// successfully made to STS, who made the request, when it was made, and so
-// on. To learn more about CloudTrail, including how to turn it on and find
-// your log files, see the AWS CloudTrail User Guide (http://docs.aws.amazon.com/awscloudtrail/latest/userguide/what_is_cloud_trail_top_level.html).
-// The service client's operations are safe to be used concurrently.
-// It is not safe to mutate any of the client's properties though.
-// Please also see https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15
+// STS methods are safe to use concurrently. It is not safe to
+// modify mutate any of the struct's properties though.
 type STS struct {
 	*client.Client
 }

+ 150 - 8
vendor/github.com/coreos/go-iptables/iptables/iptables.go

@@ -18,6 +18,7 @@ import (
 	"bytes"
 	"fmt"
 	"io"
+	"net"
 	"os/exec"
 	"regexp"
 	"strconv"
@@ -28,6 +29,7 @@ import (
 // Adds the output of stderr to exec.ExitError
 type Error struct {
 	exec.ExitError
+	cmd exec.Cmd
 	msg string
 }
 
@@ -36,32 +38,55 @@ func (e *Error) ExitStatus() int {
 }
 
 func (e *Error) Error() string {
-	return fmt.Sprintf("exit status %v: %v", e.ExitStatus(), e.msg)
+	return fmt.Sprintf("running %v: exit status %v: %v", e.cmd.Args, e.ExitStatus(), e.msg)
 }
 
+// Protocol to differentiate between IPv4 and IPv6
+type Protocol byte
+
+const (
+	ProtocolIPv4 Protocol = iota
+	ProtocolIPv6
+)
+
 type IPTables struct {
 	path     string
+	proto    Protocol
 	hasCheck bool
 	hasWait  bool
 }
 
+// New creates a new IPTables.
+// For backwards compatibility, this always uses IPv4, i.e. "iptables".
 func New() (*IPTables, error) {
-	path, err := exec.LookPath("iptables")
+	return NewWithProtocol(ProtocolIPv4)
+}
+
+// New creates a new IPTables for the given proto.
+// The proto will determine which command is used, either "iptables" or "ip6tables".
+func NewWithProtocol(proto Protocol) (*IPTables, error) {
+	path, err := exec.LookPath(getIptablesCommand(proto))
 	if err != nil {
 		return nil, err
 	}
-	checkPresent, waitPresent, err := getIptablesCommandSupport()
+	checkPresent, waitPresent, err := getIptablesCommandSupport(path)
 	if err != nil {
 		return nil, fmt.Errorf("error checking iptables version: %v", err)
 	}
 	ipt := IPTables{
 		path:     path,
+		proto:    proto,
 		hasCheck: checkPresent,
 		hasWait:  waitPresent,
 	}
 	return &ipt, nil
 }
 
+// Proto returns the protocol used by this IPTables.
+func (ipt *IPTables) Proto() Protocol {
+	return ipt.proto
+}
+
 // Exists checks if given rulespec in specified table/chain exists
 func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) {
 	if !ipt.hasCheck {
@@ -116,6 +141,107 @@ func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error {
 // List rules in specified table/chain
 func (ipt *IPTables) List(table, chain string) ([]string, error) {
 	args := []string{"-t", table, "-S", chain}
+	return ipt.executeList(args)
+}
+
+// List rules (with counters) in specified table/chain
+func (ipt *IPTables) ListWithCounters(table, chain string) ([]string, error) {
+	args := []string{"-t", table, "-v", "-S", chain}
+	return ipt.executeList(args)
+}
+
+// ListChains returns a slice containing the name of each chain in the specified table.
+func (ipt *IPTables) ListChains(table string) ([]string, error) {
+	args := []string{"-t", table, "-S"}
+
+	result, err := ipt.executeList(args)
+	if err != nil {
+		return nil, err
+	}
+
+	// Iterate over rules to find all default (-P) and user-specified (-N) chains.
+	// Chains definition always come before rules.
+	// Format is the following:
+	// -P OUTPUT ACCEPT
+	// -N Custom
+	var chains []string
+	for _, val := range result {
+		if strings.HasPrefix(val, "-P") || strings.HasPrefix(val, "-N") {
+			chains = append(chains, strings.Fields(val)[1])
+		} else {
+			break
+		}
+	}
+	return chains, nil
+}
+
+// Stats lists rules including the byte and packet counts
+func (ipt *IPTables) Stats(table, chain string) ([][]string, error) {
+	args := []string{"-t", table, "-L", chain, "-n", "-v", "-x"}
+	lines, err := ipt.executeList(args)
+	if err != nil {
+		return nil, err
+	}
+
+	appendSubnet := func(addr string) string {
+		if strings.IndexByte(addr, byte('/')) < 0 {
+			if strings.IndexByte(addr, '.') < 0 {
+				return addr + "/128"
+			}
+			return addr + "/32"
+		}
+		return addr
+	}
+
+	ipv6 := ipt.proto == ProtocolIPv6
+
+	rows := [][]string{}
+	for i, line := range lines {
+		// Skip over chain name and field header
+		if i < 2 {
+			continue
+		}
+
+		// Fields:
+		// 0=pkts 1=bytes 2=target 3=prot 4=opt 5=in 6=out 7=source 8=destination 9=options
+		line = strings.TrimSpace(line)
+		fields := strings.Fields(line)
+
+		// The ip6tables verbose output cannot be naively split due to the default "opt"
+		// field containing 2 single spaces.
+		if ipv6 {
+			// Check if field 6 is "opt" or "source" address
+			dest := fields[6]
+			ip, _, _ := net.ParseCIDR(dest)
+			if ip == nil {
+				ip = net.ParseIP(dest)
+			}
+
+			// If we detected a CIDR or IP, the "opt" field is empty.. insert it.
+			if ip != nil {
+				f := []string{}
+				f = append(f, fields[:4]...)
+				f = append(f, "  ") // Empty "opt" field for ip6tables
+				f = append(f, fields[4:]...)
+				fields = f
+			}
+		}
+
+		// Adjust "source" and "destination" to include netmask, to match regular
+		// List output
+		fields[7] = appendSubnet(fields[7])
+		fields[8] = appendSubnet(fields[8])
+
+		// Combine "options" fields 9... into a single space-delimited field.
+		options := fields[9:]
+		fields = fields[:9]
+		fields = append(fields, strings.Join(options, " "))
+		rows = append(rows, fields)
+	}
+	return rows, nil
+}
+
+func (ipt *IPTables) executeList(args []string) ([]string, error) {
 	var stdout bytes.Buffer
 	if err := ipt.runWithOutput(args, &stdout); err != nil {
 		return nil, err
@@ -129,6 +255,8 @@ func (ipt *IPTables) List(table, chain string) ([]string, error) {
 	return rules, nil
 }
 
+// NewChain creates a new chain in the specified table.
+// If the chain already exists, it will result in an error.
 func (ipt *IPTables) NewChain(table, chain string) error {
 	return ipt.run("-t", table, "-N", chain)
 }
@@ -194,15 +322,29 @@ func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
 	}
 
 	if err := cmd.Run(); err != nil {
-		return &Error{*(err.(*exec.ExitError)), stderr.String()}
+		switch e := err.(type) {
+		case *exec.ExitError:
+			return &Error{*e, cmd, stderr.String()}
+		default:
+			return err
+		}
 	}
 
 	return nil
 }
 
+// getIptablesCommand returns the correct command for the given protocol, either "iptables" or "ip6tables".
+func getIptablesCommand(proto Protocol) string {
+	if proto == ProtocolIPv6 {
+		return "ip6tables"
+	} else {
+		return "iptables"
+	}
+}
+
 // Checks if iptables has the "-C" and "--wait" flag
-func getIptablesCommandSupport() (bool, bool, error) {
-	vstring, err := getIptablesVersionString()
+func getIptablesCommandSupport(path string) (bool, bool, error) {
+	vstring, err := getIptablesVersionString(path)
 	if err != nil {
 		return false, false, err
 	}
@@ -243,8 +385,8 @@ func extractIptablesVersion(str string) (int, int, int, error) {
 }
 
 // Runs "iptables --version" to get the version string
-func getIptablesVersionString() (string, error) {
-	cmd := exec.Command("iptables", "--version")
+func getIptablesVersionString(path string) (string, error) {
+	cmd := exec.Command(path, "--version")
 	var out bytes.Buffer
 	cmd.Stdout = &out
 	err := cmd.Run()

+ 140 - 8
vendor/github.com/denverdino/aliyungo/common/client.go

@@ -7,12 +7,20 @@ import (
 	"log"
 	"net/http"
 	"net/url"
-	"time"
 	"strings"
+	"time"
 
 	"github.com/denverdino/aliyungo/util"
 )
 
+// RemovalPolicy.N add index to array item
+// RemovalPolicy=["a", "b"] => RemovalPolicy.1="a" RemovalPolicy.2="b"
+type FlattenArray []string
+
+// string contains underline which will be replaced with dot
+// SystemDisk_Category => SystemDisk.Category
+type UnderlineString string
+
 // A Client represents a client of ECS services
 type Client struct {
 	AccessKeyId     string //Access Key Id
@@ -21,6 +29,10 @@ type Client struct {
 	httpClient      *http.Client
 	endpoint        string
 	version         string
+	serviceCode     string
+	regionID        Region
+	businessInfo    string
+	userAgent 	string
 }
 
 // NewClient creates a new instance of ECS client
@@ -33,6 +45,26 @@ func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret strin
 	client.version = version
 }
 
+func (client *Client) NewInit(endpoint, version, accessKeyId, accessKeySecret, serviceCode string, regionID Region) {
+	client.Init(endpoint, version, accessKeyId, accessKeySecret)
+	client.serviceCode = serviceCode
+	client.regionID = regionID
+	client.setEndpointByLocation(regionID, serviceCode, accessKeyId, accessKeySecret)
+}
+
+//NewClient using location service
+func (client *Client) setEndpointByLocation(region Region, serviceCode, accessKeyId, accessKeySecret string) {
+	locationClient := NewLocationClient(accessKeyId, accessKeySecret)
+	ep := locationClient.DescribeOpenAPIEndpoint(region, serviceCode)
+	if ep == "" {
+		ep = loadEndpointFromFile(region, serviceCode)
+	}
+
+	if ep != "" {
+		client.endpoint = ep
+	}
+}
+
 // SetEndpoint sets custom endpoint
 func (client *Client) SetEndpoint(endpoint string) {
 	client.endpoint = endpoint
@@ -43,6 +75,15 @@ func (client *Client) SetVersion(version string) {
 	client.version = version
 }
 
+func (client *Client) SetRegionID(regionID Region) {
+	client.regionID = regionID
+}
+
+//SetServiceCode sets serviceCode
+func (client *Client) SetServiceCode(serviceCode string) {
+	client.serviceCode = serviceCode
+}
+
 // SetAccessKeyId sets new AccessKeyId
 func (client *Client) SetAccessKeyId(id string) {
 	client.AccessKeyId = id
@@ -58,6 +99,20 @@ func (client *Client) SetDebug(debug bool) {
 	client.debug = debug
 }
 
+// SetBusinessInfo sets business info to log the request/response message
+func (client *Client) SetBusinessInfo(businessInfo string) {
+	if strings.HasPrefix(businessInfo, "/") {
+		client.businessInfo = businessInfo
+	} else if businessInfo != "" {
+		client.businessInfo = "/" + businessInfo
+	}
+}
+
+// SetUserAgent sets user agent to the request/response message
+func (client *Client) SetUserAgent(userAgent string) {
+	client.userAgent = userAgent
+}
+
 // Invoke sends the raw HTTP request for ECS services
 func (client *Client) Invoke(action string, args interface{}, response interface{}) error {
 
@@ -80,7 +135,80 @@ func (client *Client) Invoke(action string, args interface{}, response interface
 	}
 
 	// TODO move to util and add build val flag
-	httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version)
+	httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
+
+	httpReq.Header.Set("User-Agent", httpReq.UserAgent()+ " " +client.userAgent)
+
+	t0 := time.Now()
+	httpResp, err := client.httpClient.Do(httpReq)
+	t1 := time.Now()
+	if err != nil {
+		return GetClientError(err)
+	}
+	statusCode := httpResp.StatusCode
+
+	if client.debug {
+		log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0))
+	}
+
+	defer httpResp.Body.Close()
+	body, err := ioutil.ReadAll(httpResp.Body)
+
+	if err != nil {
+		return GetClientError(err)
+	}
+
+	if client.debug {
+		var prettyJSON bytes.Buffer
+		err = json.Indent(&prettyJSON, body, "", "    ")
+		log.Println(string(prettyJSON.Bytes()))
+	}
+
+	if statusCode >= 400 && statusCode <= 599 {
+		errorResponse := ErrorResponse{}
+		err = json.Unmarshal(body, &errorResponse)
+		ecsError := &Error{
+			ErrorResponse: errorResponse,
+			StatusCode:    statusCode,
+		}
+		return ecsError
+	}
+
+	err = json.Unmarshal(body, response)
+	//log.Printf("%++v", response)
+	if err != nil {
+		return GetClientError(err)
+	}
+
+	return nil
+}
+
+// Invoke sends the raw HTTP request for ECS services
+func (client *Client) InvokeByFlattenMethod(action string, args interface{}, response interface{}) error {
+
+	request := Request{}
+	request.init(client.version, action, client.AccessKeyId)
+
+	query := util.ConvertToQueryValues(request)
+
+	util.SetQueryValueByFlattenMethod(args, &query)
+
+	// Sign request
+	signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret)
+
+	// Generate the request URL
+	requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature)
+
+	httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil)
+
+	if err != nil {
+		return GetClientError(err)
+	}
+
+	// TODO move to util and add build val flag
+	httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
+
+	httpReq.Header.Set("User-Agent", httpReq.UserAgent()+ " " +client.userAgent)
 
 	t0 := time.Now()
 	httpResp, err := client.httpClient.Do(httpReq)
@@ -128,7 +256,8 @@ func (client *Client) Invoke(action string, args interface{}, response interface
 
 // Invoke sends the raw HTTP request for ECS services
 //改进了一下上面那个方法,可以使用各种Http方法
-func (client *Client) InvokeByAnyMethod(method, action string, args interface{}, response interface{}) error {
+//2017.1.30 增加了一个path参数,用来拓展访问的地址
+func (client *Client) InvokeByAnyMethod(method, action, path string, args interface{}, response interface{}) error {
 
 	request := Request{}
 	request.init(client.version, action, client.AccessKeyId)
@@ -140,17 +269,18 @@ func (client *Client) InvokeByAnyMethod(method, action string, args interface{},
 	signature := util.CreateSignatureForRequest(method, &data, client.AccessKeySecret)
 
 	data.Add("Signature", signature)
-
 	// Generate the request URL
 	var (
 		httpReq *http.Request
-		err error
+		err     error
 	)
 	if method == http.MethodGet {
-		requestURL := client.endpoint + "?" + data.Encode()
+		requestURL := client.endpoint + path + "?" + data.Encode()
+		//fmt.Println(requestURL)
 		httpReq, err = http.NewRequest(method, requestURL, nil)
 	} else {
-		httpReq, err = http.NewRequest(method, client.endpoint, strings.NewReader(data.Encode()))
+		//fmt.Println(client.endpoint + path)
+		httpReq, err = http.NewRequest(method, client.endpoint+path, strings.NewReader(data.Encode()))
 		httpReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
 	}
 
@@ -159,7 +289,9 @@ func (client *Client) InvokeByAnyMethod(method, action string, args interface{},
 	}
 
 	// TODO move to util and add build val flag
-	httpReq.Header.Set("X-SDK-Client", `AliyunGO/` + Version)
+	httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version+client.businessInfo)
+
+	httpReq.Header.Set("User-Agent", httpReq.Header.Get("User-Agent")+ " " +client.userAgent)
 
 	t0 := time.Now()
 	httpResp, err := client.httpClient.Do(httpReq)

+ 118 - 0
vendor/github.com/denverdino/aliyungo/common/endpoint.go

@@ -0,0 +1,118 @@
+package common
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"strings"
+)
+
+const (
+	// LocationDefaultEndpoint is the default API endpoint of Location services
+	locationDefaultEndpoint = "https://location.aliyuncs.com"
+	locationAPIVersion      = "2015-06-12"
+	HTTP_PROTOCOL           = "http"
+	HTTPS_PROTOCOL          = "https"
+)
+
+var (
+	endpoints = make(map[Region]map[string]string)
+)
+
+//init endpoints from file
+func init() {
+
+}
+
+func NewLocationClient(accessKeyId, accessKeySecret string) *Client {
+	endpoint := os.Getenv("LOCATION_ENDPOINT")
+	if endpoint == "" {
+		endpoint = locationDefaultEndpoint
+	}
+
+	client := &Client{}
+	client.Init(endpoint, locationAPIVersion, accessKeyId, accessKeySecret)
+	return client
+}
+
+func (client *Client) DescribeEndpoint(args *DescribeEndpointArgs) (*DescribeEndpointResponse, error) {
+	response := &DescribeEndpointResponse{}
+	err := client.Invoke("DescribeEndpoint", args, response)
+	if err != nil {
+		return nil, err
+	}
+	return response, err
+}
+
+func getProductRegionEndpoint(region Region, serviceCode string) string {
+	if sp, ok := endpoints[region]; ok {
+		if endpoint, ok := sp[serviceCode]; ok {
+			return endpoint
+		}
+	}
+
+	return ""
+}
+
+func setProductRegionEndpoint(region Region, serviceCode string, endpoint string) {
+	endpoints[region] = map[string]string{
+		serviceCode: endpoint,
+	}
+}
+
+func (client *Client) DescribeOpenAPIEndpoint(region Region, serviceCode string) string {
+	if endpoint := getProductRegionEndpoint(region, serviceCode); endpoint != "" {
+		return endpoint
+	}
+
+	defaultProtocols := HTTP_PROTOCOL
+
+	args := &DescribeEndpointArgs{
+		Id:          region,
+		ServiceCode: serviceCode,
+		Type:        "openAPI",
+	}
+
+	endpoint, err := client.DescribeEndpoint(args)
+	if err != nil || endpoint.Endpoint == "" {
+		return ""
+	}
+
+	for _, protocol := range endpoint.Protocols.Protocols {
+		if strings.ToLower(protocol) == HTTPS_PROTOCOL {
+			defaultProtocols = HTTPS_PROTOCOL
+			break
+		}
+	}
+
+	ep := fmt.Sprintf("%s://%s", defaultProtocols, endpoint.Endpoint)
+
+	setProductRegionEndpoint(region, serviceCode, ep)
+	return ep
+}
+
+func loadEndpointFromFile(region Region, serviceCode string) string {
+	data, err := ioutil.ReadFile("./endpoints.xml")
+	if err != nil {
+		return ""
+	}
+
+	var endpoints Endpoints
+	err = xml.Unmarshal(data, &endpoints)
+	if err != nil {
+		return ""
+	}
+
+	for _, endpoint := range endpoints.Endpoint {
+		if endpoint.RegionIds.RegionId == string(region) {
+			for _, product := range endpoint.Products.Product {
+				if strings.ToLower(product.ProductName) == serviceCode {
+					return fmt.Sprintf("%s://%s", HTTPS_PROTOCOL, product.DomainName)
+				}
+			}
+		}
+	}
+
+	return ""
+}

+ 16 - 11
vendor/github.com/denverdino/aliyungo/common/regions.go

@@ -5,23 +5,28 @@ type Region string
 
 // Constants of region definition
 const (
-	Hangzhou     = Region("cn-hangzhou")
-	Qingdao      = Region("cn-qingdao")
-	Beijing      = Region("cn-beijing")
-	Hongkong     = Region("cn-hongkong")
-	Shenzhen     = Region("cn-shenzhen")
-	USWest1      = Region("us-west-1")
-	USEast1      = Region("us-east-1")
+	Hangzhou    = Region("cn-hangzhou")
+	Qingdao     = Region("cn-qingdao")
+	Beijing     = Region("cn-beijing")
+	Hongkong    = Region("cn-hongkong")
+	Shenzhen    = Region("cn-shenzhen")
+	Shanghai    = Region("cn-shanghai")
+	Zhangjiakou = Region("cn-zhangjiakou")
+
 	APSouthEast1 = Region("ap-southeast-1")
-	Shanghai     = Region("cn-shanghai")
-	MEEast1      = Region("me-east-1")
 	APNorthEast1 = Region("ap-northeast-1")
 	APSouthEast2 = Region("ap-southeast-2")
-	EUCentral1   = Region("eu-central-1")
+
+	USWest1 = Region("us-west-1")
+	USEast1 = Region("us-east-1")
+
+	MEEast1 = Region("me-east-1")
+
+	EUCentral1 = Region("eu-central-1")
 )
 
 var ValidRegions = []Region{
-	Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai,
+	Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, Zhangjiakou,
 	USWest1, USEast1,
 	APNorthEast1, APSouthEast1, APSouthEast2,
 	MEEast1,

+ 74 - 0
vendor/github.com/denverdino/aliyungo/common/types.go

@@ -13,3 +13,77 @@ const (
 	PrePaid  = InstanceChargeType("PrePaid")
 	PostPaid = InstanceChargeType("PostPaid")
 )
+
+type DescribeEndpointArgs struct {
+	Id          Region
+	ServiceCode string
+	Type        string
+}
+
+type EndpointItem struct {
+	Protocols struct {
+		Protocols []string
+	}
+	Type        string
+	Namespace   string
+	Id          Region
+	SerivceCode string
+	Endpoint    string
+}
+
+type DescribeEndpointResponse struct {
+	Response
+	EndpointItem
+}
+
+type NetType string
+
+const (
+	Internet = NetType("Internet")
+	Intranet = NetType("Intranet")
+)
+
+type TimeType string
+
+const (
+	Hour  = TimeType("Hour")
+	Day   = TimeType("Day")
+	Month = TimeType("Month")
+	Year  = TimeType("Year")
+)
+
+type NetworkType string
+
+const (
+	Classic = NetworkType("Classic")
+	VPC     = NetworkType("VPC")
+)
+
+type BusinessInfo struct {
+	Pack       string `json:"pack,omitempty"`
+	ActivityId string `json:"activityId,omitempty"`
+}
+
+//xml
+type Endpoints struct {
+	Endpoint []Endpoint `xml:"Endpoint"`
+}
+
+type Endpoint struct {
+	Name      string    `xml:"name,attr"`
+	RegionIds RegionIds `xml:"RegionIds"`
+	Products  Products  `xml:"Products"`
+}
+
+type RegionIds struct {
+	RegionId string `xml:"RegionId"`
+}
+
+type Products struct {
+	Product []Product `xml:"Product"`
+}
+
+type Product struct {
+	ProductName string `xml:"ProductName"`
+	DomainName  string `xml:"DomainName"`
+}

+ 38 - 1
vendor/github.com/denverdino/aliyungo/ecs/client.go

@@ -1,8 +1,9 @@
 package ecs
 
 import (
-	"github.com/denverdino/aliyungo/common"
 	"os"
+
+	"github.com/denverdino/aliyungo/common"
 )
 
 // Interval for checking status in WaitForXXX method
@@ -19,6 +20,12 @@ const (
 	// ECSDefaultEndpoint is the default API endpoint of ECS services
 	ECSDefaultEndpoint = "https://ecs-cn-hangzhou.aliyuncs.com"
 	ECSAPIVersion      = "2014-05-26"
+
+	ECSServiceCode = "ecs"
+
+	VPCDefaultEndpoint = "https://vpc.aliyuncs.com"
+	VPCAPIVersion      = "2016-04-28"
+	VPCServiceCode     = "vpc"
 )
 
 // NewClient creates a new instance of ECS client
@@ -30,8 +37,38 @@ func NewClient(accessKeyId, accessKeySecret string) *Client {
 	return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret)
 }
 
+func NewECSClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
+	endpoint := os.Getenv("ECS_ENDPOINT")
+	if endpoint == "" {
+		endpoint = ECSDefaultEndpoint
+	}
+
+	return NewClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
+}
+
+func NewClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
+	client := &Client{}
+	client.NewInit(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret, ECSServiceCode, regionID)
+	return client
+}
+
 func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client {
 	client := &Client{}
 	client.Init(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret)
 	return client
 }
+
+func NewVPCClient(accessKeyId, accessKeySecret string, regionID common.Region) *Client {
+	endpoint := os.Getenv("VPC_ENDPOINT")
+	if endpoint == "" {
+		endpoint = VPCDefaultEndpoint
+	}
+
+	return NewVPCClientWithRegion(endpoint, accessKeyId, accessKeySecret, regionID)
+}
+
+func NewVPCClientWithRegion(endpoint string, accessKeyId, accessKeySecret string, regionID common.Region) *Client {
+	client := &Client{}
+	client.NewInit(endpoint, VPCAPIVersion, accessKeyId, accessKeySecret, VPCServiceCode, regionID)
+	return client
+}

+ 104 - 0
vendor/github.com/denverdino/aliyungo/ecs/forward_entry.go

@@ -0,0 +1,104 @@
+package ecs
+
+import "github.com/denverdino/aliyungo/common"
+
+type CreateForwardEntryArgs struct {
+	RegionId       common.Region
+	ForwardTableId string
+	ExternalIp     string
+	ExternalPort   string
+	IpProtocol     string
+	InternalIp     string
+	InternalPort   string
+}
+
+type CreateForwardEntryResponse struct {
+	common.Response
+	ForwardEntryId string
+}
+
+type DescribeForwardTableEntriesArgs struct {
+	RegionId       common.Region
+	ForwardTableId string
+	common.Pagination
+}
+
+type ForwardTableEntrySetType struct {
+	RegionId       common.Region
+	ExternalIp     string
+	ExternalPort   string
+	ForwardEntryId string
+	ForwardTableId string
+	InternalIp     string
+	InternalPort   string
+	IpProtocol     string
+	Status         string
+}
+
+type DescribeForwardTableEntriesResponse struct {
+	common.Response
+	common.PaginationResult
+	ForwardTableEntries struct {
+		ForwardTableEntry []ForwardTableEntrySetType
+	}
+}
+
+type ModifyForwardEntryArgs struct {
+	RegionId       common.Region
+	ForwardTableId string
+	ForwardEntryId string
+	ExternalIp     string
+	IpProtocol     string
+	ExternalPort   string
+	InternalIp     string
+	InternalPort   string
+}
+
+type ModifyForwardEntryResponse struct {
+	common.Response
+}
+
+type DeleteForwardEntryArgs struct {
+	RegionId       common.Region
+	ForwardTableId string
+	ForwardEntryId string
+}
+
+type DeleteForwardEntryResponse struct {
+	common.Response
+}
+
+func (client *Client) CreateForwardEntry(args *CreateForwardEntryArgs) (resp *CreateForwardEntryResponse, err error) {
+	response := CreateForwardEntryResponse{}
+	err = client.Invoke("CreateForwardEntry", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return &response, err
+}
+
+func (client *Client) DescribeForwardTableEntries(args *DescribeForwardTableEntriesArgs) (forwardTableEntries []ForwardTableEntrySetType,
+	pagination *common.PaginationResult, err error) {
+
+	args.Validate()
+	response := DescribeForwardTableEntriesResponse{}
+
+	err = client.Invoke("DescribeForwardTableEntries", args, &response)
+
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return response.ForwardTableEntries.ForwardTableEntry, &response.PaginationResult, nil
+}
+
+func (client *Client) ModifyForwardEntry(args *ModifyForwardEntryArgs) error {
+	response := ModifyForwardEntryResponse{}
+	return client.Invoke("ModifyForwardEntry", args, &response)
+}
+
+func (client *Client) DeleteForwardEntry(args *DeleteForwardEntryArgs) error {
+	response := DeleteForwardEntryResponse{}
+	err := client.Invoke("DeleteForwardEntry", args, &response)
+	return err
+}

+ 39 - 3
vendor/github.com/denverdino/aliyungo/ecs/images.go

@@ -37,7 +37,7 @@ const (
 	ImageUsageNone     = ImageUsage("none")
 )
 
-// DescribeImagesArgs repsents arguements to describe images
+// DescribeImagesArgs repsents arguments to describe images
 type DescribeImagesArgs struct {
 	RegionId        common.Region
 	ImageId         string
@@ -65,6 +65,10 @@ type DiskDeviceMapping struct {
 	//Why Size Field is string-type.
 	Size   string
 	Device string
+	//For import images
+	Format    string
+	OSSBucket string
+	OSSObject string
 }
 
 //
@@ -108,10 +112,11 @@ func (client *Client) DescribeImages(args *DescribeImagesArgs) (images []ImageTy
 	return response.Images.Image, &response.PaginationResult, nil
 }
 
-// CreateImageArgs repsents arguements to create image
+// CreateImageArgs repsents arguments to create image
 type CreateImageArgs struct {
 	RegionId     common.Region
 	SnapshotId   string
+	InstanceId   string
 	ImageName    string
 	ImageVersion string
 	Description  string
@@ -158,7 +163,7 @@ func (client *Client) DeleteImage(regionId common.Region, imageId string) error
 	return client.Invoke("DeleteImage", &args, &response)
 }
 
-// ModifyImageSharePermission repsents arguements to share image
+// ModifyImageSharePermission repsents arguments to share image
 type ModifyImageSharePermissionArgs struct {
 	RegionId      common.Region
 	ImageId       string
@@ -227,6 +232,37 @@ func (client *Client) CopyImage(args *CopyImageArgs) (string, error) {
 	return response.ImageId, nil
 }
 
+// ImportImageArgs repsents arguments to import image from oss
+type ImportImageArgs struct {
+	RegionId           common.Region
+	ImageName          string
+	ImageVersion       string
+	Description        string
+	ClientToken        string
+	Architecture       string
+	OSType             string
+	Platform           string
+	DiskDeviceMappings struct {
+		DiskDeviceMapping []DiskDeviceMapping
+	}
+}
+
+func (client *Client) ImportImage(args *ImportImageArgs) (string, error) {
+	response := &CopyImageResponse{}
+	err := client.Invoke("ImportImage", args, &response)
+	if err != nil {
+		return "", err
+	}
+	return response.ImageId, nil
+}
+
+type ImportImageResponse struct {
+	common.Response
+	RegionId     common.Region
+	ImageId      string
+	ImportTaskId string
+}
+
 // Default timeout value for WaitForImageReady method
 const ImageDefaultTimeout = 120
 

+ 31 - 0
vendor/github.com/denverdino/aliyungo/ecs/instance_types.go

@@ -49,3 +49,34 @@ func (client *Client) DescribeInstanceTypesNew(args *DescribeInstanceTypesArgs)
 	return response.InstanceTypes.InstanceType, nil
 
 }
+
+type DescribeInstanceTypeFamiliesArgs struct {
+	RegionId   common.Region
+	Generation string
+}
+
+type InstanceTypeFamilies struct {
+	InstanceTypeFamily []InstanceTypeFamily
+}
+
+type InstanceTypeFamily struct {
+	InstanceTypeFamilyId string
+	Generation           string
+}
+
+type DescribeInstanceTypeFamiliesResponse struct {
+	common.Response
+
+	InstanceTypeFamilies InstanceTypeFamilies
+}
+
+func (client *Client) DescribeInstanceTypeFamilies(args *DescribeInstanceTypeFamiliesArgs) (*DescribeInstanceTypeFamiliesResponse, error) {
+	response := &DescribeInstanceTypeFamiliesResponse{}
+
+	err := client.Invoke("DescribeInstanceTypeFamilies", args, response)
+	if err != nil {
+		return nil, err
+	}
+
+	return response, nil
+}

+ 65 - 1
vendor/github.com/denverdino/aliyungo/ecs/instances.go

@@ -15,7 +15,7 @@ type InstanceStatus string
 
 // Constants of InstanceStatus
 const (
-	Creating = InstanceStatus("Creating") // For backward compatability
+	Creating = InstanceStatus("Creating") // For backward compatibility
 	Pending  = InstanceStatus("Pending")
 	Running  = InstanceStatus("Running")
 	Starting = InstanceStatus("Starting")
@@ -326,6 +326,33 @@ func (client *Client) WaitForInstance(instanceId string, status InstanceStatus,
 	return nil
 }
 
+// WaitForInstance waits for instance to given status
+// when instance.NotFound wait until timeout
+func (client *Client) WaitForInstanceAsyn(instanceId string, status InstanceStatus, timeout int) error {
+	if timeout <= 0 {
+		timeout = InstanceDefaultTimeout
+	}
+	for {
+		instance, err := client.DescribeInstanceAttribute(instanceId)
+		if err != nil {
+			e, _ := err.(*common.Error)
+			if e.Code != "InvalidInstanceId.NotFound" && e.Code != "Forbidden.InstanceNotFound" {
+				return err
+			}
+		} else if instance != nil && instance.Status == status {
+			//TODO
+			break
+		}
+		timeout = timeout - DefaultWaitForInterval
+		if timeout <= 0 {
+			return common.GetClientErrorFromString("Timeout")
+		}
+		time.Sleep(DefaultWaitForInterval * time.Second)
+
+	}
+	return nil
+}
+
 type DescribeInstanceVncUrlArgs struct {
 	RegionId   common.Region
 	InstanceId string
@@ -513,6 +540,43 @@ func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId strin
 	return response.InstanceId, err
 }
 
+type RunInstanceArgs struct {
+	CreateInstanceArgs
+	MinAmount       int
+	MaxAmount       int
+	AutoReleaseTime string
+	NetworkType     string
+	InnerIpAddress  string
+	BusinessInfo    string
+}
+
+type RunInstanceResponse struct {
+	common.Response
+	InstanceIdSets InstanceIdSets
+}
+
+type InstanceIdSets struct {
+	InstanceIdSet []string
+}
+
+type BusinessInfo struct {
+	Pack       string `json:"pack,omitempty"`
+	ActivityId string `json:"activityId,omitempty"`
+}
+
+func (client *Client) RunInstances(args *RunInstanceArgs) (instanceIdSet []string, err error) {
+	if args.UserData != "" {
+		// Encode to base64 string
+		args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData))
+	}
+	response := RunInstanceResponse{}
+	err = client.Invoke("RunInstances", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return response.InstanceIdSets.InstanceIdSet, err
+}
+
 type SecurityGroupArgs struct {
 	InstanceId      string
 	SecurityGroupId string

+ 202 - 0
vendor/github.com/denverdino/aliyungo/ecs/nat_gateway.go

@@ -0,0 +1,202 @@
+package ecs
+
+import (
+	"github.com/denverdino/aliyungo/common"
+)
+
+type BandwidthPackageType struct {
+	IpCount   int
+	Bandwidth int
+	Zone      string
+}
+
+type CreateNatGatewayArgs struct {
+	RegionId         common.Region
+	VpcId            string
+	Spec             string
+	BandwidthPackage []BandwidthPackageType
+	Name             string
+	Description      string
+	ClientToken      string
+}
+
+type ForwardTableIdType struct {
+	ForwardTableId []string
+}
+
+type SnatTableIdType struct {
+	SnatTableId []string
+}
+
+type BandwidthPackageIdType struct {
+	BandwidthPackageId []string
+}
+
+type CreateNatGatewayResponse struct {
+	common.Response
+	NatGatewayId        string
+	ForwardTableIds     ForwardTableIdType
+	BandwidthPackageIds BandwidthPackageIdType
+}
+
+// CreateNatGateway creates Virtual Private Cloud
+//
+// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&createvpc
+func (client *Client) CreateNatGateway(args *CreateNatGatewayArgs) (resp *CreateNatGatewayResponse, err error) {
+	response := CreateNatGatewayResponse{}
+	err = client.Invoke("CreateNatGateway", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return &response, err
+}
+
+type NatGatewaySetType struct {
+	BusinessStatus      string
+	Description         string
+	BandwidthPackageIds BandwidthPackageIdType
+	ForwardTableIds     ForwardTableIdType
+	SnatTableIds        SnatTableIdType
+	InstanceChargeType  string
+	Name                string
+	NatGatewayId        string
+	RegionId            common.Region
+	Spec                string
+	Status              string
+	VpcId               string
+}
+
+type DescribeNatGatewayResponse struct {
+	common.Response
+	common.PaginationResult
+	NatGateways struct {
+		NatGateway []NatGatewaySetType
+	}
+}
+
+type DescribeNatGatewaysArgs struct {
+	RegionId     common.Region
+	NatGatewayId string
+	VpcId        string
+	common.Pagination
+}
+
+func (client *Client) DescribeNatGateways(args *DescribeNatGatewaysArgs) (natGateways []NatGatewaySetType,
+	pagination *common.PaginationResult, err error) {
+
+	args.Validate()
+	response := DescribeNatGatewayResponse{}
+
+	err = client.Invoke("DescribeNatGateways", args, &response)
+
+	if err == nil {
+		return response.NatGateways.NatGateway, &response.PaginationResult, nil
+	}
+
+	return nil, nil, err
+}
+
+type ModifyNatGatewayAttributeArgs struct {
+	RegionId     common.Region
+	NatGatewayId string
+	Name         string
+	Description  string
+}
+
+type ModifyNatGatewayAttributeResponse struct {
+	common.Response
+}
+
+func (client *Client) ModifyNatGatewayAttribute(args *ModifyNatGatewayAttributeArgs) error {
+	response := ModifyNatGatewayAttributeResponse{}
+	return client.Invoke("ModifyNatGatewayAttribute", args, &response)
+}
+
+type ModifyNatGatewaySpecArgs struct {
+	RegionId     common.Region
+	NatGatewayId string
+	Spec         NatGatewaySpec
+}
+
+func (client *Client) ModifyNatGatewaySpec(args *ModifyNatGatewaySpecArgs) error {
+	response := ModifyNatGatewayAttributeResponse{}
+	return client.Invoke("ModifyNatGatewaySpec", args, &response)
+}
+
+type DeleteNatGatewayArgs struct {
+	RegionId     common.Region
+	NatGatewayId string
+}
+
+type DeleteNatGatewayResponse struct {
+	common.Response
+}
+
+func (client *Client) DeleteNatGateway(args *DeleteNatGatewayArgs) error {
+	response := DeleteNatGatewayResponse{}
+	err := client.Invoke("DeleteNatGateway", args, &response)
+	return err
+}
+
+type DescribeBandwidthPackagesArgs struct {
+	RegionId           common.Region
+	BandwidthPackageId string
+	NatGatewayId       string
+}
+
+type PublicIpAddresseType struct {
+	AllocationId string
+	IpAddress    string
+}
+
+type DescribeBandwidthPackageType struct {
+	Bandwidth          string
+	BandwidthPackageId string
+	IpCount            string
+	PublicIpAddresses  struct {
+		PublicIpAddresse []PublicIpAddresseType
+	}
+
+	ZoneId string
+}
+
+type DescribeBandwidthPackagesResponse struct {
+	common.Response
+	BandwidthPackages struct {
+		BandwidthPackage []DescribeBandwidthPackageType
+	}
+}
+
+func (client *Client) DescribeBandwidthPackages(args *DescribeBandwidthPackagesArgs) ([]DescribeBandwidthPackageType, error) {
+	response := &DescribeBandwidthPackagesResponse{}
+
+	err := client.Invoke("DescribeBandwidthPackages", args, response)
+	if err != nil {
+		return nil, err
+	}
+
+	return response.BandwidthPackages.BandwidthPackage, err
+}
+
+type DeleteBandwidthPackageArgs struct {
+	RegionId           common.Region
+	BandwidthPackageId string
+}
+
+type DeleteBandwidthPackageResponse struct {
+	common.Response
+}
+
+func (client *Client) DeleteBandwidthPackage(args *DeleteBandwidthPackageArgs) error {
+	response := DeleteBandwidthPackageResponse{}
+	err := client.Invoke("DeleteBandwidthPackage", args, &response)
+	return err
+}
+
+type NatGatewaySpec string
+
+const (
+	NatGatewaySmallSpec  = NatGatewaySpec("Small")
+	NatGatewayMiddleSpec = NatGatewaySpec("Middle")
+	NatGatewayLargeSpec  = NatGatewaySpec("Large")
+)

+ 1 - 0
vendor/github.com/denverdino/aliyungo/ecs/security_groups.go

@@ -33,6 +33,7 @@ type DescribeSecurityGroupAttributeArgs struct {
 	SecurityGroupId string
 	RegionId        common.Region
 	NicType         NicType //enum for internet (default) |intranet
+	Direction       string  // enum ingress egress
 }
 
 //

+ 95 - 0
vendor/github.com/denverdino/aliyungo/ecs/snat_entry.go

@@ -0,0 +1,95 @@
+package ecs
+
+import "github.com/denverdino/aliyungo/common"
+
+type CreateSnatEntryArgs struct {
+	RegionId        common.Region
+	SnatTableId     string
+	SourceVSwitchId string
+	SnatIp          string
+}
+
+type CreateSnatEntryResponse struct {
+	common.Response
+	SnatEntryId string
+}
+
+type SnatEntrySetType struct {
+	RegionId        common.Region
+	SnatEntryId     string
+	SnatIp          string
+	SnatTableId     string
+	SourceCIDR      string
+	SourceVSwitchId string
+	Status          string
+}
+
+type DescribeSnatTableEntriesArgs struct {
+	RegionId    common.Region
+	SnatTableId string
+	common.Pagination
+}
+
+type DescribeSnatTableEntriesResponse struct {
+	common.Response
+	common.PaginationResult
+	SnatTableEntries struct {
+		SnatTableEntry []SnatEntrySetType
+	}
+}
+
+type ModifySnatEntryArgs struct {
+	RegionId    common.Region
+	SnatTableId string
+	SnatEntryId string
+	SnatIp      string
+}
+
+type ModifySnatEntryResponse struct {
+	common.Response
+}
+
+type DeleteSnatEntryArgs struct {
+	RegionId    common.Region
+	SnatTableId string
+	SnatEntryId string
+}
+
+type DeleteSnatEntryResponse struct {
+	common.Response
+}
+
+func (client *Client) CreateSnatEntry(args *CreateSnatEntryArgs) (resp *CreateSnatEntryResponse, err error) {
+	response := CreateSnatEntryResponse{}
+	err = client.Invoke("CreateSnatEntry", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return &response, err
+}
+
+func (client *Client) DescribeSnatTableEntries(args *DescribeSnatTableEntriesArgs) (snatTableEntries []SnatEntrySetType,
+	pagination *common.PaginationResult, err error) {
+
+	args.Validate()
+	response := DescribeSnatTableEntriesResponse{}
+
+	err = client.Invoke("DescribeSnatTableEntries", args, &response)
+
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return response.SnatTableEntries.SnatTableEntry, &response.PaginationResult, nil
+}
+
+func (client *Client) ModifySnatEntry(args *ModifySnatEntryArgs) error {
+	response := ModifySnatEntryResponse{}
+	return client.Invoke("ModifySnatEntry", args, &response)
+}
+
+func (client *Client) DeleteSnatEntry(args *DeleteSnatEntryArgs) error {
+	response := DeleteSnatEntryResponse{}
+	err := client.Invoke("DeleteSnatEntry", args, &response)
+	return err
+}

+ 144 - 0
vendor/github.com/denverdino/aliyungo/ecs/ssh_key_pair.go

@@ -0,0 +1,144 @@
+package ecs
+
+import (
+	"github.com/denverdino/aliyungo/common"
+)
+
+type CreateKeyPairArgs struct {
+	RegionId    common.Region
+	KeyPairName string
+}
+
+type CreateKeyPairResponse struct {
+	common.Response
+	KeyPairName        string
+	KeyPairFingerPrint string
+	PrivateKeyBody     string
+}
+
+// CreateKeyPair creates keypair
+//
+// You can read doc at https://help.aliyun.com/document_detail/51771.html?spm=5176.doc51775.6.910.cedjfr
+func (client *Client) CreateKeyPair(args *CreateKeyPairArgs) (resp *CreateKeyPairResponse,err error) {
+	response := CreateKeyPairResponse{}
+	err = client.Invoke("CreateKeyPair", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return &response, err
+}
+
+type ImportKeyPairArgs struct {
+	RegionId      common.Region
+	PublicKeyBody string
+	KeyPairName   string
+}
+
+type ImportKeyPairResponse struct {
+	common.Response
+	KeyPairName        string
+	KeyPairFingerPrint string
+}
+
+// ImportKeyPair import keypair
+//
+// You can read doc at https://help.aliyun.com/document_detail/51774.html?spm=5176.doc51771.6.911.BicQq2
+func (client *Client) ImportKeyPair(args *ImportKeyPairArgs) (resp *ImportKeyPairResponse,err error) {
+	response := ImportKeyPairResponse{}
+	err = client.Invoke("ImportKeyPair", args, &response)
+	if err != nil {
+		return nil, err
+	}
+	return &response, err
+}
+
+type DescribeKeyPairsArgs struct {
+	RegionId           common.Region
+	KeyPairFingerPrint string
+	KeyPairName        string
+	common.Pagination
+}
+
+type KeyPairItemType struct {
+	KeyPairName        string
+	KeyPairFingerPrint string
+}
+
+type DescribeKeyPairsResponse struct {
+	common.Response
+	common.PaginationResult
+	RegionId common.Region
+	KeyPairs struct {
+			 KeyPair []KeyPairItemType
+	}
+}
+
+// DescribeKeyPairs describe keypairs
+//
+// You can read doc at https://help.aliyun.com/document_detail/51773.html?spm=5176.doc51774.6.912.lyE0iX
+func (client *Client) DescribeKeyPairs(args *DescribeKeyPairsArgs) (KeyPairs   []KeyPairItemType, pagination *common.PaginationResult, err error) {
+	response := DescribeKeyPairsResponse{}
+
+	err = client.Invoke("DescribeKeyPairs", args, &response)
+
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return response.KeyPairs.KeyPair, &response.PaginationResult, err
+}
+
+type AttachKeyPairArgs struct {
+	RegionId    common.Region
+	KeyPairName string
+	InstanceIds string
+}
+
+// AttachKeyPair keypars to instances
+//
+// You can read doc at https://help.aliyun.com/document_detail/51775.html?spm=5176.doc51773.6.913.igEem4
+func (client *Client) AttachKeyPair(args *AttachKeyPairArgs) (err error) {
+	response := common.Response{}
+	err = client.Invoke("AttachKeyPair", args, &response)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+type DetachKeyPairArgs struct {
+	RegionId    common.Region
+	KeyPairName string
+	InstanceIds string
+}
+
+// DetachKeyPair keyparis from instances
+//
+// You can read doc at https://help.aliyun.com/document_detail/51776.html?spm=5176.doc51775.6.914.DJ7Gmq
+func (client *Client) DetachKeyPair(args *DetachKeyPairArgs) (err error) {
+	response := common.Response{}
+	err = client.Invoke("DetachKeyPair", args, &response)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+type DeleteKeyPairsArgs struct {
+	RegionId     common.Region
+	KeyPairNames string
+}
+
+// DeleteKeyPairs delete keypairs
+//
+// You can read doc at https://help.aliyun.com/document_detail/51772.html?spm=5176.doc51776.6.915.Qqcv2Q
+func (client *Client) DeleteKeyPairs(args *DeleteKeyPairsArgs) (err error) {
+	response := common.Response{}
+	err = client.Invoke("DeleteKeyPairs", args, &response)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+

+ 1 - 0
vendor/github.com/denverdino/aliyungo/ecs/vpcs.go

@@ -79,6 +79,7 @@ type VpcSetType struct {
 	CidrBlock    string
 	VRouterId    string
 	Description  string
+	IsDefault    bool
 	CreationTime util.ISO6801Time
 }
 

+ 1 - 0
vendor/github.com/denverdino/aliyungo/ecs/vswitches.go

@@ -77,6 +77,7 @@ type VSwitchSetType struct {
 	AvailableIpAddressCount int
 	Description             string
 	VSwitchName             string
+	IsDefault               bool
 	CreationTime            util.ISO6801Time
 }
 

+ 162 - 0
vendor/github.com/denverdino/aliyungo/util/encoding.go

@@ -7,9 +7,26 @@ import (
 	"net/url"
 	"reflect"
 	"strconv"
+	"strings"
 	"time"
 )
 
+// change instance=["a", "b"]
+// to instance.1="a" instance.2="b"
+func FlattenFn(fieldName string, field reflect.Value, values *url.Values) {
+	l := field.Len()
+	if l > 0 {
+		for i := 0; i < l; i++ {
+			str := field.Index(i).String()
+			values.Set(fieldName+"."+strconv.Itoa(i+1), str)
+		}
+	}
+}
+
+func Underline2Dot(name string) string {
+	return strings.Replace(name, "_", ".", -1)
+}
+
 //ConvertToQueryValues converts the struct to url.Values
 func ConvertToQueryValues(ifc interface{}) url.Values {
 	values := url.Values{}
@@ -22,6 +39,10 @@ func SetQueryValues(ifc interface{}, values *url.Values) {
 	setQueryValues(ifc, values, "")
 }
 
+func SetQueryValueByFlattenMethod(ifc interface{}, values *url.Values) {
+	setQueryValuesByFlattenMethod(ifc, values, "")
+}
+
 func setQueryValues(i interface{}, values *url.Values, prefix string) {
 	// add to support url.Values
 	mapValues, ok := i.(url.Values)
@@ -150,3 +171,144 @@ func setQueryValues(i interface{}, values *url.Values, prefix string) {
 		}
 	}
 }
+
+func setQueryValuesByFlattenMethod(i interface{}, values *url.Values, prefix string) {
+	// add to support url.Values
+	mapValues, ok := i.(url.Values)
+	if ok {
+		for k, _ := range mapValues {
+			values.Set(k, mapValues.Get(k))
+		}
+		return
+	}
+
+	elem := reflect.ValueOf(i)
+	if elem.Kind() == reflect.Ptr {
+		elem = elem.Elem()
+	}
+	elemType := elem.Type()
+	for i := 0; i < elem.NumField(); i++ {
+
+		fieldName := elemType.Field(i).Name
+		anonymous := elemType.Field(i).Anonymous
+		field := elem.Field(i)
+
+		// TODO Use Tag for validation
+		// tag := typ.Field(i).Tag.Get("tagname")
+		kind := field.Kind()
+
+		if (kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map || kind == reflect.Chan) && field.IsNil() {
+			continue
+		}
+		if kind == reflect.Ptr {
+			field = field.Elem()
+			kind = field.Kind()
+		}
+
+		var value string
+		//switch field.Interface().(type) {
+		switch kind {
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			i := field.Int()
+			if i != 0 {
+				value = strconv.FormatInt(i, 10)
+			}
+		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+			i := field.Uint()
+			if i != 0 {
+				value = strconv.FormatUint(i, 10)
+			}
+		case reflect.Float32:
+			value = strconv.FormatFloat(field.Float(), 'f', 4, 32)
+		case reflect.Float64:
+			value = strconv.FormatFloat(field.Float(), 'f', 4, 64)
+		case reflect.Bool:
+			value = strconv.FormatBool(field.Bool())
+		case reflect.String:
+			value = field.String()
+		case reflect.Map:
+			ifc := field.Interface()
+			m := ifc.(map[string]string)
+			if m != nil {
+				j := 0
+				for k, v := range m {
+					j++
+					keyName := fmt.Sprintf("%s.%d.Key", fieldName, j)
+					values.Set(keyName, k)
+					valueName := fmt.Sprintf("%s.%d.Value", fieldName, j)
+					values.Set(valueName, v)
+				}
+			}
+		case reflect.Slice:
+			if field.Type().Name() == "FlattenArray" {
+				FlattenFn(fieldName, field, values)
+			} else {
+				switch field.Type().Elem().Kind() {
+				case reflect.Uint8:
+					value = string(field.Bytes())
+				case reflect.String:
+					l := field.Len()
+					if l > 0 {
+						strArray := make([]string, l)
+						for i := 0; i < l; i++ {
+							strArray[i] = field.Index(i).String()
+						}
+						bytes, err := json.Marshal(strArray)
+						if err == nil {
+							value = string(bytes)
+						} else {
+							log.Printf("Failed to convert JSON: %v", err)
+						}
+					}
+				default:
+					l := field.Len()
+					for j := 0; j < l; j++ {
+						prefixName := fmt.Sprintf("%s.%d.", fieldName, (j + 1))
+						ifc := field.Index(j).Interface()
+						//log.Printf("%s : %v", prefixName, ifc)
+						if ifc != nil {
+							setQueryValuesByFlattenMethod(ifc, values, prefixName)
+						}
+					}
+					continue
+				}
+			}
+
+		default:
+			switch field.Interface().(type) {
+			case ISO6801Time:
+				t := field.Interface().(ISO6801Time)
+				value = t.String()
+			case time.Time:
+				t := field.Interface().(time.Time)
+				value = GetISO8601TimeStamp(t)
+			default:
+
+				ifc := field.Interface()
+				if ifc != nil {
+					if anonymous {
+						SetQueryValues(ifc, values)
+					} else {
+						prefixName := fieldName + "."
+						setQueryValuesByFlattenMethod(ifc, values, prefixName)
+					}
+					continue
+				}
+			}
+		}
+		if value != "" {
+			name := elemType.Field(i).Tag.Get("ArgName")
+			if name == "" {
+				name = fieldName
+			}
+			if prefix != "" {
+				name = prefix + name
+			}
+			// NOTE: here we will change name to underline style when the type is UnderlineString
+			if field.Type().Name() == "UnderlineString" {
+				name = Underline2Dot(name)
+			}
+			values.Set(name, value)
+		}
+	}
+}

+ 48 - 25
vendor/github.com/go-ini/ini/ini.go

@@ -37,7 +37,7 @@ const (
 
 	// Maximum allowed depth when recursively substituing variable names.
 	_DEPTH_VALUES = 99
-	_VERSION      = "1.24.0"
+	_VERSION      = "1.28.1"
 )
 
 // Version returns current package version literal.
@@ -60,6 +60,9 @@ var (
 
 	// Explicitly write DEFAULT section header
 	DefaultHeader = false
+
+	// Indicate whether to put a line between sections
+	PrettySection = true
 )
 
 func init() {
@@ -173,9 +176,13 @@ type LoadOptions struct {
 	Insensitive bool
 	// IgnoreContinuation indicates whether to ignore continuation lines while parsing.
 	IgnoreContinuation bool
+	// IgnoreInlineComment indicates whether to ignore comments at the end of value and treat it as part of value.
+	IgnoreInlineComment bool
 	// AllowBooleanKeys indicates whether to allow boolean type keys or treat as value is missing.
 	// This type of keys are mostly used in my.cnf.
 	AllowBooleanKeys bool
+	// AllowShadows indicates whether to keep track of keys with same name under same section.
+	AllowShadows bool
 	// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
 	// conform to key/value pairs. Specify the names of those blocks here.
 	UnparseableSections []string
@@ -219,6 +226,12 @@ func InsensitiveLoad(source interface{}, others ...interface{}) (*File, error) {
 	return LoadSources(LoadOptions{Insensitive: true}, source, others...)
 }
 
+// InsensitiveLoad has exactly same functionality as Load function
+// except it allows have shadow keys.
+func ShadowLoad(source interface{}, others ...interface{}) (*File, error) {
+	return LoadSources(LoadOptions{AllowShadows: true}, source, others...)
+}
+
 // Empty returns an empty file object.
 func Empty() *File {
 	// Ignore error here, we sure our data is good.
@@ -311,6 +324,11 @@ func (f *File) Sections() []*Section {
 	return sections
 }
 
+// ChildSections returns a list of child sections of given section name.
+func (f *File) ChildSections(name string) []*Section {
+	return f.Section(name).ChildSections()
+}
+
 // SectionStrings returns list of section names.
 func (f *File) SectionStrings() []string {
 	list := make([]string, len(f.sectionList))
@@ -441,6 +459,7 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 		}
 		alignSpaces := bytes.Repeat([]byte(" "), alignLength)
 
+	KEY_LIST:
 		for _, kname := range sec.keyList {
 			key := sec.Key(kname)
 			if len(key.Comment) > 0 {
@@ -467,37 +486,41 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) {
 			case strings.Contains(kname, "`"):
 				kname = `"""` + kname + `"""`
 			}
-			if _, err = buf.WriteString(kname); err != nil {
-				return 0, err
-			}
 
-			if key.isBooleanType {
-				if kname != sec.keyList[len(sec.keyList)-1] {
-					buf.WriteString(LineBreak)
+			for _, val := range key.ValueWithShadows() {
+				if _, err = buf.WriteString(kname); err != nil {
+					return 0, err
 				}
-				continue
-			}
 
-			// Write out alignment spaces before "=" sign
-			if PrettyFormat {
-				buf.Write(alignSpaces[:alignLength-len(kname)])
-			}
+				if key.isBooleanType {
+					if kname != sec.keyList[len(sec.keyList)-1] {
+						buf.WriteString(LineBreak)
+					}
+					continue KEY_LIST
+				}
 
-			val := key.value
-			// In case key value contains "\n", "`", "\"", "#" or ";"
-			if strings.ContainsAny(val, "\n`") {
-				val = `"""` + val + `"""`
-			} else if strings.ContainsAny(val, "#;") {
-				val = "`" + val + "`"
-			}
-			if _, err = buf.WriteString(equalSign + val + LineBreak); err != nil {
-				return 0, err
+				// Write out alignment spaces before "=" sign
+				if PrettyFormat {
+					buf.Write(alignSpaces[:alignLength-len(kname)])
+				}
+
+				// In case key value contains "\n", "`", "\"", "#" or ";"
+				if strings.ContainsAny(val, "\n`") {
+					val = `"""` + val + `"""`
+				} else if !f.options.IgnoreInlineComment && strings.ContainsAny(val, "#;") {
+					val = "`" + val + "`"
+				}
+				if _, err = buf.WriteString(equalSign + val + LineBreak); err != nil {
+					return 0, err
+				}
 			}
 		}
 
-		// Put a line between sections
-		if _, err = buf.WriteString(LineBreak); err != nil {
-			return 0, err
+		if PrettySection {
+			// Put a line between sections
+			if _, err = buf.WriteString(LineBreak); err != nil {
+				return 0, err
+			}
 		}
 	}
 

+ 107 - 41
vendor/github.com/go-ini/ini/key.go

@@ -15,6 +15,7 @@
 package ini
 
 import (
+	"errors"
 	"fmt"
 	"strconv"
 	"strings"
@@ -29,9 +30,42 @@ type Key struct {
 	isAutoIncrement bool
 	isBooleanType   bool
 
+	isShadow bool
+	shadows  []*Key
+
 	Comment string
 }
 
+// newKey simply return a key object with given values.
+func newKey(s *Section, name, val string) *Key {
+	return &Key{
+		s:     s,
+		name:  name,
+		value: val,
+	}
+}
+
+func (k *Key) addShadow(val string) error {
+	if k.isShadow {
+		return errors.New("cannot add shadow to another shadow key")
+	} else if k.isAutoIncrement || k.isBooleanType {
+		return errors.New("cannot add shadow to auto-increment or boolean key")
+	}
+
+	shadow := newKey(k.s, k.name, val)
+	shadow.isShadow = true
+	k.shadows = append(k.shadows, shadow)
+	return nil
+}
+
+// AddShadow adds a new shadow key to itself.
+func (k *Key) AddShadow(val string) error {
+	if !k.s.f.options.AllowShadows {
+		return errors.New("shadow key is not allowed")
+	}
+	return k.addShadow(val)
+}
+
 // ValueMapper represents a mapping function for values, e.g. os.ExpandEnv
 type ValueMapper func(string) string
 
@@ -45,16 +79,29 @@ func (k *Key) Value() string {
 	return k.value
 }
 
-// String returns string representation of value.
-func (k *Key) String() string {
-	val := k.value
+// ValueWithShadows returns raw values of key and its shadows if any.
+func (k *Key) ValueWithShadows() []string {
+	if len(k.shadows) == 0 {
+		return []string{k.value}
+	}
+	vals := make([]string, len(k.shadows)+1)
+	vals[0] = k.value
+	for i := range k.shadows {
+		vals[i+1] = k.shadows[i].value
+	}
+	return vals
+}
+
+// transformValue takes a raw value and transforms to its final string.
+func (k *Key) transformValue(val string) string {
 	if k.s.f.ValueMapper != nil {
 		val = k.s.f.ValueMapper(val)
 	}
-	if strings.Index(val, "%") == -1 {
+
+	// Fail-fast if no indicate char found for recursive value
+	if !strings.Contains(val, "%") {
 		return val
 	}
-
 	for i := 0; i < _DEPTH_VALUES; i++ {
 		vr := varPattern.FindString(val)
 		if len(vr) == 0 {
@@ -78,6 +125,11 @@ func (k *Key) String() string {
 	return val
 }
 
+// String returns string representation of value.
+func (k *Key) String() string {
+	return k.transformValue(k.value)
+}
+
 // Validate accepts a validate function which can
 // return modifed result as key value.
 func (k *Key) Validate(fn func(string) string) string {
@@ -394,45 +446,65 @@ func (k *Key) Strings(delim string) []string {
 
 	vals := strings.Split(str, delim)
 	for i := range vals {
+		// vals[i] = k.transformValue(strings.TrimSpace(vals[i]))
 		vals[i] = strings.TrimSpace(vals[i])
 	}
 	return vals
 }
 
+// StringsWithShadows returns list of string divided by given delimiter.
+// Shadows will also be appended if any.
+func (k *Key) StringsWithShadows(delim string) []string {
+	vals := k.ValueWithShadows()
+	results := make([]string, 0, len(vals)*2)
+	for i := range vals {
+		if len(vals) == 0 {
+			continue
+		}
+
+		results = append(results, strings.Split(vals[i], delim)...)
+	}
+
+	for i := range results {
+		results[i] = k.transformValue(strings.TrimSpace(results[i]))
+	}
+	return results
+}
+
 // Float64s returns list of float64 divided by given delimiter. Any invalid input will be treated as zero value.
 func (k *Key) Float64s(delim string) []float64 {
-	vals, _ := k.getFloat64s(delim, true, false)
+	vals, _ := k.parseFloat64s(k.Strings(delim), true, false)
 	return vals
 }
 
 // Ints returns list of int divided by given delimiter. Any invalid input will be treated as zero value.
 func (k *Key) Ints(delim string) []int {
-	vals, _ := k.getInts(delim, true, false)
+	vals, _ := k.parseInts(k.Strings(delim), true, false)
 	return vals
 }
 
 // Int64s returns list of int64 divided by given delimiter. Any invalid input will be treated as zero value.
 func (k *Key) Int64s(delim string) []int64 {
-	vals, _ := k.getInt64s(delim, true, false)
+	vals, _ := k.parseInt64s(k.Strings(delim), true, false)
 	return vals
 }
 
 // Uints returns list of uint divided by given delimiter. Any invalid input will be treated as zero value.
 func (k *Key) Uints(delim string) []uint {
-	vals, _ := k.getUints(delim, true, false)
+	vals, _ := k.parseUints(k.Strings(delim), true, false)
 	return vals
 }
 
 // Uint64s returns list of uint64 divided by given delimiter. Any invalid input will be treated as zero value.
 func (k *Key) Uint64s(delim string) []uint64 {
-	vals, _ := k.getUint64s(delim, true, false)
+	vals, _ := k.parseUint64s(k.Strings(delim), true, false)
 	return vals
 }
 
 // TimesFormat parses with given format and returns list of time.Time divided by given delimiter.
 // Any invalid input will be treated as zero value (0001-01-01 00:00:00 +0000 UTC).
 func (k *Key) TimesFormat(format, delim string) []time.Time {
-	vals, _ := k.getTimesFormat(format, delim, true, false)
+	vals, _ := k.parseTimesFormat(format, k.Strings(delim), true, false)
 	return vals
 }
 
@@ -445,41 +517,41 @@ func (k *Key) Times(delim string) []time.Time {
 // ValidFloat64s returns list of float64 divided by given delimiter. If some value is not float, then
 // it will not be included to result list.
 func (k *Key) ValidFloat64s(delim string) []float64 {
-	vals, _ := k.getFloat64s(delim, false, false)
+	vals, _ := k.parseFloat64s(k.Strings(delim), false, false)
 	return vals
 }
 
 // ValidInts returns list of int divided by given delimiter. If some value is not integer, then it will
 // not be included to result list.
 func (k *Key) ValidInts(delim string) []int {
-	vals, _ := k.getInts(delim, false, false)
+	vals, _ := k.parseInts(k.Strings(delim), false, false)
 	return vals
 }
 
 // ValidInt64s returns list of int64 divided by given delimiter. If some value is not 64-bit integer,
 // then it will not be included to result list.
 func (k *Key) ValidInt64s(delim string) []int64 {
-	vals, _ := k.getInt64s(delim, false, false)
+	vals, _ := k.parseInt64s(k.Strings(delim), false, false)
 	return vals
 }
 
 // ValidUints returns list of uint divided by given delimiter. If some value is not unsigned integer,
 // then it will not be included to result list.
 func (k *Key) ValidUints(delim string) []uint {
-	vals, _ := k.getUints(delim, false, false)
+	vals, _ := k.parseUints(k.Strings(delim), false, false)
 	return vals
 }
 
 // ValidUint64s returns list of uint64 divided by given delimiter. If some value is not 64-bit unsigned
 // integer, then it will not be included to result list.
 func (k *Key) ValidUint64s(delim string) []uint64 {
-	vals, _ := k.getUint64s(delim, false, false)
+	vals, _ := k.parseUint64s(k.Strings(delim), false, false)
 	return vals
 }
 
 // ValidTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
 func (k *Key) ValidTimesFormat(format, delim string) []time.Time {
-	vals, _ := k.getTimesFormat(format, delim, false, false)
+	vals, _ := k.parseTimesFormat(format, k.Strings(delim), false, false)
 	return vals
 }
 
@@ -490,33 +562,33 @@ func (k *Key) ValidTimes(delim string) []time.Time {
 
 // StrictFloat64s returns list of float64 divided by given delimiter or error on first invalid input.
 func (k *Key) StrictFloat64s(delim string) ([]float64, error) {
-	return k.getFloat64s(delim, false, true)
+	return k.parseFloat64s(k.Strings(delim), false, true)
 }
 
 // StrictInts returns list of int divided by given delimiter or error on first invalid input.
 func (k *Key) StrictInts(delim string) ([]int, error) {
-	return k.getInts(delim, false, true)
+	return k.parseInts(k.Strings(delim), false, true)
 }
 
 // StrictInt64s returns list of int64 divided by given delimiter or error on first invalid input.
 func (k *Key) StrictInt64s(delim string) ([]int64, error) {
-	return k.getInt64s(delim, false, true)
+	return k.parseInt64s(k.Strings(delim), false, true)
 }
 
 // StrictUints returns list of uint divided by given delimiter or error on first invalid input.
 func (k *Key) StrictUints(delim string) ([]uint, error) {
-	return k.getUints(delim, false, true)
+	return k.parseUints(k.Strings(delim), false, true)
 }
 
 // StrictUint64s returns list of uint64 divided by given delimiter or error on first invalid input.
 func (k *Key) StrictUint64s(delim string) ([]uint64, error) {
-	return k.getUint64s(delim, false, true)
+	return k.parseUint64s(k.Strings(delim), false, true)
 }
 
 // StrictTimesFormat parses with given format and returns list of time.Time divided by given delimiter
 // or error on first invalid input.
 func (k *Key) StrictTimesFormat(format, delim string) ([]time.Time, error) {
-	return k.getTimesFormat(format, delim, false, true)
+	return k.parseTimesFormat(format, k.Strings(delim), false, true)
 }
 
 // StrictTimes parses with RFC3339 format and returns list of time.Time divided by given delimiter
@@ -525,9 +597,8 @@ func (k *Key) StrictTimes(delim string) ([]time.Time, error) {
 	return k.StrictTimesFormat(time.RFC3339, delim)
 }
 
-// getFloat64s returns list of float64 divided by given delimiter.
-func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]float64, error) {
-	strs := k.Strings(delim)
+// parseFloat64s transforms strings to float64s.
+func (k *Key) parseFloat64s(strs []string, addInvalid, returnOnInvalid bool) ([]float64, error) {
 	vals := make([]float64, 0, len(strs))
 	for _, str := range strs {
 		val, err := strconv.ParseFloat(str, 64)
@@ -541,9 +612,8 @@ func (k *Key) getFloat64s(delim string, addInvalid, returnOnInvalid bool) ([]flo
 	return vals, nil
 }
 
-// getInts returns list of int divided by given delimiter.
-func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, error) {
-	strs := k.Strings(delim)
+// parseInts transforms strings to ints.
+func (k *Key) parseInts(strs []string, addInvalid, returnOnInvalid bool) ([]int, error) {
 	vals := make([]int, 0, len(strs))
 	for _, str := range strs {
 		val, err := strconv.Atoi(str)
@@ -557,9 +627,8 @@ func (k *Key) getInts(delim string, addInvalid, returnOnInvalid bool) ([]int, er
 	return vals, nil
 }
 
-// getInt64s returns list of int64 divided by given delimiter.
-func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64, error) {
-	strs := k.Strings(delim)
+// parseInt64s transforms strings to int64s.
+func (k *Key) parseInt64s(strs []string, addInvalid, returnOnInvalid bool) ([]int64, error) {
 	vals := make([]int64, 0, len(strs))
 	for _, str := range strs {
 		val, err := strconv.ParseInt(str, 10, 64)
@@ -573,9 +642,8 @@ func (k *Key) getInt64s(delim string, addInvalid, returnOnInvalid bool) ([]int64
 	return vals, nil
 }
 
-// getUints returns list of uint divided by given delimiter.
-func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint, error) {
-	strs := k.Strings(delim)
+// parseUints transforms strings to uints.
+func (k *Key) parseUints(strs []string, addInvalid, returnOnInvalid bool) ([]uint, error) {
 	vals := make([]uint, 0, len(strs))
 	for _, str := range strs {
 		val, err := strconv.ParseUint(str, 10, 0)
@@ -589,9 +657,8 @@ func (k *Key) getUints(delim string, addInvalid, returnOnInvalid bool) ([]uint,
 	return vals, nil
 }
 
-// getUint64s returns list of uint64 divided by given delimiter.
-func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
-	strs := k.Strings(delim)
+// parseUint64s transforms strings to uint64s.
+func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]uint64, error) {
 	vals := make([]uint64, 0, len(strs))
 	for _, str := range strs {
 		val, err := strconv.ParseUint(str, 10, 64)
@@ -605,9 +672,8 @@ func (k *Key) getUint64s(delim string, addInvalid, returnOnInvalid bool) ([]uint
 	return vals, nil
 }
 
-// getTimesFormat parses with given format and returns list of time.Time divided by given delimiter.
-func (k *Key) getTimesFormat(format, delim string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
-	strs := k.Strings(delim)
+// parseTimesFormat transforms strings to times in given format.
+func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
 	vals := make([]time.Time, 0, len(strs))
 	for _, str := range strs {
 		val, err := time.Parse(format, str)

+ 15 - 13
vendor/github.com/go-ini/ini/parser.go

@@ -189,11 +189,11 @@ func (p *parser) readContinuationLines(val string) (string, error) {
 // are quotes \" or \'.
 // It returns false if any other parts also contain same kind of quotes.
 func hasSurroundedQuote(in string, quote byte) bool {
-	return len(in) > 2 && in[0] == quote && in[len(in)-1] == quote &&
+	return len(in) >= 2 && in[0] == quote && in[len(in)-1] == quote &&
 		strings.IndexByte(in[1:], quote) == len(in)-2
 }
 
-func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
+func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bool) (string, error) {
 	line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
 	if len(line) == 0 {
 		return "", nil
@@ -217,18 +217,21 @@ func (p *parser) readValue(in []byte, ignoreContinuation bool) (string, error) {
 		return line[startIdx : pos+startIdx], nil
 	}
 
-	// Won't be able to reach here if value only contains whitespace.
+	// Won't be able to reach here if value only contains whitespace
 	line = strings.TrimSpace(line)
 
-	// Check continuation lines when desired.
+	// Check continuation lines when desired
 	if !ignoreContinuation && line[len(line)-1] == '\\' {
 		return p.readContinuationLines(line[:len(line)-1])
 	}
 
-	i := strings.IndexAny(line, "#;")
-	if i > -1 {
-		p.comment.WriteString(line[i:])
-		line = strings.TrimSpace(line[:i])
+	// Check if ignore inline comment
+	if !ignoreInlineComment {
+		i := strings.IndexAny(line, "#;")
+		if i > -1 {
+			p.comment.WriteString(line[i:])
+			line = strings.TrimSpace(line[:i])
+		}
 	}
 
 	// Trim single quotes
@@ -318,7 +321,7 @@ func (f *File) parse(reader io.Reader) (err error) {
 		if err != nil {
 			// Treat as boolean key when desired, and whole line is key name.
 			if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
-				kname, err := p.readValue(line, f.options.IgnoreContinuation)
+				kname, err := p.readValue(line, f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
 				if err != nil {
 					return err
 				}
@@ -341,17 +344,16 @@ func (f *File) parse(reader io.Reader) (err error) {
 			p.count++
 		}
 
-		key, err := section.NewKey(kname, "")
+		value, err := p.readValue(line[offset:], f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
 		if err != nil {
 			return err
 		}
-		key.isAutoIncrement = isAutoIncr
 
-		value, err := p.readValue(line[offset:], f.options.IgnoreContinuation)
+		key, err := section.NewKey(kname, value)
 		if err != nil {
 			return err
 		}
-		key.SetValue(value)
+		key.isAutoIncrement = isAutoIncr
 		key.Comment = strings.TrimSpace(p.comment.String())
 		p.comment.Reset()
 	}

+ 22 - 6
vendor/github.com/go-ini/ini/section.go

@@ -68,16 +68,18 @@ func (s *Section) NewKey(name, val string) (*Key, error) {
 	}
 
 	if inSlice(name, s.keyList) {
-		s.keys[name].value = val
+		if s.f.options.AllowShadows {
+			if err := s.keys[name].addShadow(val); err != nil {
+				return nil, err
+			}
+		} else {
+			s.keys[name].value = val
+		}
 		return s.keys[name], nil
 	}
 
 	s.keyList = append(s.keyList, name)
-	s.keys[name] = &Key{
-		s:     s,
-		name:  name,
-		value: val,
-	}
+	s.keys[name] = newKey(s, name, val)
 	s.keysHash[name] = val
 	return s.keys[name], nil
 }
@@ -230,3 +232,17 @@ func (s *Section) DeleteKey(name string) {
 		}
 	}
 }
+
+// ChildSections returns a list of child sections of current section.
+// For example, "[parent.child1]" and "[parent.child12]" are child sections
+// of section "[parent]".
+func (s *Section) ChildSections() []*Section {
+	prefix := s.name + "."
+	children := make([]*Section, 0, 3)
+	for _, name := range s.f.sectionList {
+		if strings.HasPrefix(name, prefix) {
+			children = append(children, s.f.sections[name])
+		}
+	}
+	return children
+}

+ 93 - 24
vendor/github.com/go-ini/ini/struct.go

@@ -78,34 +78,44 @@ func parseDelim(actual string) string {
 var reflectTime = reflect.TypeOf(time.Now()).Kind()
 
 // setSliceWithProperType sets proper values to slice based on its type.
-func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
-	strs := key.Strings(delim)
+func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
+	var strs []string
+	if allowShadow {
+		strs = key.StringsWithShadows(delim)
+	} else {
+		strs = key.Strings(delim)
+	}
+
 	numVals := len(strs)
 	if numVals == 0 {
 		return nil
 	}
 
 	var vals interface{}
+	var err error
 
 	sliceOf := field.Type().Elem().Kind()
 	switch sliceOf {
 	case reflect.String:
 		vals = strs
 	case reflect.Int:
-		vals = key.Ints(delim)
+		vals, err = key.parseInts(strs, true, false)
 	case reflect.Int64:
-		vals = key.Int64s(delim)
+		vals, err = key.parseInt64s(strs, true, false)
 	case reflect.Uint:
-		vals = key.Uints(delim)
+		vals, err = key.parseUints(strs, true, false)
 	case reflect.Uint64:
-		vals = key.Uint64s(delim)
+		vals, err = key.parseUint64s(strs, true, false)
 	case reflect.Float64:
-		vals = key.Float64s(delim)
+		vals, err = key.parseFloat64s(strs, true, false)
 	case reflectTime:
-		vals = key.Times(delim)
+		vals, err = key.parseTimesFormat(time.RFC3339, strs, true, false)
 	default:
 		return fmt.Errorf("unsupported type '[]%s'", sliceOf)
 	}
+	if isStrict {
+		return err
+	}
 
 	slice := reflect.MakeSlice(field.Type(), numVals, numVals)
 	for i := 0; i < numVals; i++ {
@@ -130,10 +140,17 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string) error {
 	return nil
 }
 
+func wrapStrictError(err error, isStrict bool) error {
+	if isStrict {
+		return err
+	}
+	return nil
+}
+
 // 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 {
+func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim string, allowShadow, isStrict bool) error {
 	switch t.Kind() {
 	case reflect.String:
 		if len(key.String()) == 0 {
@@ -143,7 +160,7 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 	case reflect.Bool:
 		boolVal, err := key.Bool()
 		if err != nil {
-			return nil
+			return wrapStrictError(err, isStrict)
 		}
 		field.SetBool(boolVal)
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
@@ -155,8 +172,8 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 		}
 
 		intVal, err := key.Int64()
-		if err != nil || intVal == 0 {
-			return nil
+		if err != nil {
+			return wrapStrictError(err, isStrict)
 		}
 		field.SetInt(intVal)
 	//	byte is an alias for uint8, so supporting uint8 breaks support for byte
@@ -170,31 +187,43 @@ func setWithProperType(t reflect.Type, key *Key, field reflect.Value, delim stri
 
 		uintVal, err := key.Uint64()
 		if err != nil {
-			return nil
+			return wrapStrictError(err, isStrict)
 		}
 		field.SetUint(uintVal)
 
 	case reflect.Float32, reflect.Float64:
 		floatVal, err := key.Float64()
 		if err != nil {
-			return nil
+			return wrapStrictError(err, isStrict)
 		}
 		field.SetFloat(floatVal)
 	case reflectTime:
 		timeVal, err := key.Time()
 		if err != nil {
-			return nil
+			return wrapStrictError(err, isStrict)
 		}
 		field.Set(reflect.ValueOf(timeVal))
 	case reflect.Slice:
-		return setSliceWithProperType(key, field, delim)
+		return setSliceWithProperType(key, field, delim, allowShadow, isStrict)
 	default:
 		return fmt.Errorf("unsupported type '%s'", t)
 	}
 	return nil
 }
 
-func (s *Section) mapTo(val reflect.Value) error {
+func parseTagOptions(tag string) (rawName string, omitEmpty bool, allowShadow bool) {
+	opts := strings.SplitN(tag, ",", 3)
+	rawName = opts[0]
+	if len(opts) > 1 {
+		omitEmpty = opts[1] == "omitempty"
+	}
+	if len(opts) > 2 {
+		allowShadow = opts[2] == "allowshadow"
+	}
+	return rawName, omitEmpty, allowShadow
+}
+
+func (s *Section) mapTo(val reflect.Value, isStrict bool) error {
 	if val.Kind() == reflect.Ptr {
 		val = val.Elem()
 	}
@@ -209,8 +238,8 @@ func (s *Section) mapTo(val reflect.Value) error {
 			continue
 		}
 
-		opts := strings.SplitN(tag, ",", 2) // strip off possible omitempty
-		fieldName := s.parseFieldName(tpField.Name, opts[0])
+		rawName, _, allowShadow := parseTagOptions(tag)
+		fieldName := s.parseFieldName(tpField.Name, rawName)
 		if len(fieldName) == 0 || !field.CanSet() {
 			continue
 		}
@@ -223,7 +252,7 @@ func (s *Section) mapTo(val reflect.Value) error {
 
 		if isAnonymous || isStruct {
 			if sec, err := s.f.GetSection(fieldName); err == nil {
-				if err = sec.mapTo(field); err != nil {
+				if err = sec.mapTo(field, isStrict); err != nil {
 					return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
 				}
 				continue
@@ -231,7 +260,8 @@ func (s *Section) mapTo(val reflect.Value) error {
 		}
 
 		if key, err := s.GetKey(fieldName); err == nil {
-			if err = setWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
+			delim := parseDelim(tpField.Tag.Get("delim"))
+			if err = setWithProperType(tpField.Type, key, field, delim, allowShadow, isStrict); err != nil {
 				return fmt.Errorf("error mapping field(%s): %v", fieldName, err)
 			}
 		}
@@ -250,7 +280,22 @@ func (s *Section) MapTo(v interface{}) error {
 		return errors.New("cannot map to non-pointer struct")
 	}
 
-	return s.mapTo(val)
+	return s.mapTo(val, false)
+}
+
+// MapTo maps section to given struct in strict mode,
+// which returns all possible error including value parsing error.
+func (s *Section) StrictMapTo(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, true)
 }
 
 // MapTo maps file to given struct.
@@ -258,6 +303,12 @@ func (f *File) MapTo(v interface{}) error {
 	return f.Section("").MapTo(v)
 }
 
+// MapTo maps file to given struct in strict mode,
+// which returns all possible error including value parsing error.
+func (f *File) StrictMapTo(v interface{}) error {
+	return f.Section("").StrictMapTo(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...)
@@ -268,11 +319,28 @@ func MapToWithMapper(v interface{}, mapper NameMapper, source interface{}, other
 	return cfg.MapTo(v)
 }
 
+// StrictMapToWithMapper maps data sources to given struct with name mapper in strict mode,
+// which returns all possible error including value parsing error.
+func StrictMapToWithMapper(v interface{}, mapper NameMapper, source interface{}, others ...interface{}) error {
+	cfg, err := Load(source, others...)
+	if err != nil {
+		return err
+	}
+	cfg.NameMapper = mapper
+	return cfg.StrictMapTo(v)
+}
+
 // MapTo maps data sources to given struct.
 func MapTo(v, source interface{}, others ...interface{}) error {
 	return MapToWithMapper(v, nil, source, others...)
 }
 
+// StrictMapTo maps data sources to given struct in strict mode,
+// which returns all possible error including value parsing error.
+func StrictMapTo(v, source interface{}, others ...interface{}) error {
+	return StrictMapToWithMapper(v, nil, source, others...)
+}
+
 // reflectSliceWithProperType does the opposite thing as setSliceWithProperType.
 func reflectSliceWithProperType(key *Key, field reflect.Value, delim string) error {
 	slice := field.Slice(0, field.Len())
@@ -340,10 +408,11 @@ func isEmptyValue(v reflect.Value) bool {
 		return v.Uint() == 0
 	case reflect.Float32, reflect.Float64:
 		return v.Float() == 0
-	case reflectTime:
-		return v.Interface().(time.Time).IsZero()
 	case reflect.Interface, reflect.Ptr:
 		return v.IsNil()
+	case reflectTime:
+		t, ok := v.Interface().(time.Time)
+		return ok && t.IsZero()
 	}
 	return false
 }

+ 15 - 0
vendor/github.com/howeyc/gopass/LICENSE.txt

@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2012 Chris Howey
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 91 - 0
vendor/github.com/howeyc/gopass/pass.go

@@ -0,0 +1,91 @@
+package gopass
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"os"
+)
+
+var defaultGetCh = func() (byte, error) {
+	buf := make([]byte, 1)
+	if n, err := os.Stdin.Read(buf); n == 0 || err != nil {
+		if err != nil {
+			return 0, err
+		}
+		return 0, io.EOF
+	}
+	return buf[0], nil
+}
+
+var (
+	maxLength            = 512
+	ErrInterrupted       = errors.New("interrupted")
+	ErrMaxLengthExceeded = fmt.Errorf("maximum byte limit (%v) exceeded", maxLength)
+
+	// Provide variable so that tests can provide a mock implementation.
+	getch = defaultGetCh
+)
+
+// getPasswd returns the input read from terminal.
+// If masked is true, typing will be matched by asterisks on the screen.
+// Otherwise, typing will echo nothing.
+func getPasswd(masked bool) ([]byte, error) {
+	var err error
+	var pass, bs, mask []byte
+	if masked {
+		bs = []byte("\b \b")
+		mask = []byte("*")
+	}
+
+	if isTerminal(os.Stdin.Fd()) {
+		if oldState, err := makeRaw(os.Stdin.Fd()); err != nil {
+			return pass, err
+		} else {
+			defer restore(os.Stdin.Fd(), oldState)
+		}
+	}
+
+	// Track total bytes read, not just bytes in the password.  This ensures any
+	// errors that might flood the console with nil or -1 bytes infinitely are
+	// capped.
+	var counter int
+	for counter = 0; counter <= maxLength; counter++ {
+		if v, e := getch(); e != nil {
+			err = e
+			break
+		} else if v == 127 || v == 8 {
+			if l := len(pass); l > 0 {
+				pass = pass[:l-1]
+				fmt.Print(string(bs))
+			}
+		} else if v == 13 || v == 10 {
+			break
+		} else if v == 3 {
+			err = ErrInterrupted
+			break
+		} else if v != 0 {
+			pass = append(pass, v)
+			fmt.Print(string(mask))
+		}
+	}
+
+	if counter > maxLength {
+		err = ErrMaxLengthExceeded
+	}
+
+	fmt.Println()
+	return pass, err
+}
+
+// GetPasswd returns the password read from the terminal without echoing input.
+// The returned byte array does not include end-of-line characters.
+func GetPasswd() ([]byte, error) {
+	return getPasswd(false)
+}
+
+// GetPasswdMasked returns the password read from the terminal, echoing asterisks.
+// The returned byte array does not include end-of-line characters.
+func GetPasswdMasked() ([]byte, error) {
+	return getPasswd(true)
+}

+ 25 - 0
vendor/github.com/howeyc/gopass/terminal.go

@@ -0,0 +1,25 @@
+// +build !solaris
+
+package gopass
+
+import "golang.org/x/crypto/ssh/terminal"
+
+type terminalState struct {
+	state *terminal.State
+}
+
+func isTerminal(fd uintptr) bool {
+	return terminal.IsTerminal(int(fd))
+}
+
+func makeRaw(fd uintptr) (*terminalState, error) {
+	state, err := terminal.MakeRaw(int(fd))
+
+	return &terminalState{
+		state: state,
+	}, err
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+	return terminal.Restore(int(fd), oldState.state)
+}

+ 69 - 0
vendor/github.com/howeyc/gopass/terminal_solaris.go

@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+// Below is derived from Solaris source, so CDDL license is included.
+
+package gopass
+
+import (
+	"syscall"
+
+	"golang.org/x/sys/unix"
+)
+
+type terminalState struct {
+	state *unix.Termios
+}
+
+// isTerminal returns true if there is a terminal attached to the given
+// file descriptor.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
+func isTerminal(fd uintptr) bool {
+	var termio unix.Termio
+	err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
+	return err == nil
+}
+
+// makeRaw puts the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+// Source: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
+func makeRaw(fd uintptr) (*terminalState, error) {
+	oldTermiosPtr, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
+	if err != nil {
+		return nil, err
+	}
+	oldTermios := *oldTermiosPtr
+
+	newTermios := oldTermios
+	newTermios.Lflag &^= syscall.ECHO | syscall.ECHOE | syscall.ECHOK | syscall.ECHONL
+	if err := unix.IoctlSetTermios(int(fd), unix.TCSETS, &newTermios); err != nil {
+		return nil, err
+	}
+
+	return &terminalState{
+		state: oldTermiosPtr,
+	}, nil
+}
+
+func restore(fd uintptr, oldState *terminalState) error {
+	return unix.IoctlSetTermios(int(fd), unix.TCSETS, oldState.state)
+}

+ 28 - 0
vendor/github.com/imdario/mergo/LICENSE

@@ -0,0 +1,28 @@
+Copyright (c) 2013 Dario Castañé. All rights reserved.
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 44 - 0
vendor/github.com/imdario/mergo/doc.go

@@ -0,0 +1,44 @@
+// Copyright 2013 Dario Castañé. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package mergo merges same-type structs and maps by setting default values in zero-value fields.
+
+Mergo won't merge unexported (private) fields but will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
+
+Usage
+
+From my own work-in-progress project:
+
+	type networkConfig struct {
+		Protocol string
+		Address string
+		ServerType string `json: "server_type"`
+		Port uint16
+	}
+
+	type FssnConfig struct {
+		Network networkConfig
+	}
+
+	var fssnDefault = FssnConfig {
+		networkConfig {
+			"tcp",
+			"127.0.0.1",
+			"http",
+			31560,
+		},
+	}
+
+	// Inside a function [...]
+
+	if err := mergo.Merge(&config, fssnDefault); err != nil {
+		log.Fatal(err)
+	}
+
+	// More code [...]
+
+*/
+package mergo

+ 146 - 0
vendor/github.com/imdario/mergo/map.go

@@ -0,0 +1,146 @@
+// Copyright 2014 Dario Castañé. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Based on src/pkg/reflect/deepequal.go from official
+// golang's stdlib.
+
+package mergo
+
+import (
+	"fmt"
+	"reflect"
+	"unicode"
+	"unicode/utf8"
+)
+
+func changeInitialCase(s string, mapper func(rune) rune) string {
+	if s == "" {
+		return s
+	}
+	r, n := utf8.DecodeRuneInString(s)
+	return string(mapper(r)) + s[n:]
+}
+
+func isExported(field reflect.StructField) bool {
+	r, _ := utf8.DecodeRuneInString(field.Name)
+	return r >= 'A' && r <= 'Z'
+}
+
+// Traverses recursively both values, assigning src's fields values to dst.
+// The map argument tracks comparisons that have already been seen, which allows
+// short circuiting on recursive types.
+func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
+	if dst.CanAddr() {
+		addr := dst.UnsafeAddr()
+		h := 17 * addr
+		seen := visited[h]
+		typ := dst.Type()
+		for p := seen; p != nil; p = p.next {
+			if p.ptr == addr && p.typ == typ {
+				return nil
+			}
+		}
+		// Remember, remember...
+		visited[h] = &visit{addr, typ, seen}
+	}
+	zeroValue := reflect.Value{}
+	switch dst.Kind() {
+	case reflect.Map:
+		dstMap := dst.Interface().(map[string]interface{})
+		for i, n := 0, src.NumField(); i < n; i++ {
+			srcType := src.Type()
+			field := srcType.Field(i)
+			if !isExported(field) {
+				continue
+			}
+			fieldName := field.Name
+			fieldName = changeInitialCase(fieldName, unicode.ToLower)
+			if v, ok := dstMap[fieldName]; !ok || isEmptyValue(reflect.ValueOf(v)) {
+				dstMap[fieldName] = src.Field(i).Interface()
+			}
+		}
+	case reflect.Struct:
+		srcMap := src.Interface().(map[string]interface{})
+		for key := range srcMap {
+			srcValue := srcMap[key]
+			fieldName := changeInitialCase(key, unicode.ToUpper)
+			dstElement := dst.FieldByName(fieldName)
+			if dstElement == zeroValue {
+				// We discard it because the field doesn't exist.
+				continue
+			}
+			srcElement := reflect.ValueOf(srcValue)
+			dstKind := dstElement.Kind()
+			srcKind := srcElement.Kind()
+			if srcKind == reflect.Ptr && dstKind != reflect.Ptr {
+				srcElement = srcElement.Elem()
+				srcKind = reflect.TypeOf(srcElement.Interface()).Kind()
+			} else if dstKind == reflect.Ptr {
+				// Can this work? I guess it can't.
+				if srcKind != reflect.Ptr && srcElement.CanAddr() {
+					srcPtr := srcElement.Addr()
+					srcElement = reflect.ValueOf(srcPtr)
+					srcKind = reflect.Ptr
+				}
+			}
+			if !srcElement.IsValid() {
+				continue
+			}
+			if srcKind == dstKind {
+				if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
+					return
+				}
+			} else {
+				if srcKind == reflect.Map {
+					if err = deepMap(dstElement, srcElement, visited, depth+1); err != nil {
+						return
+					}
+				} else {
+					return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
+				}
+			}
+		}
+	}
+	return
+}
+
+// Map sets fields' values in dst from src.
+// src can be a map with string keys or a struct. dst must be the opposite:
+// if src is a map, dst must be a valid pointer to struct. If src is a struct,
+// dst must be map[string]interface{}.
+// It won't merge unexported (private) fields and will do recursively
+// any exported field.
+// If dst is a map, keys will be src fields' names in lower camel case.
+// Missing key in src that doesn't match a field in dst will be skipped. This
+// doesn't apply if dst is a map.
+// This is separated method from Merge because it is cleaner and it keeps sane
+// semantics: merging equal types, mapping different (restricted) types.
+func Map(dst, src interface{}) error {
+	var (
+		vDst, vSrc reflect.Value
+		err        error
+	)
+	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
+		return err
+	}
+	// To be friction-less, we redirect equal-type arguments
+	// to deepMerge. Only because arguments can be anything.
+	if vSrc.Kind() == vDst.Kind() {
+		return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0)
+	}
+	switch vSrc.Kind() {
+	case reflect.Struct:
+		if vDst.Kind() != reflect.Map {
+			return ErrExpectedMapAsDestination
+		}
+	case reflect.Map:
+		if vDst.Kind() != reflect.Struct {
+			return ErrExpectedStructAsDestination
+		}
+	default:
+		return ErrNotSupported
+	}
+	return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0)
+}

+ 99 - 0
vendor/github.com/imdario/mergo/merge.go

@@ -0,0 +1,99 @@
+// Copyright 2013 Dario Castañé. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Based on src/pkg/reflect/deepequal.go from official
+// golang's stdlib.
+
+package mergo
+
+import (
+	"reflect"
+)
+
+// Traverses recursively both values, assigning src's fields values to dst.
+// The map argument tracks comparisons that have already been seen, which allows
+// short circuiting on recursive types.
+func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
+	if !src.IsValid() {
+		return
+	}
+	if dst.CanAddr() {
+		addr := dst.UnsafeAddr()
+		h := 17 * addr
+		seen := visited[h]
+		typ := dst.Type()
+		for p := seen; p != nil; p = p.next {
+			if p.ptr == addr && p.typ == typ {
+				return nil
+			}
+		}
+		// Remember, remember...
+		visited[h] = &visit{addr, typ, seen}
+	}
+	switch dst.Kind() {
+	case reflect.Struct:
+		for i, n := 0, dst.NumField(); i < n; i++ {
+			if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1); err != nil {
+				return
+			}
+		}
+	case reflect.Map:
+		for _, key := range src.MapKeys() {
+			srcElement := src.MapIndex(key)
+			if !srcElement.IsValid() {
+				continue
+			}
+			dstElement := dst.MapIndex(key)
+			switch reflect.TypeOf(srcElement.Interface()).Kind() {
+			case reflect.Struct:
+				fallthrough
+			case reflect.Map:
+				if err = deepMerge(dstElement, srcElement, visited, depth+1); err != nil {
+					return
+				}
+			}
+			if !dstElement.IsValid() {
+				dst.SetMapIndex(key, srcElement)
+			}
+		}
+	case reflect.Ptr:
+		fallthrough
+	case reflect.Interface:
+		if src.IsNil() {
+			break
+		} else if dst.IsNil() {
+			if dst.CanSet() && isEmptyValue(dst) {
+				dst.Set(src)
+			}
+		} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1); err != nil {
+			return
+		}
+	default:
+		if dst.CanSet() && !isEmptyValue(src) {
+			dst.Set(src)
+		}
+	}
+	return
+}
+
+// Merge sets fields' values in dst from src if they have a zero
+// value of their type.
+// dst and src must be valid same-type structs and dst must be
+// a pointer to struct.
+// It won't merge unexported (private) fields and will do recursively
+// any exported field.
+func Merge(dst, src interface{}) error {
+	var (
+		vDst, vSrc reflect.Value
+		err        error
+	)
+	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
+		return err
+	}
+	if vDst.Type() != vSrc.Type() {
+		return ErrDifferentArgumentsTypes
+	}
+	return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0)
+}

+ 90 - 0
vendor/github.com/imdario/mergo/mergo.go

@@ -0,0 +1,90 @@
+// Copyright 2013 Dario Castañé. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Based on src/pkg/reflect/deepequal.go from official
+// golang's stdlib.
+
+package mergo
+
+import (
+	"errors"
+	"reflect"
+)
+
+// Errors reported by Mergo when it finds invalid arguments.
+var (
+	ErrNilArguments                = errors.New("src and dst must not be nil")
+	ErrDifferentArgumentsTypes     = errors.New("src and dst must be of same type")
+	ErrNotSupported                = errors.New("only structs and maps are supported")
+	ErrExpectedMapAsDestination    = errors.New("dst was expected to be a map")
+	ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
+)
+
+// During deepMerge, must keep track of checks that are
+// in progress.  The comparison algorithm assumes that all
+// checks in progress are true when it reencounters them.
+// Visited are stored in a map indexed by 17 * a1 + a2;
+type visit struct {
+	ptr  uintptr
+	typ  reflect.Type
+	next *visit
+}
+
+// From src/pkg/encoding/json.
+func isEmptyValue(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return false
+}
+
+func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
+	if dst == nil || src == nil {
+		err = ErrNilArguments
+		return
+	}
+	vDst = reflect.ValueOf(dst).Elem()
+	if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
+		err = ErrNotSupported
+		return
+	}
+	vSrc = reflect.ValueOf(src)
+	// We check if vSrc is a pointer to dereference it.
+	if vSrc.Kind() == reflect.Ptr {
+		vSrc = vSrc.Elem()
+	}
+	return
+}
+
+// Traverses recursively both values, assigning src's fields values to dst.
+// The map argument tracks comparisons that have already been seen, which allows
+// short circuiting on recursive types.
+func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
+	if dst.CanAddr() {
+		addr := dst.UnsafeAddr()
+		h := 17 * addr
+		seen := visited[h]
+		typ := dst.Type()
+		for p := seen; p != nil; p = p.next {
+			if p.ptr == addr && p.typ == typ {
+				return nil
+			}
+		}
+		// Remember, remember...
+		visited[h] = &visit{addr, typ, seen}
+	}
+	return // TODO refactor
+}

+ 37 - 0
vendor/github.com/jmespath/go-jmespath/api.go

@@ -1,5 +1,42 @@
 package jmespath
 
+import "strconv"
+
+// JmesPath is the epresentation of a compiled JMES path query. A JmesPath is
+// safe for concurrent use by multiple goroutines.
+type JMESPath struct {
+	ast  ASTNode
+	intr *treeInterpreter
+}
+
+// Compile parses a JMESPath expression and returns, if successful, a JMESPath
+// object that can be used to match against data.
+func Compile(expression string) (*JMESPath, error) {
+	parser := NewParser()
+	ast, err := parser.Parse(expression)
+	if err != nil {
+		return nil, err
+	}
+	jmespath := &JMESPath{ast: ast, intr: newInterpreter()}
+	return jmespath, nil
+}
+
+// MustCompile is like Compile but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled
+// JMESPaths.
+func MustCompile(expression string) *JMESPath {
+	jmespath, err := Compile(expression)
+	if err != nil {
+		panic(`jmespath: Compile(` + strconv.Quote(expression) + `): ` + err.Error())
+	}
+	return jmespath
+}
+
+// Search evaluates a JMESPath expression against input data and returns the result.
+func (jp *JMESPath) Search(data interface{}) (interface{}, error) {
+	return jp.intr.Execute(jp.ast, data)
+}
+
 // Search evaluates a JMESPath expression against input data and returns the result.
 func Search(expression string, data interface{}) (interface{}, error) {
 	intr := newInterpreter()

+ 65 - 63
vendor/github.com/jmespath/go-jmespath/functions.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"math"
+	"reflect"
 	"sort"
 	"strconv"
 	"strings"
@@ -124,197 +125,197 @@ type functionCaller struct {
 func newFunctionCaller() *functionCaller {
 	caller := &functionCaller{}
 	caller.functionTable = map[string]functionEntry{
-		"length": functionEntry{
+		"length": {
 			name: "length",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpString, jpArray, jpObject}},
+				{types: []jpType{jpString, jpArray, jpObject}},
 			},
 			handler: jpfLength,
 		},
-		"starts_with": functionEntry{
+		"starts_with": {
 			name: "starts_with",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpString}},
-				argSpec{types: []jpType{jpString}},
+				{types: []jpType{jpString}},
+				{types: []jpType{jpString}},
 			},
 			handler: jpfStartsWith,
 		},
-		"abs": functionEntry{
+		"abs": {
 			name: "abs",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpNumber}},
+				{types: []jpType{jpNumber}},
 			},
 			handler: jpfAbs,
 		},
-		"avg": functionEntry{
+		"avg": {
 			name: "avg",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArrayNumber}},
+				{types: []jpType{jpArrayNumber}},
 			},
 			handler: jpfAvg,
 		},
-		"ceil": functionEntry{
+		"ceil": {
 			name: "ceil",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpNumber}},
+				{types: []jpType{jpNumber}},
 			},
 			handler: jpfCeil,
 		},
-		"contains": functionEntry{
+		"contains": {
 			name: "contains",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArray, jpString}},
-				argSpec{types: []jpType{jpAny}},
+				{types: []jpType{jpArray, jpString}},
+				{types: []jpType{jpAny}},
 			},
 			handler: jpfContains,
 		},
-		"ends_with": functionEntry{
+		"ends_with": {
 			name: "ends_with",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpString}},
-				argSpec{types: []jpType{jpString}},
+				{types: []jpType{jpString}},
+				{types: []jpType{jpString}},
 			},
 			handler: jpfEndsWith,
 		},
-		"floor": functionEntry{
+		"floor": {
 			name: "floor",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpNumber}},
+				{types: []jpType{jpNumber}},
 			},
 			handler: jpfFloor,
 		},
-		"map": functionEntry{
+		"map": {
 			name: "amp",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpExpref}},
-				argSpec{types: []jpType{jpArray}},
+				{types: []jpType{jpExpref}},
+				{types: []jpType{jpArray}},
 			},
 			handler:   jpfMap,
 			hasExpRef: true,
 		},
-		"max": functionEntry{
+		"max": {
 			name: "max",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
+				{types: []jpType{jpArrayNumber, jpArrayString}},
 			},
 			handler: jpfMax,
 		},
-		"merge": functionEntry{
+		"merge": {
 			name: "merge",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpObject}, variadic: true},
+				{types: []jpType{jpObject}, variadic: true},
 			},
 			handler: jpfMerge,
 		},
-		"max_by": functionEntry{
+		"max_by": {
 			name: "max_by",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArray}},
-				argSpec{types: []jpType{jpExpref}},
+				{types: []jpType{jpArray}},
+				{types: []jpType{jpExpref}},
 			},
 			handler:   jpfMaxBy,
 			hasExpRef: true,
 		},
-		"sum": functionEntry{
+		"sum": {
 			name: "sum",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArrayNumber}},
+				{types: []jpType{jpArrayNumber}},
 			},
 			handler: jpfSum,
 		},
-		"min": functionEntry{
+		"min": {
 			name: "min",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
+				{types: []jpType{jpArrayNumber, jpArrayString}},
 			},
 			handler: jpfMin,
 		},
-		"min_by": functionEntry{
+		"min_by": {
 			name: "min_by",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArray}},
-				argSpec{types: []jpType{jpExpref}},
+				{types: []jpType{jpArray}},
+				{types: []jpType{jpExpref}},
 			},
 			handler:   jpfMinBy,
 			hasExpRef: true,
 		},
-		"type": functionEntry{
+		"type": {
 			name: "type",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpAny}},
+				{types: []jpType{jpAny}},
 			},
 			handler: jpfType,
 		},
-		"keys": functionEntry{
+		"keys": {
 			name: "keys",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpObject}},
+				{types: []jpType{jpObject}},
 			},
 			handler: jpfKeys,
 		},
-		"values": functionEntry{
+		"values": {
 			name: "values",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpObject}},
+				{types: []jpType{jpObject}},
 			},
 			handler: jpfValues,
 		},
-		"sort": functionEntry{
+		"sort": {
 			name: "sort",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArrayString, jpArrayNumber}},
+				{types: []jpType{jpArrayString, jpArrayNumber}},
 			},
 			handler: jpfSort,
 		},
-		"sort_by": functionEntry{
+		"sort_by": {
 			name: "sort_by",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArray}},
-				argSpec{types: []jpType{jpExpref}},
+				{types: []jpType{jpArray}},
+				{types: []jpType{jpExpref}},
 			},
 			handler:   jpfSortBy,
 			hasExpRef: true,
 		},
-		"join": functionEntry{
+		"join": {
 			name: "join",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpString}},
-				argSpec{types: []jpType{jpArrayString}},
+				{types: []jpType{jpString}},
+				{types: []jpType{jpArrayString}},
 			},
 			handler: jpfJoin,
 		},
-		"reverse": functionEntry{
+		"reverse": {
 			name: "reverse",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpArray, jpString}},
+				{types: []jpType{jpArray, jpString}},
 			},
 			handler: jpfReverse,
 		},
-		"to_array": functionEntry{
+		"to_array": {
 			name: "to_array",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpAny}},
+				{types: []jpType{jpAny}},
 			},
 			handler: jpfToArray,
 		},
-		"to_string": functionEntry{
+		"to_string": {
 			name: "to_string",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpAny}},
+				{types: []jpType{jpAny}},
 			},
 			handler: jpfToString,
 		},
-		"to_number": functionEntry{
+		"to_number": {
 			name: "to_number",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpAny}},
+				{types: []jpType{jpAny}},
 			},
 			handler: jpfToNumber,
 		},
-		"not_null": functionEntry{
+		"not_null": {
 			name: "not_null",
 			arguments: []argSpec{
-				argSpec{types: []jpType{jpAny}, variadic: true},
+				{types: []jpType{jpAny}, variadic: true},
 			},
 			handler: jpfNotNull,
 		},
@@ -357,7 +358,7 @@ func (a *argSpec) typeCheck(arg interface{}) error {
 				return nil
 			}
 		case jpArray:
-			if _, ok := arg.([]interface{}); ok {
+			if isSliceType(arg) {
 				return nil
 			}
 		case jpObject:
@@ -409,8 +410,9 @@ func jpfLength(arguments []interface{}) (interface{}, error) {
 	arg := arguments[0]
 	if c, ok := arg.(string); ok {
 		return float64(utf8.RuneCountInString(c)), nil
-	} else if c, ok := arg.([]interface{}); ok {
-		return float64(len(c)), nil
+	} else if isSliceType(arg) {
+		v := reflect.ValueOf(arg)
+		return float64(v.Len()), nil
 	} else if c, ok := arg.(map[string]interface{}); ok {
 		return float64(len(c)), nil
 	}

+ 2 - 2
vendor/github.com/jmespath/go-jmespath/parser.go

@@ -353,7 +353,7 @@ func (p *Parser) nud(token token) (ASTNode, error) {
 	case tFlatten:
 		left := ASTNode{
 			nodeType: ASTFlatten,
-			children: []ASTNode{ASTNode{nodeType: ASTIdentity}},
+			children: []ASTNode{{nodeType: ASTIdentity}},
 		}
 		right, err := p.parseProjectionRHS(bindingPowers[tFlatten])
 		if err != nil {
@@ -378,7 +378,7 @@ func (p *Parser) nud(token token) (ASTNode, error) {
 			}
 			return ASTNode{
 				nodeType: ASTProjection,
-				children: []ASTNode{ASTNode{nodeType: ASTIdentity}, right},
+				children: []ASTNode{{nodeType: ASTIdentity}, right},
 			}, nil
 		} else {
 			return p.parseMultiSelectList()

+ 0 - 1
vendor/github.com/joho/godotenv/.gitignore

@@ -1 +0,0 @@
-.DS_Store

+ 0 - 127
vendor/github.com/joho/godotenv/README.md

@@ -1,127 +0,0 @@
-# GoDotEnv [![wercker status](https://app.wercker.com/status/507594c2ec7e60f19403a568dfea0f78 "wercker status")](https://app.wercker.com/project/bykey/507594c2ec7e60f19403a568dfea0f78)
-
-A Go (golang) port of the Ruby dotenv project (which loads env vars from a .env file)
-
-From the original Library:
-
-> Storing configuration in the environment is one of the tenets of a twelve-factor app. Anything that is likely to change between deployment environments–such as resource handles for databases or credentials for external services–should be extracted from the code into environment variables.
->
-> But it is not always practical to set environment variables on development machines or continuous integration servers where multiple projects are run. Dotenv load variables from a .env file into ENV when the environment is bootstrapped.
-
-It can be used as a library (for loading in env for your own daemons etc) or as a bin command.
-
-There is test coverage and CI for both linuxish and windows environments, but I make no guarantees about the bin version working on windows.
-
-## Installation
-
-As a library
-
-```shell
-go get github.com/joho/godotenv
-```
-
-or if you want to use it as a bin command
-```shell
-go get github.com/joho/godotenv/cmd/godotenv
-```
-
-## Usage
-
-Add your application configuration to your `.env` file in the root of your project:
-
-```shell
-S3_BUCKET=YOURS3BUCKET
-SECRET_KEY=YOURSECRETKEYGOESHERE
-```
-
-Then in your Go app you can do something like
-
-```go
-package main
-
-import (
-    "github.com/joho/godotenv"
-    "log"
-    "os"
-)
-
-func main() {
-  err := godotenv.Load()
-  if err != nil {
-    log.Fatal("Error loading .env file")
-  }
-
-  s3Bucket := os.Getenv("S3_BUCKET")
-  secretKey := os.Getenv("SECRET_KEY")
-
-  // now do something with s3 or whatever
-}
-```
-
-If you're even lazier than that, you can just take advantage of the autoload package which will read in `.env` on import
-
-```go
-import _ "github.com/joho/godotenv/autoload"
-```
-
-While `.env` in the project root is the default, you don't have to be constrained, both examples below are 100% legit
-
-```go
-_ = godotenv.Load("somerandomfile")
-_ = godotenv.Load("filenumberone.env", "filenumbertwo.env")
-```
-
-If you want to be really fancy with your env file you can do comments and exports (below is a valid env file)
-
-```shell
-# I am a comment and that is OK
-SOME_VAR=someval
-FOO=BAR # comments at line end are OK too
-export BAR=BAZ
-```
-
-Or finally you can do YAML(ish) style
-
-```yaml
-FOO: bar
-BAR: baz
-```
-
-as a final aside, if you don't want godotenv munging your env you can just get a map back instead
-
-```go
-var myEnv map[string]string
-myEnv, err := godotenv.Read()
-
-s3Bucket := myEnv["S3_BUCKET"]
-```
-
-### Command Mode
-
-Assuming you've installed the command as above and you've got `$GOPATH/bin` in your `$PATH`
-
-```
-godotenv -f /some/path/to/.env some_command with some args
-```
-
-If you don't specify `-f` it will fall back on the default of loading `.env` in `PWD`
-
-## Contributing
-
-Contributions are most welcome! The parser itself is pretty stupidly naive and I wouldn't be surprised if it breaks with edge cases.
-
-*code changes without tests will not be accepted*
-
-1. Fork it
-2. Create your feature branch (`git checkout -b my-new-feature`)
-3. Commit your changes (`git commit -am 'Added some feature'`)
-4. Push to the branch (`git push origin my-new-feature`)
-5. Create new Pull Request
-
-## CI
-
-Linux: [![wercker status](https://app.wercker.com/status/507594c2ec7e60f19403a568dfea0f78/m "wercker status")](https://app.wercker.com/project/bykey/507594c2ec7e60f19403a568dfea0f78) Windows: [![Build status](https://ci.appveyor.com/api/projects/status/9v40vnfvvgde64u4)](https://ci.appveyor.com/project/joho/godotenv)
-
-## Who?
-
-The original library [dotenv](https://github.com/bkeepers/dotenv) was written by [Brandon Keepers](http://opensoul.org/), and this port was done by [John Barton](http://whoisjohnbarton.com) based off the tests/fixtures in the original library.

+ 0 - 15
vendor/github.com/joho/godotenv/autoload/autoload.go

@@ -1,15 +0,0 @@
-package autoload
-
-/*
-	You can just read the .env file on import just by doing
-
-		import _ "github.com/joho/godotenv/autoload"
-
-	And bob's your mother's brother
-*/
-
-import "github.com/joho/godotenv"
-
-func init() {
-	godotenv.Load()
-}

+ 0 - 54
vendor/github.com/joho/godotenv/cmd/godotenv/cmd.go

@@ -1,54 +0,0 @@
-package main
-
-import (
-	"flag"
-	"fmt"
-	"log"
-
-	"strings"
-
-	"github.com/joho/godotenv"
-)
-
-func main() {
-	var showHelp bool
-	flag.BoolVar(&showHelp, "h", false, "show help")
-	var rawEnvFilenames string
-	flag.StringVar(&rawEnvFilenames, "f", "", "comma separated paths to .env files")
-
-	flag.Parse()
-
-	usage := `
-Run a process with a env setup from a .env file
-
-godotenv [-f ENV_FILE_PATHS] COMMAND_ARGS
-
-ENV_FILE_PATHS: comma separated paths to .env files
-COMMAND_ARGS: command and args you want to run
-
-example
-  godotenv -f /path/to/something/.env,/another/path/.env fortune
-`
-	// if no args or -h flag
-	// print usage and return
-	args := flag.Args()
-	if showHelp || len(args) == 0 {
-		fmt.Println(usage)
-		return
-	}
-
-	// load env
-	var envFilenames []string
-	if rawEnvFilenames != "" {
-		envFilenames = strings.Split(rawEnvFilenames, ",")
-	}
-
-	// take rest of args and "exec" them
-	cmd := args[0]
-	cmdArgs := args[1:]
-
-	err := godotenv.Exec(envFilenames, cmd, cmdArgs)
-	if err != nil {
-		log.Fatal(err)
-	}
-}

+ 0 - 2
vendor/github.com/joho/godotenv/fixtures/equals.env

@@ -1,2 +0,0 @@
-export OPTION_A='postgres://localhost:5432/database?sslmode=disable'
-

+ 0 - 2
vendor/github.com/joho/godotenv/fixtures/exported.env

@@ -1,2 +0,0 @@
-export OPTION_A=2
-export OPTION_B='\n'

+ 0 - 2
vendor/github.com/joho/godotenv/fixtures/invalid1.env

@@ -1,2 +0,0 @@
-INVALID LINE
-foo=bar

+ 0 - 5
vendor/github.com/joho/godotenv/fixtures/plain.env

@@ -1,5 +0,0 @@
-OPTION_A=1
-OPTION_B=2
-OPTION_C= 3
-OPTION_D =4
-OPTION_E = 5

+ 0 - 8
vendor/github.com/joho/godotenv/fixtures/quoted.env

@@ -1,8 +0,0 @@
-OPTION_A='1'
-OPTION_B='2'
-OPTION_C=''
-OPTION_D='\n'
-OPTION_E="1"
-OPTION_F="2"
-OPTION_G=""
-OPTION_H="\n"

+ 0 - 288
vendor/github.com/joho/godotenv/godotenv_test.go

@@ -1,288 +0,0 @@
-package godotenv
-
-import (
-	"os"
-	"testing"
-)
-
-var noopPresets = make(map[string]string)
-
-func parseAndCompare(t *testing.T, rawEnvLine string, expectedKey string, expectedValue string) {
-	key, value, _ := parseLine(rawEnvLine)
-	if key != expectedKey || value != expectedValue {
-		t.Errorf("Expected '%v' to parse as '%v' => '%v', got '%v' => '%v' instead", rawEnvLine, expectedKey, expectedValue, key, value)
-	}
-}
-
-func loadEnvAndCompareValues(t *testing.T, loader func(files ...string) error, envFileName string, expectedValues map[string]string, presets map[string]string) {
-	// first up, clear the env
-	os.Clearenv()
-
-	for k, v := range presets {
-		os.Setenv(k, v)
-	}
-
-	err := loader(envFileName)
-	if err != nil {
-		t.Fatalf("Error loading %v", envFileName)
-	}
-
-	for k := range expectedValues {
-		envValue := os.Getenv(k)
-		v := expectedValues[k]
-		if envValue != v {
-			t.Errorf("Mismatch for key '%v': expected '%v' got '%v'", k, v, envValue)
-		}
-	}
-}
-
-func TestLoadWithNoArgsLoadsDotEnv(t *testing.T) {
-	err := Load()
-	pathError := err.(*os.PathError)
-	if pathError == nil || pathError.Op != "open" || pathError.Path != ".env" {
-		t.Errorf("Didn't try and open .env by default")
-	}
-}
-
-func TestOverloadWithNoArgsOverloadsDotEnv(t *testing.T) {
-	err := Overload()
-	pathError := err.(*os.PathError)
-	if pathError == nil || pathError.Op != "open" || pathError.Path != ".env" {
-		t.Errorf("Didn't try and open .env by default")
-	}
-}
-
-func TestLoadFileNotFound(t *testing.T) {
-	err := Load("somefilethatwillneverexistever.env")
-	if err == nil {
-		t.Error("File wasn't found but Load didn't return an error")
-	}
-}
-
-func TestOverloadFileNotFound(t *testing.T) {
-	err := Overload("somefilethatwillneverexistever.env")
-	if err == nil {
-		t.Error("File wasn't found but Overload didn't return an error")
-	}
-}
-
-func TestReadPlainEnv(t *testing.T) {
-	envFileName := "fixtures/plain.env"
-	expectedValues := map[string]string{
-		"OPTION_A": "1",
-		"OPTION_B": "2",
-		"OPTION_C": "3",
-		"OPTION_D": "4",
-		"OPTION_E": "5",
-	}
-
-	envMap, err := Read(envFileName)
-	if err != nil {
-		t.Error("Error reading file")
-	}
-
-	if len(envMap) != len(expectedValues) {
-		t.Error("Didn't get the right size map back")
-	}
-
-	for key, value := range expectedValues {
-		if envMap[key] != value {
-			t.Error("Read got one of the keys wrong")
-		}
-	}
-}
-
-func TestLoadDoesNotOverride(t *testing.T) {
-	envFileName := "fixtures/plain.env"
-
-	// ensure NO overload
-	presets := map[string]string{
-		"OPTION_A": "do_not_override",
-	}
-
-	expectedValues := map[string]string{
-		"OPTION_A": "do_not_override",
-	}
-	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, presets)
-}
-
-func TestOveroadDoesOverride(t *testing.T) {
-	envFileName := "fixtures/plain.env"
-
-	// ensure NO overload
-	presets := map[string]string{
-		"OPTION_A": "do_not_override",
-	}
-
-	expectedValues := map[string]string{
-		"OPTION_A": "1",
-	}
-	loadEnvAndCompareValues(t, Overload, envFileName, expectedValues, presets)
-}
-
-func TestLoadPlainEnv(t *testing.T) {
-	envFileName := "fixtures/plain.env"
-	expectedValues := map[string]string{
-		"OPTION_A": "1",
-		"OPTION_B": "2",
-		"OPTION_C": "3",
-		"OPTION_D": "4",
-		"OPTION_E": "5",
-	}
-
-	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
-}
-
-func TestLoadExportedEnv(t *testing.T) {
-	envFileName := "fixtures/exported.env"
-	expectedValues := map[string]string{
-		"OPTION_A": "2",
-		"OPTION_B": "\n",
-	}
-
-	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
-}
-
-func TestLoadEqualsEnv(t *testing.T) {
-	envFileName := "fixtures/equals.env"
-	expectedValues := map[string]string{
-		"OPTION_A": "postgres://localhost:5432/database?sslmode=disable",
-	}
-
-	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
-}
-
-func TestLoadQuotedEnv(t *testing.T) {
-	envFileName := "fixtures/quoted.env"
-	expectedValues := map[string]string{
-		"OPTION_A": "1",
-		"OPTION_B": "2",
-		"OPTION_C": "",
-		"OPTION_D": "\n",
-		"OPTION_E": "1",
-		"OPTION_F": "2",
-		"OPTION_G": "",
-		"OPTION_H": "\n",
-	}
-
-	loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
-}
-
-func TestActualEnvVarsAreLeftAlone(t *testing.T) {
-	os.Clearenv()
-	os.Setenv("OPTION_A", "actualenv")
-	_ = Load("fixtures/plain.env")
-
-	if os.Getenv("OPTION_A") != "actualenv" {
-		t.Error("An ENV var set earlier was overwritten")
-	}
-}
-
-func TestParsing(t *testing.T) {
-	// unquoted values
-	parseAndCompare(t, "FOO=bar", "FOO", "bar")
-
-	// parses values with spaces around equal sign
-	parseAndCompare(t, "FOO =bar", "FOO", "bar")
-	parseAndCompare(t, "FOO= bar", "FOO", "bar")
-
-	// parses double quoted values
-	parseAndCompare(t, "FOO=\"bar\"", "FOO", "bar")
-
-	// parses single quoted values
-	parseAndCompare(t, "FOO='bar'", "FOO", "bar")
-
-	// parses escaped double quotes
-	parseAndCompare(t, "FOO=escaped\\\"bar\"", "FOO", "escaped\"bar")
-
-	// parses yaml style options
-	parseAndCompare(t, "OPTION_A: 1", "OPTION_A", "1")
-
-	// parses export keyword
-	parseAndCompare(t, "export OPTION_A=2", "OPTION_A", "2")
-	parseAndCompare(t, "export OPTION_B='\\n'", "OPTION_B", "\n")
-
-	// it 'expands newlines in quoted strings' do
-	// expect(env('FOO="bar\nbaz"')).to eql('FOO' => "bar\nbaz")
-	parseAndCompare(t, "FOO=\"bar\\nbaz\"", "FOO", "bar\nbaz")
-
-	// it 'parses varibales with "." in the name' do
-	// expect(env('FOO.BAR=foobar')).to eql('FOO.BAR' => 'foobar')
-	parseAndCompare(t, "FOO.BAR=foobar", "FOO.BAR", "foobar")
-
-	// it 'parses varibales with several "=" in the value' do
-	// expect(env('FOO=foobar=')).to eql('FOO' => 'foobar=')
-	parseAndCompare(t, "FOO=foobar=", "FOO", "foobar=")
-
-	// it 'strips unquoted values' do
-	// expect(env('foo=bar ')).to eql('foo' => 'bar') # not 'bar '
-	parseAndCompare(t, "FOO=bar ", "FOO", "bar")
-
-	// it 'ignores inline comments' do
-	// expect(env("foo=bar # this is foo")).to eql('foo' => 'bar')
-	parseAndCompare(t, "FOO=bar # this is foo", "FOO", "bar")
-
-	// it 'allows # in quoted value' do
-	// expect(env('foo="bar#baz" # comment')).to eql('foo' => 'bar#baz')
-	parseAndCompare(t, "FOO=\"bar#baz\" # comment", "FOO", "bar#baz")
-	parseAndCompare(t, "FOO='bar#baz' # comment", "FOO", "bar#baz")
-	parseAndCompare(t, "FOO=\"bar#baz#bang\" # comment", "FOO", "bar#baz#bang")
-
-	// it 'parses # in quoted values' do
-	// expect(env('foo="ba#r"')).to eql('foo' => 'ba#r')
-	// expect(env("foo='ba#r'")).to eql('foo' => 'ba#r')
-	parseAndCompare(t, "FOO=\"ba#r\"", "FOO", "ba#r")
-	parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r")
-
-	// it 'throws an error if line format is incorrect' do
-	// expect{env('lol$wut')}.to raise_error(Dotenv::FormatError)
-	badlyFormattedLine := "lol$wut"
-	_, _, err := parseLine(badlyFormattedLine)
-	if err == nil {
-		t.Errorf("Expected \"%v\" to return error, but it didn't", badlyFormattedLine)
-	}
-}
-
-func TestLinesToIgnore(t *testing.T) {
-	// it 'ignores empty lines' do
-	// expect(env("\n \t  \nfoo=bar\n \nfizz=buzz")).to eql('foo' => 'bar', 'fizz' => 'buzz')
-	if !isIgnoredLine("\n") {
-		t.Error("Line with nothing but line break wasn't ignored")
-	}
-
-	if !isIgnoredLine("\t\t ") {
-		t.Error("Line full of whitespace wasn't ignored")
-	}
-
-	// it 'ignores comment lines' do
-	// expect(env("\n\n\n # HERE GOES FOO \nfoo=bar")).to eql('foo' => 'bar')
-	if !isIgnoredLine("# comment") {
-		t.Error("Comment wasn't ignored")
-	}
-
-	if !isIgnoredLine("\t#comment") {
-		t.Error("Indented comment wasn't ignored")
-	}
-
-	// make sure we're not getting false positives
-	if isIgnoredLine("export OPTION_B='\\n'") {
-		t.Error("ignoring a perfectly valid line to parse")
-	}
-}
-
-func TestErrorReadDirectory(t *testing.T) {
-	envFileName := "fixtures/"
-	envMap, err := Read(envFileName)
-
-	if err == nil {
-		t.Errorf("Expected error, got %v", envMap)
-	}
-}
-
-func TestErrorParsing(t *testing.T) {
-	envFileName := "fixtures/invalid1.env"
-	envMap, err := Read(envFileName)
-	if err == nil {
-		t.Errorf("Expected error, got %v", envMap)
-	}
-}

+ 0 - 1
vendor/github.com/joho/godotenv/wercker.yml

@@ -1 +0,0 @@
-box: pjvds/golang

+ 12 - 3
vendor/github.com/vishvananda/netlink/addr.go

@@ -10,9 +10,11 @@ import (
 // include a mask, so it stores the address as a net.IPNet.
 type Addr struct {
 	*net.IPNet
-	Label string
-	Flags int
-	Scope int
+	Label     string
+	Flags     int
+	Scope     int
+	Peer      *net.IPNet
+	Broadcast net.IP
 }
 
 // String returns $ip/$netmask $label
@@ -43,3 +45,10 @@ func (a Addr) Equal(x Addr) bool {
 	// ignore label for comparison
 	return a.IP.Equal(x.IP) && sizea == sizeb
 }
+
+func (a Addr) PeerEqual(x Addr) bool {
+	sizea, _ := a.Peer.Mask.Size()
+	sizeb, _ := x.Peer.Mask.Size()
+	// ignore label for comparison
+	return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb
+}

+ 21 - 5
vendor/github.com/vishvananda/netlink/addr_linux.go

@@ -56,17 +56,27 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
 	msg.Prefixlen = uint8(prefixlen)
 	req.AddData(msg)
 
-	var addrData []byte
+	var localAddrData []byte
 	if family == FAMILY_V4 {
-		addrData = addr.IP.To4()
+		localAddrData = addr.IP.To4()
 	} else {
-		addrData = addr.IP.To16()
+		localAddrData = addr.IP.To16()
 	}
 
-	localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData)
+	localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
 	req.AddData(localData)
+	var peerAddrData []byte
+	if addr.Peer != nil {
+		if family == FAMILY_V4 {
+			peerAddrData = addr.Peer.IP.To4()
+		} else {
+			peerAddrData = addr.Peer.IP.To16()
+		}
+	} else {
+		peerAddrData = localAddrData
+	}
 
-	addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData)
+	addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
 	req.AddData(addressData)
 
 	if addr.Flags != 0 {
@@ -80,6 +90,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
 		}
 	}
 
+	if addr.Broadcast != nil {
+		req.AddData(nl.NewRtAttr(syscall.IFA_BROADCAST, addr.Broadcast))
+	}
+
 	if addr.Label != "" {
 		labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
 		req.AddData(labelData)
@@ -161,11 +175,13 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
 				IP:   attr.Value,
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 			}
+			addr.Peer = dst
 		case syscall.IFA_LOCAL:
 			local = &net.IPNet{
 				IP:   attr.Value,
 				Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
 			}
+			addr.IPNet = local
 		case syscall.IFA_LABEL:
 			addr.Label = string(attr.Value[:len(attr.Value)-1])
 		case IFA_FLAGS:

+ 7 - 5
vendor/github.com/vishvananda/netlink/bpf_linux.go

@@ -8,11 +8,11 @@ package netlink
 #include <stdint.h>
 #include <unistd.h>
 
-static int load_simple_bpf(int prog_type) {
+static int load_simple_bpf(int prog_type, int ret) {
 #ifdef __NR_bpf
-	// { return 1; }
+	// { return ret; }
 	__u64 __attribute__((aligned(8))) insns[] = {
-		0x00000001000000b7ull,
+		0x00000000000000b7ull | ((__u64)ret<<32),
 		0x0000000000000095ull,
 	};
 	__u8 __attribute__((aligned(8))) license[] = "ASL2";
@@ -51,10 +51,12 @@ const (
 	BPF_PROG_TYPE_KPROBE
 	BPF_PROG_TYPE_SCHED_CLS
 	BPF_PROG_TYPE_SCHED_ACT
+	BPF_PROG_TYPE_TRACEPOINT
+	BPF_PROG_TYPE_XDP
 )
 
 // loadSimpleBpf loads a trivial bpf program for testing purposes
-func loadSimpleBpf(progType BpfProgType) (int, error) {
-	fd, err := C.load_simple_bpf(C.int(progType))
+func loadSimpleBpf(progType BpfProgType, ret int) (int, error) {
+	fd, err := C.load_simple_bpf(C.int(progType), C.int(ret))
 	return int(fd), err
 }

+ 2 - 2
vendor/github.com/vishvananda/netlink/filter.go

@@ -60,7 +60,7 @@ func (a TcAct) String() string {
 	case TC_ACT_JUMP:
 		return "jump"
 	}
-	return fmt.Sprintf("0x%x", a)
+	return fmt.Sprintf("0x%x", int32(a))
 }
 
 type TcPolAct int32
@@ -86,7 +86,7 @@ func (a TcPolAct) String() string {
 	case TC_POLICE_PIPE:
 		return "pipe"
 	}
-	return fmt.Sprintf("0x%x", a)
+	return fmt.Sprintf("0x%x", int32(a))
 }
 
 type ActionAttrs struct {

+ 25 - 0
vendor/github.com/vishvananda/netlink/handle_linux.go

@@ -1,7 +1,9 @@
 package netlink
 
 import (
+	"fmt"
 	"syscall"
+	"time"
 
 	"github.com/vishvananda/netlink/nl"
 	"github.com/vishvananda/netns"
@@ -33,6 +35,29 @@ func NewHandle(nlFamilies ...int) (*Handle, error) {
 	return newHandle(netns.None(), netns.None(), nlFamilies...)
 }
 
+// SetSocketTimeout sets the send and receive timeout for each socket in the
+// netlink handle. Although the socket timeout has granularity of one
+// microsecond, the effective granularity is floored by the kernel timer tick,
+// which default value is four milliseconds.
+func (h *Handle) SetSocketTimeout(to time.Duration) error {
+	if to < time.Microsecond {
+		return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond)
+	}
+	tv := syscall.NsecToTimeval(to.Nanoseconds())
+	for _, sh := range h.sockets {
+		fd := sh.Socket.GetFd()
+		err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv)
+		if err != nil {
+			return err
+		}
+		err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
 // NewHandle returns a netlink handle on the network namespace
 // specified by ns. If ns=netns.None(), current network namespace
 // will be assumed

+ 218 - 0
vendor/github.com/vishvananda/netlink/handle_unspecified.go

@@ -0,0 +1,218 @@
+// +build !linux
+
+package netlink
+
+import (
+	"net"
+	"time"
+
+	"github.com/vishvananda/netns"
+)
+
+type Handle struct{}
+
+func NewHandle(nlFamilies ...int) (*Handle, error) {
+	return nil, ErrNotImplemented
+}
+
+func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) {
+	return nil, ErrNotImplemented
+}
+
+func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) Delete() {}
+
+func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
+	return false
+}
+
+func (h *Handle) SetSocketTimeout(to time.Duration) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) SetPromiscOn(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) SetPromiscOff(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetUp(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetDown(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetMTU(link Link, mtu int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetName(link Link, name string) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetAlias(link Link, name string) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetMaster(link Link, master *Bridge) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetNoMaster(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetNsPid(link Link, nspid int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetNsFd(link Link, fd int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkAdd(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkDel(link Link) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkByName(name string) (Link, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) LinkByAlias(alias string) (Link, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) LinkByIndex(index int) (Link, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) LinkList() ([]Link, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) LinkSetHairpin(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetGuard(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetFastLeave(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetLearning(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetRootBlock(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) LinkSetFlood(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) AddrAdd(link Link, addr *Addr) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) AddrDel(link Link, addr *Addr) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) AddrList(link Link, family int) ([]Addr, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) ClassDel(class Class) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) ClassChange(class Class) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) ClassReplace(class Class) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) ClassAdd(class Class) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) FilterDel(filter Filter) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) FilterAdd(filter Filter) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) NeighAdd(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) NeighSet(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) NeighAppend(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) NeighDel(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) {
+	return nil, ErrNotImplemented
+}
+
+func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) {
+	return nil, ErrNotImplemented
+}

+ 160 - 6
vendor/github.com/vishvananda/netlink/link.go

@@ -26,11 +26,50 @@ type LinkAttrs struct {
 	Name         string
 	HardwareAddr net.HardwareAddr
 	Flags        net.Flags
+	RawFlags     uint32
 	ParentIndex  int         // index of the parent link device
 	MasterIndex  int         // must be the index of a bridge
 	Namespace    interface{} // nil | NsPid | NsFd
 	Alias        string
 	Statistics   *LinkStatistics
+	Promisc      int
+	Xdp          *LinkXdp
+	EncapType    string
+	Protinfo     *Protinfo
+	OperState    LinkOperState
+}
+
+// LinkOperState represents the values of the IFLA_OPERSTATE link
+// attribute, which contains the RFC2863 state of the interface.
+type LinkOperState uint8
+
+const (
+	OperUnknown        = iota // Status can't be determined.
+	OperNotPresent            // Some component is missing.
+	OperDown                  // Down.
+	OperLowerLayerDown        // Down due to state of lower layer.
+	OperTesting               // In some test mode.
+	OperDormant               // Not up but pending an external event.
+	OperUp                    // Up, ready to send packets.
+)
+
+func (s LinkOperState) String() string {
+	switch s {
+	case OperNotPresent:
+		return "not-present"
+	case OperDown:
+		return "down"
+	case OperLowerLayerDown:
+		return "lower-layer-down"
+	case OperTesting:
+		return "testing"
+	case OperDormant:
+		return "dormant"
+	case OperUp:
+		return "up"
+	default:
+		return "unknown"
+	}
 }
 
 // NewLinkAttrs returns LinkAttrs structure filled with default values
@@ -40,10 +79,12 @@ func NewLinkAttrs() LinkAttrs {
 	}
 }
 
+type LinkStatistics LinkStatistics64
+
 /*
 Ref: struct rtnl_link_stats {...}
 */
-type LinkStatistics struct {
+type LinkStatistics32 struct {
 	RxPackets         uint32
 	TxPackets         uint32
 	RxBytes           uint32
@@ -69,6 +110,68 @@ type LinkStatistics struct {
 	TxCompressed      uint32
 }
 
+func (s32 LinkStatistics32) to64() *LinkStatistics64 {
+	return &LinkStatistics64{
+		RxPackets:         uint64(s32.RxPackets),
+		TxPackets:         uint64(s32.TxPackets),
+		RxBytes:           uint64(s32.RxBytes),
+		TxBytes:           uint64(s32.TxBytes),
+		RxErrors:          uint64(s32.RxErrors),
+		TxErrors:          uint64(s32.TxErrors),
+		RxDropped:         uint64(s32.RxDropped),
+		TxDropped:         uint64(s32.TxDropped),
+		Multicast:         uint64(s32.Multicast),
+		Collisions:        uint64(s32.Collisions),
+		RxLengthErrors:    uint64(s32.RxLengthErrors),
+		RxOverErrors:      uint64(s32.RxOverErrors),
+		RxCrcErrors:       uint64(s32.RxCrcErrors),
+		RxFrameErrors:     uint64(s32.RxFrameErrors),
+		RxFifoErrors:      uint64(s32.RxFifoErrors),
+		RxMissedErrors:    uint64(s32.RxMissedErrors),
+		TxAbortedErrors:   uint64(s32.TxAbortedErrors),
+		TxCarrierErrors:   uint64(s32.TxCarrierErrors),
+		TxFifoErrors:      uint64(s32.TxFifoErrors),
+		TxHeartbeatErrors: uint64(s32.TxHeartbeatErrors),
+		TxWindowErrors:    uint64(s32.TxWindowErrors),
+		RxCompressed:      uint64(s32.RxCompressed),
+		TxCompressed:      uint64(s32.TxCompressed),
+	}
+}
+
+/*
+Ref: struct rtnl_link_stats64 {...}
+*/
+type LinkStatistics64 struct {
+	RxPackets         uint64
+	TxPackets         uint64
+	RxBytes           uint64
+	TxBytes           uint64
+	RxErrors          uint64
+	TxErrors          uint64
+	RxDropped         uint64
+	TxDropped         uint64
+	Multicast         uint64
+	Collisions        uint64
+	RxLengthErrors    uint64
+	RxOverErrors      uint64
+	RxCrcErrors       uint64
+	RxFrameErrors     uint64
+	RxFifoErrors      uint64
+	RxMissedErrors    uint64
+	TxAbortedErrors   uint64
+	TxCarrierErrors   uint64
+	TxFifoErrors      uint64
+	TxHeartbeatErrors uint64
+	TxWindowErrors    uint64
+	RxCompressed      uint64
+	TxCompressed      uint64
+}
+
+type LinkXdp struct {
+	Fd       int
+	Attached bool
+}
+
 // Device links cannot be created via netlink. These links
 // are links created by udev like 'lo' and 'etho0'
 type Device struct {
@@ -171,11 +274,13 @@ func (macvtap Macvtap) Type() string {
 }
 
 type TuntapMode uint16
+type TuntapFlag uint16
 
 // Tuntap links created via /dev/tun/tap, but can be destroyed via netlink
 type Tuntap struct {
 	LinkAttrs
-	Mode TuntapMode
+	Mode  TuntapMode
+	Flags TuntapFlag
 }
 
 func (tuntap *Tuntap) Attrs() *LinkAttrs {
@@ -251,6 +356,7 @@ type IPVlanMode uint16
 const (
 	IPVLAN_MODE_L2 IPVlanMode = iota
 	IPVLAN_MODE_L3
+	IPVLAN_MODE_L3S
 	IPVLAN_MODE_MAX
 )
 
@@ -289,31 +395,31 @@ func StringToBondMode(s string) BondMode {
 
 // Possible BondMode
 const (
-	BOND_MODE_802_3AD BondMode = iota
-	BOND_MODE_BALANCE_RR
+	BOND_MODE_BALANCE_RR BondMode = iota
 	BOND_MODE_ACTIVE_BACKUP
 	BOND_MODE_BALANCE_XOR
 	BOND_MODE_BROADCAST
+	BOND_MODE_802_3AD
 	BOND_MODE_BALANCE_TLB
 	BOND_MODE_BALANCE_ALB
 	BOND_MODE_UNKNOWN
 )
 
 var bondModeToString = map[BondMode]string{
-	BOND_MODE_802_3AD:       "802.3ad",
 	BOND_MODE_BALANCE_RR:    "balance-rr",
 	BOND_MODE_ACTIVE_BACKUP: "active-backup",
 	BOND_MODE_BALANCE_XOR:   "balance-xor",
 	BOND_MODE_BROADCAST:     "broadcast",
+	BOND_MODE_802_3AD:       "802.3ad",
 	BOND_MODE_BALANCE_TLB:   "balance-tlb",
 	BOND_MODE_BALANCE_ALB:   "balance-alb",
 }
 var StringToBondModeMap = map[string]BondMode{
-	"802.3ad":       BOND_MODE_802_3AD,
 	"balance-rr":    BOND_MODE_BALANCE_RR,
 	"active-backup": BOND_MODE_ACTIVE_BACKUP,
 	"balance-xor":   BOND_MODE_BALANCE_XOR,
 	"broadcast":     BOND_MODE_BROADCAST,
+	"802.3ad":       BOND_MODE_802_3AD,
 	"balance-tlb":   BOND_MODE_BALANCE_TLB,
 	"balance-alb":   BOND_MODE_BALANCE_ALB,
 }
@@ -577,6 +683,54 @@ func (gretap *Gretap) Type() string {
 	return "gretap"
 }
 
+type Iptun struct {
+	LinkAttrs
+	Ttl      uint8
+	Tos      uint8
+	PMtuDisc uint8
+	Link     uint32
+	Local    net.IP
+	Remote   net.IP
+}
+
+func (iptun *Iptun) Attrs() *LinkAttrs {
+	return &iptun.LinkAttrs
+}
+
+func (iptun *Iptun) Type() string {
+	return "ipip"
+}
+
+type Vti struct {
+	LinkAttrs
+	IKey   uint32
+	OKey   uint32
+	Link   uint32
+	Local  net.IP
+	Remote net.IP
+}
+
+func (vti *Vti) Attrs() *LinkAttrs {
+	return &vti.LinkAttrs
+}
+
+func (iptun *Vti) Type() string {
+	return "vti"
+}
+
+type Vrf struct {
+	LinkAttrs
+	Table uint32
+}
+
+func (vrf *Vrf) Attrs() *LinkAttrs {
+	return &vrf.LinkAttrs
+}
+
+func (vrf *Vrf) Type() string {
+	return "vrf"
+}
+
 // iproute2 supported devices;
 // vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
 // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません