diff --git a/Gopkg.lock b/Gopkg.lock index aaad8169e..7c4d43c05 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -2,34 +2,27 @@ [[projects]] - digest = "1:e4549155be72f065cf860ada7148bbeb0857360e81da2d5e28b799bd8720f1bc" name = "cloud.google.com/go" packages = ["compute/metadata"] - pruneopts = "T" revision = "0ebda48a7f143b1cce9eb37a8c1106ac762a3430" version = "v0.34.0" [[projects]] - digest = "1:b92928b73320648b38c93cacb9082c0fe3f8ac3383ad9bd537eef62c380e0e7a" name = "contrib.go.opencensus.io/exporter/ocagent" packages = ["."] - pruneopts = "T" revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d" version = "v0.2.0" [[projects]] branch = "master" - digest = "1:6da51e5ec493ad2b44cb04129e2d0a068c8fb9bd6cb5739d199573558696bb94" name = "github.com/Azure/go-ansiterm" packages = [ ".", - "winterm", + "winterm" ] - pruneopts = "T" revision = "d6e3b3328b783f23731bc4d058875b0371ff8109" [[projects]] - digest = "1:4827c7440869600b1e44806702a649c5055692063056e165026d46518e33db12" name = "github.com/Azure/go-autorest" packages = [ "autorest", @@ -37,158 +30,122 @@ "autorest/azure", "autorest/date", "logger", - "tracing", + "tracing" ] - pruneopts = "T" revision = "f401b1ccc8eb505927fae7a0c7f6406d37ca1c7e" version = "v11.2.8" [[projects]] - digest = "1:147748cfa709da38076c3df47f6bca6814c8ced6cba510065ec03f2120cc4819" name = "github.com/BurntSushi/toml" packages = ["."] - pruneopts = "T" revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005" version = "v0.3.1" [[projects]] branch = "master" - digest = "1:414b0f57170d23e2941aa5cd393e99d0ab7a639e27d9784ef3949eae6cddfdb3" name = "github.com/MakeNowJust/heredoc" packages = ["."] - pruneopts = "T" revision = "e9091a26100e9cfb2b6a8f470085bfa541931a91" [[projects]] - digest = "1:3b10c6fd33854dc41de2cf78b7bae105da94c2789b6fa5b9ac9e593ea43484ac" name = "github.com/Masterminds/goutils" packages = ["."] - pruneopts = "T" revision = "41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0" version = "v1.1.0" [[projects]] - digest = "1:55388fd080150b9a072912f97b1f5891eb0b50df43401f8b75fb4273d3fec9fc" name = "github.com/Masterminds/semver" packages = ["."] - pruneopts = "T" revision = "c7af12943936e8c39859482e61f0574c2fd7fc75" version = "v1.4.2" [[projects]] - digest = "1:167d20f2417c3188e4f4d02a8870ac65b4d4f9fe0ac6f450873fcffa39623a37" name = "github.com/Masterminds/sprig" packages = ["."] - pruneopts = "T" revision = "258b00ffa7318e8b109a141349980ffbd30a35db" version = "v2.20.0" [[projects]] - digest = "1:74334b154a542b15a7391df3db5428675fdaa56b4d3f3de7b750289b9500d70e" name = "github.com/Masterminds/vcs" packages = ["."] - pruneopts = "T" revision = "b4f55832432b95a611cf1495272b5c8e24952a1a" version = "v1.13.0" [[projects]] - digest = "1:ef2f0eff765cd6c60594654adc602ac5ba460462ac395c6f3c144e5bea24babe" name = "github.com/Microsoft/go-winio" packages = ["."] - pruneopts = "T" revision = "1a8911d1ed007260465c3bfbbc785ac6915a0bb8" version = "v0.4.12" [[projects]] branch = "master" - digest = "1:3721a10686511b80c052323423f0de17a8c06d417dbdd3b392b1578432a33aae" name = "github.com/Nvveen/Gotty" packages = ["."] - pruneopts = "T" revision = "cd527374f1e5bff4938207604a14f2e38a9cf512" [[projects]] - digest = "1:352fc094dbd1438593b64251de6788bffdf30f9925cf763c7f62e1fd27142b76" name = "github.com/PuerkitoBio/purell" packages = ["."] - pruneopts = "T" revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4" version = "v1.1.0" [[projects]] branch = "master" - digest = "1:c739832d67eb1e9cc478a19cc1a1ccd78df0397bf8a32978b759152e205f644b" name = "github.com/PuerkitoBio/urlesc" packages = ["."] - pruneopts = "T" revision = "de5bf2ad457846296e2031421a34e2568e304e35" [[projects]] branch = "master" - digest = "1:5b8a3b9e8d146a93f6d0538d3be408c9adff07fd694d4094b814a376b4727b14" name = "github.com/Shopify/logrus-bugsnag" packages = ["."] - pruneopts = "T" revision = "577dee27f20dd8f1a529f82210094af593be12bd" [[projects]] - digest = "1:297a3c21bf1d3b4695a222e43e982bb52b4b9e156ca2eadbe32b898d0a1ae551" name = "github.com/asaskevich/govalidator" packages = ["."] - pruneopts = "T" revision = "ccb8e960c48f04d6935e72476ae4a51028f9e22f" version = "v9" [[projects]] branch = "master" - digest = "1:ad4589ec239820ee99eb01c1ad47ebc5f8e02c4f5103a9b210adff9696d89f36" name = "github.com/beorn7/perks" packages = ["quantile"] - pruneopts = "T" revision = "3a771d992973f24aa725d07868b467d1ddfceafb" [[projects]] - digest = "1:7b81d2ed76bf960333a8020c4b8c22abd6072f0b54ad31c66e90e6a17a19315a" name = "github.com/bshuster-repo/logrus-logstash-hook" packages = ["."] - pruneopts = "T" revision = "dbc1e22735aa6ed7bd9579a407c17bc7c4a4e046" version = "v0.4.1" [[projects]] - digest = "1:f18852f146423bf4c60dcd2f84e8819cfeabac15a875d7ea49daddb2d021f9d5" name = "github.com/bugsnag/bugsnag-go" packages = [ ".", - "errors", + "errors" ] - pruneopts = "T" revision = "3f5889f222e9c07aa1f62c5e8c202e402ce574cd" version = "v1.3.2" [[projects]] - digest = "1:3049c43c6d1cfaa347acd27d6342187f8f38d9f416bbba7b02b43f82848302d2" name = "github.com/bugsnag/panicwrap" packages = ["."] - pruneopts = "T" revision = "4009b2b7c78d820cc4a2e42f035bb557ce4ae45b" version = "v1.2.0" [[projects]] - digest = "1:0b2d5839372f6dc106fcaa70b6bd5832789a633c4e470540f76c2ec6c560e1c1" name = "github.com/census-instrumentation/opencensus-proto" packages = [ "gen-go/agent/common/v1", "gen-go/agent/trace/v1", "gen-go/resource/v1", - "gen-go/trace/v1", + "gen-go/trace/v1" ] - pruneopts = "T" revision = "7f2434bc10da710debe5c4315ed6d4df454b4024" version = "v0.1.0" [[projects]] - digest = "1:b5f139796b532342966b835fb26fe41b6b488e94b914f1af1aba4cd3a9fee6dc" name = "github.com/containerd/containerd" packages = [ "content", @@ -198,73 +155,59 @@ "platforms", "reference", "remotes", - "remotes/docker", + "remotes/docker" ] - pruneopts = "T" revision = "894b81a4b802e4eb2a91d1ce216b8817763c29fb" version = "v1.2.6" [[projects]] branch = "master" - digest = "1:1271f7f8cc5f5b2eb0c683f92c7adf8fca1813b9da5218d6df1c9cf4bdc3f8d5" name = "github.com/containerd/continuity" packages = ["pathdriver"] - pruneopts = "T" revision = "004b46473808b3e7a4a3049c20e4376c91eb966d" [[projects]] - digest = "1:607c4f1f646bfe5ec1a4eac4a505608f280829550ed546a243698a525d3c5fe8" name = "github.com/cpuguy83/go-md2man" packages = ["md2man"] - pruneopts = "T" revision = "20f5889cbdc3c73dbd2862796665e7c465ade7d1" version = "v1.0.8" [[projects]] - digest = "1:9f42202ac457c462ad8bb9642806d275af9ab4850cf0b1960b9c6f083d4a309a" name = "github.com/davecgh/go-spew" packages = ["spew"] - pruneopts = "T" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" version = "v1.1.1" [[projects]] - digest = "1:7dd5499cbbbb141b28c7b98bcf9a14af1ca69d368796096784ccef3292407a52" name = "github.com/deislabs/oras" packages = [ "pkg/auth", "pkg/auth/docker", "pkg/content", "pkg/context", - "pkg/oras", + "pkg/oras" ] - pruneopts = "T" revision = "b3b6ce7eeb31a5c0d891d33f585c84ae3dcc9046" version = "v0.5.0" [[projects]] - digest = "1:6b014c67cb522566c30ef02116f9acb50cd60954708cf92c6654e2985696db18" name = "github.com/dgrijalva/jwt-go" packages = ["."] - pruneopts = "T" revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" version = "v3.2.0" [[projects]] - digest = "1:82905edd0b7a5bca3774725e162e1befecd500cd95df2c9909358d4835d36310" name = "github.com/docker/cli" packages = [ "cli/config", "cli/config/configfile", "cli/config/credentials", - "cli/config/types", + "cli/config/types" ] - pruneopts = "T" revision = "f28d9cc92972044feb72ab6833699102992d40a2" version = "v19.03.0-beta3" [[projects]] - digest = "1:bd3ffa8395e5f3cee7a1d38a7f4de0df088301e25c4e6910fc53936c4be09278" name = "github.com/docker/distribution" packages = [ ".", @@ -306,15 +249,13 @@ "registry/storage/driver/inmemory", "registry/storage/driver/middleware", "uuid", - "version", + "version" ] - pruneopts = "T" revision = "40b7b5830a2337bb07627617740c0e39eb92800c" version = "v2.7.0" [[projects]] branch = "master" - digest = "1:3d23e50eab6b3aa4ced1b1cc8b5c40534b9c9a54b0f5648a2e76d72599134e4e" name = "github.com/docker/docker" packages = [ "api/types", @@ -341,157 +282,123 @@ "pkg/term", "pkg/term/windows", "registry", - "registry/resumable", + "registry/resumable" ] - pruneopts = "T" revision = "2cb26cfe9cbf8a64c5046c74d65f4528b22e67f4" [[projects]] - digest = "1:523611f6876df8a1fd1aea07499e6ae33585238e8fdd8793f48a2441438a12d6" name = "github.com/docker/docker-credential-helpers" packages = [ "client", - "credentials", + "credentials" ] - pruneopts = "T" revision = "5241b46610f2491efdf9d1c85f1ddf5b02f6d962" version = "v0.6.1" [[projects]] - digest = "1:b64eea95d41af3792092af9c951efcd2d8d8bfd2335c851f7afaf54d6be12c66" name = "github.com/docker/go-connections" packages = [ "nat", "sockets", - "tlsconfig", + "tlsconfig" ] - pruneopts = "T" revision = "7395e3f8aa162843a74ed6d48e79627d9792ac55" version = "v0.4.0" [[projects]] branch = "master" - digest = "1:2b126e77be4ab4b92cdb3924c87894dd76bf365ba282f358a13133e848aa0059" name = "github.com/docker/go-metrics" packages = ["."] - pruneopts = "T" revision = "b84716841b82eab644a0c64fc8b42d480e49add5" [[projects]] - digest = "1:6f82cacd0af5921e99bf3f46748705239b36489464f4529a1589bc895764fb18" name = "github.com/docker/go-units" packages = ["."] - pruneopts = "T" revision = "47565b4f722fb6ceae66b95f853feed578a4a51c" version = "v0.3.3" [[projects]] branch = "master" - digest = "1:46cb138b11721830161dd8293356e3dc5dd7ec774825b7fc5f2bf2fbbf2bed33" name = "github.com/docker/libtrust" packages = ["."] - pruneopts = "T" revision = "aabc10ec26b754e797f9028f4589c5b7bd90dc20" [[projects]] branch = "master" - digest = "1:0d4540d92fd82f9957e1f718e2b1e5f2d301ed8169e2923bba23558fbbbd08a1" name = "github.com/docker/spdystream" packages = [ ".", - "spdy", + "spdy" ] - pruneopts = "T" revision = "6480d4af844c189cf5dd913db24ddd339d3a4f85" [[projects]] - digest = "1:0ffd93121f3971aea43f6a26b3eaaa64c8af20fb0ff0731087d8dab7164af5a8" name = "github.com/emicklei/go-restful" packages = [ ".", - "log", + "log" ] - pruneopts = "T" revision = "3eb9738c1697594ea6e71a7156a9bb32ed216cf0" version = "v2.8.0" [[projects]] - digest = "1:75c3d1e7907ed7a800afd0569783a99a2b6421b634c404565de537b224826703" name = "github.com/evanphx/json-patch" packages = ["."] - pruneopts = "T" revision = "afac545df32f2287a079e2dfb7ba2745a643747e" version = "v3.0.0" [[projects]] branch = "master" - digest = "1:5e0da1aba1a7b125f46e6ddca43e98b40cf6eaea3322b016c331cf6afe53c30a" name = "github.com/exponent-io/jsonpath" packages = ["."] - pruneopts = "T" revision = "d6023ce2651d8eafb5c75bb0c7167536102ec9f5" [[projects]] - digest = "1:bbc4aacabe6880bdbce849c64cb061b7eddf39f132af4ea2853ddd32f85fbec3" name = "github.com/fatih/camelcase" packages = ["."] - pruneopts = "T" revision = "44e46d280b43ec1531bb25252440e34f1b800b65" version = "v1.0.0" [[projects]] - digest = "1:30c81df6bc8e5518535aee2b1eacb1a9dab172ee608eeadb40f4db30f007027e" name = "github.com/garyburd/redigo" packages = [ "internal", - "redis", + "redis" ] - pruneopts = "T" revision = "a69d19351219b6dd56f274f96d85a7014a2ec34e" version = "v1.6.0" [[projects]] - digest = "1:2cd7915ab26ede7d95b8749e6b1f933f1c6d5398030684e6505940a10f31cfda" name = "github.com/ghodss/yaml" packages = ["."] - pruneopts = "T" revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" version = "v1.0.0" [[projects]] - digest = "1:701ec53dfa0182bf25e5c09e664906f11d697e779b59461a2607dbd4dc75a4f9" name = "github.com/go-openapi/jsonpointer" packages = ["."] - pruneopts = "T" revision = "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004" version = "v0.17.2" [[projects]] - digest = "1:3f17ebd557845adeb347c9e398394e96ebc18e0ec94cc04972be87851a4679e0" name = "github.com/go-openapi/jsonreference" packages = ["."] - pruneopts = "T" revision = "8483a886a90412cd6858df4ea3483dce9c8e35a3" version = "v0.17.2" [[projects]] - digest = "1:76b8b440ca412e287dff607469a5a40a9445fe7168ad1fb85916d87c66011c83" name = "github.com/go-openapi/spec" packages = ["."] - pruneopts = "T" revision = "5bae59e25b21498baea7f9d46e9c147ec106a42e" version = "v0.17.2" [[projects]] - digest = "1:0d8057a212a27a625bb8e57b1e25fb8e8e4a0feb0b7df543fd46d8d15c31d870" name = "github.com/go-openapi/swag" packages = ["."] - pruneopts = "T" revision = "5899d5c5e619fda5fa86e14795a835f473ca284c" version = "v0.17.2" [[projects]] - digest = "1:0a5d2a670ac050354afcf572e65aceabefdebdbb90973ea729d8640fa211a9e2" name = "github.com/gobwas/glob" packages = [ ".", @@ -501,33 +408,27 @@ "syntax/ast", "syntax/lexer", "util/runes", - "util/strings", + "util/strings" ] - pruneopts = "T" revision = "5ccd90ef52e1e632236f7326478d4faa74f99438" version = "v0.2.3" [[projects]] - digest = "1:f5ccd717b5f093cbabc51ee2e7a5979b92f17d217f9031d6d64f337101c408e4" name = "github.com/gogo/protobuf" packages = [ "proto", - "sortkeys", + "sortkeys" ] - pruneopts = "T" revision = "4cbf7e384e768b4e01799441fdf2a706a5635ae7" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:8f3489cb7352125027252a6517757cbd1706523119f1e14e20741ae8d2f70428" name = "github.com/golang/groupcache" packages = ["lru"] - pruneopts = "T" revision = "c65c006176ff7ff98bb916961c7abbc6b0afc0aa" [[projects]] - digest = "1:a2ecb56e5053d942aafc86738915fb94c9131bac848c543b8b6764365fd69080" name = "github.com/golang/protobuf" packages = [ "proto", @@ -535,65 +436,53 @@ "ptypes/any", "ptypes/duration", "ptypes/timestamp", - "ptypes/wrappers", + "ptypes/wrappers" ] - pruneopts = "T" revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5" version = "v1.2.0" [[projects]] branch = "master" - digest = "1:0bfbe13936953a98ae3cfe8ed6670d396ad81edf069a806d2f6515d7bb6950df" name = "github.com/google/btree" packages = ["."] - pruneopts = "T" revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306" [[projects]] - digest = "1:ec7c114271a6226a146c64cb0d95348ac85350fde7dbb2564a1911165aa63ced" name = "github.com/google/go-cmp" packages = [ "cmp", "cmp/internal/diff", "cmp/internal/flags", "cmp/internal/function", - "cmp/internal/value", + "cmp/internal/value" ] - pruneopts = "T" revision = "6f77996f0c42f7b84e5a2b252227263f93432e9b" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:3ee90c0d94da31b442dde97c99635aaafec68d0b8a3c12ee2075c6bdabeec6bb" name = "github.com/google/gofuzz" packages = ["."] - pruneopts = "T" revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" [[projects]] - digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8" name = "github.com/google/uuid" packages = ["."] - pruneopts = "T" revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8" version = "v1.1.0" [[projects]] - digest = "1:35735e2255fa34521c2a1355fb2a3a2300bc9949f487be1c1ce8ee8efcfa2d04" name = "github.com/googleapis/gnostic" packages = [ "OpenAPIv2", "compiler", - "extensions", + "extensions" ] - pruneopts = "T" revision = "7c663266750e7d82587642f65e60bc4083f1f84e" version = "v0.2.0" [[projects]] branch = "master" - digest = "1:115dd91e62130f4751ab7bf3f9e892bc3b46670a99d5f680128082fe470cbcf4" name = "github.com/gophercloud/gophercloud" packages = [ ".", @@ -602,383 +491,297 @@ "openstack/identity/v2/tokens", "openstack/identity/v3/tokens", "openstack/utils", - "pagination", + "pagination" ] - pruneopts = "T" revision = "94924357ebf6c7d448c70d65082ff7ca6f78ddc5" [[projects]] - digest = "1:664d37ea261f0fc73dd17f4a1f5f46d01fbb0b0d75f6375af064824424109b7d" name = "github.com/gorilla/handlers" packages = ["."] - pruneopts = "T" revision = "7e0847f9db758cdebd26c149d0ae9d5d0b9c98ce" version = "v1.4.0" [[projects]] - digest = "1:03e234a7f71e1bab87804517e5f729b4cc3534cabd2b7cc692052282f6215192" name = "github.com/gorilla/mux" packages = ["."] - pruneopts = "T" revision = "a7962380ca08b5a188038c69871b8d3fbdf31e89" version = "v1.7.0" [[projects]] branch = "master" - digest = "1:fae5efc46b655e70e982e4d8b6af5a829333bc98edfaa91dde5ac608f142c00c" name = "github.com/gosuri/uitable" packages = [ ".", "util/strutil", - "util/wordwrap", + "util/wordwrap" ] - pruneopts = "T" revision = "36ee7e946282a3fb1cfecd476ddc9b35d8847e42" [[projects]] branch = "master" - digest = "1:8c0ceab65d43f49dce22aac0e8f670c170fc74dcf2dfba66d3a89516f7ae2c15" name = "github.com/gregjones/httpcache" packages = [ ".", - "diskcache", + "diskcache" ] - pruneopts = "T" revision = "c63ab54fda8f77302f8d414e19933f2b6026a089" [[projects]] - digest = "1:8ec8d88c248041a6df5f6574b87bc00e7e0b493881dad2e7ef47b11dc69093b5" name = "github.com/hashicorp/golang-lru" packages = [ ".", - "simplelru", + "simplelru" ] - pruneopts = "T" revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768" version = "v0.5.0" [[projects]] - digest = "1:f9a5e090336881be43cfc1cf468330c1bdd60abdc9dd194e0b1ab69f4b94dd7c" name = "github.com/huandu/xstrings" packages = ["."] - pruneopts = "T" revision = "f02667b379e2fb5916c3cda2cf31e0eb885d79f8" version = "v1.2.0" [[projects]] - digest = "1:3477d9dd8c135faab978bac762eaeafb31f28d6da97ef500d5c271966f74140a" name = "github.com/imdario/mergo" packages = ["."] - pruneopts = "T" revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4" version = "v0.3.6" [[projects]] - digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" name = "github.com/inconshreveable/mousetrap" packages = ["."] - pruneopts = "T" revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" version = "v1.0" [[projects]] - digest = "1:5d713dbcad44f3358fec51fd5573d4f733c02cac5a40dcb177787ad5ffe9272f" name = "github.com/json-iterator/go" packages = ["."] - pruneopts = "T" revision = "1624edc4454b8682399def8740d46db5e4362ba4" version = "v1.1.5" [[projects]] branch = "master" - digest = "1:caf6db28595425c0e0f2301a00257d11712f65c1878e12cffc42f6b9a9cf3f23" name = "github.com/kardianos/osext" packages = ["."] - pruneopts = "T" revision = "ae77be60afb1dcacde03767a8c37337fad28ac14" [[projects]] - digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8" name = "github.com/konsorten/go-windows-terminal-sequences" packages = ["."] - pruneopts = "T" revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242" version = "v1.0.1" [[projects]] branch = "master" - digest = "1:4be65cb3a11626a0d89fc72b34f62a8768040512d45feb086184ac30fdfbef65" name = "github.com/mailru/easyjson" packages = [ "buffer", "jlexer", - "jwriter", + "jwriter" ] - pruneopts = "T" revision = "60711f1a8329503b04e1c88535f419d0bb440bff" [[projects]] - digest = "1:0356f3312c9bd1cbeda81505b7fd437501d8e778ab66998ef69f00d7f9b3a0d7" name = "github.com/mattn/go-runewidth" packages = ["."] - pruneopts = "T" revision = "3ee7d812e62a0804a7d0a324e0249ca2db3476d3" version = "v0.0.4" [[projects]] - digest = "1:7efe48dea4db6b35dcc15e15394b627247e5b3fb814242de986b746ba8e0abf0" name = "github.com/mattn/go-shellwords" packages = ["."] - pruneopts = "T" revision = "02e3cf038dcea8290e44424da473dd12be796a8a" version = "v1.0.3" [[projects]] - digest = "1:a8e3d14801bed585908d130ebfc3b925ba642208e6f30d879437ddfc7bb9b413" name = "github.com/matttproud/golang_protobuf_extensions" packages = ["pbutil"] - pruneopts = "T" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" version = "v1.0.1" [[projects]] - digest = "1:ceb81990372dadfe39e96b9b3df793d4838bbc21cfa02d2f34e7fcbbed227f37" name = "github.com/miekg/dns" packages = ["."] - pruneopts = "T" revision = "0d29b283ac0f967dd3a02739bf26a22702210d7a" [[projects]] - digest = "1:abf08734a6527df70ed361d7c369fb580e6840d8f7a6012e5f609fdfd93b4e48" name = "github.com/mitchellh/go-wordwrap" packages = ["."] - pruneopts = "T" revision = "9e67c67572bc5dd02aef930e2b0ae3c02a4b5a5c" version = "v1.0.0" [[projects]] - digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" name = "github.com/modern-go/concurrent" packages = ["."] - pruneopts = "T" revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" version = "1.0.3" [[projects]] - digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855" name = "github.com/modern-go/reflect2" packages = ["."] - pruneopts = "T" revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" version = "1.0.1" [[projects]] - digest = "1:ee4d4af67d93cc7644157882329023ce9a7bcfce956a079069a9405521c7cc8d" name = "github.com/opencontainers/go-digest" packages = ["."] - pruneopts = "T" revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf" version = "v1.0.0-rc1" [[projects]] - digest = "1:eb47da2fdabb69f64ce3a42a1790ec0ed9da6718c8378f3fdc41cbe6af184519" name = "github.com/opencontainers/image-spec" packages = [ "specs-go", - "specs-go/v1", + "specs-go/v1" ] - pruneopts = "T" revision = "d60099175f88c47cd379c4738d158884749ed235" version = "v1.0.1" [[projects]] - digest = "1:52254f0d6ce1358972c08cb1ecd91a449af3a7f927f829abec962613fb167403" name = "github.com/opencontainers/runc" packages = ["libcontainer/user"] - pruneopts = "T" revision = "baf6536d6259209c3edfa2b22237af82942d3dfa" version = "v0.1.1" [[projects]] branch = "master" - digest = "1:0c29d499ffc3b9f33e7136444575527d0c3a9463a89b3cbeda0523b737f910b3" name = "github.com/petar/GoLLRB" packages = ["llrb"] - pruneopts = "T" revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" [[projects]] - digest = "1:598241bd36d3a5f6d9102a306bd9bf78f3bc253672460d92ac70566157eae648" name = "github.com/peterbourgon/diskv" packages = ["."] - pruneopts = "T" revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" version = "v2.0.1" [[projects]] - digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" name = "github.com/pkg/errors" packages = ["."] - pruneopts = "T" revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" [[projects]] - digest = "1:22aa691fe0213cb5c07d103f9effebcb7ad04bee45a0ce5fe5369d0ca2ec3a1f" name = "github.com/pmezard/go-difflib" packages = ["difflib"] - pruneopts = "T" revision = "792786c7400a136282c1664665ae0a8db921c6c2" version = "v1.0.0" [[projects]] - digest = "1:3b5729e3fc486abc6fc16ce026331c3d196e788c3b973081ecf5d28ae3e1050d" name = "github.com/prometheus/client_golang" packages = [ "prometheus", "prometheus/internal", - "prometheus/promhttp", + "prometheus/promhttp" ] - pruneopts = "T" revision = "505eaef017263e299324067d40ca2c48f6a2cf50" version = "v0.9.2" [[projects]] branch = "master" - digest = "1:cd67319ee7536399990c4b00fae07c3413035a53193c644549a676091507cadc" name = "github.com/prometheus/client_model" packages = ["go"] - pruneopts = "T" revision = "fd36f4220a901265f90734c3183c5f0c91daa0b8" [[projects]] - digest = "1:1688d03416102590c2a93f23d44e4297cb438bff146830aae35e66b33c9af114" name = "github.com/prometheus/common" packages = [ "expfmt", "internal/bitbucket.org/ww/goautoneg", - "model", + "model" ] - pruneopts = "T" revision = "cfeb6f9992ffa54aaa4f2170ade4067ee478b250" version = "v0.2.0" [[projects]] branch = "master" - digest = "1:eb94fa4ad4d1e3c7a084f6f19d60a7dbafa3194147655e2b5db14e8bc9dcef74" name = "github.com/prometheus/procfs" packages = [ ".", "internal/util", "nfs", - "xfs", + "xfs" ] - pruneopts = "T" revision = "316cf8ccfec56d206735d46333ca162eb374da8b" [[projects]] - digest = "1:40e527269f1feb16b3069bfe80ff05a462d190eacfe07eb0a59fa25c381db7af" name = "github.com/russross/blackfriday" packages = ["."] - pruneopts = "T" revision = "05f3235734ad95d0016f6a23902f06461fcf567a" version = "v1.5.2" [[projects]] - digest = "1:c3498d1186a4f84897812aa2dccfbd5d805955846f2cd020aa384bf0b218e9e9" name = "github.com/sirupsen/logrus" packages = ["."] - pruneopts = "T" revision = "8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f" version = "v1.4.1" [[projects]] - digest = "1:674fedb5641490b913f0f01e4f97f3f578f7a1c5f106cd47cfd5394eca8155db" name = "github.com/spf13/cobra" packages = [ ".", - "doc", + "doc" ] - pruneopts = "T" revision = "67fc4837d267bc9bfd6e47f77783fcc3dffc68de" version = "v0.0.4" [[projects]] - digest = "1:0f775ea7a72e30d5574267692aaa9ff265aafd15214a7ae7db26bc77f2ca04dc" name = "github.com/spf13/pflag" packages = ["."] - pruneopts = "T" revision = "298182f68c66c05229eb03ac171abe6e309ee79a" version = "v1.0.3" [[projects]] - digest = "1:17c4ccf5cdb1627aaaeb5c1725cb13aec97b63ea2033d4a6824dcaedf94223dc" name = "github.com/stretchr/testify" packages = [ "assert", "require", - "suite", + "suite" ] - pruneopts = "T" revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" version = "v1.3.0" [[projects]] branch = "master" - digest = "1:f4e5276a3b356f4692107047fd2890f2fe534f4feeb6b1fd2f6dfbd87f1ccf54" name = "github.com/xeipuuv/gojsonpointer" packages = ["."] - pruneopts = "T" revision = "4e3ac2762d5f479393488629ee9370b50873b3a6" [[projects]] branch = "master" - digest = "1:dc6a6c28ca45d38cfce9f7cb61681ee38c5b99ec1425339bfc1e1a7ba769c807" name = "github.com/xeipuuv/gojsonreference" packages = ["."] - pruneopts = "T" revision = "bd5ef7bd5415a7ac448318e64f11a24cd21e594b" [[projects]] - digest = "1:6d01aadbf9c582bc90c520707fcab1e63af19649218d785c49d6aa561c8948a8" name = "github.com/xeipuuv/gojsonschema" packages = ["."] - pruneopts = "T" revision = "f971f3cd73b2899de6923801c147f075263e0c50" version = "v1.1.0" [[projects]] - digest = "1:89d64b91ff6c1ede3cbc3f3ff6ac101977ee5e56547aebb85af5504adbdb4c63" name = "github.com/xenolf/lego" packages = ["acme"] - pruneopts = "T" revision = "a9d8cec0e6563575e5868a005359ac97911b5985" [[projects]] branch = "master" - digest = "1:f5abbb52b11b97269d74b7ebf9e057e8e34d477eedd171741fe21cc190bedb02" name = "github.com/yvasiyarov/go-metrics" packages = ["."] - pruneopts = "T" revision = "c25f46c4b94079672242ec48a545e7ca9ebe3aec" [[projects]] - digest = "1:6ce16ef7a4c7f60d648676d2c1fbf142c6dbdb96624743472078260150d519c2" name = "github.com/yvasiyarov/gorelic" packages = ["."] - pruneopts = "T" revision = "4dc1bb7ab951bc884feb2c009092b1a454152355" version = "v0.0.6" [[projects]] - digest = "1:c20b060d66ecf0fe4dfbef1bc7d314b352289b8f6cd37069abb5ba6a0f8e0b91" name = "github.com/yvasiyarov/newrelic_platform_go" packages = ["."] - pruneopts = "T" revision = "b21fdbd4370f3717f3bbd2bf41c223bc273068e6" [[projects]] - digest = "1:b6f574d818cb549185939ce3c228983b339eeba4aee229c74c5848ff9e806836" name = "go.opencensus.io" packages = [ ".", @@ -995,15 +798,13 @@ "trace", "trace/internal", "trace/propagation", - "trace/tracestate", + "trace/tracestate" ] - pruneopts = "T" revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b" version = "v0.18.0" [[projects]] branch = "master" - digest = "1:d470cb69884835b1800e93ceceb85afcf981ea647e61d99398a76af7a95bad6a" name = "golang.org/x/crypto" packages = [ "bcrypt", @@ -1021,14 +822,12 @@ "openpgp/s2k", "pbkdf2", "scrypt", - "ssh/terminal", + "ssh/terminal" ] - pruneopts = "T" revision = "505ab145d0a99da450461ae2c1a9f6cd10d1f447" [[projects]] branch = "master" - digest = "1:6a668f89e7e121bf970a6dc37c729f05f5261ae64e27945326d896ad158e5a10" name = "golang.org/x/net" packages = [ "bpf", @@ -1046,49 +845,41 @@ "ipv6", "proxy", "publicsuffix", - "trace", + "trace" ] - pruneopts = "T" revision = "927f97764cc334a6575f4b7a1584a147864d5723" [[projects]] branch = "master" - digest = "1:320e5ba9ea8000060bec710764b8b26c251ee28f6012422b669cb8cb100c9815" name = "golang.org/x/oauth2" packages = [ ".", "google", "internal", "jws", - "jwt", + "jwt" ] - pruneopts = "T" revision = "d668ce993890a79bda886613ee587a69dd5da7a6" [[projects]] branch = "master" - digest = "1:6932d1ef4294f3ea819748e89d1003f5df3804b20b84b5f1c60f8f1d7c933e2d" name = "golang.org/x/sync" packages = [ "errgroup", - "semaphore", + "semaphore" ] - pruneopts = "T" revision = "37e7f081c4d4c64e13b10787722085407fe5d15f" [[projects]] branch = "master" - digest = "1:50eb9e3f847dc29971fecac71bf84a32e9d756dd34216cf9219c50bd3801b4c4" name = "golang.org/x/sys" packages = [ "unix", - "windows", + "windows" ] - pruneopts = "T" revision = "b4a75ba826a64a70990f11a225237acd6ef35c9f" [[projects]] - digest = "1:6164911cb5e94e8d8d5131d646613ff82c14f5a8ce869de2f6d80d9889df8c5a" name = "golang.org/x/text" packages = [ "collate", @@ -1111,30 +902,24 @@ "unicode/cldr", "unicode/norm", "unicode/rangetable", - "width", + "width" ] - pruneopts = "T" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" version = "v0.3.0" [[projects]] branch = "master" - digest = "1:077216d94c076b8cd7bd057cb6f7c6d224970cc991bdfe49c0c7a24e8e39ee33" name = "golang.org/x/time" packages = ["rate"] - pruneopts = "T" revision = "85acf8d2951cb2a3bde7632f9ff273ef0379bcbd" [[projects]] branch = "master" - digest = "1:9eaf0fc3f9a9b24531d89e1e0adf916e0d3f5ac7d3ce61f520af19212b1798b0" name = "google.golang.org/api" packages = ["support/bundler"] - pruneopts = "T" revision = "65a46cafb132eff435c7d1e0f439cc73c8eebb85" [[projects]] - digest = "1:1469235a5a8e192cfe6a99c4804b883a02f0ff96a693cd1660515a3a3b94d5ac" name = "google.golang.org/appengine" packages = [ ".", @@ -1146,22 +931,18 @@ "internal/modules", "internal/remote_api", "internal/urlfetch", - "urlfetch", + "urlfetch" ] - pruneopts = "T" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1" version = "v1.4.0" [[projects]] branch = "master" - digest = "1:8c7bf8f974d0b63a83834e83b6dd39c2b40d61d409d76172c81d67eba8fee4a8" name = "google.golang.org/genproto" packages = ["googleapis/rpc/status"] - pruneopts = "T" revision = "bd9b4fb69e2ffd37621a6caa54dcbead29b546f2" [[projects]] - digest = "1:c32026b4d2b9f7240ad72edf0dffca4e5863d5edc1ea25416d64929926b5ac67" name = "google.golang.org/grpc" packages = [ ".", @@ -1194,60 +975,50 @@ "resolver/passthrough", "stats", "status", - "tap", + "tap" ] - pruneopts = "T" revision = "df014850f6dee74ba2fc94874043a9f3f75fbfd8" version = "v1.17.0" [[projects]] - digest = "1:2d1fbdc6777e5408cabeb02bf336305e724b925ff4546ded0fa8715a7267922a" name = "gopkg.in/inf.v0" packages = ["."] - pruneopts = "T" revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" source = "https://github.com/go-inf/inf.git" version = "v0.9.1" [[projects]] - digest = "1:12f4009e9a437d974387eaf60699ac6a401d146fe8560b01c16478c629af59b4" name = "gopkg.in/square/go-jose.v1" packages = [ ".", "cipher", - "json", + "json" ] - pruneopts = "T" revision = "56062818b5e15ee405eb8363f9498c7113e98337" source = "https://github.com/square/go-jose.git" version = "v1.1.2" [[projects]] - digest = "1:3effe4e6f8af2d27c9cd6070c7c332344490cbeeaa5476ae2bc9e05eb1079f0c" name = "gopkg.in/square/go-jose.v2" packages = [ ".", "cipher", "json", - "jwt", + "jwt" ] - pruneopts = "T" revision = "628223f44a71f715d2881ea69afc795a1e9c01be" source = "https://github.com/square/go-jose.git" version = "v2.3.0" [[projects]] - digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" name = "gopkg.in/yaml.v2" packages = ["."] - pruneopts = "T" revision = "51d6538a90f86fe93ac480b35f37b2be17fef232" source = "https://github.com/go-yaml/yaml" version = "v2.2.2" [[projects]] branch = "release-1.15" - digest = "1:0f34ccf9357fb875ee20b8ba48a240576dfbb1a247d0f1c763f2fec6e93d2e32" name = "k8s.io/api" packages = [ "admission/v1beta1", @@ -1287,22 +1058,18 @@ "settings/v1alpha1", "storage/v1", "storage/v1alpha1", - "storage/v1beta1", + "storage/v1beta1" ] - pruneopts = "T" revision = "1634385ce4626e4da21367d139c4ee5d72437e3b" [[projects]] branch = "release-1.15" - digest = "1:dffbde7aabb4d8c613f9dd53317fd5b3aa0b2722cd4d7159772be68637116793" name = "k8s.io/apiextensions-apiserver" packages = ["pkg/features"] - pruneopts = "T" revision = "23f08c7096c0273b53178de488b95473d5cd3808" [[projects]] branch = "release-1.15" - digest = "1:2656a0f23465fb97265dd7dc176fada8e954dd191f198aa32e6bb52597514aa4" name = "k8s.io/apimachinery" packages = [ "pkg/api/equality", @@ -1357,28 +1124,24 @@ "pkg/watch", "third_party/forked/golang/json", "third_party/forked/golang/netutil", - "third_party/forked/golang/reflect", + "third_party/forked/golang/reflect" ] - pruneopts = "T" revision = "1799e75a07195de9460b8ef7300883499f12127b" [[projects]] branch = "release-1.15" - digest = "1:9e18a8310252d4101ea877fb517b52ca76975742065d86e9cf525f3ddda38b7e" name = "k8s.io/apiserver" packages = [ "pkg/authentication/authenticator", "pkg/authentication/serviceaccount", "pkg/authentication/user", "pkg/features", - "pkg/util/feature", + "pkg/util/feature" ] - pruneopts = "T" revision = "07da2c5601ffacb40aecb4ad92adea2c775d1dd9" [[projects]] branch = "master" - digest = "1:cd2774546a9f0db8e29e6a9792a1b5a7fabf7c0091f7b2845ad048652d74fcc2" name = "k8s.io/cli-runtime" packages = [ "pkg/genericclioptions", @@ -1392,13 +1155,11 @@ "pkg/kustomize/k8sdeps/transformer/patch", "pkg/kustomize/k8sdeps/validator", "pkg/printers", - "pkg/resource", + "pkg/resource" ] - pruneopts = "T" revision = "44a48934c135b31e4f1c0d12e91d384e1cb2304c" [[projects]] - digest = "1:0b9d76929add96339229991d4aeabf4ad1dc716bc8e1353e17a3d3d543480070" name = "k8s.io/client-go" packages = [ "discovery", @@ -1612,44 +1373,36 @@ "util/homedir", "util/jsonpath", "util/keyutil", - "util/retry", + "util/retry" ] - pruneopts = "T" revision = "8e956561bbf57253b1d19c449d0f24e8cb18d467" version = "kubernetes-1.15.1" [[projects]] branch = "master" - digest = "1:bde2bf8d78ad97dbe011a98ed73e0706f2e2d8c80e80caf90f35c6a9620af623" name = "k8s.io/component-base" packages = ["featuregate"] - pruneopts = "T" revision = "b4f50308a6168b3e1e8687b3fb46e9bf1a112ee5" [[projects]] - digest = "1:7a3ef99d492d30157b8e933624a8f0292b4cee5934c23269f7640c8030eb83cd" name = "k8s.io/klog" packages = ["."] - pruneopts = "T" revision = "a5bc97fbc634d635061f3146511332c7e313a55a" version = "v0.1.0" [[projects]] branch = "master" - digest = "1:90f16a49f856e6d94089444e487c535f4cd41f59a1e90c51deb9dcf965f3c50b" name = "k8s.io/kube-openapi" packages = [ "pkg/common", "pkg/util/proto", "pkg/util/proto/testing", - "pkg/util/proto/validation", + "pkg/util/proto/validation" ] - pruneopts = "T" revision = "0317810137be915b9cf888946c6e115c1bfac693" [[projects]] branch = "release-1.15" - digest = "1:06497e8bfb946cef502730eb1ab10dc4e60bac72123f634eef162aaf44999474" name = "k8s.io/kubernetes" packages = [ "pkg/api/legacyscheme", @@ -1703,14 +1456,12 @@ "pkg/util/hash", "pkg/util/labels", "pkg/util/parsers", - "pkg/util/taints", + "pkg/util/taints" ] - pruneopts = "T" revision = "92b2e906d7aa618588167817feaed137a44e6d92" [[projects]] branch = "master" - digest = "1:50d36d11cbcdc86bca9c3eede8bf7bee9947e2f350b3013a28282edf8d6e8b58" name = "k8s.io/utils" packages = [ "buffer", @@ -1719,22 +1470,18 @@ "net", "path", "pointer", - "trace", + "trace" ] - pruneopts = "T" revision = "21c4ce38f2a793ec01e925ddc31216500183b773" [[projects]] branch = "master" - digest = "1:15fbb9f95a13abe2be748b1159b491369d46a2ccc3f378e0f93c391f89608929" name = "rsc.io/letsencrypt" packages = ["."] - pruneopts = "T" revision = "1847a81d2087eba73081db43989e54dabe0768cd" source = "https://github.com/dmcgowan/letsencrypt.git" [[projects]] - digest = "1:663cc8454702691d4d089e6df5acc61d87b9c9a933a28b7615200e5b5a4f0cfd" name = "sigs.k8s.io/kustomize" packages = [ "pkg/commands/build", @@ -1758,103 +1505,20 @@ "pkg/transformers", "pkg/transformers/config", "pkg/transformers/config/defaultconfig", - "pkg/types", + "pkg/types" ] - pruneopts = "T" revision = "a6f65144121d1955266b0cd836ce954c04122dc8" version = "v2.0.3" [[projects]] - digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849" name = "sigs.k8s.io/yaml" packages = ["."] - pruneopts = "T" revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" version = "v1.1.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - input-imports = [ - "github.com/BurntSushi/toml", - "github.com/Masterminds/semver", - "github.com/Masterminds/sprig", - "github.com/Masterminds/vcs", - "github.com/asaskevich/govalidator", - "github.com/containerd/containerd/reference", - "github.com/containerd/containerd/remotes", - "github.com/deislabs/oras/pkg/auth", - "github.com/deislabs/oras/pkg/auth/docker", - "github.com/deislabs/oras/pkg/content", - "github.com/deislabs/oras/pkg/context", - "github.com/deislabs/oras/pkg/oras", - "github.com/docker/distribution/configuration", - "github.com/docker/distribution/registry", - "github.com/docker/distribution/registry/auth/htpasswd", - "github.com/docker/distribution/registry/storage/driver/inmemory", - "github.com/docker/docker/pkg/term", - "github.com/docker/go-units", - "github.com/evanphx/json-patch", - "github.com/gobwas/glob", - "github.com/gosuri/uitable", - "github.com/gosuri/uitable/util/strutil", - "github.com/mattn/go-shellwords", - "github.com/opencontainers/go-digest", - "github.com/opencontainers/image-spec/specs-go/v1", - "github.com/pkg/errors", - "github.com/sirupsen/logrus", - "github.com/spf13/cobra", - "github.com/spf13/cobra/doc", - "github.com/spf13/pflag", - "github.com/stretchr/testify/assert", - "github.com/stretchr/testify/require", - "github.com/stretchr/testify/suite", - "github.com/xeipuuv/gojsonschema", - "golang.org/x/crypto/bcrypt", - "golang.org/x/crypto/openpgp", - "golang.org/x/crypto/openpgp/clearsign", - "golang.org/x/crypto/openpgp/errors", - "golang.org/x/crypto/openpgp/packet", - "golang.org/x/crypto/ssh/terminal", - "gopkg.in/yaml.v2", - "k8s.io/api/apps/v1", - "k8s.io/api/apps/v1beta1", - "k8s.io/api/apps/v1beta2", - "k8s.io/api/batch/v1", - "k8s.io/api/core/v1", - "k8s.io/api/extensions/v1beta1", - "k8s.io/apimachinery/pkg/api/equality", - "k8s.io/apimachinery/pkg/api/errors", - "k8s.io/apimachinery/pkg/api/meta", - "k8s.io/apimachinery/pkg/apis/meta/v1", - "k8s.io/apimachinery/pkg/labels", - "k8s.io/apimachinery/pkg/runtime", - "k8s.io/apimachinery/pkg/runtime/schema", - "k8s.io/apimachinery/pkg/types", - "k8s.io/apimachinery/pkg/util/intstr", - "k8s.io/apimachinery/pkg/util/strategicpatch", - "k8s.io/apimachinery/pkg/util/validation", - "k8s.io/apimachinery/pkg/util/wait", - "k8s.io/apimachinery/pkg/watch", - "k8s.io/cli-runtime/pkg/genericclioptions", - "k8s.io/cli-runtime/pkg/resource", - "k8s.io/client-go/discovery", - "k8s.io/client-go/kubernetes", - "k8s.io/client-go/kubernetes/fake", - "k8s.io/client-go/kubernetes/scheme", - "k8s.io/client-go/kubernetes/typed/core/v1", - "k8s.io/client-go/plugin/pkg/client/auth", - "k8s.io/client-go/rest", - "k8s.io/client-go/rest/fake", - "k8s.io/client-go/tools/clientcmd", - "k8s.io/client-go/tools/watch", - "k8s.io/client-go/util/homedir", - "k8s.io/klog", - "k8s.io/kubernetes/pkg/controller/deployment/util", - "k8s.io/kubernetes/pkg/kubectl/cmd/testing", - "k8s.io/kubernetes/pkg/kubectl/cmd/util", - "k8s.io/kubernetes/pkg/kubectl/validation", - "sigs.k8s.io/yaml", - ] + inputs-digest = "41fffcba41c216580ccc31a7a09f407955aac28550c9fad6f05d44a5db9dc59b" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index bdefca6f9..bd863f24a 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -58,6 +58,18 @@ name = "github.com/stretchr/testify" version = "^1.3.0" +[[constraint]] + name = "github.com/xeipuuv/gojsonschema" + version = "1.1.0" + +[[constraint]] + name = "github.com/spf13/cobra" + version = "0.0.4" + +[[constraint]] + name = "sigs.k8s.io/yaml" + version = "1.1.0" + [[override]] name = "sigs.k8s.io/kustomize" version = "2.0.3" @@ -104,15 +116,3 @@ [prune] go-tests = true - -[[constraint]] - name = "github.com/xeipuuv/gojsonschema" - version = "1.1.0" - -[[constraint]] - name = "github.com/spf13/cobra" - version = "0.0.4" - -[[constraint]] - name = "sigs.k8s.io/yaml" - version = "1.1.0" diff --git a/pkg/action/action.go b/pkg/action/action.go index 07aef4f4e..c7d1e34f6 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -17,8 +17,11 @@ limitations under the License. package action import ( + "bytes" "path" "regexp" + "sort" + "strings" "time" "github.com/pkg/errors" @@ -27,6 +30,7 @@ import ( "k8s.io/client-go/rest" "helm.sh/helm/pkg/chartutil" + "helm.sh/helm/pkg/hooks" "helm.sh/helm/pkg/kube" "helm.sh/helm/pkg/registry" "helm.sh/helm/pkg/release" @@ -190,3 +194,73 @@ type RESTClientGetter interface { ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) ToRESTMapper() (meta.RESTMapper, error) } + +// execHooks is a method for exec-ing all hooks of the given type. This is to +// avoid duplicate code in various actions +func execHooks(client kube.Interface, hs []*release.Hook, hook string, timeout time.Duration) error { + executingHooks := []*release.Hook{} + + for _, h := range hs { + for _, e := range h.Events { + if string(e) == hook { + executingHooks = append(executingHooks, h) + } + } + } + + sort.Sort(hookByWeight(executingHooks)) + for _, h := range executingHooks { + if err := deleteHookByPolicy(client, h, hooks.BeforeHookCreation); err != nil { + return err + } + + resources, err := client.Build(bytes.NewBufferString(h.Manifest)) + if err != nil { + return errors.Wrapf(err, "unable to build kubernetes object for %s hook %s", hook, h.Path) + } + if _, err := client.Create(resources); err != nil { + return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path) + } + + if err := client.WatchUntilReady(resources, timeout); err != nil { + // If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted + // under failed condition. If so, then clear the corresponding resource object in the hook + if err := deleteHookByPolicy(client, h, hooks.HookFailed); err != nil { + return err + } + return err + } + } + + // If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted + // under succeeded condition. If so, then clear the corresponding resource object in each hook + for _, h := range executingHooks { + if err := deleteHookByPolicy(client, h, hooks.HookSucceeded); err != nil { + return err + } + h.LastRun = time.Now() + } + + return nil +} + +// deleteHookByPolicy deletes a hook if the hook policy instructs it to +func deleteHookByPolicy(client kube.Interface, h *release.Hook, policy string) error { + if hookHasDeletePolicy(h, policy) { + resources, err := client.Build(bytes.NewBufferString(h.Manifest)) + if err != nil { + return errors.Wrapf(err, "unable to build kubernetes object for deleting hook %s", h.Path) + } + _, errs := client.Delete(resources) + return errors.New(joinErrors(errs)) + } + return nil +} + +func joinErrors(errs []error) string { + es := make([]string, 0, len(errs)) + for _, e := range errs { + es = append(es, e.Error()) + } + return strings.Join(es, "; ") +} diff --git a/pkg/action/install.go b/pkg/action/install.go index c9dcc0b0c..1a30dc056 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -19,13 +19,11 @@ package action import ( "bytes" "fmt" - "io" "io/ioutil" "net/url" "os" "path" "path/filepath" - "sort" "strings" "text/template" "time" @@ -170,8 +168,10 @@ func (i *Install) Run(chrt *chart.Chart) (*release.Release, error) { // Mark this release as in-progress rel.SetStatus(release.StatusPendingInstall, "Initial install underway") - if err := i.validateManifest(manifestDoc); err != nil { - return rel, err + + resources, err := i.cfg.KubeClient.Build(bytes.NewBufferString(rel.Manifest)) + if err != nil { + return nil, errors.Wrap(err, "unable to build kubernetes objects from release manifest") } // Bail out here if it is a dry run @@ -198,7 +198,7 @@ func (i *Install) Run(chrt *chart.Chart) (*release.Release, error) { // pre-install hooks if !i.DisableHooks { - if err := i.execHook(rel.Hooks, hooks.PreInstall); err != nil { + if err := execHooks(i.cfg.KubeClient, rel.Hooks, hooks.PreInstall, i.Timeout); err != nil { return i.failRelease(rel, fmt.Errorf("failed pre-install: %s", err)) } } @@ -206,21 +206,19 @@ func (i *Install) Run(chrt *chart.Chart) (*release.Release, error) { // At this point, we can do the install. Note that before we were detecting whether to // do an update, but it's not clear whether we WANT to do an update if the re-use is set // to true, since that is basically an upgrade operation. - buf := bytes.NewBufferString(rel.Manifest) - if err := i.cfg.KubeClient.Create(buf); err != nil { + if _, err := i.cfg.KubeClient.Create(resources); err != nil { return i.failRelease(rel, err) } if i.Wait { - buf := bytes.NewBufferString(rel.Manifest) - if err := i.cfg.KubeClient.Wait(buf, i.Timeout); err != nil { + if err := i.cfg.KubeClient.Wait(resources, i.Timeout); err != nil { return i.failRelease(rel, err) } } if !i.DisableHooks { - if err := i.execHook(rel.Hooks, hooks.PostInstall); err != nil { + if err := execHooks(i.cfg.KubeClient, rel.Hooks, hooks.PostInstall, i.Timeout); err != nil { return i.failRelease(rel, fmt.Errorf("failed post-install: %s", err)) } } @@ -455,60 +453,6 @@ func ensureDirectoryForFile(file string) error { return os.MkdirAll(baseDir, defaultDirectoryPermission) } -// validateManifest checks to see whether the given manifest is valid for the current Kubernetes -func (i *Install) validateManifest(manifest io.Reader) error { - _, err := i.cfg.KubeClient.BuildUnstructured(manifest) - return err -} - -// execHook executes all of the hooks for the given hook event. -func (i *Install) execHook(hs []*release.Hook, hook string) error { - executingHooks := []*release.Hook{} - - for _, h := range hs { - for _, e := range h.Events { - if string(e) == hook { - executingHooks = append(executingHooks, h) - } - } - } - - sort.Sort(hookByWeight(executingHooks)) - - for _, h := range executingHooks { - if err := deleteHookByPolicy(i.cfg, h, hooks.BeforeHookCreation); err != nil { - return err - } - - b := bytes.NewBufferString(h.Manifest) - if err := i.cfg.KubeClient.Create(b); err != nil { - return errors.Wrapf(err, "warning: Release %s %s %s failed", i.ReleaseName, hook, h.Path) - } - b.Reset() - b.WriteString(h.Manifest) - - if err := i.cfg.KubeClient.WatchUntilReady(b, i.Timeout); err != nil { - // If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted - // under failed condition. If so, then clear the corresponding resource object in the hook - if err := deleteHookByPolicy(i.cfg, h, hooks.HookFailed); err != nil { - return err - } - return err - } - } - - // If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted - // under succeeded condition. If so, then clear the corresponding resource object in each hook - for _, h := range executingHooks { - if err := deleteHookByPolicy(i.cfg, h, hooks.HookSucceeded); err != nil { - return err - } - h.LastRun = time.Now() - } - - return nil -} - // deletePolices represents a mapping between the key in the annotation for label deleting policy and its real meaning // FIXME: Can we refactor this out? var deletePolices = map[string]release.HookDeletePolicy{ diff --git a/pkg/action/rollback.go b/pkg/action/rollback.go index 2db6ed7a9..7d88adfbf 100644 --- a/pkg/action/rollback.go +++ b/pkg/action/rollback.go @@ -19,7 +19,6 @@ package action import ( "bytes" "fmt" - "sort" "time" "github.com/pkg/errors" @@ -132,25 +131,32 @@ func (r *Rollback) prepareRollback(name string) (*release.Release, *release.Rele } func (r *Rollback) performRollback(currentRelease, targetRelease *release.Release) (*release.Release, error) { - if r.DryRun { r.cfg.Log("dry run for %s", targetRelease.Name) return targetRelease, nil } + current, err := r.cfg.KubeClient.Build(bytes.NewBufferString(currentRelease.Manifest)) + if err != nil { + return targetRelease, errors.Wrap(err, "unable to build kubernetes objects from current release manifest") + } + target, err := r.cfg.KubeClient.Build(bytes.NewBufferString(targetRelease.Manifest)) + if err != nil { + return targetRelease, errors.Wrap(err, "unable to build kubernetes objects from new release manifest") + } + // pre-rollback hooks if !r.DisableHooks { - if err := r.execHook(targetRelease.Hooks, hooks.PreRollback); err != nil { + if err := execHooks(r.cfg.KubeClient, targetRelease.Hooks, hooks.PreRollback, r.Timeout); err != nil { return targetRelease, err } } else { r.cfg.Log("rollback hooks disabled for %s", targetRelease.Name) } - cr := bytes.NewBufferString(currentRelease.Manifest) - tr := bytes.NewBufferString(targetRelease.Manifest) + results, err := r.cfg.KubeClient.Update(current, target, r.Force) - if err := r.cfg.KubeClient.Update(cr, tr, r.Force, r.Recreate); err != nil { + if err != nil { msg := fmt.Sprintf("Rollback %q failed: %s", targetRelease.Name, err) r.cfg.Log("warning: %s", msg) currentRelease.Info.Status = release.StatusSuperseded @@ -161,9 +167,18 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas return targetRelease, err } + if r.Recreate { + // NOTE: Because this is not critical for a release to succeed, we just + // log if an error occurs and continue onward. If we ever introduce log + // levels, we should make these error level logs so users are notified + // that they'll need to go do the cleanup on their own + if err := recreate(r.cfg.KubeClient, results.Updated); err != nil { + r.cfg.Log(err.Error()) + } + } + if r.Wait { - buf := bytes.NewBufferString(targetRelease.Manifest) - if err := r.cfg.KubeClient.Wait(buf, r.Timeout); err != nil { + if err := r.cfg.KubeClient.Wait(target, r.Timeout); err != nil { targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error())) r.cfg.recordRelease(currentRelease) r.cfg.recordRelease(targetRelease) @@ -173,7 +188,7 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas // post-rollback hooks if !r.DisableHooks { - if err := r.execHook(targetRelease.Hooks, hooks.PostRollback); err != nil { + if err := execHooks(r.cfg.KubeClient, targetRelease.Hooks, hooks.PostRollback, r.Timeout); err != nil { return targetRelease, err } } @@ -193,61 +208,3 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas return targetRelease, nil } - -// execHook executes all of the hooks for the given hook event. -func (r *Rollback) execHook(hs []*release.Hook, hook string) error { - timeout := r.Timeout - executingHooks := []*release.Hook{} - - for _, h := range hs { - for _, e := range h.Events { - if string(e) == hook { - executingHooks = append(executingHooks, h) - } - } - } - - sort.Sort(hookByWeight(executingHooks)) - - for _, h := range executingHooks { - if err := deleteHookByPolicy(r.cfg, h, hooks.BeforeHookCreation); err != nil { - return err - } - - b := bytes.NewBufferString(h.Manifest) - if err := r.cfg.KubeClient.Create(b); err != nil { - return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path) - } - b.Reset() - b.WriteString(h.Manifest) - - if err := r.cfg.KubeClient.WatchUntilReady(b, timeout); err != nil { - // If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted - // under failed condition. If so, then clear the corresponding resource object in the hook - if err := deleteHookByPolicy(r.cfg, h, hooks.HookFailed); err != nil { - return err - } - return err - } - } - - // If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted - // under succeeded condition. If so, then clear the corresponding resource object in each hook - for _, h := range executingHooks { - if err := deleteHookByPolicy(r.cfg, h, hooks.HookSucceeded); err != nil { - return err - } - h.LastRun = time.Now() - } - - return nil -} - -// deleteHookByPolicy deletes a hook if the hook policy instructs it to -func deleteHookByPolicy(cfg *Configuration, h *release.Hook, policy string) error { - if hookHasDeletePolicy(h, policy) { - b := bytes.NewBufferString(h.Manifest) - return cfg.KubeClient.Delete(b) - } - return nil -} diff --git a/pkg/action/uninstall.go b/pkg/action/uninstall.go index cbe3f49dc..16dc9827b 100644 --- a/pkg/action/uninstall.go +++ b/pkg/action/uninstall.go @@ -17,15 +17,12 @@ limitations under the License. package action import ( - "bytes" - "sort" "strings" "time" "github.com/pkg/errors" "helm.sh/helm/pkg/hooks" - "helm.sh/helm/pkg/kube" "helm.sh/helm/pkg/release" "helm.sh/helm/pkg/releaseutil" ) @@ -94,7 +91,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) res := &release.UninstallReleaseResponse{Release: rel} if !u.DisableHooks { - if err := u.execHook(rel.Hooks, hooks.PreDelete); err != nil { + if err := execHooks(u.cfg.KubeClient, rel.Hooks, hooks.PreDelete, u.Timeout); err != nil { return res, err } } else { @@ -111,7 +108,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) res.Info = kept if !u.DisableHooks { - if err := u.execHook(rel.Hooks, hooks.PostDelete); err != nil { + if err := execHooks(u.cfg.KubeClient, rel.Hooks, hooks.PostDelete, u.Timeout); err != nil { errs = append(errs, err) } } @@ -153,64 +150,8 @@ func (u *Uninstall) purgeReleases(rels ...*release.Release) error { return nil } -func joinErrors(errs []error) string { - es := make([]string, 0, len(errs)) - for _, e := range errs { - es = append(es, e.Error()) - } - return strings.Join(es, "; ") -} - -// execHook executes all of the hooks for the given hook event. -func (u *Uninstall) execHook(hs []*release.Hook, hook string) error { - executingHooks := []*release.Hook{} - - for _, h := range hs { - for _, e := range h.Events { - if string(e) == hook { - executingHooks = append(executingHooks, h) - } - } - } - - sort.Sort(hookByWeight(executingHooks)) - - for _, h := range executingHooks { - if err := deleteHookByPolicy(u.cfg, h, hooks.BeforeHookCreation); err != nil { - return err - } - - b := bytes.NewBufferString(h.Manifest) - if err := u.cfg.KubeClient.Create(b); err != nil { - return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path) - } - b.Reset() - b.WriteString(h.Manifest) - - if err := u.cfg.KubeClient.WatchUntilReady(b, u.Timeout); err != nil { - // If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted - // under failed condition. If so, then clear the corresponding resource object in the hook - if err := deleteHookByPolicy(u.cfg, h, hooks.HookFailed); err != nil { - return err - } - return err - } - } - - // If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted - // under succeeded condition. If so, then clear the corresponding resource object in each hook - for _, h := range executingHooks { - if err := deleteHookByPolicy(u.cfg, h, hooks.HookSucceeded); err != nil { - return err - } - h.LastRun = time.Now() - } - - return nil -} - // deleteRelease deletes the release and returns manifests that were kept in the deletion process -func (u *Uninstall) deleteRelease(rel *release.Release) (kept string, errs []error) { +func (u *Uninstall) deleteRelease(rel *release.Release) (string, []error) { caps, err := u.cfg.getCapabilities() if err != nil { return rel.Manifest, []error{errors.Wrap(err, "could not get apiVersions from Kubernetes")} @@ -227,23 +168,20 @@ func (u *Uninstall) deleteRelease(rel *release.Release) (kept string, errs []err } filesToKeep, filesToDelete := filterManifestsToKeep(files) + var kept string for _, f := range filesToKeep { kept += f.Name + "\n" } + var builder strings.Builder for _, file := range filesToDelete { - b := bytes.NewBufferString(strings.TrimSpace(file.Content)) - if b.Len() == 0 { - continue - } - if err := u.cfg.KubeClient.Delete(b); err != nil { - u.cfg.Log("uninstall: Failed deletion of %q: %s", rel.Name, err) - if err == kube.ErrNoObjectsVisited { - // Rewrite the message from "no objects visited" - err = errors.New("object not found, skipping delete") - } - errs = append(errs, err) - } + builder.WriteString(file.Content) + } + resources, err := u.cfg.KubeClient.Build(strings.NewReader(builder.String())) + if err != nil { + return "", []error{errors.Wrap(err, "unable to build kubernetes objects for delete")} } + + _, errs := u.cfg.KubeClient.Delete(resources) return kept, errs } diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 5863f9bc7..32eda9a5a 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -19,10 +19,10 @@ package action import ( "bytes" "fmt" - "sort" "time" "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "helm.sh/helm/pkg/chart" "helm.sh/helm/pkg/chartutil" @@ -76,7 +76,7 @@ func (u *Upgrade) Run(name string, chart *chart.Chart) (*release.Release, error) u.Wait = u.Wait || u.Atomic if err := validateReleaseName(name); err != nil { - return nil, errors.Errorf("upgradeRelease: Release name is invalid: %s", name) + return nil, errors.Errorf("release name is invalid: %s", name) } u.cfg.Log("preparing upgrade for %s", name) currentRelease, upgradedRelease, err := u.prepareUpgrade(name, chart) @@ -199,22 +199,42 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea return upgradedRelease, nil } + current, err := u.cfg.KubeClient.Build(bytes.NewBufferString(originalRelease.Manifest)) + if err != nil { + return upgradedRelease, errors.Wrap(err, "unable to build kubernetes objects from current release manifest") + } + target, err := u.cfg.KubeClient.Build(bytes.NewBufferString(upgradedRelease.Manifest)) + if err != nil { + return upgradedRelease, errors.Wrap(err, "unable to build kubernetes objects from new release manifest") + } + // pre-upgrade hooks if !u.DisableHooks { - if err := u.execHook(upgradedRelease.Hooks, hooks.PreUpgrade); err != nil { + if err := execHooks(u.cfg.KubeClient, upgradedRelease.Hooks, hooks.PreUpgrade, u.Timeout); err != nil { return u.failRelease(upgradedRelease, fmt.Errorf("pre-upgrade hooks failed: %s", err)) } } else { u.cfg.Log("upgrade hooks disabled for %s", upgradedRelease.Name) } - if err := u.upgradeRelease(originalRelease, upgradedRelease); err != nil { + + results, err := u.cfg.KubeClient.Update(current, target, u.Force) + if err != nil { u.cfg.recordRelease(originalRelease) return u.failRelease(upgradedRelease, err) } + if u.Recreate { + // NOTE: Because this is not critical for a release to succeed, we just + // log if an error occurs and continue onward. If we ever introduce log + // levels, we should make these error level logs so users are notified + // that they'll need to go do the cleanup on their own + if err := recreate(u.cfg.KubeClient, results.Updated); err != nil { + u.cfg.Log(err.Error()) + } + } + if u.Wait { - buf := bytes.NewBufferString(upgradedRelease.Manifest) - if err := u.cfg.KubeClient.Wait(buf, u.Timeout); err != nil { + if err := u.cfg.KubeClient.Wait(target, u.Timeout); err != nil { u.cfg.recordRelease(originalRelease) return u.failRelease(upgradedRelease, err) } @@ -222,7 +242,7 @@ func (u *Upgrade) performUpgrade(originalRelease, upgradedRelease *release.Relea // post-upgrade hooks if !u.DisableHooks { - if err := u.execHook(upgradedRelease.Hooks, hooks.PostUpgrade); err != nil { + if err := execHooks(u.cfg.KubeClient, upgradedRelease.Hooks, hooks.PostUpgrade, u.Timeout); err != nil { return u.failRelease(upgradedRelease, fmt.Errorf("post-upgrade hooks failed: %s", err)) } } @@ -282,14 +302,6 @@ func (u *Upgrade) failRelease(rel *release.Release, err error) (*release.Release return rel, err } -// upgradeRelease performs an upgrade from current to target release -func (u *Upgrade) upgradeRelease(current, target *release.Release) error { - cm := bytes.NewBufferString(current.Manifest) - tm := bytes.NewBufferString(target.Manifest) - // TODO add wait - return u.cfg.KubeClient.Update(cm, tm, u.Force, u.Recreate) -} - // reuseValues copies values from the current release to a new release if the // new release does not have any values. // @@ -334,50 +346,38 @@ func validateManifest(c kube.Interface, manifest []byte) error { return err } -// execHook executes all of the hooks for the given hook event. -func (u *Upgrade) execHook(hs []*release.Hook, hook string) error { - timeout := u.Timeout - executingHooks := []*release.Hook{} - - for _, h := range hs { - for _, e := range h.Events { - if string(e) == hook { - executingHooks = append(executingHooks, h) - } +// recreate captures all the logic for recreating pods for both upgrade and +// rollback. If we end up refactoring rollback to use upgrade, this can just be +// made an unexported method on the upgrade action. +func recreate(client kube.Interface, resources kube.ResourceList) error { + for _, res := range resources { + versioned := kube.AsVersioned(res) + selector, err := kube.SelectorsForObject(versioned) + if err != nil { + // If no selector is returned, it means this object is + // definitely not a pod, so continue onward + continue } - } - sort.Sort(hookByWeight(executingHooks)) - for _, h := range executingHooks { - if err := deleteHookByPolicy(u.cfg, h, hooks.BeforeHookCreation); err != nil { - return err + client, err := client.KubernetesClientSet() + if err != nil { + return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) } - b := bytes.NewBufferString(h.Manifest) - if err := u.cfg.KubeClient.Create(b); err != nil { - return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path) - } - b.Reset() - b.WriteString(h.Manifest) - - if err := u.cfg.KubeClient.WatchUntilReady(b, timeout); err != nil { - // If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted - // under failed condition. If so, then clear the corresponding resource object in the hook - if err := deleteHookByPolicy(u.cfg, h, hooks.HookFailed); err != nil { - return err - } - return err + pods, err := client.CoreV1().Pods(res.Namespace).List(metav1.ListOptions{ + LabelSelector: selector.String(), + }) + if err != nil { + return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) } - } - // If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted - // under succeeded condition. If so, then clear the corresponding resource object in each hook - for _, h := range executingHooks { - if err := deleteHookByPolicy(u.cfg, h, hooks.HookSucceeded); err != nil { - return err + // Restart pods + for _, pod := range pods.Items { + // Delete each pod for get them restarted with changed spec. + if err := client.CoreV1().Pods(pod.Namespace).Delete(pod.Name, metav1.NewPreconditionDeleteOptions(string(pod.UID))); err != nil { + return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) + } } - h.LastRun = time.Now() } - return nil } diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 02c0d25da..9ddc42645 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -39,7 +39,6 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/scheme" watchtools "k8s.io/client-go/tools/watch" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) @@ -65,30 +64,23 @@ func New(getter genericclioptions.RESTClientGetter) *Client { } // KubernetesClientSet returns a client set from the client factory. -func (c *Client) KubernetesClientSet() (*kubernetes.Clientset, error) { +func (c *Client) KubernetesClientSet() (kubernetes.Interface, error) { return c.Factory.KubernetesClientSet() } var nopLogger = func(_ string, _ ...interface{}) {} -// Create creates Kubernetes resources from an io.reader. -// -// Namespace will set the namespace. -func (c *Client) Create(reader io.Reader) error { - c.Log("building resources from manifest") - infos, err := c.BuildUnstructured(reader) - if err != nil { - return err +// Create creates Kubernetes resources specified in the resource list. +func (c *Client) Create(resources ResourceList) (*Result, error) { + c.Log("creating %d resource(s)", len(resources)) + if err := perform(resources, createResource); err != nil { + return nil, err } - c.Log("creating %d resource(s)", len(infos)) - return perform(infos, createResource) + return &Result{Created: resources}, nil } -func (c *Client) Wait(reader io.Reader, timeout time.Duration) error { - infos, err := c.BuildUnstructured(reader) - if err != nil { - return err - } +// Wait up to the given timeout for the specified resources to be ready +func (c *Client) Wait(resources ResourceList, timeout time.Duration) error { cs, err := c.KubernetesClientSet() if err != nil { return err @@ -98,7 +90,7 @@ func (c *Client) Wait(reader io.Reader, timeout time.Duration) error { log: c.Log, timeout: timeout, } - return w.waitForResources(infos) + return w.waitForResources(resources) } func (c *Client) namespace() string { @@ -125,8 +117,8 @@ func (c *Client) validator() resource.ContentValidator { return schema } -// BuildUnstructured validates for Kubernetes objects and returns unstructured infos. -func (c *Client) BuildUnstructured(reader io.Reader) (ResourceList, error) { +// Build validates for Kubernetes objects and returns unstructured infos. +func (c *Client) Build(reader io.Reader) (ResourceList, error) { result, err := c.newBuilder(). Unstructured(). Stream(reader, ""). @@ -134,39 +126,16 @@ func (c *Client) BuildUnstructured(reader io.Reader) (ResourceList, error) { return result, scrubValidationError(err) } -// Build validates for Kubernetes objects and returns resource Infos from a io.Reader. -func (c *Client) Build(reader io.Reader) (ResourceList, error) { - result, err := c.newBuilder(). - WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). - Schema(c.validator()). - Stream(reader, ""). - Do(). - Infos() - return result, scrubValidationError(err) -} - // Update reads in the current configuration and a target configuration from io.reader // and creates resources that don't already exists, updates resources that have been modified // in the target configuration and deletes resources from the current configuration that are // not present in the target configuration. -// -// Namespace will set the namespaces. -func (c *Client) Update(originalReader, targetReader io.Reader, force, recreate bool) error { - original, err := c.BuildUnstructured(originalReader) - if err != nil { - return errors.Wrap(err, "failed decoding reader into objects") - } - - c.Log("building resources from updated manifest") - target, err := c.BuildUnstructured(targetReader) - if err != nil { - return errors.Wrap(err, "failed decoding reader into objects") - } - +func (c *Client) Update(original, target ResourceList, force bool) (*Result, error) { updateErrors := []string{} + res := &Result{} c.Log("checking %d resources for changes", len(target)) - err = target.Visit(func(info *resource.Info, err error) error { + err := target.Visit(func(info *resource.Info, err error) error { if err != nil { return err } @@ -182,6 +151,9 @@ func (c *Client) Update(originalReader, targetReader io.Reader, force, recreate return errors.Wrap(err, "failed to create resource") } + // Append the created resource to the results + res.Created = append(res.Created, info) + kind := info.Mapping.GroupVersionKind.Kind c.Log("Created a new %s called %q\n", kind, info.Name) return nil @@ -193,43 +165,64 @@ func (c *Client) Update(originalReader, targetReader io.Reader, force, recreate return errors.Errorf("no %s with the name %q found", kind, info.Name) } - if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil { + if err := updateResource(c, info, originalInfo.Object, force); err != nil { c.Log("error updating the resource %q:\n\t %v", info.Name, err) updateErrors = append(updateErrors, err.Error()) } + // Because we check for errors later, append the info regardless + res.Updated = append(res.Updated, info) return nil }) switch { case err != nil: - return err + return nil, err case len(updateErrors) != 0: - return errors.Errorf(strings.Join(updateErrors, " && ")) + return nil, errors.Errorf(strings.Join(updateErrors, " && ")) } for _, info := range original.Difference(target) { c.Log("Deleting %q in %s...", info.Name, info.Namespace) if err := deleteResource(info); err != nil { c.Log("Failed to delete %q, err: %s", info.Name, err) + } else { + // Only append ones we succeeded in deleting + res.Deleted = append(res.Deleted, info) } } - return nil + return res, nil } -// Delete deletes Kubernetes resources from an io.reader. -// -// Namespace will set the namespace. -func (c *Client) Delete(reader io.Reader) error { - infos, err := c.BuildUnstructured(reader) - if err != nil { - return err - } - return perform(infos, func(info *resource.Info) error { +// Delete deletes Kubernetes resources specified in the resources list. It will +// attempt to delete all resources even if one or more fail and collect any +// errors. All successfully deleted items will be returned in the `Deleted` +// ResourceList that is part of the result. +func (c *Client) Delete(resources ResourceList) (*Result, []error) { + var errs []error + res := &Result{} + err := perform(resources, func(info *resource.Info) error { c.Log("Starting delete for %q %s", info.Name, info.Mapping.GroupVersionKind.Kind) - err := deleteResource(info) - return c.skipIfNotFound(err) + if err := c.skipIfNotFound(deleteResource(info)); err != nil { + // Collect the error and continue on + errs = append(errs, err) + } else { + res.Deleted = append(res.Deleted, info) + } + return nil }) + if err != nil { + // Rewrite the message from "no objects visited" if that is what we got + // back + if err == ErrNoObjectsVisited { + err = errors.New("object not found, skipping delete") + } + errs = append(errs, err) + } + if errs != nil { + return nil, errs + } + return res, nil } func (c *Client) skipIfNotFound(err error) error { @@ -246,7 +239,7 @@ func (c *Client) watchTimeout(t time.Duration) func(*resource.Info) error { } } -// WatchUntilReady watches the resource given in the reader, and waits until it is ready. +// WatchUntilReady watches the resources given and waits until it is ready. // // This function is mainly for hook implementations. It watches for a resource to // hit a particular milestone. The milestone depends on the Kind. @@ -258,14 +251,10 @@ func (c *Client) watchTimeout(t time.Duration) func(*resource.Info) error { // ascertained by watching the Status fields in a job's output. // // Handling for other kinds will be added as necessary. -func (c *Client) WatchUntilReady(reader io.Reader, timeout time.Duration) error { - infos, err := c.Build(reader) - if err != nil { - return err - } +func (c *Client) WatchUntilReady(resources ResourceList, timeout time.Duration) error { // For jobs, there's also the option to do poll c.Jobs(namespace).Get(): // https://github.com/adamreese/kubernetes/blob/master/test/e2e/job.go#L291-L300 - return perform(infos, c.watchTimeout(timeout)) + return perform(resources, c.watchTimeout(timeout)) } func perform(infos ResourceList, fn func(*resource.Info) error) error { @@ -315,7 +304,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P } // Get a versioned object - versionedObject := asVersioned(target) + versionedObject := AsVersioned(target) // Unstructured objects, such as CRDs, may not have an not registered error // returned from ConvertToVersion. Anything that's unstructured should @@ -330,7 +319,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P return patch, types.StrategicMergePatchType, err } -func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force, recreate bool) error { +func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool) error { patch, patchType, err := createPatch(target, currentObj) if err != nil { return errors.Wrap(err, "failed to create patch") @@ -377,37 +366,6 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, } } - if !recreate { - return nil - } - - versioned := asVersioned(target) - selector, err := selectorsForObject(versioned) - if err != nil { - return nil - } - - client, err := c.KubernetesClientSet() - if err != nil { - return err - } - - pods, err := client.CoreV1().Pods(target.Namespace).List(metav1.ListOptions{ - LabelSelector: selector.String(), - }) - if err != nil { - return err - } - - // Restart pods - for _, pod := range pods.Items { - c.Log("Restarting pod: %v/%v", pod.Namespace, pod.Name) - - // Delete each pod for get them restarted with changed spec. - if err := client.CoreV1().Pods(pod.Namespace).Delete(pod.Name, metav1.NewPreconditionDeleteOptions(string(pod.UID))); err != nil { - return err - } - } return nil } diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 01008c819..a465f5f00 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -142,7 +142,16 @@ func TestUpdate(t *testing.T) { } }), } - if err := c.Update(objBody(&listA), objBody(&listB), false, false); err != nil { + first, err := c.Build(objBody(&listA)) + if err != nil { + t.Fatal(err) + } + second, err := c.Build(objBody(&listB)) + if err != nil { + t.Fatal(err) + } + + if _, err := c.Update(first, second, false); err != nil { t.Fatal(err) } // TODO: Find a way to test methods that use Client Set @@ -188,11 +197,6 @@ func TestBuild(t *testing.T) { namespace: "test", reader: strings.NewReader(guestbookManifest), count: 6, - }, { - name: "Invalid schema", - namespace: "test", - reader: strings.NewReader(testInvalidServiceManifest), - err: true, }, { name: "Valid input, deploying resources into different namespaces", namespace: "test", @@ -272,24 +276,41 @@ func TestPerform(t *testing.T) { func TestReal(t *testing.T) { t.Skip("This is a live test, comment this line to run") c := New(nil) - if err := c.Create(strings.NewReader(guestbookManifest)); err != nil { + resources, err := c.Build(strings.NewReader(guestbookManifest)) + if err != nil { + t.Fatal(err) + } + if _, err := c.Create(resources); err != nil { t.Fatal(err) } testSvcEndpointManifest := testServiceManifest + "\n---\n" + testEndpointManifest c = New(nil) - if err := c.Create(strings.NewReader(testSvcEndpointManifest)); err != nil { + resources, err = c.Build(strings.NewReader(testSvcEndpointManifest)) + if err != nil { + t.Fatal(err) + } + if _, err := c.Create(resources); err != nil { t.Fatal(err) } - if err := c.Delete(strings.NewReader(testEndpointManifest)); err != nil { + resources, err = c.Build(strings.NewReader(testEndpointManifest)) + if err != nil { t.Fatal(err) } - // ensures that delete does not fail if a resource is not found - if err := c.Delete(strings.NewReader(testSvcEndpointManifest)); err != nil { + if _, errs := c.Delete(resources); errs != nil { + t.Fatal(errs) + } + + resources, err = c.Build(strings.NewReader(testSvcEndpointManifest)) + if err != nil { t.Fatal(err) } + // ensures that delete does not fail if a resource is not found + if _, errs := c.Delete(resources); errs != nil { + t.Fatal(errs) + } } const testServiceManifest = ` diff --git a/pkg/kube/converter.go b/pkg/kube/converter.go index eff61a530..92b56ab6c 100644 --- a/pkg/kube/converter.go +++ b/pkg/kube/converter.go @@ -23,7 +23,9 @@ import ( "k8s.io/client-go/kubernetes/scheme" ) -func asVersioned(info *resource.Info) runtime.Object { +// AsVersioned converts the given info into a runtime.Object with the correct +// group and version set +func AsVersioned(info *resource.Info) runtime.Object { gv := runtime.GroupVersioner(schema.GroupVersions(scheme.Scheme.PrioritizedVersionsAllGroups())) if info.Mapping != nil { gv = info.Mapping.GroupVersionKind.GroupVersion() diff --git a/pkg/kube/fake/fake.go b/pkg/kube/fake/fake.go index c0c3e508c..cb4702329 100644 --- a/pkg/kube/fake/fake.go +++ b/pkg/kube/fake/fake.go @@ -23,6 +23,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/kubernetes" "helm.sh/helm/pkg/kube" ) @@ -34,7 +35,6 @@ type FailingKubeClient struct { PrintingKubeClient CreateError error WaitError error - GetError error DeleteError error WatchUntilReadyError error UpdateError error @@ -44,51 +44,43 @@ type FailingKubeClient struct { } // Create returns the configured error if set or prints -func (f *FailingKubeClient) Create(r io.Reader) error { +func (f *FailingKubeClient) Create(resources kube.ResourceList) (*kube.Result, error) { if f.CreateError != nil { - return f.CreateError + return nil, f.CreateError } - return f.PrintingKubeClient.Create(r) + return f.PrintingKubeClient.Create(resources) } // Wait returns the configured error if set or prints -func (f *FailingKubeClient) Wait(r io.Reader, d time.Duration) error { +func (f *FailingKubeClient) Wait(resources kube.ResourceList, d time.Duration) error { if f.WaitError != nil { return f.WaitError } - return f.PrintingKubeClient.Wait(r, d) -} - -// Create returns the configured error if set or prints -func (f *FailingKubeClient) Get(r io.Reader) (string, error) { - if f.GetError != nil { - return "", f.GetError - } - return f.PrintingKubeClient.Get(r) + return f.PrintingKubeClient.Wait(resources, d) } // Delete returns the configured error if set or prints -func (f *FailingKubeClient) Delete(r io.Reader) error { +func (f *FailingKubeClient) Delete(resources kube.ResourceList) (*kube.Result, []error) { if f.DeleteError != nil { - return f.DeleteError + return nil, []error{f.DeleteError} } - return f.PrintingKubeClient.Delete(r) + return f.PrintingKubeClient.Delete(resources) } // WatchUntilReady returns the configured error if set or prints -func (f *FailingKubeClient) WatchUntilReady(r io.Reader, d time.Duration) error { +func (f *FailingKubeClient) WatchUntilReady(resources kube.ResourceList, d time.Duration) error { if f.WatchUntilReadyError != nil { return f.WatchUntilReadyError } - return f.PrintingKubeClient.WatchUntilReady(r, d) + return f.PrintingKubeClient.WatchUntilReady(resources, d) } // Update returns the configured error if set or prints -func (f *FailingKubeClient) Update(r, modifiedReader io.Reader, not, needed bool) error { +func (f *FailingKubeClient) Update(r, modified kube.ResourceList, ignoreMe bool) (*kube.Result, error) { if f.UpdateError != nil { - return f.UpdateError + return nil, f.UpdateError } - return f.PrintingKubeClient.Update(r, modifiedReader, not, needed) + return f.PrintingKubeClient.Update(r, modified, ignoreMe) } // Build returns the configured error if set or prints @@ -99,12 +91,9 @@ func (f *FailingKubeClient) Build(r io.Reader) (kube.ResourceList, error) { return f.PrintingKubeClient.Build(r) } -// BuildUnstructured returns the configured error if set or prints -func (f *FailingKubeClient) BuildUnstructured(r io.Reader) (kube.ResourceList, error) { - if f.BuildUnstructuredError != nil { - return []*resource.Info{}, f.BuildUnstructuredError - } - return f.PrintingKubeClient.Build(r) +// KubernetesClientSet implements the KubeClient interface +func (f *FailingKubeClient) KubernetesClientSet() (kubernetes.Interface, error) { + return f.PrintingKubeClient.KubernetesClientSet() } // WaitAndGetCompletedPodPhase returns the configured error if set or prints diff --git a/pkg/kube/fake/printer.go b/pkg/kube/fake/printer.go index d6cdb3be1..2a4dc1861 100644 --- a/pkg/kube/fake/printer.go +++ b/pkg/kube/fake/printer.go @@ -18,10 +18,13 @@ package fake import ( "io" + "strings" "time" v1 "k8s.io/api/core/v1" "k8s.io/cli-runtime/pkg/resource" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/fake" "helm.sh/helm/pkg/kube" ) @@ -33,40 +36,46 @@ type PrintingKubeClient struct { } // Create prints the values of what would be created with a real KubeClient. -func (p *PrintingKubeClient) Create(r io.Reader) error { - _, err := io.Copy(p.Out, r) - return err +func (p *PrintingKubeClient) Create(resources kube.ResourceList) (*kube.Result, error) { + _, err := io.Copy(p.Out, bufferize(resources)) + if err != nil { + return nil, err + } + return &kube.Result{Created: resources}, nil } -func (p *PrintingKubeClient) Wait(r io.Reader, _ time.Duration) error { - _, err := io.Copy(p.Out, r) +func (p *PrintingKubeClient) Wait(resources kube.ResourceList, _ time.Duration) error { + _, err := io.Copy(p.Out, bufferize(resources)) return err } -// Get prints the values of what would be created with a real KubeClient. -func (p *PrintingKubeClient) Get(r io.Reader) (string, error) { - _, err := io.Copy(p.Out, r) - return "", err -} - // Delete implements KubeClient delete. // // It only prints out the content to be deleted. -func (p *PrintingKubeClient) Delete(r io.Reader) error { - _, err := io.Copy(p.Out, r) - return err +func (p *PrintingKubeClient) Delete(resources kube.ResourceList) (*kube.Result, []error) { + _, err := io.Copy(p.Out, bufferize(resources)) + if err != nil { + return nil, []error{err} + } + return &kube.Result{Deleted: resources}, nil } // WatchUntilReady implements KubeClient WatchUntilReady. -func (p *PrintingKubeClient) WatchUntilReady(r io.Reader, _ time.Duration) error { - _, err := io.Copy(p.Out, r) +func (p *PrintingKubeClient) WatchUntilReady(resources kube.ResourceList, _ time.Duration) error { + _, err := io.Copy(p.Out, bufferize(resources)) return err } // Update implements KubeClient Update. -func (p *PrintingKubeClient) Update(_, modifiedReader io.Reader, _, _ bool) error { - _, err := io.Copy(p.Out, modifiedReader) - return err +func (p *PrintingKubeClient) Update(_, modified kube.ResourceList, _ bool) (*kube.Result, error) { + _, err := io.Copy(p.Out, bufferize(modified)) + if err != nil { + return nil, err + } + // TODO: This doesn't completely mock out have some that get created, + // updated, and deleted. I don't think these are used in any unit tests, but + // we may want to refactor a way to handle future tests + return &kube.Result{Updated: modified}, nil } // Build implements KubeClient Build. @@ -74,11 +83,20 @@ func (p *PrintingKubeClient) Build(_ io.Reader) (kube.ResourceList, error) { return []*resource.Info{}, nil } -func (p *PrintingKubeClient) BuildUnstructured(_ io.Reader) (kube.ResourceList, error) { - return p.Build(nil) -} - // WaitAndGetCompletedPodPhase implements KubeClient WaitAndGetCompletedPodPhase. func (p *PrintingKubeClient) WaitAndGetCompletedPodPhase(_ string, _ time.Duration) (v1.PodPhase, error) { return v1.PodSucceeded, nil } + +// KubernetesClientSet implements the KubeClient interface +func (p *PrintingKubeClient) KubernetesClientSet() (kubernetes.Interface, error) { + return fake.NewSimpleClientset(), nil +} + +func bufferize(resources kube.ResourceList) io.Reader { + var builder strings.Builder + for _, info := range resources { + builder.WriteString(info.String() + "\n") + } + return strings.NewReader(builder.String()) +} diff --git a/pkg/kube/interface.go b/pkg/kube/interface.go index 5bf89aa00..49802281b 100644 --- a/pkg/kube/interface.go +++ b/pkg/kube/interface.go @@ -21,6 +21,7 @@ import ( "time" v1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes" ) // KubernetesClient represents a client capable of communicating with the Kubernetes API. @@ -28,39 +29,36 @@ import ( // A KubernetesClient must be concurrency safe. type Interface interface { // Create creates one or more resources. - // - // reader must contain a YAML stream (one or more YAML documents separated - // by "\n---\n"). - Create(reader io.Reader) error + Create(resources ResourceList) (*Result, error) - Wait(r io.Reader, timeout time.Duration) error + Wait(resources ResourceList, timeout time.Duration) error // Delete destroys one or more resources. - // - // reader must contain a YAML stream (one or more YAML documents separated - // by "\n---\n"). - Delete(io.Reader) error + Delete(resources ResourceList) (*Result, []error) - // Watch the resource in reader until it is "ready". + // Watch the resource in reader until it is "ready". This method // // For Jobs, "ready" means the job ran to completion (excited without error). // For all other kinds, it means the kind was created or modified without // error. - WatchUntilReady(reader io.Reader, timeout time.Duration) error + WatchUntilReady(resources ResourceList, timeout time.Duration) error // Update updates one or more resources or creates the resource // if it doesn't exist. + Update(original, target ResourceList, force bool) (*Result, error) + + // Build creates a resource list from a Reader // // reader must contain a YAML stream (one or more YAML documents separated - // by "\n---\n"). - Update(originalReader, modifiedReader io.Reader, force bool, recreate bool) error - + // by "\n---\n") Build(reader io.Reader) (ResourceList, error) - BuildUnstructured(reader io.Reader) (ResourceList, error) // WaitAndGetCompletedPodPhase waits up to a timeout until a pod enters a completed phase // and returns said phase (PodSucceeded or PodFailed qualify). WaitAndGetCompletedPodPhase(name string, timeout time.Duration) (v1.PodPhase, error) + + // KubernetesClientSet returns the underlying kubernetes clientset + KubernetesClientSet() (kubernetes.Interface, error) } var _ Interface = (*Client)(nil) diff --git a/pkg/kube/result.go b/pkg/kube/result.go new file mode 100644 index 000000000..c3e171c2e --- /dev/null +++ b/pkg/kube/result.go @@ -0,0 +1,28 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kube + +// Result contains the information of created, updated, and deleted resources +// for various kube API calls along with helper methods for using those +// resources +type Result struct { + Created ResourceList + Updated ResourceList + Deleted ResourceList +} + +// If needed, we can add methods to the Result type for things like diffing diff --git a/pkg/kube/wait.go b/pkg/kube/wait.go index 491013f72..bf502baea 100644 --- a/pkg/kube/wait.go +++ b/pkg/kube/wait.go @@ -56,7 +56,7 @@ func (w *waiter) waitForResources(created ResourceList) error { ok = true err error ) - switch value := asVersioned(v).(type) { + switch value := AsVersioned(v).(type) { case *corev1.Pod: pod, err := w.c.CoreV1().Pods(value.Namespace).Get(value.Name, metav1.GetOptions{}) if err != nil || !w.isPodReady(pod) { @@ -178,7 +178,7 @@ func (w *waiter) podsReadyForObject(namespace string, obj runtime.Object) (bool, } func (w *waiter) podsforObject(namespace string, obj runtime.Object) ([]corev1.Pod, error) { - selector, err := selectorsForObject(obj) + selector, err := SelectorsForObject(obj) if err != nil { return nil, err } @@ -300,10 +300,10 @@ func getPods(client kubernetes.Interface, namespace, selector string) ([]corev1. return list.Items, err } -// selectorsForObject returns the pod label selector for a given object +// SelectorsForObject returns the pod label selector for a given object // // Modified version of https://github.com/kubernetes/kubernetes/blob/v1.14.1/pkg/kubectl/polymorphichelpers/helpers.go#L84 -func selectorsForObject(object runtime.Object) (selector labels.Selector, err error) { +func SelectorsForObject(object runtime.Object) (selector labels.Selector, err error) { switch t := object.(type) { case *extensionsv1beta1.ReplicaSet: selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) diff --git a/pkg/releasetesting/environment.go b/pkg/releasetesting/environment.go index 7bff936b8..319e3f501 100644 --- a/pkg/releasetesting/environment.go +++ b/pkg/releasetesting/environment.go @@ -37,8 +37,11 @@ type Environment struct { } func (env *Environment) createTestPod(test *test) error { - b := bytes.NewBufferString(test.manifest) - if err := env.KubeClient.Create(b); err != nil { + resources, err := env.KubeClient.Build(bytes.NewBufferString(test.manifest)) + if err != nil { + return err + } + if _, err := env.KubeClient.Create(resources); err != nil { test.result.Info = err.Error() test.result.Status = release.TestRunFailure return err @@ -112,9 +115,15 @@ func (env *Environment) streamMessage(msg string, status release.TestRunStatus) // DeleteTestPods deletes resources given in testManifests func (env *Environment) DeleteTestPods(testManifests []string) { for _, testManifest := range testManifests { - err := env.KubeClient.Delete(bytes.NewBufferString(testManifest)) + resources, err := env.KubeClient.Build(bytes.NewBufferString(testManifest)) if err != nil { env.streamError(err.Error()) } + _, errs := env.KubeClient.Delete(resources) + if err != nil { + for _, e := range errs { + env.streamError(e.Error()) + } + } } } diff --git a/pkg/releasetesting/test_suite_test.go b/pkg/releasetesting/test_suite_test.go index 9256df467..6317e6523 100644 --- a/pkg/releasetesting/test_suite_test.go +++ b/pkg/releasetesting/test_suite_test.go @@ -17,13 +17,14 @@ limitations under the License. package releasetesting import ( - "io" + "io/ioutil" "testing" "time" v1 "k8s.io/api/core/v1" "helm.sh/helm/pkg/kube" + "helm.sh/helm/pkg/kube/fake" "helm.sh/helm/pkg/release" ) @@ -237,14 +238,14 @@ func testSuiteFixture(testManifests []string) *TestSuite { func testEnvFixture() *Environment { return &Environment{ Namespace: "default", - KubeClient: &mockKubeClient{}, + KubeClient: &mockKubeClient{PrintingKubeClient: fake.PrintingKubeClient{Out: ioutil.Discard}}, Timeout: 1, Messages: make(chan *release.TestReleaseResponse, 1), } } type mockKubeClient struct { - kube.Interface + fake.PrintingKubeClient podFail bool err error } @@ -255,5 +256,4 @@ func (c *mockKubeClient) WaitAndGetCompletedPodPhase(_ string, _ time.Duration) } return v1.PodSucceeded, nil } -func (c *mockKubeClient) Create(_ io.Reader) error { return c.err } -func (c *mockKubeClient) Delete(_ io.Reader) error { return nil } +func (c *mockKubeClient) Create(_ kube.ResourceList) (*kube.Result, error) { return nil, c.err }