Преглед на файлове

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 |

Някои файлове не бяха показани, защото твърде много файлове са промени