diff --git a/go.sum b/go.sum index a4dc275f..54b332dd 100644 --- a/go.sum +++ b/go.sum @@ -40,11 +40,13 @@ github.com/InVisionApp/go-health v2.1.0+incompatible h1:m5nRf/RKaMCkob7V5Vc3tuzl github.com/InVisionApp/go-health v2.1.0+incompatible/go.mod h1:/+Gv1o8JUsrjC6pi6MN6/CgKJo4OqZ6x77XAnImrzhg= github.com/InVisionApp/go-logger v1.0.1 h1:WFL19PViM1mHUmUWfsv5zMo379KSWj2MRmBlzMFDRiE= github.com/InVisionApp/go-logger v1.0.1/go.mod h1:+cGTDSn+P8105aZkeOfIhdd7vFO5X1afUHcjvanY0L8= +github.com/Kount/pq-timeouts v1.0.0 h1:6a23dhwmQ2PukftCWm56T4RPJ4zc2iE9y5E42TMAl6E= github.com/Kount/pq-timeouts v1.0.0/go.mod h1:Y7rNVWI9KiI3xj1QxBmOSB12Eyv9g5Gjego8KFpV5PY= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Peripli/service-manager v0.18.7-0.20210131140341-a199050d9407 h1:CgUicBDc3lqSZe4MZUI30lFN8u/LsfPfnas0sxzCcnA= github.com/Peripli/service-manager v0.18.7-0.20210131140341-a199050d9407/go.mod h1:FtRJlibH3yLD1v/JCp6yTBx+m2GDpodxnwmawl756Fo= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -66,11 +68,13 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudfoundry-community/go-cfenv v1.17.1-0.20171115121958-e84b5c116637 h1:tPkTfFW8UDGAqVC+4rZO93iuIC7bYTqFNWQ2i7mOl8Q= github.com/cloudfoundry-community/go-cfenv v1.17.1-0.20171115121958-e84b5c116637/go.mod h1:2UgWvQTRXUuIZ/x3KnW6fk6CgPBhcV4UQb/UGIrUyyI= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg= github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -78,6 +82,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -90,12 +95,16 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/structs v1.0.0 h1:BrX964Rv5uQ3wwS+KRUAJCBBw5PQmgJfJ6v4yly5QwU= github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gavv/httpexpect v0.0.0-20170820080527-c44a6d7bb636 h1:FbWwmG7qBNykpmPppq5767far39ty4P7lOhpPNK8Ik4= github.com/gavv/httpexpect v0.0.0-20170820080527-c44a6d7bb636/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424 h1:Vh7rylVZRZCj6W41lRlP17xPk4Nq260H4Xo/DDYmEZk= github.com/gavv/monotime v0.0.0-20190418164738-30dba4353424/go.mod h1:vmp8DIyckQMXOPl0AQVHt+7n5h7Gb7hS6CUydiV8QeA= +github.com/gbrlsnchs/jwt v0.5.0 h1:plMOnB6WUDm9uCrhM+ZpTMcHI7fLsmUquUXwvNk8sN0= github.com/gbrlsnchs/jwt v0.5.0/go.mod h1:p5fttBhRV34dmDL7zpqJ2ctL8yaWm5DJTtBm/evgQ/c= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -113,7 +122,9 @@ github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPh github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA= github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -150,6 +161,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -165,7 +177,9 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A= github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -193,9 +207,11 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jmoiron/sqlx v1.2.1-0.20201120164427-00c6e74d816a h1:74FsVHi8zuvyUTv1W3Wry/oiAQYhZzcB5vEKLYEAv0E= github.com/jmoiron/sqlx v1.2.1-0.20201120164427-00c6e74d816a/go.mod h1:ClpsPFzLpSBl7MvJ+BhV0JHz4vmKRBarpvZ9644v9Oo= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= @@ -207,16 +223,21 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.6 h1:EgWPCW6O3n1D5n99Zq3xXBt9uCwRGvpwGOusOLNBRSQ= github.com/klauspost/compress v1.11.6/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kubernetes-sigs/go-open-service-broker-client v0.0.0-20180330214919-dca737037ce6 h1:Z9ijvkCpBIi2y50CnXX2oUEbiLHvTpSISYoKW0V/Hv0= github.com/kubernetes-sigs/go-open-service-broker-client v0.0.0-20180330214919-dca737037ce6/go.mod h1:s8wBC55/DEkNa3YMY1WLgpT33Ghpmw7v+waIxh15dYI= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= @@ -242,6 +263,7 @@ github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXy github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -269,10 +291,13 @@ github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNC github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac h1:jWKYCNlX4J5s8M0nHYkh7Y7c9gRVDEb3mq51j5J0F5M= github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -290,6 +315,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -322,6 +348,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -331,20 +358,30 @@ github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.4 h1:bTSsPLdAYF5QNLSwYsKfBKKTnlGbIuhqL3CpRsjzGhg= github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ulule/limiter v2.2.2+incompatible h1:1lk9jesmps1ziYHHb4doL7l5hFkYYYA3T8dkNyw7ffY= github.com/ulule/limiter v2.2.2+incompatible/go.mod h1:VJx/ZNGmClQDS5F6EmsGqK8j3jz1qJYZ6D9+MdAD+kw= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v0.0.0-20171207120941-e5f51c11919d h1:pAXG0woN37FQD08beB53orVchWU97qUUdjKtSuMGqi4= github.com/valyala/fasthttp v0.0.0-20171207120941-e5f51c11919d/go.mod h1:+g/po7GqyG5E+1CNgquiIxJnsXEi5vwFn5weFujbO78= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d h1:yJIizrfO599ot2kQ6Af1enICnwBD3XoxgX3MrMwot2M= github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -645,6 +682,7 @@ gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtW gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -652,6 +690,7 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -664,6 +703,7 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= diff --git a/internal/cmd/instance/update_instance.go b/internal/cmd/instance/update_instance.go new file mode 100644 index 00000000..da4c3724 --- /dev/null +++ b/internal/cmd/instance/update_instance.go @@ -0,0 +1,154 @@ +/* + * Copyright 2021 The Service Manager 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 instance + +import ( + "encoding/json" + "fmt" + "github.com/Peripli/service-manager-cli/internal/cmd" + "github.com/Peripli/service-manager-cli/internal/output" + "github.com/Peripli/service-manager-cli/pkg/query" + "github.com/Peripli/service-manager-cli/pkg/types" + + "github.com/spf13/cobra" +) + +type UpdateCmd struct { + *cmd.Context + instance types.ServiceInstance + instanceName string + planName string + parametersJSON string + outputFormat output.Format +} + + +func NewUpdateInstanceCmd(context *cmd.Context) *UpdateCmd { + return &UpdateCmd{Context: context,instance: types.ServiceInstance{}} +} + +// Prepare returns cobra command +func (uc *UpdateCmd) Prepare(prepare cmd.PrepareFunc) *cobra.Command { + result := &cobra.Command{ + Use: "update-instance [name] --id service-instance-id --new-name new-service-name --plan new-plan-name --instance-params new-configuration-parameters", + Short: "Update a service instance", + Long: `Update the name, associated plan, and configuration parameters of an existing service instance`, + + PreRunE: prepare(uc, uc.Context), + RunE: cmd.RunE(uc), + } + result.Flags().StringVarP(&uc.instance.ID, "id", "", "", "The id of the service instance to update") + result.Flags().StringVarP(&uc.instance.Name, "new-name", "", "", "The new name of the service instance") + result.Flags().StringVarP(&uc.planName, "plan", "", "", "The name of the new service plan to use for the instance") + result.Flags().StringVarP(&uc.parametersJSON, "instance-params", "c", "", "Valid JSON object containing instance configuration parameters") + cmd.AddFormatFlag(result.Flags()) + cmd.AddModeFlag(result.Flags(), "async") + return result +} + +func (uc *UpdateCmd) Validate(args []string) error { + if len(args) < 1 { + return fmt.Errorf("name is required") + } + uc.instanceName = args[0] + return nil +} + +func (uc *UpdateCmd) Run() error { + var instanceBeforeUpdate *types.ServiceInstance + if uc.instance.ID == "" { + instances, err := uc.Client.ListInstances(&query.Parameters{ + FieldQuery: []string{ + fmt.Sprintf("name eq '%s'", uc.instanceName), + }, + GeneralParams: uc.Parameters.GeneralParams, + }) + if err != nil { + return err + } + if len(instances.ServiceInstances) == 0 { + return fmt.Errorf("no instances found with name %s", uc.instanceName) + } + + if len(instances.ServiceInstances) > 1 { + return fmt.Errorf("more than 1 instance found with name %s. Use --id flag to specify one", uc.instanceName) + } + instanceBeforeUpdate = &instances.ServiceInstances[0] + + } else { + instance, err := uc.Client.GetInstanceByID(uc.instance.ID, nil) + if err != nil { + return err + } + instanceBeforeUpdate = instance + + } + + if uc.planName != "" { + currentPlan, err := uc.Client.GetPlanByID(instanceBeforeUpdate.ServicePlanID, &uc.Parameters) + if err != nil { + return err + } + + plans, err := uc.Client.ListPlans(&query.Parameters{ + FieldQuery: []string{ + fmt.Sprintf("catalog_name eq '%s'", uc.planName), + fmt.Sprintf("service_offering_id eq '%s'", currentPlan.ServiceOfferingID), + }, + GeneralParams: uc.Parameters.GeneralParams, + }) + + if err != nil { + return err + } + if len(plans.ServicePlans) == 0 { + return fmt.Errorf("service plan with name %s for offering with id %s not found", uc.planName, currentPlan.ServiceOfferingID) + } + if len(plans.ServicePlans) > 1 { + return fmt.Errorf("exactly one service plan with name %s for offering with id %s expected", uc.planName, currentPlan.ServiceOfferingID) + } + + uc.instance.ServicePlanID = plans.ServicePlans[0].ID + } + if len(uc.parametersJSON) > 0 { + uc.instance.Parameters = json.RawMessage(uc.parametersJSON) + } + + resultInstance, location, err := uc.Client.UpdateInstance(instanceBeforeUpdate.ID, &uc.instance, &uc.Parameters) + if err != nil { + output.PrintMessage(uc.Output, "Could not update service instance. Reason: ") + return err + } + + if len(location) != 0 { + cmd.CommonHandleAsyncExecution(uc.Context, location, fmt.Sprintf("Service Instance %s successfully scheduled for update. To see status of the operation use:\n", uc.instance.Name)) + return nil + } + output.PrintServiceManagerObject(uc.Output, uc.outputFormat, resultInstance) + output.Println(uc.Output) + return nil +} + +// SetOutputFormat set output format +func (uc *UpdateCmd) SetOutputFormat(format output.Format) { + uc.outputFormat = format +} + +// HideUsage hide command's usage +func (uc *UpdateCmd) HideUsage() bool { + return true +} diff --git a/internal/cmd/instance/update_instance_test.go b/internal/cmd/instance/update_instance_test.go new file mode 100644 index 00000000..b425ee57 --- /dev/null +++ b/internal/cmd/instance/update_instance_test.go @@ -0,0 +1,288 @@ +package instance + +import ( + "bytes" + "github.com/Peripli/service-manager-cli/pkg/types" + "github.com/Peripli/service-manager-cli/pkg/smclient/smclientfakes" + "github.com/Peripli/service-manager-cli/internal/cmd" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "fmt" + "errors" + "io/ioutil" + "github.com/Peripli/service-manager/pkg/util" + "net/http" + "github.com/spf13/cobra" + "encoding/json" +) + +var _ = Describe("update instance command test", func() { + var client *smclientfakes.FakeClient + var command *UpdateCmd + var buffer *bytes.Buffer + var instances *types.ServiceInstances + var instance *types.ServiceInstance + var updatedIntance *types.ServiceInstance + var plan *types.ServicePlan + var plans *types.ServicePlans + var errGetInstance error + + const instanceId = "instanceid" + const planId = "planId" + const newPlanId = "plandidnew" + const offeringId = "offeringId" + BeforeEach(func() { + buffer = &bytes.Buffer{} + client = &smclientfakes.FakeClient{} + context := &cmd.Context{Output: buffer, Client: client} + command = NewUpdateInstanceCmd(context) + errGetInstance = nil + }) + + validAsyncUpdateExecution := func(location string, args ...string) *cobra.Command { + var planName, instanceName, newInstanceName, instanceParams, serviceInstanceId string + instanceName = args[0] + for i, value := range args { + switch value { + case "--plan": + planName = args[i+1] + case "--new-name": + newInstanceName = args[i+1] + case "--instance-params": + instanceParams = args[i+1] + case "id": + serviceInstanceId = args[i+1] + } + } + instance = &types.ServiceInstance{ + ID: instanceId, + Name: instanceName, + ServicePlanID: newPlanId, + } + + instances = &types.ServiceInstances{ + ServiceInstances: []types.ServiceInstance{types.ServiceInstance{ + ID: instanceId, + Name: instanceName, + ServicePlanID: newPlanId, + }, + }, + } + plan = &types.ServicePlan{ + ID: planId, + ServiceOfferingID: offeringId, + CatalogName: "large", + } + + plans = &types.ServicePlans{ + ServicePlans: []types.ServicePlan{ + {ID: newPlanId, + ServiceOfferingID: offeringId, + CatalogName: planName}, + }, + } + if newInstanceName == "" { + newInstanceName = instanceName + } + updatedIntance = &types.ServiceInstance{ + ID: instanceId, + Name: newInstanceName, + ServicePlanID: newPlanId, + Parameters: json.RawMessage(instanceParams), + } + if serviceInstanceId != "" { + updatedIntance.ID = serviceInstanceId + } + + operation := &types.Operation{ + State: "in progress", + } + client.StatusReturns(operation, nil) + client.ListInstancesReturns(instances, nil) + client.GetPlanByIDReturns(plan, nil) + client.GetInstanceByIDReturns(instance, errGetInstance) + client.ListPlansReturns(plans, nil) + client.UpdateInstanceReturns(updatedIntance, location, nil) + piCmd := command.Prepare(cmd.SmPrepare) + piCmd.SetArgs(args) + Expect(piCmd.Execute()).ToNot(HaveOccurred()) + + return piCmd + } + + validSyncUpdateExecution := func(args ...string) *cobra.Command { + return validAsyncUpdateExecution("", append(args, "--mode", "sync")...) + } + + invalidUpdateInstanceCommandExecution := func(args ...string) error { + trCmd := command.Prepare(cmd.SmPrepare) + trCmd.SetArgs(args) + return trCmd.Execute() + } + + Describe("valid request", func() { + Context("async call", func() { + It("should print status command", func() { + validAsyncUpdateExecution("location", + "myinstancename", "--plan", "small", "--new-name", "new-service-instance-name", "--instance-params", "{\"color\":\"red\"}") + Expect(buffer.String()).To(ContainSubstring(`smctl status location`)) + }) + }) + + Context("sync call", func() { + It("should print object", func() { + validSyncUpdateExecution("myinstancename", "--plan", "small", "--new-name", "new-service-instance-name", "--instance-params", "{\"color\":\"red\"}") + Expect(command.instanceName).To(Equal("myinstancename")) + Expect(command.instance.Name).To(Equal("new-service-instance-name")) + Expect(command.instance.ServicePlanID).To(Equal(newPlanId)) + Expect(command.instance.Parameters).To(Equal(json.RawMessage("{\"color\":\"red\"}"))) + tableOutputExpected := updatedIntance.TableData().String() + Expect(buffer.String()).To(ContainSubstring(tableOutputExpected)) + }) + }) + Context("sync call by id", func() { + It("should print object", func() { + validSyncUpdateExecution("myinstancename", "--id", "serviceinstanceid", "--plan", "small", "--new-name", "new-service-instance-name", "--instance-params", "{\"color\":\"red\"}") + Expect(command.instance.ID).To(Equal("serviceinstanceid")) + Expect(command.instanceName).To(Equal("myinstancename")) + Expect(command.instance.Name).To(Equal("new-service-instance-name")) + Expect(command.instance.ServicePlanID).To(Equal(newPlanId)) + Expect(command.instance.Parameters).To(Equal(json.RawMessage("{\"color\":\"red\"}"))) + tableOutputExpected := updatedIntance.TableData().String() + Expect(buffer.String()).To(ContainSubstring(tableOutputExpected)) + }) + }) + + }) + + Describe("invalid request", func() { + JustBeforeEach(func() { + client.ListInstancesReturns(instances, nil) + client.GetPlanByIDReturns(plan, nil) + client.GetInstanceByIDReturns(instance, errGetInstance) + client.ListPlansReturns(plans, nil) + }) + + Context("when service instance not found", func() { + BeforeEach(func() { + instances = &types.ServiceInstances{} + }) + + Context("by name", func() { + It("should return an error", func() { + err := invalidUpdateInstanceCommandExecution("instance-name", "--new-name", "new name") + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("no instances found with name %s", "instance-name"))) + }) + + }) + Context("by id", func() { + BeforeEach(func() { + errGetInstance = errors.New("errore occured") + }) + It("should return an error", func() { + err := invalidUpdateInstanceCommandExecution("instance-name", "--new-name", "new name", "--id", "service-instance-id") + Expect(err.Error()).To(ContainSubstring("errore occured")) + }) + + }) + + }) + + Context("when more than once instance found", func() { + BeforeEach(func() { + client.ListInstancesReturnsOnCall(0, &types.ServiceInstances{ + ServiceInstances: []types.ServiceInstance{ + types.ServiceInstance{ + Name: "instance-name", + }, + types.ServiceInstance{ + Name: "instance-name", + }, + }, + }, nil) + }) + It("should return an error", func() { + err := invalidUpdateInstanceCommandExecution("instance-name", "--new-name", "new name") + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("more than 1 instance found with name %s", "instance-name"))) + }) + + }) + Context("update plan", func() { + BeforeEach(func() { + instances = &types.ServiceInstances{ + ServiceInstances: []types.ServiceInstance{ + {ID: "instanceid", Name: "instance"}, + }, + } + plan = &types.ServicePlan{ + ID: "plandid", + ServiceOfferingID: "offeringid", + CatalogName: "large", + } + + }) + Context("when service plan is not found", func() { + BeforeEach(func() { + plans = &types.ServicePlans{} + }) + It("should return an error", func() { + err := invalidUpdateInstanceCommandExecution("instance-name", "--new-name", "new name", "--plan", plan.CatalogName) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("service plan with name %s for offering with id %s not found", plan.CatalogName, plan.ServiceOfferingID))) + }) + + }) + Context("when more than one service plan found", func() { + BeforeEach(func() { + plans = &types.ServicePlans{ + ServicePlans: []types.ServicePlan{ + {ID: "plandid", + ServiceOfferingID: "offeringid", + CatalogName: "large"}, + {ID: "plandid2", + ServiceOfferingID: "offeringid", + CatalogName: "large"}, + }, + } + }) + + It("should return an error", func() { + err := invalidUpdateInstanceCommandExecution("instance-name", "--new-name", "new name", "--plan", plan.CatalogName) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("exactly one service plan with name %s for offering with id %s expected", plan.CatalogName, plan.ServiceOfferingID))) + }) + }) + + Context("update instance", func() { + BeforeEach(func() { + plans = &types.ServicePlans{ + ServicePlans: []types.ServicePlan{ + {ID: "plandid", + ServiceOfferingID: "offeringid", + CatalogName: "small"}, + }, + } + }) + Context("With http response error from http client", func() { + It("should return error's description", func() { + body := ioutil.NopCloser(bytes.NewReader([]byte("HTTP response error"))) + expectedError := util.HandleResponseError(&http.Response{Body: body}) + client.UpdateInstanceReturns(nil, "", expectedError) + err := invalidUpdateInstanceCommandExecution("instance-name", "plan", "small") + Expect(err).Should(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("HTTP response error")) + }) + }) + + Context("With invalid output format", func() { + It("should return error", func() { + invFormat := "invalid-format" + err := invalidUpdateInstanceCommandExecution("validName", "--plan", "small", "--output", invFormat) + Expect(err).Should(HaveOccurred()) + Expect(err.Error()).To(Equal("unknown output: " + invFormat)) + }) + }) + }) + + }) + + }) +}) diff --git a/main.go b/main.go index ae013c86..dcf7d8bc 100644 --- a/main.go +++ b/main.go @@ -92,6 +92,8 @@ func main() { instance.NewProvisionCmd(cmdContext), instance.NewDeprovisionCmd(cmdContext, os.Stdin), instance.NewTransferCmd(cmdContext, os.Stdin), + instance.NewUpdateInstanceCmd(cmdContext), + }, PrepareFn: cmd.SmPrepare, } diff --git a/pkg/smclient/client.go b/pkg/smclient/client.go index d1ae812b..16558293 100644 --- a/pkg/smclient/client.go +++ b/pkg/smclient/client.go @@ -61,7 +61,7 @@ type Client interface { ListOfferings(*query.Parameters) (*types.ServiceOfferings, error) ListPlans(*query.Parameters) (*types.ServicePlans, error) - + GetPlanByID(string,*query.Parameters) (*types.ServicePlan, error) ListInstances(*query.Parameters) (*types.ServiceInstances, error) GetInstanceByID(string, *query.Parameters) (*types.ServiceInstance, error) GetInstanceParameters(string, *query.Parameters) (map[string]interface{}, error) @@ -285,6 +285,15 @@ func (client *serviceManagerClient) GetInstanceParameters(id string, q *query.Pa return parameters, err } +// GetPlanByID returns pla by id +func (client *serviceManagerClient) GetPlanByID(id string, q *query.Parameters) (*types.ServicePlan, error) { + plan := &types.ServicePlan{} + err := client.get(plan, web.ServicePlansURL+"/"+id, &query.Parameters{ + GeneralParams: q.GeneralParams, + }) + + return plan, err +} // GetInstanceByID returns instance registered in the Service Manager satisfying provided queries func (client *serviceManagerClient) GetInstanceByID(id string, q *query.Parameters) (*types.ServiceInstance, error) { diff --git a/pkg/smclient/smclientfakes/fake_client.go b/pkg/smclient/smclientfakes/fake_client.go index 42bf381d..45d2d653 100644 --- a/pkg/smclient/smclientfakes/fake_client.go +++ b/pkg/smclient/smclientfakes/fake_client.go @@ -463,6 +463,23 @@ type FakeClient struct { } invocations map[string][][]interface{} invocationsMutex sync.RWMutex + + GetPlanByIDStub func(string, *query.Parameters) (*types.ServicePlan, error) + getPlanByIDMutex sync.RWMutex + getPlanByIDArgsForCall []struct { + arg1 string + arg2 *query.Parameters + } + getPlanByIDReturns struct { + result1 *types.ServicePlan + result2 error + } + getPlanByIDReturnsOnCall map[int]struct { + result1 *types.ServicePlan + result2 error + } + + } func (fake *FakeClient) Bind(arg1 *types.ServiceBinding, arg2 *query.Parameters) (*types.ServiceBinding, string, error) { @@ -1293,6 +1310,70 @@ func (fake *FakeClient) GetInstanceParametersReturnsOnCall(i int, result1 map[st }{result1, result2} } +func (fake *FakeClient) GetPlanByID(arg1 string, arg2 *query.Parameters) (*types.ServicePlan, error) { + fake.getPlanByIDMutex.Lock() + ret, specificReturn := fake.getPlanByIDReturnsOnCall[len(fake.getPlanByIDArgsForCall)] + fake.getPlanByIDArgsForCall = append(fake.getPlanByIDArgsForCall, struct { + arg1 string + arg2 *query.Parameters + }{arg1, arg2}) + fake.recordInvocation("GetPlanByID", []interface{}{arg1, arg2}) + fake.getPlanByIDMutex.Unlock() + if fake.GetPlanByIDStub != nil { + return fake.GetPlanByIDStub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + fakeReturns := fake.getPlanByIDReturns + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeClient) GetPlanByIDCallCount() int { + fake.getPlanByIDMutex.RLock() + defer fake.getPlanByIDMutex.RUnlock() + return len(fake.getPlanByIDArgsForCall) +} + +func (fake *FakeClient) GetPlanByIDCalls(stub func(string, *query.Parameters) (*types.ServicePlan, error)) { + fake.getPlanByIDMutex.Lock() + defer fake.getPlanByIDMutex.Unlock() + fake.GetPlanByIDStub = stub +} + +func (fake *FakeClient) GetPlanByIDArgsForCall(i int) (string, *query.Parameters) { + fake.getPlanByIDMutex.RLock() + defer fake.getPlanByIDMutex.RUnlock() + argsForCall := fake.getPlanByIDArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeClient) GetPlanByIDReturns(result1 *types.ServicePlan, result2 error) { + fake.getPlanByIDMutex.Lock() + defer fake.getPlanByIDMutex.Unlock() + fake.GetPlanByIDStub = nil + fake.getPlanByIDReturns = struct { + result1 *types.ServicePlan + result2 error + }{result1, result2} +} + +func (fake *FakeClient) GetPlanByIDReturnsOnCall(i int, result1 *types.ServicePlan, result2 error) { + fake.getPlanByIDMutex.Lock() + defer fake.getPlanByIDMutex.Unlock() + fake.GetPlanByIDStub = nil + if fake.getPlanByIDReturnsOnCall == nil { + fake.getPlanByIDReturnsOnCall = make(map[int]struct { + result1 *types.ServicePlan + result2 error + }) + } + fake.getPlanByIDReturnsOnCall[i] = struct { + result1 *types.ServicePlan + result2 error + }{result1, result2} +} + func (fake *FakeClient) Label(arg1 string, arg2 string, arg3 *types.LabelChanges, arg4 *query.Parameters) error { fake.labelMutex.Lock() ret, specificReturn := fake.labelReturnsOnCall[len(fake.labelArgsForCall)]