diff --git a/Gopkg.lock b/Gopkg.lock index 5124918421..b7a326467f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -3,29 +3,38 @@ [[projects]] branch = "default" + digest = "1:db5c4e7a9516334fb1e9d5951fb9943d0f13e4f415a77c22b97e60f4d10a62a7" name = "bitbucket.org/ww/goautoneg" packages = ["."] + pruneopts = "" revision = "75cd24fc2f2c2a2088577d12123ddee5f54e0675" [[projects]] + digest = "1:b0fe84bcee1d0c3579d855029ccd3a76deea187412da2976985e4946289dbb2c" name = "github.com/NYTimes/gziphandler" packages = ["."] + pruneopts = "" revision = "2600fb119af974220d3916a5916d6e31176aac1b" version = "v1.0.1" [[projects]] + digest = "1:8e47871087b94913898333f37af26732faaab30cdb41571136cf7aec9921dae7" name = "github.com/PuerkitoBio/purell" packages = ["."] + pruneopts = "" revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4" version = "v1.1.0" [[projects]] branch = "master" + digest = "1:331a419049c2be691e5ba1d24342fc77c7e767a80c666a18fd8a9f7b82419c1c" name = "github.com/PuerkitoBio/urlesc" packages = ["."] + pruneopts = "" revision = "de5bf2ad457846296e2031421a34e2568e304e35" [[projects]] + digest = "1:a2a50777147a804aae42d78e53e638c4f13dac91abc92f53ef35e1e811f58b83" name = "github.com/aws/aws-sdk-go" packages = [ "aws", @@ -60,27 +69,33 @@ "service/ec2/ec2iface", "service/elb", "service/elb/elbiface", - "service/sts" + "service/sts", ] + pruneopts = "" revision = "34699de98eac41fa94737f6ce7b83d7a621c2634" version = "v1.15.36" [[projects]] + digest = "1:81ff47b77ad70c2f24a1aeb990890e57219cae2cb9640314be13b6dca0da9e62" name = "github.com/awslabs/goformation" packages = [ "cloudformation", - "intrinsics" + "intrinsics", ] + pruneopts = "" revision = "d42502ef32a8892bf380256e2f57c6f69190d802" version = "1.2.2" [[projects]] branch = "master" + digest = "1:c0bec5f9b98d0bc872ff5e834fac186b807b656683bd29cb82fb207a1513fabb" name = "github.com/beorn7/perks" packages = ["quantile"] + pruneopts = "" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] + digest = "1:b4db6b7d53a74b5abc1ae87921536138fe66a2788a0d205892c97e19d1b84683" name = "github.com/coreos/etcd" packages = [ "auth/authpb", @@ -94,358 +109,462 @@ "pkg/tlsutil", "pkg/transport", "pkg/types", - "version" + "version", ] + pruneopts = "" revision = "fca8add78a9d926166eb739b8e4a124434025ba3" version = "v3.3.9" [[projects]] + digest = "1:3c3f68ebab415344aef64363d23471e953a4715645115604aaf57923ae904f5e" name = "github.com/coreos/go-semver" packages = ["semver"] + pruneopts = "" revision = "8ab6407b697782a06568d4b7f1db25550ec2e4c6" version = "v0.2.0" [[projects]] + digest = "1:1a99671bb8620f32c88d20f65c7069a8c3745d1533bd486b9c0c538a1d981a5c" name = "github.com/coreos/go-systemd" packages = ["daemon"] + pruneopts = "" revision = "39ca1b05acc7ad1220e09f133283b8859a8b71ab" version = "v17" [[projects]] + digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77" name = "github.com/davecgh/go-spew" packages = ["spew"] + pruneopts = "" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" [[projects]] + digest = "1:044b2f1eea2f5cfb0d3678baf60892734f59d5c2ea3932cb6ed894a97ccba15c" name = "github.com/elazarl/go-bindata-assetfs" packages = ["."] + pruneopts = "" revision = "30f82fa23fd844bd5bb1e5f216db87fd77b5eb43" version = "v1.0.0" [[projects]] + digest = "1:8a34d7a37b8f07239487752e14a5faafcbbc718fc385ad429a2c4ac6f27a207f" name = "github.com/emicklei/go-restful" packages = [ ".", - "log" + "log", ] + pruneopts = "" revision = "3eb9738c1697594ea6e71a7156a9bb32ed216cf0" version = "v2.8.0" [[projects]] + digest = "1:cad2dd7061b8dcb4e0014d89e8070f185fb70ac9ba26acf27ff42b9c3eb0ff9b" name = "github.com/emicklei/go-restful-swagger12" packages = ["."] + pruneopts = "" revision = "dcef7f55730566d41eae5db10e7d6981829720f6" version = "1.0.1" [[projects]] + digest = "1:4216202f4088a73e2982df875e2f0d1401137bbc248e57391e70547af167a18a" name = "github.com/evanphx/json-patch" packages = ["."] + pruneopts = "" revision = "72bf35d0ff611848c1dc9df0f976c81192392fa5" version = "v4.1.0" [[projects]] + digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/ghodss/yaml" packages = ["."] + pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:cd5bab9c9e23ffa6858eaa79dc827fd84bc24bc00b0cfb0b14036e393da2b1fa" name = "github.com/go-ini/ini" packages = ["."] + pruneopts = "" revision = "5cf292cae48347c2490ac1a58fe36735fb78df7e" version = "v1.38.2" [[projects]] + digest = "1:e116a4866bffeec941056a1fcfd37e520fad1ee60e4e3579719f19a43c392e10" name = "github.com/go-openapi/jsonpointer" packages = ["."] + pruneopts = "" revision = "3a0015ad55fa9873f41605d3e8f28cd279c32ab2" version = "0.16.0" [[projects]] + digest = "1:3830527ef0f4f9b268d9286661c0f52f9115f8aefd9f45ee7352516f93489ac9" name = "github.com/go-openapi/jsonreference" packages = ["."] + pruneopts = "" revision = "3fb327e6747da3043567ee86abd02bb6376b6be2" version = "0.16.0" [[projects]] + digest = "1:222a38a6f9a0bac95fa14fb97b0bf4734dd652a3341306aa79dda33980d91f42" name = "github.com/go-openapi/spec" packages = ["."] + pruneopts = "" revision = "384415f06ee238aae1df5caad877de6ceac3a5c4" version = "0.16.0" [[projects]] + digest = "1:a8255150a79fa9cc785561966bacda7ff5b386abed1b5f5a9a784660407df836" name = "github.com/go-openapi/swag" packages = ["."] + pruneopts = "" revision = "becd2f08beafcca035645a8a101e0e3e18140458" version = "0.16.0" [[projects]] + digest = "1:6e73003ecd35f4487a5e88270d3ca0a81bc80dc88053ac7e4dcfec5fba30d918" name = "github.com/gogo/protobuf" packages = [ "gogoproto", "proto", "protoc-gen-gogo/descriptor", - "sortkeys" + "sortkeys", ] + pruneopts = "" revision = "636bf0302bc95575d69441b25a2603156ffdddf1" version = "v1.1.1" [[projects]] branch = "master" + digest = "1:107b233e45174dbab5b1324201d092ea9448e58243ab9f039e4c0f332e121e3a" name = "github.com/golang/glog" packages = ["."] + pruneopts = "" revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" [[projects]] branch = "master" + digest = "1:1d8a57fce1f68298ce54967c0752a2ab54bf55dff261d245b8f3440a217700cb" name = "github.com/golang/groupcache" packages = ["lru"] + pruneopts = "" revision = "24b0969c4cb722950103eed87108c8d291a8df00" [[projects]] branch = "master" + digest = "1:718dbab642c6d914aff8fedee621bb4f017acaa75a13dcb84af8ecf354d11585" name = "github.com/golang/mock" packages = ["gomock"] + pruneopts = "" revision = "600781dde9cca80734169b9e969d9054ccc57937" [[projects]] + digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18" name = "github.com/golang/protobuf" packages = [ "proto", "ptypes", "ptypes/any", "ptypes/duration", - "ptypes/timestamp" + "ptypes/timestamp", ] + pruneopts = "" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" version = "v1.2.0" [[projects]] branch = "master" + digest = "1:1e5b1e14524ed08301977b7b8e10c719ed853cbf3f24ecb66fae783a46f207a6" name = "github.com/google/btree" packages = ["."] + pruneopts = "" revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" [[projects]] branch = "master" + digest = "1:754f77e9c839b24778a4b64422236d38515301d2baeb63113aa3edc42e6af692" name = "github.com/google/gofuzz" packages = ["."] + pruneopts = "" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] + digest = "1:5247b135b5492aa232a731acdcb52b08f32b874cb398f21ab460396eadbe866b" name = "github.com/google/uuid" packages = ["."] + pruneopts = "" revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494" version = "v1.0.0" [[projects]] + digest = "1:16b2837c8b3cf045fa2cdc82af0cf78b19582701394484ae76b2c3bc3c99ad73" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions" + "extensions", ] + pruneopts = "" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] branch = "master" + digest = "1:009a1928b8c096338b68b5822d838a72b4d8520715c1463614476359f3282ec8" name = "github.com/gregjones/httpcache" packages = [ ".", - "diskcache" + "diskcache", ] + pruneopts = "" revision = "9cad4c3443a7200dd6400aef47183728de563a38" [[projects]] + digest = "1:3313a63031ae281e5f6fd7b0bbca733dfa04d2429df86519e3b4d4c016ccb836" name = "github.com/hashicorp/golang-lru" packages = [ ".", - "simplelru" + "simplelru", ] + pruneopts = "" revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768" version = "v0.5.0" [[projects]] branch = "master" + digest = "1:f81c8d7354cc0c6340f2f7a48724ee6c2b3db3e918ecd441c985b4d2d97dd3e7" name = "github.com/howeyc/gopass" packages = ["."] + pruneopts = "" revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8" [[projects]] + digest = "1:7ab38c15bd21e056e3115c8b526d201eaf74e0308da9370997c6b3c187115d36" name = "github.com/imdario/mergo" packages = ["."] + pruneopts = "" revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" version = "v0.3.6" [[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] + pruneopts = "" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] + digest = "1:6f49eae0c1e5dab1dafafee34b207aeb7a42303105960944828c2079b92fc88e" name = "github.com/jmespath/go-jmespath" packages = ["."] + pruneopts = "" revision = "0b12d6b5" [[projects]] + digest = "1:b79fc583e4dc7055ed86742e22164ac41bf8c0940722dbcb600f1a3ace1a8cb5" name = "github.com/json-iterator/go" packages = ["."] + pruneopts = "" revision = "1624edc4454b8682399def8740d46db5e4362ba4" version = "v1.1.5" [[projects]] + digest = "1:d26c006cbf54ca5c040463d5678013169e2bd91fb62c2f960ae283a1723d4278" name = "github.com/juju/ratelimit" packages = ["."] + pruneopts = "" revision = "59fac5042749a5afb9af70e813da1dd5474f0167" version = "1.0.1" [[projects]] + digest = "1:c5f67fc5798614e530a02f177f684a943ac3bf3cc5113b74475da3c532068887" name = "github.com/kubernetes-incubator/apiserver-builder" packages = [ "pkg/builders", - "pkg/controller" + "pkg/controller", ] + pruneopts = "" revision = "e809ac2f9f0c238f08d08a876f8b3f499604f941" version = "v1.9-alpha.3" [[projects]] branch = "master" + digest = "1:212bebc561f4f654a653225868b2a97353cd5e160dc0b0bbc7232b06608474ec" name = "github.com/mailru/easyjson" packages = [ "buffer", "jlexer", - "jwriter" + "jwriter", ] + pruneopts = "" revision = "60711f1a8329503b04e1c88535f419d0bb440bff" [[projects]] + digest = "1:63722a4b1e1717be7b98fc686e0b30d5e7f734b9e93d7dee86293b6deab7ea28" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] + pruneopts = "" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" version = "v1.0.1" [[projects]] + digest = "1:bcc46a0fbd9e933087bef394871256b5c60269575bb661935874729c65bbbf60" name = "github.com/mitchellh/mapstructure" packages = ["."] + pruneopts = "" revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe" version = "v1.1.2" [[projects]] + digest = "1:0c0ff2a89c1bb0d01887e1dac043ad7efbf3ec77482ef058ac423d13497e16fd" name = "github.com/modern-go/concurrent" packages = ["."] + pruneopts = "" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] + digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" name = "github.com/modern-go/reflect2" packages = ["."] + pruneopts = "" revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" version = "1.0.1" [[projects]] branch = "master" + digest = "1:d33ce379780d7c43405b9251289493cabada82f6bf9ab35eea6915d04f6ac8e0" name = "github.com/mxk/go-flowrate" packages = ["flowrate"] + pruneopts = "" revision = "cca7078d478f8520f85629ad7c68962d31ed7682" [[projects]] + digest = "1:a5484d4fa43127138ae6e7b2299a6a52ae006c7f803d98d717f60abf3e97192e" name = "github.com/pborman/uuid" packages = ["."] + pruneopts = "" revision = "adf5a7427709b9deb95d29d3fa8a2bf9cfd388f1" version = "v1.2" [[projects]] branch = "master" + digest = "1:c24598ffeadd2762552269271b3b1510df2d83ee6696c1e543a0ff653af494bc" name = "github.com/petar/GoLLRB" packages = ["llrb"] + pruneopts = "" revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] + digest = "1:b46305723171710475f2dd37547edd57b67b9de9f2a6267cafdd98331fd6897f" name = "github.com/peterbourgon/diskv" packages = ["."] + pruneopts = "" revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" version = "v2.0.1" [[projects]] + digest = "1:7365acd48986e205ccb8652cc746f09c8b7876030d53710ea6ef7d0bd0dcd7ca" name = "github.com/pkg/errors" packages = ["."] + pruneopts = "" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] + digest = "1:4142d94383572e74b42352273652c62afec5b23f325222ed09198f46009022d1" name = "github.com/prometheus/client_golang" packages = ["prometheus"] + pruneopts = "" revision = "c5b7fccd204277076155f10851dad72b76a49317" version = "v0.8.0" [[projects]] branch = "master" + digest = "1:185cf55b1f44a1bf243558901c3f06efa5c64ba62cfdcbb1bf7bbe8c3fb68561" name = "github.com/prometheus/client_model" packages = ["go"] + pruneopts = "" revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" [[projects]] branch = "master" + digest = "1:f477ef7b65d94fb17574fc6548cef0c99a69c1634ea3b6da248b63a61ebe0498" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model" + "model", ] + pruneopts = "" revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" [[projects]] branch = "master" + digest = "1:e04aaa0e8f8da0ed3d6c0700bd77eda52a47f38510063209d72d62f0ef807d5e" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfs", - "xfs" + "xfs", ] + pruneopts = "" revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" [[projects]] branch = "v2" + digest = "1:7568f79067cb0c23544a5f970fd70c4497d75a28f9f0dec3fbc9aa8d1b35760d" name = "github.com/sanathkr/go-yaml" packages = ["."] + pruneopts = "" revision = "ed9d249f429b3f5a69f80a7abef6bfce81fef894" [[projects]] + digest = "1:b13707423743d41665fd23f0c36b2f37bb49c30e94adb813319c44188a51ba22" name = "github.com/sanathkr/yaml" packages = ["."] + pruneopts = "" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] + digest = "1:a1403cc8a94b8d7956ee5e9694badef0e7b051af289caad1cf668331e3ffa4f6" name = "github.com/spf13/cobra" packages = ["."] + pruneopts = "" revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" version = "v0.0.3" [[projects]] + digest = "1:0a52bcb568386d98f4894575d53ce3e456f56471de6897bb8b9de13c33d9340e" name = "github.com/spf13/pflag" packages = ["."] + pruneopts = "" revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" version = "v1.0.2" [[projects]] + digest = "1:2e7f653483e51243b6cd6de60ce39bde0d6927d10a3c24295ab0f82cb1efeae2" name = "github.com/ugorji/go" packages = ["codec"] + pruneopts = "" revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab" version = "v1.1.1" [[projects]] branch = "master" + digest = "1:61a86f0be8b466d6e3fbdabb155aaa4006137cb5e3fd3b949329d103fa0ceb0f" name = "golang.org/x/crypto" packages = ["ssh/terminal"] + pruneopts = "" revision = "0e37d006457bf46f9e6692014ba72ef82c33022c" [[projects]] branch = "master" + digest = "1:fbdbb6cf8db3278412c9425ad78b26bb8eb788181f26a3ffb3e4f216b314f86a" name = "golang.org/x/net" packages = [ "context", @@ -457,20 +576,24 @@ "idna", "internal/timeseries", "trace", - "websocket" + "websocket", ] + pruneopts = "" revision = "26e67e76b6c3f6ce91f7c52def5af501b4e0f3a2" [[projects]] branch = "master" + digest = "1:6f8f4a4fffbef9ef137261e37fd4da98981b978efeb79837434be05831bb87fc" name = "golang.org/x/sys" packages = [ "unix", - "windows" + "windows", ] + pruneopts = "" revision = "ee1b12c67af419cf5a9be3bdbeea7fc1c5f32f11" [[projects]] + digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4" name = "golang.org/x/text" packages = [ "collate", @@ -487,28 +610,34 @@ "unicode/cldr", "unicode/norm", "unicode/rangetable", - "width" + "width", ] + pruneopts = "" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" + digest = "1:88401f863a34cfd82173ef2ad015652c2c47c866affc424bfdd4d5fafad1dd53" name = "golang.org/x/tools" packages = [ "go/ast/astutil", "imports", - "internal/fastwalk" + "internal/fastwalk", ] + pruneopts = "" revision = "90fa682c2a6e6a37b3a1364ce2fe1d5e41af9d6d" [[projects]] branch = "master" + digest = "1:b5eb34042d1d82e055da36ad49c74b362be8d857a140239cdfc7ddca1f41019f" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] + pruneopts = "" revision = "4b56f30a1fd96a133a036b62cdd2a249883dd89b" [[projects]] + digest = "1:15656947b87a6a240e61dcfae9e71a55a8d5677f240d12ab48f02cdbabf1e309" name = "google.golang.org/grpc" packages = [ ".", @@ -537,25 +666,31 @@ "resolver/passthrough", "stats", "status", - "tap" + "tap", ] + pruneopts = "" revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1" version = "v1.15.0" [[projects]] + digest = "1:75fb3fcfc73a8c723efde7777b40e8e8ff9babf30d8c56160d01beffea8a95a6" name = "gopkg.in/inf.v0" packages = ["."] + pruneopts = "" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" version = "v0.9.1" [[projects]] + digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2" name = "gopkg.in/yaml.v2" packages = ["."] + pruneopts = "" revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" version = "v2.2.1" [[projects]] branch = "release-1.9" + digest = "1:8a154464dc1ea7a9c16a34583693b194235218c08e4ff668eee49a3746bcc0a5" name = "k8s.io/api" packages = [ "admission/v1beta1", @@ -586,12 +721,14 @@ "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1" + "storage/v1beta1", ] + pruneopts = "" revision = "9273ee02527c608cecc74969b3e489f5dba686da" [[projects]] branch = "release-1.9" + digest = "1:5ab6164cabb8b939ae6d7a01d6e534c5e88eaf3c4f5040f803ad22591c95c639" name = "k8s.io/apimachinery" packages = [ "pkg/api/equality", @@ -647,12 +784,14 @@ "pkg/watch", "third_party/forked/golang/json", "third_party/forked/golang/netutil", - "third_party/forked/golang/reflect" + "third_party/forked/golang/reflect", ] + pruneopts = "" revision = "fb40df2b502912cbe3a93aa61c2b2487f39cb42f" [[projects]] branch = "release-1.9" + digest = "1:191e0f4717a3fdf371239cc947e27ae381b98c16fbb29fe60696da48d2664999" name = "k8s.io/apiserver" packages = [ "pkg/admission", @@ -732,12 +871,14 @@ "pkg/util/webhook", "pkg/util/wsstream", "plugin/pkg/authenticator/token/webhook", - "plugin/pkg/authorizer/webhook" + "plugin/pkg/authorizer/webhook", ] + pruneopts = "" revision = "b2fdecc78668ca10ae83e151a11d8c4cbfce9431" [[projects]] branch = "release-6.0" + digest = "1:751dccece6307a20592bef2c1ac850444aaf9c4b84307c75be7e2b87c8f2ff11" name = "k8s.io/client-go" packages = [ "discovery", @@ -857,18 +998,22 @@ "util/flowcontrol", "util/homedir", "util/integer", - "util/workqueue" + "util/workqueue", ] + pruneopts = "" revision = "115d23201cc1aa2260c19f8f6bb79d400d123dbd" [[projects]] branch = "release-1.9" + digest = "1:e041412a6b251f795b4d001a0e67c9e7f52c4fe35263dd750af14019fa5735f9" name = "k8s.io/code-generator" packages = ["cmd/deepcopy-gen"] + pruneopts = "" revision = "0ab89e584187c20cc7c1a3f30db69f3b4ab64196" [[projects]] branch = "master" + digest = "1:4a75352fad3a8e993928462643415e8263f94ae845aa5e7dce1de2f34f961e36" name = "k8s.io/gengo" packages = [ "args", @@ -877,24 +1022,28 @@ "generator", "namer", "parser", - "types" + "types", ] + pruneopts = "" revision = "4242d8e6c5dba56827bb7bcf14ad11cda38f3991" [[projects]] branch = "master" + digest = "1:951bc2047eea6d316a17850244274554f26fd59189360e45f4056b424dadf2c1" name = "k8s.io/kube-openapi" packages = [ "pkg/builder", "pkg/common", "pkg/handler", "pkg/util", - "pkg/util/proto" + "pkg/util/proto", ] + pruneopts = "" revision = "e3762e86a74c878ffed47484592986685639c2cd" [[projects]] branch = "master" + digest = "1:0859664ec0d20e3c7406ddc26ed27f5285d0155657f022026959e14b641bf277" name = "sigs.k8s.io/cluster-api" packages = [ "clusterctl/clusterdeployer", @@ -923,13 +1072,59 @@ "pkg/controller/noderefutil", "pkg/controller/sharedinformers", "pkg/deployer", - "pkg/util" + "pkg/util", ] + pruneopts = "" revision = "5b128c0f9ab134087d1331be8176099201055a36" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "921bb1abfeb17ad98b811c5ddaed73473477a57b5530c79fa21d8abcb161c64c" + input-imports = [ + "github.com/aws/aws-sdk-go/aws", + "github.com/aws/aws-sdk-go/aws/awserr", + "github.com/aws/aws-sdk-go/aws/request", + "github.com/aws/aws-sdk-go/aws/session", + "github.com/aws/aws-sdk-go/service/cloudformation", + "github.com/aws/aws-sdk-go/service/ec2", + "github.com/aws/aws-sdk-go/service/ec2/ec2iface", + "github.com/aws/aws-sdk-go/service/elb", + "github.com/aws/aws-sdk-go/service/elb/elbiface", + "github.com/awslabs/goformation/cloudformation", + "github.com/golang/glog", + "github.com/golang/mock/gomock", + "github.com/kubernetes-incubator/apiserver-builder/pkg/controller", + "github.com/pkg/errors", + "github.com/spf13/cobra", + "github.com/spf13/pflag", + "k8s.io/api/core/v1", + "k8s.io/apimachinery/pkg/apis/meta/v1", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/runtime/schema", + "k8s.io/apimachinery/pkg/runtime/serializer", + "k8s.io/apimachinery/pkg/types", + "k8s.io/apimachinery/pkg/util/uuid", + "k8s.io/apimachinery/pkg/util/wait", + "k8s.io/apimachinery/pkg/watch", + "k8s.io/apiserver/pkg/util/logs", + "k8s.io/client-go/kubernetes", + "k8s.io/client-go/kubernetes/typed/core/v1", + "k8s.io/client-go/rest", + "k8s.io/client-go/tools/leaderelection", + "k8s.io/client-go/tools/leaderelection/resourcelock", + "k8s.io/client-go/tools/record", + "k8s.io/code-generator/cmd/deepcopy-gen", + "sigs.k8s.io/cluster-api/clusterctl/cmd", + "sigs.k8s.io/cluster-api/pkg/apis/cluster/common", + "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha1", + "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset", + "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/scheme", + "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha1", + "sigs.k8s.io/cluster-api/pkg/controller/cluster", + "sigs.k8s.io/cluster-api/pkg/controller/config", + "sigs.k8s.io/cluster-api/pkg/controller/error", + "sigs.k8s.io/cluster-api/pkg/controller/machine", + "sigs.k8s.io/cluster-api/pkg/controller/sharedinformers", + ] solver-name = "gps-cdcl" solver-version = 1 diff --git a/cloud/aws/services/ec2/bastion.go b/cloud/aws/services/ec2/bastion.go index 9673cd6cde..54c007b621 100644 --- a/cloud/aws/services/ec2/bastion.go +++ b/cloud/aws/services/ec2/bastion.go @@ -25,9 +25,6 @@ import ( ) const ( - // TagValueBastionRole describes the value associated with the role tag. - TagValueBastionRole = "bastion" - bastionUserData = `#!/bin/bash BASTION_BOOTSTRAP_FILE=bastion_bootstrap.sh @@ -103,14 +100,23 @@ func (s *Service) describeBastionInstance(clusterName string, status *v1alpha1.A return nil, errors.Wrap(err, "failed to describe bastion host") } - if len(out.Reservations) == 0 || len(out.Reservations[0].Instances) == 0 { - return nil, NewNotFound(errors.New("bastion host not found")) + // TODO: properly handle multiple bastions found rather than just returning + // the first non-terminated. + for _, res := range out.Reservations { + for _, instance := range res.Instances { + if aws.StringValue(instance.State.Name) != ec2.InstanceStateNameTerminated { + return fromSDKTypeToInstance(instance), nil + } + } } - return fromSDKTypeToInstance(out.Reservations[0].Instances[0]), nil + return nil, NewNotFound(errors.New("bastion host not found")) } func (s *Service) getDefaultBastion(clusterName string, region string, network v1alpha1.Network, keyName string) *v1alpha1.Instance { + name := fmt.Sprintf("%s-bastion", clusterName) + tags := s.buildTags(clusterName, ResourceLifecycleOwned, name, TagValueBastionRole, nil) + i := &v1alpha1.Instance{ Type: "t2.micro", SubnetID: network.Subnets.FilterPublic()[0].ID, @@ -120,10 +126,7 @@ func (s *Service) getDefaultBastion(clusterName string, region string, network v SecurityGroupIDs: []string{ network.SecurityGroups[v1alpha1.SecurityGroupBastion].ID, }, - Tags: map[string]string{ - s.clusterTagKey(clusterName): string(ResourceLifecycleOwned), - TagNameAWSClusterAPIRole: TagValueBastionRole, - }, + Tags: tags, } return i diff --git a/cloud/aws/services/ec2/eips.go b/cloud/aws/services/ec2/eips.go index a346f4ce36..df9951148c 100644 --- a/cloud/aws/services/ec2/eips.go +++ b/cloud/aws/services/ec2/eips.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/glog" @@ -21,20 +23,46 @@ import ( "sigs.k8s.io/cluster-api-provider-aws/cloud/aws/services/wait" ) -func (s *Service) allocateAddress(clusterName string) (string, error) { +func (s *Service) getOrAllocateAddress(clusterName string, role string) (string, error) { + out, err := s.describeAddresses(clusterName, role) + if err != nil { + return "", errors.Wrap(err, "failed to query addresses") + } + + // TODO: better handle multiple addresses returned + for _, address := range out.Addresses { + if address.AssociationId == nil { + return aws.StringValue(address.AllocationId), nil + } + } + return s.allocateAddress(clusterName, role) +} + +func (s *Service) allocateAddress(clusterName string, role string) (string, error) { out, err := s.EC2.AllocateAddress(&ec2.AllocateAddressInput{ Domain: aws.String("vpc"), }) if err != nil { - return "", errors.Wrapf(err, "failed to create Elastic IP address") + return "", errors.Wrap(err, "failed to create Elastic IP address") } - if err := s.createTags(clusterName, *out.AllocationId, ResourceLifecycleOwned, nil); err != nil { - return "", errors.Wrapf(err, "failed to tag elastic IP %q", *out.AllocationId) + name := fmt.Sprintf("%s-eip-%s", clusterName, role) + if err := s.createTags(clusterName, *out.AllocationId, ResourceLifecycleOwned, name, role, nil); err != nil { + return "", errors.Wrapf(err, "failed to tag elastic IP %q", aws.StringValue(out.AllocationId)) } - return *out.AllocationId, nil + return aws.StringValue(out.AllocationId), nil +} + +func (s *Service) describeAddresses(clusterName string, role string) (*ec2.DescribeAddressesOutput, error) { + filters := []*ec2.Filter{s.filterCluster(clusterName)} + if role != "" { + filters = append(filters, s.filterAWSProviderRole(role)) + } + return s.EC2.DescribeAddresses(&ec2.DescribeAddressesInput{ + Filters: filters, + }) } func (s *Service) releaseAddresses(clusterName string) error { diff --git a/cloud/aws/services/ec2/errors.go b/cloud/aws/services/ec2/errors.go index 5c3942a1bb..0c8251bacf 100644 --- a/cloud/aws/services/ec2/errors.go +++ b/cloud/aws/services/ec2/errors.go @@ -58,7 +58,10 @@ func NewConflict(err error) error { // IsNotFound returns true if the error was created by NewNotFound. func IsNotFound(err error) bool { - return ReasonForError(err) == http.StatusNotFound + if ReasonForError(err) == http.StatusNotFound { + return true + } + return IsInvalidNotFoundError(err) } // IsConflict returns true if the error was created by NewConflict. @@ -72,6 +75,17 @@ func IsSDKError(err error) (ok bool) { return } +// IsInvalidNotFoundError tests for common aws not found errors +func IsInvalidNotFoundError(err error) bool { + if awsErr, ok := err.(awserr.Error); ok { + switch code := awsErr.Code(); code { + case "InvalidVpcID.NotFound": + return true + } + } + return false +} + // ReasonForError returns the HTTP status for a particular error. func ReasonForError(err error) int { switch t := err.(type) { diff --git a/cloud/aws/services/ec2/filters.go b/cloud/aws/services/ec2/filters.go index cdf60f0c09..63b75c447b 100644 --- a/cloud/aws/services/ec2/filters.go +++ b/cloud/aws/services/ec2/filters.go @@ -1,6 +1,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" ) @@ -20,6 +22,40 @@ func (s *Service) filterCluster(clusterName string) *ec2.Filter { } } +// Returns an EC2 filter using the Cluster API per-cluster tag where +// the resource is owned +func (s *Service) filterClusterOwned(clusterName string) *ec2.Filter { + return &ec2.Filter{ + Name: aws.String(fmt.Sprintf("tag:%s", s.clusterTagKey(clusterName))), + Values: aws.StringSlice([]string{string(ResourceLifecycleOwned)}), + } +} + +// Returns an EC2 filter using the Cluster API per-cluster tag where +// the resource is shared +func (s *Service) filterClusterShared(clusterName string) *ec2.Filter { + return &ec2.Filter{ + Name: aws.String(fmt.Sprintf("tag:%s", s.clusterTagKey(clusterName))), + Values: aws.StringSlice([]string{string(ResourceLifecycleShared)}), + } +} + +// Returns an EC2 filter using cluster-api-provider-aws managed tag +func (s *Service) filterAWSProviderManaged() *ec2.Filter { + return &ec2.Filter{ + Name: aws.String(filterNameTagKey), + Values: aws.StringSlice([]string{TagNameAWSProviderManaged}), + } +} + +// Returns an EC2 filter using cluster-api-provider-aws role tag +func (s *Service) filterAWSProviderRole(role string) *ec2.Filter { + return &ec2.Filter{ + Name: aws.String(fmt.Sprintf("tag:%s", TagNameAWSClusterAPIRole)), + Values: aws.StringSlice([]string{role}), + } +} + // Returns an EC2 filter for the specified VPC ID func (s *Service) filterVpc(vpcID string) *ec2.Filter { return &ec2.Filter{ diff --git a/cloud/aws/services/ec2/gateways.go b/cloud/aws/services/ec2/gateways.go index 2c4385b6b0..64ecd0ad8c 100644 --- a/cloud/aws/services/ec2/gateways.go +++ b/cloud/aws/services/ec2/gateways.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/glog" @@ -73,7 +75,8 @@ func (s *Service) createInternetGateway(clusterName string, vpc *v1alpha1.VPC) ( return nil, errors.Wrap(err, "failed to create internet gateway") } - if err := s.createTags(clusterName, *ig.InternetGateway.InternetGatewayId, ResourceLifecycleOwned, nil); err != nil { + name := fmt.Sprintf("%s-igw", clusterName) + if err := s.createTags(clusterName, *ig.InternetGateway.InternetGatewayId, ResourceLifecycleOwned, name, TagValueCommonRole, nil); err != nil { return nil, errors.Wrapf(err, "failed to tag internet gateway %q", *ig.InternetGateway.InternetGatewayId) } diff --git a/cloud/aws/services/ec2/gateways_test.go b/cloud/aws/services/ec2/gateways_test.go index 4c960bb3a1..c20ef3d603 100644 --- a/cloud/aws/services/ec2/gateways_test.go +++ b/cloud/aws/services/ec2/gateways_test.go @@ -76,13 +76,7 @@ func TestReconcileInternetGateways(t *testing.T) { }, nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"igw-1"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). diff --git a/cloud/aws/services/ec2/natgateways.go b/cloud/aws/services/ec2/natgateways.go index 07150cd24a..626e5b0e39 100644 --- a/cloud/aws/services/ec2/natgateways.go +++ b/cloud/aws/services/ec2/natgateways.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/glog" @@ -114,7 +116,7 @@ func (s *Service) describeNatGatewaysBySubnet(vpcID string) (map[string]*ec2.Nat } func (s *Service) createNatGateway(clusterName string, subnetID string) (*ec2.NatGateway, error) { - ip, err := s.allocateAddress(clusterName) + ip, err := s.getOrAllocateAddress(clusterName, TagValueAPIServerRole) if err != nil { return nil, errors.Wrapf(err, "failed to create IP address for NAT gateway for subnet ID %q", subnetID) } @@ -128,6 +130,11 @@ func (s *Service) createNatGateway(clusterName string, subnetID string) (*ec2.Na return nil, errors.Wrapf(err, "failed to create NAT gateway for subnet ID %q", subnetID) } + name := fmt.Sprintf("%s-nat", clusterName) + if err := s.createTags(clusterName, *out.NatGateway.NatGatewayId, ResourceLifecycleOwned, name, TagValueCommonRole, nil); err != nil { + return nil, errors.Wrapf(err, "failed to tag nat gateway %q", *out.NatGateway.NatGatewayId) + } + glog.Infof("Created NAT gateway %q for subnet ID %q, waiting for it to become available...", *out.NatGateway.NatGatewayId, subnetID) wReq := &ec2.DescribeNatGatewaysInput{NatGatewayIds: []*string{out.NatGateway.NatGatewayId}} @@ -137,10 +144,6 @@ func (s *Service) createNatGateway(clusterName string, subnetID string) (*ec2.Na glog.Infof("NAT gateway %q for subnet ID %q is now available", *out.NatGateway.NatGatewayId, subnetID) - if err := s.createTags(clusterName, *out.NatGateway.NatGatewayId, ResourceLifecycleOwned, nil); err != nil { - return nil, errors.Wrapf(err, "failed to tag nat gateway %q", *out.NatGateway.NatGatewayId) - } - return out.NatGateway, nil } diff --git a/cloud/aws/services/ec2/natgateways_test.go b/cloud/aws/services/ec2/natgateways_test.go index 2b845c4c2e..04acad211d 100644 --- a/cloud/aws/services/ec2/natgateways_test.go +++ b/cloud/aws/services/ec2/natgateways_test.go @@ -108,6 +108,10 @@ func TestReconcileNatGateways(t *testing.T) { }), gomock.Any()).Return(nil) + m.EXPECT(). + DescribeAddresses(gomock.Any()). + Return(&ec2.DescribeAddressesOutput{}, nil) + m.EXPECT(). AllocateAddress(&ec2.AllocateAddressInput{Domain: aws.String("vpc")}). Return(&ec2.AllocateAddressOutput{ @@ -130,25 +134,12 @@ func TestReconcileNatGateways(t *testing.T) { }).Return(nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{ElasticIPAllocationID}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"natgateway"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) - }, }, { @@ -200,6 +191,10 @@ func TestReconcileNatGateways(t *testing.T) { }}}, true) }).Return(nil) + m.EXPECT(). + DescribeAddresses(gomock.Any()). + Return(&ec2.DescribeAddressesOutput{}, nil) + m.EXPECT(). AllocateAddress(&ec2.AllocateAddressInput{Domain: aws.String("vpc")}). Return(&ec2.AllocateAddressOutput{ @@ -222,23 +217,11 @@ func TestReconcileNatGateways(t *testing.T) { }).Return(nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{ElasticIPAllocationID}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"natgateway"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) }, }, @@ -284,6 +267,8 @@ func TestReconcileNatGateways(t *testing.T) { }}}, true) }).Return(nil) + m.EXPECT().DescribeAddresses(gomock.Any()).Times(0) + m.EXPECT().AllocateAddress(gomock.Any()).Times(0) m.EXPECT().CreateNatGateway(gomock.Any()).Times(0) diff --git a/cloud/aws/services/ec2/routetables.go b/cloud/aws/services/ec2/routetables.go index 03fe78282d..753deece74 100644 --- a/cloud/aws/services/ec2/routetables.go +++ b/cloud/aws/services/ec2/routetables.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/glog" @@ -59,7 +61,7 @@ func (s *Service) reconcileRouteTables(clusterName string, in *v1alpha1.Network) routes = s.getDefaultPrivateRoutes(natGatewayID) } - rt, err := s.createRouteTableWithRoutes(clusterName, &in.VPC, routes) + rt, err := s.createRouteTableWithRoutes(clusterName, &in.VPC, routes, sn.IsPublic) if err != nil { return err } @@ -142,12 +144,20 @@ func (s *Service) describeVpcRouteTables(clusterName string, vpcID string) ([]*e return out.RouteTables, nil } -func (s *Service) createRouteTableWithRoutes(clusterName string, vpc *v1alpha1.VPC, routes []*ec2.Route) (*v1alpha1.RouteTable, error) { +// TODO: dedup some of the public/private logic shared with createSubnet +func (s *Service) createRouteTableWithRoutes(clusterName string, vpc *v1alpha1.VPC, routes []*ec2.Route, isPublic bool) (*v1alpha1.RouteTable, error) { out, err := s.EC2.CreateRouteTable(&ec2.CreateRouteTableInput{ VpcId: aws.String(vpc.ID), }) - if err := s.createTags(clusterName, *out.RouteTable.RouteTableId, ResourceLifecycleOwned, nil); err != nil { + suffix := "private" + role := TagValueCommonRole + if isPublic { + suffix = "public" + role = TagValueBastionRole + } + name := fmt.Sprintf("%s-rt-%s", clusterName, suffix) + if err := s.createTags(clusterName, *out.RouteTable.RouteTableId, ResourceLifecycleOwned, name, role, nil); err != nil { return nil, errors.Wrapf(err, "failed to tag route table %q", *out.RouteTable.RouteTableId) } diff --git a/cloud/aws/services/ec2/routetables_test.go b/cloud/aws/services/ec2/routetables_test.go index f698ecb5e6..ffda590257 100644 --- a/cloud/aws/services/ec2/routetables_test.go +++ b/cloud/aws/services/ec2/routetables_test.go @@ -68,13 +68,7 @@ func TestReconcileRouteTables(t *testing.T) { Return(&ec2.CreateRouteTableOutput{RouteTable: &ec2.RouteTable{RouteTableId: aws.String("rt-1")}}, nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"rt-1"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). @@ -106,13 +100,7 @@ func TestReconcileRouteTables(t *testing.T) { After(publicRouteTable) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"rt-2"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). diff --git a/cloud/aws/services/ec2/securitygroups.go b/cloud/aws/services/ec2/securitygroups.go index 4a45fba27f..bb390bf47d 100644 --- a/cloud/aws/services/ec2/securitygroups.go +++ b/cloud/aws/services/ec2/securitygroups.go @@ -279,19 +279,13 @@ func (s *Service) getSecurityGroupName(clusterName string, role v1alpha1.Securit func (s *Service) getDefaultSecurityGroup(clusterName string, vpcID string, role v1alpha1.SecurityGroupRole) *ec2.SecurityGroup { name := s.getSecurityGroupName(clusterName, role) + // TODO: reconcile v1alpha1.SecurityGroupRoles with tag roles + tags := s.buildTags(clusterName, ResourceLifecycleOwned, name, string(role), nil) + return &ec2.SecurityGroup{ GroupName: aws.String(name), VpcId: aws.String(vpcID), - Tags: []*ec2.Tag{ - &ec2.Tag{ - Key: aws.String("Name"), - Value: aws.String(name), - }, - &ec2.Tag{ - Key: aws.String(s.clusterTagKey(clusterName)), - Value: aws.String(string(ResourceLifecycleOwned)), - }, - }, + Tags: mapToTags(tags), } } diff --git a/cloud/aws/services/ec2/subnets.go b/cloud/aws/services/ec2/subnets.go index 1c8714f82d..0d46cf5f76 100644 --- a/cloud/aws/services/ec2/subnets.go +++ b/cloud/aws/services/ec2/subnets.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/glog" @@ -170,7 +172,14 @@ func (s *Service) createSubnet(clusterName string, sn *v1alpha1.Subnet) (*v1alph return nil, errors.Wrapf(err, "failed to wait for subnet %q", *out.Subnet.SubnetId) } - if err := s.createTags(clusterName, *out.Subnet.SubnetId, ResourceLifecycleOwned, nil); err != nil { + suffix := "private" + role := TagValueCommonRole + if mapPublicIP { + suffix = "public" + role = TagValueBastionRole + } + name := fmt.Sprintf("%s-subnet-%s", clusterName, suffix) + if err := s.createTags(clusterName, *out.Subnet.SubnetId, ResourceLifecycleOwned, name, role, nil); err != nil { return nil, errors.Wrapf(err, "failed to tag subnet %q", *out.Subnet.SubnetId) } diff --git a/cloud/aws/services/ec2/subnets_test.go b/cloud/aws/services/ec2/subnets_test.go index be91fe9e13..adf38e47fb 100644 --- a/cloud/aws/services/ec2/subnets_test.go +++ b/cloud/aws/services/ec2/subnets_test.go @@ -106,13 +106,7 @@ func TestReconcileSubnets(t *testing.T) { WaitUntilSubnetAvailable(gomock.Any()) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"subnet-2"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) m.EXPECT(). @@ -181,13 +175,7 @@ func TestReconcileSubnets(t *testing.T) { After(firstSubnet) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"subnet-1"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) secondSubnet := m.EXPECT(). @@ -212,14 +200,7 @@ func TestReconcileSubnets(t *testing.T) { After(secondSubnet) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: aws.StringSlice([]string{"subnet-2"}), - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). - Return(nil, nil) + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})) m.EXPECT(). ModifySubnetAttribute(&ec2.ModifySubnetAttributeInput{ diff --git a/cloud/aws/services/ec2/tags.go b/cloud/aws/services/ec2/tags.go index 79086c570e..befbb2fc08 100644 --- a/cloud/aws/services/ec2/tags.go +++ b/cloud/aws/services/ec2/tags.go @@ -28,9 +28,23 @@ const ( // The tag value is an ownership value TagNameKubernetesClusterPrefix = "kubernetes.io/cluster/" + // TagNameAWSProviderManaged is the tag name we use to differentiate + // cluster-api-provider-aws owned components from other tooling that + // uses TagNameKubernetesClusterPrefix + TagNameAWSProviderManaged = "sigs.k8s.io/cluster-api-provider-aws/managed" + // TagNameAWSClusterAPIRole is the tag name we use to mark roles for resources // dedicated to this cluster api provider implementation. TagNameAWSClusterAPIRole = "sigs.k8s.io/cluster-api-provider-aws/role" + + // TagValueAPIServerRole describes the value for the apiserver role + TagValueAPIServerRole = "apiserver" + + // TagValueBastionRole describes the value for the bastion role + TagValueBastionRole = "bastion" + + // TagValueCommonRole describes the value for the common role + TagValueCommonRole = "common" ) // ResourceLifecycle configures the lifecycle of a resource @@ -53,8 +67,8 @@ func (s *Service) clusterTagKey(clusterName string) string { } // createTags tags a resource with tags including the cluster tag -func (s *Service) createTags(clusterName string, resourceID string, lifecycle ResourceLifecycle, additionalTags map[string]string) error { - tags := s.buildTags(clusterName, lifecycle, additionalTags) +func (s *Service) createTags(clusterName, resourceID string, lifecycle ResourceLifecycle, name, role string, additionalTags map[string]string) error { + tags := s.buildTags(clusterName, lifecycle, name, role, additionalTags) awsTags := make([]*ec2.Tag, 0, len(tags)) for k, v := range tags { @@ -76,13 +90,24 @@ func (s *Service) createTags(clusterName string, resourceID string, lifecycle Re } // buildTags builds tags including the cluster tag -func (s *Service) buildTags(clusterName string, lifecycle ResourceLifecycle, additionalTags map[string]string) map[string]string { +func (s *Service) buildTags(clusterName string, lifecycle ResourceLifecycle, name, role string, additionalTags map[string]string) map[string]string { tags := make(map[string]string) for k, v := range additionalTags { tags[k] = v } tags[s.clusterTagKey(clusterName)] = string(lifecycle) + if lifecycle == ResourceLifecycleOwned { + tags[TagNameAWSProviderManaged] = "true" + } + + if role != "" { + tags[TagNameAWSClusterAPIRole] = role + } + + if name != "" { + tags["Name"] = name + } return tags } diff --git a/cloud/aws/services/ec2/vpc.go b/cloud/aws/services/ec2/vpc.go index 570be9dca4..bf817a5980 100644 --- a/cloud/aws/services/ec2/vpc.go +++ b/cloud/aws/services/ec2/vpc.go @@ -14,6 +14,8 @@ package ec2 import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/ec2" @@ -65,7 +67,8 @@ func (s *Service) createVPC(clusterName string, v *v1alpha1.VPC) (*v1alpha1.VPC, return nil, errors.Wrapf(err, "failed to wait for vpc %q", *out.Vpc.VpcId) } - if err := s.createTags(clusterName, *out.Vpc.VpcId, ResourceLifecycleOwned, nil); err != nil { + name := fmt.Sprintf("%s-vpc", clusterName) + if err := s.createTags(clusterName, *out.Vpc.VpcId, ResourceLifecycleOwned, name, TagValueCommonRole, nil); err != nil { return nil, errors.Wrapf(err, "failed to tag vpc %q", *out.Vpc.VpcId) } @@ -111,6 +114,9 @@ func (s *Service) describeVPC(clusterName string, id string) (*v1alpha1.VPC, err out, err := s.EC2.DescribeVpcs(input) if err != nil { + if IsNotFound(err) { + return nil, err + } return nil, errors.Wrap(err, "failed to query ec2 for VPCs") } diff --git a/cloud/aws/services/ec2/vpc_test.go b/cloud/aws/services/ec2/vpc_test.go index d44662e765..6c8df4c6f0 100644 --- a/cloud/aws/services/ec2/vpc_test.go +++ b/cloud/aws/services/ec2/vpc_test.go @@ -84,13 +84,7 @@ func TestReconcileVPC(t *testing.T) { Return(nil) m.EXPECT(). - CreateTags(gomock.Eq(&ec2.CreateTagsInput{ - Resources: []*string{aws.String("vpc-new")}, - Tags: []*ec2.Tag{&ec2.Tag{ - Key: aws.String("kubernetes.io/cluster/test-cluster"), - Value: aws.String("owned"), - }}, - })). + CreateTags(gomock.AssignableToTypeOf(&ec2.CreateTagsInput{})). Return(nil, nil) }, }, diff --git a/cloud/aws/services/elb/loadbalancer.go b/cloud/aws/services/elb/loadbalancer.go index 5131d955c3..a7ab4f5c58 100644 --- a/cloud/aws/services/elb/loadbalancer.go +++ b/cloud/aws/services/elb/loadbalancer.go @@ -72,10 +72,7 @@ func (s *Service) getAPIServerClassicELBSpec(clusterName string, network *v1alph UnhealthyThreshold: 3, }, SecurityGroupIDs: []string{network.SecurityGroups[v1alpha1.SecurityGroupControlPlane].ID}, - Tags: map[string]string{ - fmt.Sprintf("%s%s", TagNameKubernetesClusterPrefix, clusterName): string(ResourceLifecycleOwned), - TagNameAWSClusterAPIRole: "apiserver", - }, + Tags: s.buildTags(clusterName, ResourceLifecycleOwned, "", TagValueAPIServerRole, nil), } for _, sn := range network.Subnets.FilterPrivate() { @@ -91,10 +88,7 @@ func (s *Service) createClassicELB(spec *v1alpha1.ClassicELB) (*v1alpha1.Classic Subnets: aws.StringSlice(spec.SubnetIDs), SecurityGroups: aws.StringSlice(spec.SecurityGroupIDs), Scheme: aws.String(string(spec.Scheme)), - } - - for key, value := range spec.Tags { - input.Tags = append(input.Tags, &elb.Tag{Key: aws.String(key), Value: aws.String(value)}) + Tags: mapToTags(spec.Tags), } for _, ln := range spec.Listeners { diff --git a/cloud/aws/services/elb/tags.go b/cloud/aws/services/elb/tags.go index 571068eca2..92404de07c 100644 --- a/cloud/aws/services/elb/tags.go +++ b/cloud/aws/services/elb/tags.go @@ -13,6 +13,13 @@ package elb +import ( + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/elb" +) + const ( // TagNameKubernetesClusterPrefix is the tag name we use to differentiate multiple // logically independent clusters running in the same AZ. @@ -20,9 +27,17 @@ const ( // The tag value is an ownership value TagNameKubernetesClusterPrefix = "kubernetes.io/cluster/" + // TagNameAWSProviderManaged is the tag name we use to differentiate + // cluster-api-provider-aws owned components from other tooling that + // uses TagNameKubernetesClusterPrefix + TagNameAWSProviderManaged = "sigs.k8s.io/cluster-api-provider-aws/managed" + // TagNameAWSClusterAPIRole is the tag name we use to mark roles for resources // dedicated to this cluster api provider implementation. TagNameAWSClusterAPIRole = "sigs.k8s.io/cluster-api-provider-aws/role" + + TagValueCommonRole = "common" + TagValueAPIServerRole = "apiserver" ) // ResourceLifecycle configures the lifecycle of a resource @@ -39,3 +54,61 @@ const ( // if the cluster is destroyed. ResourceLifecycleShared = ResourceLifecycle("shared") ) + +func (s *Service) clusterTagKey(clusterName string) string { + return fmt.Sprintf("%s%s", TagNameKubernetesClusterPrefix, clusterName) +} + +// buildTags builds tags including the cluster tag +func (s *Service) buildTags(clusterName string, lifecycle ResourceLifecycle, name string, role string, additionalTags map[string]string) map[string]string { + tags := make(map[string]string) + for k, v := range additionalTags { + tags[k] = v + } + + tags[s.clusterTagKey(clusterName)] = string(lifecycle) + if lifecycle == ResourceLifecycleOwned { + tags[TagNameAWSProviderManaged] = "true" + } + + if role != "" { + tags[TagNameAWSClusterAPIRole] = role + } + + if name != "" { + tags["Name"] = name + } + + return tags +} + +// tagsToMap converts a []*elb.Tag into a map[string]string. +func tagsToMap(src []*elb.Tag) map[string]string { + // Create an array of exactly the length we require to hopefully avoid some + // allocations while looping. + tags := make(map[string]string) + + for _, t := range src { + tags[*t.Key] = *t.Value + } + + return tags +} + +// mapToTags converts a map[string]string to a []*elb.Tag +func mapToTags(src map[string]string) []*elb.Tag { + // Create an array of exactly the length we require to hopefully avoid some + // allocations while looping. + tags := make([]*elb.Tag, 0, len(src)) + + for k, v := range src { + tag := &elb.Tag{ + Key: aws.String(k), + Value: aws.String(v), + } + + tags = append(tags, tag) + } + + return tags +}