diff --git a/go.mod b/go.mod index e83f6f2..5b56fa9 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,12 @@ module github.com/cloudfoundry-community/go-cf-clients-helper/v2 -go 1.20 +go 1.21 + +toolchain go1.21.1 exclude ( + github.com/imdario/mergo v0.3.16 + github.com/imdario/mergo v1.0.0 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/vito/go-interact v1.0.1 ) @@ -13,65 +17,81 @@ require ( ) require ( - code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5 // indirect + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4 // indirect + code.cloudfoundry.org/cli-plugin-repo v0.0.0-20230525012251-b9c89116786e // indirect code.cloudfoundry.org/clock v1.0.0 // indirect code.cloudfoundry.org/go-log-cache v1.0.1-0.20211011162012-ede82a99d3cc // indirect code.cloudfoundry.org/go-loggregator/v8 v8.0.5 // indirect code.cloudfoundry.org/jsonry v1.1.4 // indirect - code.cloudfoundry.org/tlsconfig v0.0.0-20230320190829-8f91c367795b // indirect + code.cloudfoundry.org/tlsconfig v0.0.0-20230612153104-23c0622de227 // indirect code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.18 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f // indirect github.com/charlievieth/fs v0.0.3 // indirect github.com/cloudfoundry/bosh-cli v6.4.1+incompatible // indirect - github.com/cloudfoundry/bosh-utils v0.0.360 // indirect + github.com/cloudfoundry/bosh-utils v0.0.394 // indirect github.com/cppforlife/go-patch v0.2.0 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect - github.com/imdario/mergo v0.3.15 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/imdario/mergo v0.3.5 // indirect github.com/jessevdk/go-flags v1.5.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect + github.com/json-iterator/go v1.1.11 // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/moby/moby v20.10.22+incompatible // indirect - github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect github.com/rivo/uniseg v0.4.4 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 // indirect - github.com/sirupsen/logrus v1.9.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tedsuo/rata v1.0.1-0.20170830210128-07d200713958 // indirect github.com/vito/go-interact v1.0.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/net v0.15.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect - google.golang.org/grpc v1.54.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/genproto v0.0.0-20230911183012-2d3300fd4832 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230911183012-2d3300fd4832 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 // indirect + google.golang.org/grpc v1.58.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.26.3 // indirect - k8s.io/client-go v0.26.3 // indirect + k8s.io/apimachinery v0.22.2 // indirect + k8s.io/client-go v0.22.2 // indirect k8s.io/klog/v2 v2.90.1 // indirect - k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 56de149..f490264 100644 --- a/go.sum +++ b/go.sum @@ -19,6 +19,10 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -30,16 +34,18 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5 h1:tM5+dn2C9xZw1RzgI6WTQW1rGqdUimKB3RFbyu4h6Hc= -code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5/go.mod h1:v4VVB6oBMz/c9fRY6vZrwr5xKRWOH5NPDjQZlPk0Gbs= +code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4 h1:9G5F8zgma5v0GdDvNz6iZwwJp3RS/z0SY/aHGfVwvTo= +code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4/go.mod h1:wYHCXH/gI19ujoFVuMkY48qPpPCoHLKBKXPkn67h/Yc= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli v0.0.0-20220602204915-eda2b7b2321c h1:EaIB5O4kD7qFRuueRxotGws5ZizriECglGyveM1ZDKM= code.cloudfoundry.org/cli v0.0.0-20220602204915-eda2b7b2321c/go.mod h1:vS0rCfoWEgSCHPhwfJ3C//uVe3GDrfLrY4wEBGUqh4o= -code.cloudfoundry.org/cli-plugin-repo v0.0.0-20200304195157-af98c4be9b85 h1:jaHWw9opYjKPrDT19uydBBWSxl+g5F4Hv030fqMsalo= +code.cloudfoundry.org/cli-plugin-repo v0.0.0-20230525012251-b9c89116786e h1:S3mdVd/uTwYYtrf5j9feucRuTqb05SsO5D1H2Mj09ao= +code.cloudfoundry.org/cli-plugin-repo v0.0.0-20230525012251-b9c89116786e/go.mod h1:R1EiyOAr7lW0l/YkZNqItUNZ01Q/dYUfbTn4X4Z+82M= code.cloudfoundry.org/clock v1.0.0 h1:kFXWQM4bxYvdBw2X8BbBeXwQNgfoWv1vqAk2ZZyBN2o= code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= code.cloudfoundry.org/diego-ssh v0.0.0-20170109142818-18cdb3586e7f h1:xDSTgaS6b/AkaBqvyEYfu6i1Z+y8JSCHAd/e1HGqyF4= +code.cloudfoundry.org/diego-ssh v0.0.0-20170109142818-18cdb3586e7f/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/go-diodes v0.0.0-20180905200951-72629b5276e3/go.mod h1:Jzi+ccHgo/V/PLQUaQ6hnZcC1c4BS790gx21LRRui4g= code.cloudfoundry.org/go-envstruct v1.5.0/go.mod h1:E2S/gzRZpZ51PZnIv7Bo7QvcgH18yio19upkrRk0xLU= code.cloudfoundry.org/go-log-cache v1.0.1-0.20211011162012-ede82a99d3cc h1:8gj5Z08i9ZvoIGi1A/E2CEQTbvJjogYQgBQUI2/DyNE= @@ -48,27 +54,49 @@ code.cloudfoundry.org/go-loggregator/v8 v8.0.2-0.20200722201844-b5130958b65d/go. code.cloudfoundry.org/go-loggregator/v8 v8.0.5 h1:p1rrGxTwUqLjlUVtbjTAvKOSGNmPuBja8LeQOQgRrBc= code.cloudfoundry.org/go-loggregator/v8 v8.0.5/go.mod h1:mLlJ1ZyG6gVvBEtYypvbztRvFeCtBsTxE9tt+85tS6Y= code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f h1:UrKzEwTgeiff9vxdrfdqxibzpWjxLnuXDI5m6z3GJAk= +code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f/go.mod h1:sk5LnIjB/nIEU7yP5sDQExVm62wu0pBh3yrElngUisI= code.cloudfoundry.org/jsonry v1.1.4 h1:P9N7IlH1/4aRCLcXLgLFj1hkcBmV7muijJzY+K6U4hE= code.cloudfoundry.org/jsonry v1.1.4/go.mod h1:6aKilShQP7w/Ez76h1El2/n9y2OkHuU56nKSBB9Gp0A= code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be h1:rnGRgbKlOPKbI9N/PscJ78Ug5Iw+o1kE7aDW01V+0FM= +code.cloudfoundry.org/lager v1.1.1-0.20191008172124-a9afc05ee5be/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= code.cloudfoundry.org/rfc5424 v0.0.0-20180905210152-236a6d29298a/go.mod h1:tkZo8GtzBjySJ7USvxm4E36lNQw1D3xM6oKHGqdaAJ4= code.cloudfoundry.org/tlsconfig v0.0.0-20200131000646-bbe0f8da39b3/go.mod h1:eTbFJpyXRGuFVyg5+oaj9B2eIbIc+0/kZjH8ftbtdew= -code.cloudfoundry.org/tlsconfig v0.0.0-20230320190829-8f91c367795b h1:FjTuGbVBKeaSyvW7WEATlIFCyb0uCpaiuTSaMQXjUyY= -code.cloudfoundry.org/tlsconfig v0.0.0-20230320190829-8f91c367795b/go.mod h1:C8SxvGRSutmgzV2FxH8Zwqz2Q8HsaAITQRQFKhlDzPw= +code.cloudfoundry.org/tlsconfig v0.0.0-20230612153104-23c0622de227 h1:QYyb6Ur0Ys6FciDB3+8zCW3eVk7AxAs2++Foa5DAdt0= +code.cloudfoundry.org/tlsconfig v0.0.0-20230612153104-23c0622de227/go.mod h1:C8SxvGRSutmgzV2FxH8Zwqz2Q8HsaAITQRQFKhlDzPw= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d/go.mod h1:YUJiVOr5xl0N/RjMxM1tHmgSpBbi5UM+KoVR5AoejO0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= +github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2 h1:koK7z0nSsRiRiBWwa+E714Puh+DO+ZRdIyAXiXzL+lg= github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apoydence/eachers v0.0.0-20181020210610-23942921fe77/go.mod h1:bXvGk6IkT1Agy7qzJ+DjIw/SJ1AaB3AvAuMDVV+Vkoo= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= @@ -85,8 +113,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudfoundry/bosh-cli v6.4.1+incompatible h1:n5/+NIF9QxvGINOrjh6DmO+GTen78MoCj5+LU9L8bR4= github.com/cloudfoundry/bosh-cli v6.4.1+incompatible/go.mod h1:rzIB+e1sn7wQL/TJ54bl/FemPKRhXby5BIMS3tLuWFM= -github.com/cloudfoundry/bosh-utils v0.0.360 h1:Jxx6sGJ89IprlHBZrx5cQdgPeisAca+583EamIjy95U= -github.com/cloudfoundry/bosh-utils v0.0.360/go.mod h1:bMTLG2/kn3lIvvUAwocBAwOvxSt3Oog8RcGN8f5sOrk= +github.com/cloudfoundry/bosh-utils v0.0.394 h1:5BRITkopHz5wG5QbeRsSJx/Swb/30RIlatTaIk/bYMc= +github.com/cloudfoundry/bosh-utils v0.0.394/go.mod h1:ZkFvNYahG9Sh3nKP0OMHqLcOgFROuOVqmIVi09x3a7w= github.com/cloudfoundry/dropsonde v1.0.0/go.mod h1:6zwvrWK5TpxBVYi1cdkE5WDsIO8E0n7qAJg3wR9B67c= github.com/cloudfoundry/gosteno v0.0.0-20150423193413-0c8581caea35/go.mod h1:3YBPUR85RIrvaUTdA1dL38YSp6s3OHu1xrWLkGt2Mog= github.com/cloudfoundry/loggregatorlib v0.0.0-20170823162133-36eddf15ef12/go.mod h1:ucj7+svyACshmxV3Zze2NAcEcdbBf9scZYR+QKCX9/w= @@ -94,46 +122,63 @@ github.com/cloudfoundry/sonde-go v0.0.0-20171206171820-b33733203bb4/go.mod h1:GS github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/cppforlife/go-patch v0.2.0 h1:Y14MnCQjDlbw7WXT4k+u6DPAA9XnygN4BfrSpI/19RU= github.com/cppforlife/go-patch v0.2.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/cyphar/filepath-securejoin v0.2.1 h1:5DPkzz/0MwUpvR4fxASKzgApeq2OMFY5FfYtrX28Coo= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= 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= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -161,7 +206,7 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -169,14 +214,17 @@ 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-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 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= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -187,85 +235,109 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= +github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb h1:LCMfzVg3sflxTs4UvuP4D8CkoZnfHLe2qzqgDn/4OHs= +github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0/go.mod h1:qrJPVzv9YlhsrxJc3P/Q85nr0w1lIRikTl4JlhdDH5w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2/go.mod h1:7pdNwVWBBHGiCxa9lAszqCJMbfTISJ7oMftp8+UGV08= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/jessevdk/go-flags v0.0.0-20170926144705-f88afde2fa19/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/loggregator/go-bindata v0.0.0-20190422223605-5f11cfb2d7d9/go.mod h1:PvsJfK9t/8OdGvSanpYlwJ1EPoJ/hwT3c52txAzqooY= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/moby/moby v20.10.22+incompatible h1:KHnFMlxjgGizH7+3fQj8+PjmrwEnilKgahf/TgTQIxI= github.com/moby/moby v20.10.22+incompatible/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= -github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20171031171758-652e15c9a27e/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= +github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20171105031654-1eecca0ba8e6/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/poy/eachers v0.0.0-20181020210610-23942921fe77/go.mod h1:x1vqpbcMW9T/KRcQ4b48diSiSVtYgvwQ5xzDByEg4WE= @@ -275,23 +347,36 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/square/certstrap v1.2.0/go.mod h1:CUHqV+fxJW0Y5UQFnnbYwQ7bpKXO1AKbic9g73799yw= github.com/square/certstrap v1.3.0 h1:N9P0ZRA+DjT8pq5fGDj0z3FjafRKnBDypP0QHpMlaAk= +github.com/square/certstrap v1.3.0/go.mod h1:wGZo9eE1B7WX2GKBn0htJ+B3OuRl2UsdCFySNooy9hU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tedsuo/rata v1.0.1-0.20170830210128-07d200713958 h1:mueRRuRjR35dEOkHdhpoRcruNgBz0ohG659HxxmcAwA= github.com/tedsuo/rata v1.0.1-0.20170830210128-07d200713958/go.mod h1:X47ELzhOoLbfFIY0Cql9P6yo3Cdwf2CMX3FVZxRzJPc= +github.com/unrolled/secure v0.0.0-20180416205222-a1cf62cc2159/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= github.com/vito/go-interact v1.0.0 h1:niLW3NjGoMWOayoR6iQ8AxWVM1Q4rR8VGZ1mt6uK3BM= github.com/vito/go-interact v1.0.0/go.mod h1:W1mz+UVUZScRM3eUjQhEQiLDnQ+yLnXkB2rjBfGPrXg= @@ -301,6 +386,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -308,6 +394,7 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.step.sm/crypto v0.16.2 h1:Pr9aazTwWBBZNogUsOqhOrPSdwAa9pPs+lMB602lnDA= +go.step.sm/crypto v0.16.2/go.mod h1:1WkTOTY+fOX/RY4TnZREp6trQAsBHRQ7nu6QJBiNQF8= golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -315,9 +402,12 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -352,6 +442,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20180418062111-d41e8174641f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -366,6 +458,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -385,19 +478,22 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -408,6 +504,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180419222023-a2a45943ae67/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -423,6 +521,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -437,6 +536,7 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -452,15 +552,21 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -469,13 +575,14 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -523,7 +630,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -582,9 +691,14 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230911183012-2d3300fd4832 h1:/30npZKtUjXqju7ZA2MsvpkGKD4mQFtf+zPnZasABjg= +google.golang.org/genproto v0.0.0-20230911183012-2d3300fd4832/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230911183012-2d3300fd4832 h1:4E7rZzBdR5LmiZx6n47Dg4AjH8JLhMQWywsYqvXNLcs= +google.golang.org/genproto/googleapis/api v0.0.0-20230911183012-2d3300fd4832/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 h1:o4LtQxebKIJ4vkzyhtD2rfUNZ20Zf0ik5YVP5E7G7VE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -600,8 +714,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= +google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -616,11 +730,14 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -629,6 +746,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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= +gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -638,6 +756,8 @@ 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-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -648,23 +768,26 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.4.0-0.dev/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70= -k8s.io/api v0.26.3 h1:emf74GIQMTik01Aum9dPP0gAypL8JTLl/lHa4V9RFSU= -k8s.io/apimachinery v0.26.3 h1:dQx6PNETJ7nODU3XPtrwkfuubs6w7sX0M8n61zHIV/k= -k8s.io/apimachinery v0.26.3/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/client-go v0.26.3 h1:k1UY+KXfkxV2ScEL3gilKcF7761xkYsSD6BC9szIu8s= -k8s.io/client-go v0.26.3/go.mod h1:ZPNu9lm8/dbRIPAgteN30RSXea6vrCpFvq+MateTUuQ= +k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= +k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= +k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= +k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= +k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= -k8s.io/utils v0.0.0-20230313181309-38a27ef9d749 h1:xMMXJlJbsU8w3V5N2FLDQ8YgU8s1EoULdbQBcAeNJkY= -k8s.io/utils v0.0.0-20230313181309-38a27ef9d749/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/session.go b/session.go index b557478..d29751f 100644 --- a/session.go +++ b/session.go @@ -119,7 +119,6 @@ func (s *Session) init(config *configv3.Config, configUaa *configv3.Config, conf ccWrappersV3 := []ccv3.ConnectionWrapper{} authWrapperV3 := ccWrapper.NewUAAAuthentication(nil, config) - ccWrappersV3 = append(ccWrappersV3, authWrapperV3) ccWrappersV3 = append(ccWrappersV3, ccWrapper.NewRetryRequest(config.RequestRetryCount())) if s.IsDebugMode() { diff --git a/vendor/cloud.google.com/go/compute/LICENSE b/vendor/cloud.google.com/go/compute/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/cloud.google.com/go/compute/internal/version.go b/vendor/cloud.google.com/go/compute/internal/version.go new file mode 100644 index 0000000..6395537 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/internal/version.go @@ -0,0 +1,18 @@ +// Copyright 2022 Google LLC +// +// 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 internal + +// Version is the current tagged release of the library. +const Version = "1.23.0" diff --git a/vendor/cloud.google.com/go/compute/metadata/CHANGES.md b/vendor/cloud.google.com/go/compute/metadata/CHANGES.md new file mode 100644 index 0000000..06b9573 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/CHANGES.md @@ -0,0 +1,19 @@ +# Changes + +## [0.2.3](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.2.2...compute/metadata/v0.2.3) (2022-12-15) + + +### Bug Fixes + +* **compute/metadata:** Switch DNS lookup to an absolute lookup ([119b410](https://github.com/googleapis/google-cloud-go/commit/119b41060c7895e45e48aee5621ad35607c4d021)), refs [#7165](https://github.com/googleapis/google-cloud-go/issues/7165) + +## [0.2.2](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.2.1...compute/metadata/v0.2.2) (2022-12-01) + + +### Bug Fixes + +* **compute/metadata:** Set IdleConnTimeout for http.Client ([#7084](https://github.com/googleapis/google-cloud-go/issues/7084)) ([766516a](https://github.com/googleapis/google-cloud-go/commit/766516aaf3816bfb3159efeea65aa3d1d205a3e2)), refs [#5430](https://github.com/googleapis/google-cloud-go/issues/5430) + +## [0.1.0] (2022-10-26) + +Initial release of metadata being it's own module. diff --git a/vendor/cloud.google.com/go/compute/metadata/LICENSE b/vendor/cloud.google.com/go/compute/metadata/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/cloud.google.com/go/compute/metadata/README.md b/vendor/cloud.google.com/go/compute/metadata/README.md new file mode 100644 index 0000000..f940fb2 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/README.md @@ -0,0 +1,27 @@ +# Compute API + +[![Go Reference](https://pkg.go.dev/badge/cloud.google.com/go/compute.svg)](https://pkg.go.dev/cloud.google.com/go/compute/metadata) + +This is a utility library for communicating with Google Cloud metadata service +on Google Cloud. + +## Install + +```bash +go get cloud.google.com/go/compute/metadata +``` + +## Go Version Support + +See the [Go Versions Supported](https://github.com/googleapis/google-cloud-go#go-versions-supported) +section in the root directory's README. + +## Contributing + +Contributions are welcome. Please, see the [CONTRIBUTING](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/main/CONTRIBUTING.md) +document for details. + +Please note that this project is released with a Contributor Code of Conduct. +By participating in this project you agree to abide by its terms. See +[Contributor Code of Conduct](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/main/CONTRIBUTING.md#contributor-code-of-conduct) +for more information. diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go new file mode 100644 index 0000000..c17faa1 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/metadata.go @@ -0,0 +1,543 @@ +// Copyright 2014 Google LLC +// +// 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 metadata provides access to Google Compute Engine (GCE) +// metadata and API service accounts. +// +// This package is a wrapper around the GCE metadata service, +// as documented at https://cloud.google.com/compute/docs/metadata/overview. +package metadata // import "cloud.google.com/go/compute/metadata" + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net" + "net/http" + "net/url" + "os" + "runtime" + "strings" + "sync" + "time" +) + +const ( + // metadataIP is the documented metadata server IP address. + metadataIP = "169.254.169.254" + + // metadataHostEnv is the environment variable specifying the + // GCE metadata hostname. If empty, the default value of + // metadataIP ("169.254.169.254") is used instead. + // This is variable name is not defined by any spec, as far as + // I know; it was made up for the Go package. + metadataHostEnv = "GCE_METADATA_HOST" + + userAgent = "gcloud-golang/0.1" +) + +type cachedValue struct { + k string + trim bool + mu sync.Mutex + v string +} + +var ( + projID = &cachedValue{k: "project/project-id", trim: true} + projNum = &cachedValue{k: "project/numeric-project-id", trim: true} + instID = &cachedValue{k: "instance/id", trim: true} +) + +var defaultClient = &Client{hc: newDefaultHTTPClient()} + +func newDefaultHTTPClient() *http.Client { + return &http.Client{ + Transport: &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 2 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + IdleConnTimeout: 60 * time.Second, + }, + Timeout: 5 * time.Second, + } +} + +// NotDefinedError is returned when requested metadata is not defined. +// +// The underlying string is the suffix after "/computeMetadata/v1/". +// +// This error is not returned if the value is defined to be the empty +// string. +type NotDefinedError string + +func (suffix NotDefinedError) Error() string { + return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix)) +} + +func (c *cachedValue) get(cl *Client) (v string, err error) { + defer c.mu.Unlock() + c.mu.Lock() + if c.v != "" { + return c.v, nil + } + if c.trim { + v, err = cl.getTrimmed(c.k) + } else { + v, err = cl.Get(c.k) + } + if err == nil { + c.v = v + } + return +} + +var ( + onGCEOnce sync.Once + onGCE bool +) + +// OnGCE reports whether this process is running on Google Compute Engine. +func OnGCE() bool { + onGCEOnce.Do(initOnGCE) + return onGCE +} + +func initOnGCE() { + onGCE = testOnGCE() +} + +func testOnGCE() bool { + // The user explicitly said they're on GCE, so trust them. + if os.Getenv(metadataHostEnv) != "" { + return true + } + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + resc := make(chan bool, 2) + + // Try two strategies in parallel. + // See https://github.com/googleapis/google-cloud-go/issues/194 + go func() { + req, _ := http.NewRequest("GET", "http://"+metadataIP, nil) + req.Header.Set("User-Agent", userAgent) + res, err := newDefaultHTTPClient().Do(req.WithContext(ctx)) + if err != nil { + resc <- false + return + } + defer res.Body.Close() + resc <- res.Header.Get("Metadata-Flavor") == "Google" + }() + + go func() { + resolver := &net.Resolver{} + addrs, err := resolver.LookupHost(ctx, "metadata.google.internal.") + if err != nil || len(addrs) == 0 { + resc <- false + return + } + resc <- strsContains(addrs, metadataIP) + }() + + tryHarder := systemInfoSuggestsGCE() + if tryHarder { + res := <-resc + if res { + // The first strategy succeeded, so let's use it. + return true + } + // Wait for either the DNS or metadata server probe to + // contradict the other one and say we are running on + // GCE. Give it a lot of time to do so, since the system + // info already suggests we're running on a GCE BIOS. + timer := time.NewTimer(5 * time.Second) + defer timer.Stop() + select { + case res = <-resc: + return res + case <-timer.C: + // Too slow. Who knows what this system is. + return false + } + } + + // There's no hint from the system info that we're running on + // GCE, so use the first probe's result as truth, whether it's + // true or false. The goal here is to optimize for speed for + // users who are NOT running on GCE. We can't assume that + // either a DNS lookup or an HTTP request to a blackholed IP + // address is fast. Worst case this should return when the + // metaClient's Transport.ResponseHeaderTimeout or + // Transport.Dial.Timeout fires (in two seconds). + return <-resc +} + +// systemInfoSuggestsGCE reports whether the local system (without +// doing network requests) suggests that we're running on GCE. If this +// returns true, testOnGCE tries a bit harder to reach its metadata +// server. +func systemInfoSuggestsGCE() bool { + if runtime.GOOS != "linux" { + // We don't have any non-Linux clues available, at least yet. + return false + } + slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name") + name := strings.TrimSpace(string(slurp)) + return name == "Google" || name == "Google Compute Engine" +} + +// Subscribe calls Client.Subscribe on the default client. +func Subscribe(suffix string, fn func(v string, ok bool) error) error { + return defaultClient.Subscribe(suffix, fn) +} + +// Get calls Client.Get on the default client. +func Get(suffix string) (string, error) { return defaultClient.Get(suffix) } + +// ProjectID returns the current instance's project ID string. +func ProjectID() (string, error) { return defaultClient.ProjectID() } + +// NumericProjectID returns the current instance's numeric project ID. +func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() } + +// InternalIP returns the instance's primary internal IP address. +func InternalIP() (string, error) { return defaultClient.InternalIP() } + +// ExternalIP returns the instance's primary external (public) IP address. +func ExternalIP() (string, error) { return defaultClient.ExternalIP() } + +// Email calls Client.Email on the default client. +func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) } + +// Hostname returns the instance's hostname. This will be of the form +// ".c..internal". +func Hostname() (string, error) { return defaultClient.Hostname() } + +// InstanceTags returns the list of user-defined instance tags, +// assigned when initially creating a GCE instance. +func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() } + +// InstanceID returns the current VM's numeric instance ID. +func InstanceID() (string, error) { return defaultClient.InstanceID() } + +// InstanceName returns the current VM's instance ID string. +func InstanceName() (string, error) { return defaultClient.InstanceName() } + +// Zone returns the current VM's zone, such as "us-central1-b". +func Zone() (string, error) { return defaultClient.Zone() } + +// InstanceAttributes calls Client.InstanceAttributes on the default client. +func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() } + +// ProjectAttributes calls Client.ProjectAttributes on the default client. +func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() } + +// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client. +func InstanceAttributeValue(attr string) (string, error) { + return defaultClient.InstanceAttributeValue(attr) +} + +// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client. +func ProjectAttributeValue(attr string) (string, error) { + return defaultClient.ProjectAttributeValue(attr) +} + +// Scopes calls Client.Scopes on the default client. +func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) } + +func strsContains(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +} + +// A Client provides metadata. +type Client struct { + hc *http.Client +} + +// NewClient returns a Client that can be used to fetch metadata. +// Returns the client that uses the specified http.Client for HTTP requests. +// If nil is specified, returns the default client. +func NewClient(c *http.Client) *Client { + if c == nil { + return defaultClient + } + + return &Client{hc: c} +} + +// getETag returns a value from the metadata service as well as the associated ETag. +// This func is otherwise equivalent to Get. +func (c *Client) getETag(suffix string) (value, etag string, err error) { + ctx := context.TODO() + // Using a fixed IP makes it very difficult to spoof the metadata service in + // a container, which is an important use-case for local testing of cloud + // deployments. To enable spoofing of the metadata service, the environment + // variable GCE_METADATA_HOST is first inspected to decide where metadata + // requests shall go. + host := os.Getenv(metadataHostEnv) + if host == "" { + // Using 169.254.169.254 instead of "metadata" here because Go + // binaries built with the "netgo" tag and without cgo won't + // know the search suffix for "metadata" is + // ".google.internal", and this IP address is documented as + // being stable anyway. + host = metadataIP + } + suffix = strings.TrimLeft(suffix, "/") + u := "http://" + host + "/computeMetadata/v1/" + suffix + req, err := http.NewRequest("GET", u, nil) + if err != nil { + return "", "", err + } + req.Header.Set("Metadata-Flavor", "Google") + req.Header.Set("User-Agent", userAgent) + var res *http.Response + var reqErr error + retryer := newRetryer() + for { + res, reqErr = c.hc.Do(req) + var code int + if res != nil { + code = res.StatusCode + } + if delay, shouldRetry := retryer.Retry(code, reqErr); shouldRetry { + if err := sleep(ctx, delay); err != nil { + return "", "", err + } + continue + } + break + } + if reqErr != nil { + return "", "", reqErr + } + defer res.Body.Close() + if res.StatusCode == http.StatusNotFound { + return "", "", NotDefinedError(suffix) + } + all, err := ioutil.ReadAll(res.Body) + if err != nil { + return "", "", err + } + if res.StatusCode != 200 { + return "", "", &Error{Code: res.StatusCode, Message: string(all)} + } + return string(all), res.Header.Get("Etag"), nil +} + +// Get returns a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// +// If the GCE_METADATA_HOST environment variable is not defined, a default of +// 169.254.169.254 will be used instead. +// +// If the requested metadata is not defined, the returned error will +// be of type NotDefinedError. +func (c *Client) Get(suffix string) (string, error) { + val, _, err := c.getETag(suffix) + return val, err +} + +func (c *Client) getTrimmed(suffix string) (s string, err error) { + s, err = c.Get(suffix) + s = strings.TrimSpace(s) + return +} + +func (c *Client) lines(suffix string) ([]string, error) { + j, err := c.Get(suffix) + if err != nil { + return nil, err + } + s := strings.Split(strings.TrimSpace(j), "\n") + for i := range s { + s[i] = strings.TrimSpace(s[i]) + } + return s, nil +} + +// ProjectID returns the current instance's project ID string. +func (c *Client) ProjectID() (string, error) { return projID.get(c) } + +// NumericProjectID returns the current instance's numeric project ID. +func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) } + +// InstanceID returns the current VM's numeric instance ID. +func (c *Client) InstanceID() (string, error) { return instID.get(c) } + +// InternalIP returns the instance's primary internal IP address. +func (c *Client) InternalIP() (string, error) { + return c.getTrimmed("instance/network-interfaces/0/ip") +} + +// Email returns the email address associated with the service account. +// The account may be empty or the string "default" to use the instance's +// main account. +func (c *Client) Email(serviceAccount string) (string, error) { + if serviceAccount == "" { + serviceAccount = "default" + } + return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email") +} + +// ExternalIP returns the instance's primary external (public) IP address. +func (c *Client) ExternalIP() (string, error) { + return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip") +} + +// Hostname returns the instance's hostname. This will be of the form +// ".c..internal". +func (c *Client) Hostname() (string, error) { + return c.getTrimmed("instance/hostname") +} + +// InstanceTags returns the list of user-defined instance tags, +// assigned when initially creating a GCE instance. +func (c *Client) InstanceTags() ([]string, error) { + var s []string + j, err := c.Get("instance/tags") + if err != nil { + return nil, err + } + if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil { + return nil, err + } + return s, nil +} + +// InstanceName returns the current VM's instance ID string. +func (c *Client) InstanceName() (string, error) { + return c.getTrimmed("instance/name") +} + +// Zone returns the current VM's zone, such as "us-central1-b". +func (c *Client) Zone() (string, error) { + zone, err := c.getTrimmed("instance/zone") + // zone is of the form "projects//zones/". + if err != nil { + return "", err + } + return zone[strings.LastIndex(zone, "/")+1:], nil +} + +// InstanceAttributes returns the list of user-defined attributes, +// assigned when initially creating a GCE VM instance. The value of an +// attribute can be obtained with InstanceAttributeValue. +func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") } + +// ProjectAttributes returns the list of user-defined attributes +// applying to the project as a whole, not just this VM. The value of +// an attribute can be obtained with ProjectAttributeValue. +func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") } + +// InstanceAttributeValue returns the value of the provided VM +// instance attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// InstanceAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func (c *Client) InstanceAttributeValue(attr string) (string, error) { + return c.Get("instance/attributes/" + attr) +} + +// ProjectAttributeValue returns the value of the provided +// project attribute. +// +// If the requested attribute is not defined, the returned error will +// be of type NotDefinedError. +// +// ProjectAttributeValue may return ("", nil) if the attribute was +// defined to be the empty string. +func (c *Client) ProjectAttributeValue(attr string) (string, error) { + return c.Get("project/attributes/" + attr) +} + +// Scopes returns the service account scopes for the given account. +// The account may be empty or the string "default" to use the instance's +// main account. +func (c *Client) Scopes(serviceAccount string) ([]string, error) { + if serviceAccount == "" { + serviceAccount = "default" + } + return c.lines("instance/service-accounts/" + serviceAccount + "/scopes") +} + +// Subscribe subscribes to a value from the metadata service. +// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". +// The suffix may contain query parameters. +// +// Subscribe calls fn with the latest metadata value indicated by the provided +// suffix. If the metadata value is deleted, fn is called with the empty string +// and ok false. Subscribe blocks until fn returns a non-nil error or the value +// is deleted. Subscribe returns the error value returned from the last call to +// fn, which may be nil when ok == false. +func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error { + const failedSubscribeSleep = time.Second * 5 + + // First check to see if the metadata value exists at all. + val, lastETag, err := c.getETag(suffix) + if err != nil { + return err + } + + if err := fn(val, true); err != nil { + return err + } + + ok := true + if strings.ContainsRune(suffix, '?') { + suffix += "&wait_for_change=true&last_etag=" + } else { + suffix += "?wait_for_change=true&last_etag=" + } + for { + val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag)) + if err != nil { + if _, deleted := err.(NotDefinedError); !deleted { + time.Sleep(failedSubscribeSleep) + continue // Retry on other errors. + } + ok = false + } + lastETag = etag + + if err := fn(val, ok); err != nil || !ok { + return err + } + } +} + +// Error contains an error response from the server. +type Error struct { + // Code is the HTTP response status code. + Code int + // Message is the server response message. + Message string +} + +func (e *Error) Error() string { + return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message) +} diff --git a/vendor/cloud.google.com/go/compute/metadata/retry.go b/vendor/cloud.google.com/go/compute/metadata/retry.go new file mode 100644 index 0000000..0f18f3c --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/retry.go @@ -0,0 +1,114 @@ +// Copyright 2021 Google LLC +// +// 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 metadata + +import ( + "context" + "io" + "math/rand" + "net/http" + "time" +) + +const ( + maxRetryAttempts = 5 +) + +var ( + syscallRetryable = func(err error) bool { return false } +) + +// defaultBackoff is basically equivalent to gax.Backoff without the need for +// the dependency. +type defaultBackoff struct { + max time.Duration + mul float64 + cur time.Duration +} + +func (b *defaultBackoff) Pause() time.Duration { + d := time.Duration(1 + rand.Int63n(int64(b.cur))) + b.cur = time.Duration(float64(b.cur) * b.mul) + if b.cur > b.max { + b.cur = b.max + } + return d +} + +// sleep is the equivalent of gax.Sleep without the need for the dependency. +func sleep(ctx context.Context, d time.Duration) error { + t := time.NewTimer(d) + select { + case <-ctx.Done(): + t.Stop() + return ctx.Err() + case <-t.C: + return nil + } +} + +func newRetryer() *metadataRetryer { + return &metadataRetryer{bo: &defaultBackoff{ + cur: 100 * time.Millisecond, + max: 30 * time.Second, + mul: 2, + }} +} + +type backoff interface { + Pause() time.Duration +} + +type metadataRetryer struct { + bo backoff + attempts int +} + +func (r *metadataRetryer) Retry(status int, err error) (time.Duration, bool) { + if status == http.StatusOK { + return 0, false + } + retryOk := shouldRetry(status, err) + if !retryOk { + return 0, false + } + if r.attempts == maxRetryAttempts { + return 0, false + } + r.attempts++ + return r.bo.Pause(), true +} + +func shouldRetry(status int, err error) bool { + if 500 <= status && status <= 599 { + return true + } + if err == io.ErrUnexpectedEOF { + return true + } + // Transient network errors should be retried. + if syscallRetryable(err) { + return true + } + if err, ok := err.(interface{ Temporary() bool }); ok { + if err.Temporary() { + return true + } + } + if err, ok := err.(interface{ Unwrap() error }); ok { + return shouldRetry(status, err.Unwrap()) + } + return false +} diff --git a/vendor/cloud.google.com/go/compute/metadata/retry_linux.go b/vendor/cloud.google.com/go/compute/metadata/retry_linux.go new file mode 100644 index 0000000..bb412f8 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/retry_linux.go @@ -0,0 +1,26 @@ +// Copyright 2021 Google LLC +// +// 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. + +//go:build linux +// +build linux + +package metadata + +import "syscall" + +func init() { + // Initialize syscallRetryable to return true on transient socket-level + // errors. These errors are specific to Linux. + syscallRetryable = func(err error) bool { return err == syscall.ECONNRESET || err == syscall.ECONNREFUSED } +} diff --git a/vendor/cloud.google.com/go/compute/metadata/tidyfix.go b/vendor/cloud.google.com/go/compute/metadata/tidyfix.go new file mode 100644 index 0000000..4cef485 --- /dev/null +++ b/vendor/cloud.google.com/go/compute/metadata/tidyfix.go @@ -0,0 +1,23 @@ +// Copyright 2022 Google LLC +// +// 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. + +// This file, and the {{.RootMod}} import, won't actually become part of +// the resultant binary. +//go:build modhack +// +build modhack + +package metadata + +// Necessary for safely adding multi-module repo. See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository +import _ "cloud.google.com/go/compute/internal" diff --git a/vendor/code.cloudfoundry.org/bytefmt/CODEOWNERS b/vendor/code.cloudfoundry.org/bytefmt/CODEOWNERS new file mode 100644 index 0000000..6a633c7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/CODEOWNERS @@ -0,0 +1 @@ +* @cloudfoundry/wg-app-runtime-platform-diego-approvers diff --git a/vendor/code.cloudfoundry.org/bytefmt/LICENSE b/vendor/code.cloudfoundry.org/bytefmt/LICENSE new file mode 100644 index 0000000..f49a4e1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/bytefmt/NOTICE b/vendor/code.cloudfoundry.org/bytefmt/NOTICE new file mode 100644 index 0000000..8625a7f --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/NOTICE @@ -0,0 +1,20 @@ +Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved. + +This project contains software that is Copyright (c) 2013-2015 Pivotal Software, Inc. + +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. + +This project may include a number of subcomponents with separate +copyright notices and license terms. Your use of these subcomponents +is subject to the terms and conditions of each subcomponent's license, +as noted in the LICENSE file. diff --git a/vendor/code.cloudfoundry.org/bytefmt/README.md b/vendor/code.cloudfoundry.org/bytefmt/README.md new file mode 100644 index 0000000..778fd38 --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/README.md @@ -0,0 +1,19 @@ +bytefmt +======= + +**Note**: This repository should be imported as `code.cloudfoundry.org/bytefmt`. + +Human-readable byte formatter. + +Example: + +```go +bytefmt.ByteSize(100.5*bytefmt.MEGABYTE) // returns "100.5M" +bytefmt.ByteSize(uint64(1024)) // returns "1K" +``` + +For documentation, please see http://godoc.org/code.cloudfoundry.org/bytefmt + +## Reporting issues and requesting features + +Please report all issues and feature requests in [cloudfoundry/diego-release](https://github.com/cloudfoundry/diego-release/issues). diff --git a/vendor/code.cloudfoundry.org/bytefmt/bytes.go b/vendor/code.cloudfoundry.org/bytefmt/bytes.go new file mode 100644 index 0000000..7395604 --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/bytes.go @@ -0,0 +1,121 @@ +// Package bytefmt contains helper methods and constants for converting to and from a human-readable byte format. +// +// bytefmt.ByteSize(100.5*bytefmt.MEGABYTE) // "100.5M" +// bytefmt.ByteSize(uint64(1024)) // "1K" +// +package bytefmt + +import ( + "errors" + "strconv" + "strings" + "unicode" +) + +const ( + BYTE = 1 << (10 * iota) + KILOBYTE + MEGABYTE + GIGABYTE + TERABYTE + PETABYTE + EXABYTE +) + +var invalidByteQuantityError = errors.New("byte quantity must be a positive integer with a unit of measurement like M, MB, MiB, G, GiB, or GB") + +// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available: +// E: Exabyte +// P: Petabyte +// T: Terabyte +// G: Gigabyte +// M: Megabyte +// K: Kilobyte +// B: Byte +// The unit that results in the smallest number greater than or equal to 1 is always chosen. +func ByteSize(bytes uint64) string { + unit := "" + value := float64(bytes) + + switch { + case bytes >= EXABYTE: + unit = "E" + value = value / EXABYTE + case bytes >= PETABYTE: + unit = "P" + value = value / PETABYTE + case bytes >= TERABYTE: + unit = "T" + value = value / TERABYTE + case bytes >= GIGABYTE: + unit = "G" + value = value / GIGABYTE + case bytes >= MEGABYTE: + unit = "M" + value = value / MEGABYTE + case bytes >= KILOBYTE: + unit = "K" + value = value / KILOBYTE + case bytes >= BYTE: + unit = "B" + case bytes == 0: + return "0B" + } + + result := strconv.FormatFloat(value, 'f', 1, 64) + result = strings.TrimSuffix(result, ".0") + return result + unit +} + +// ToMegabytes parses a string formatted by ByteSize as megabytes. +func ToMegabytes(s string) (uint64, error) { + bytes, err := ToBytes(s) + if err != nil { + return 0, err + } + + return bytes / MEGABYTE, nil +} + +// ToBytes parses a string formatted by ByteSize as bytes. Note binary-prefixed and SI prefixed units both mean a base-2 units +// KB = K = KiB = 1024 +// MB = M = MiB = 1024 * K +// GB = G = GiB = 1024 * M +// TB = T = TiB = 1024 * G +// PB = P = PiB = 1024 * T +// EB = E = EiB = 1024 * P +func ToBytes(s string) (uint64, error) { + s = strings.TrimSpace(s) + s = strings.ToUpper(s) + + i := strings.IndexFunc(s, unicode.IsLetter) + + if i == -1 { + return 0, invalidByteQuantityError + } + + bytesString, multiple := s[:i], s[i:] + bytes, err := strconv.ParseFloat(bytesString, 64) + if err != nil || bytes < 0 { + return 0, invalidByteQuantityError + } + + switch multiple { + case "E", "EB", "EIB": + return uint64(bytes * EXABYTE), nil + case "P", "PB", "PIB": + return uint64(bytes * PETABYTE), nil + case "T", "TB", "TIB": + return uint64(bytes * TERABYTE), nil + case "G", "GB", "GIB": + return uint64(bytes * GIGABYTE), nil + case "M", "MB", "MIB": + return uint64(bytes * MEGABYTE), nil + case "K", "KB", "KIB": + return uint64(bytes * KILOBYTE), nil + case "B": + return uint64(bytes), nil + default: + return 0, invalidByteQuantityError + } +} diff --git a/vendor/code.cloudfoundry.org/bytefmt/package.go b/vendor/code.cloudfoundry.org/bytefmt/package.go new file mode 100644 index 0000000..0342930 --- /dev/null +++ b/vendor/code.cloudfoundry.org/bytefmt/package.go @@ -0,0 +1 @@ +package bytefmt // import "code.cloudfoundry.org/bytefmt" diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/LICENSE b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/NOTICE b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/NOTICE new file mode 100644 index 0000000..56399e4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/NOTICE @@ -0,0 +1,9 @@ +Copyright (c) 2016-Present CloudFoundry.org Foundation, Inc. All Rights Reserved. + +This project is licensed to you under the Apache License, Version 2.0 (the "License"). + +You may not use this project except in compliance with the License. + +This project may include a number of subcomponents with separate copyright notices +and license terms. Your use of these subcomponents is subject to the terms and +conditions of the subcomponent's license, as noted in the LICENSE file. diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/client.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/client.go new file mode 100644 index 0000000..3a8213b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/client.go @@ -0,0 +1,136 @@ +// Package cfnetv1 represents a CF Networking V1 client. +// +// These sets of packages are still under development/pre-pre-pre...alpha. Use +// at your own risk! Functionality and design may change without warning. +// +// For more information on the CF Networking API see +// https://github.com/cloudfoundry-incubator/cf-networking-release/blob/develop/docs/API.md +// +// Method Naming Conventions +// +// The client takes a '' +// approach to method names. If the and +// are similar, they do not need to be repeated. If a GUID is required for the +// , the pluralization is removed from said endpoint in the +// method name. +// +// For Example: +// Method Name: GetApplication +// Endpoint: /v2/applications/:guid +// Action Name: Get +// Top Level Endpoint: applications +// Return Value: Application +// +// Method Name: GetServiceInstances +// Endpoint: /v2/service_instances +// Action Name: Get +// Top Level Endpoint: service_instances +// Return Value: []ServiceInstance +// +// Method Name: GetSpaceServiceInstances +// Endpoint: /v2/spaces/:guid/service_instances +// Action Name: Get +// Top Level Endpoint: spaces +// Return Value: []ServiceInstance +// +// Use the following table to determine which HTTP Command equates to which +// Action Name: +// HTTP Command -> Action Name +// POST -> Create +// GET -> Get +// PUT -> Update +// DELETE -> Delete +// +// Method Locations +// +// Methods exist in the same file as their return type, regardless of which +// endpoint they use. +// +// Error Handling +// +// All error handling that requires parsing the error_code/code returned back +// from the Cloud Controller should be placed in the errorWrapper. Everything +// else can be handled in the individual operations. All parsed cloud +// controller errors should exist in errors.go, all generic HTTP errors should +// exist in the cloudcontroller's errors.go. Errors related to the individaul +// operation should exist at the top of that operation's file. +// +// No inline-relations-depth And summary Endpoints +// +// This package will not use ever use 'inline-relations-depth' or the +// '/summary' endpoints for any operations. These requests can be extremely +// taxing on the Cloud Controller and are avoided at all costs. Additionally, +// the objects returned back from these requests can become extremely +// inconsistant across versions and are problematic to deal with in general. +package cfnetv1 + +import ( + "fmt" + "runtime" + "time" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/internal" + + "github.com/tedsuo/rata" +) + +// Client is a client that can be used to talk to a CF Networking API. +type Client struct { + connection cfnetworking.Connection + router *rata.RequestGenerator + url string + userAgent string +} + +// Config allows the Client to be configured +type Config struct { + // AppName is the name of the application/process using the client. + AppName string + + // AppVersion is the version of the application/process using the client. + AppVersion string + + // DialTimeout is the DNS timeout used to make all requests to the Cloud + // Controller. + DialTimeout time.Duration + + // SkipSSLValidation controls whether a client verifies the server's + // certificate chain and host name. If SkipSSLValidation is true, TLS accepts + // any certificate presented by the server and any host name in that + // certificate for *all* client requests going forward. + // + // In this mode, TLS is susceptible to man-in-the-middle attacks. This should + // be used only for testing. + SkipSSLValidation bool + + // URL is a fully qualified URL to the CF Networking API. + URL string + + // Wrappers that apply to the client connection. + Wrappers []ConnectionWrapper +} + +// NewClient returns a new CF Networking client. +func NewClient(config Config) *Client { + userAgent := fmt.Sprintf("%s/%s (%s; %s %s)", config.AppName, config.AppVersion, runtime.Version(), runtime.GOARCH, runtime.GOOS) + + connection := cfnetworking.NewConnection(cfnetworking.Config{ + DialTimeout: config.DialTimeout, + SkipSSLValidation: config.SkipSSLValidation, + }) + + wrappedConnection := cfnetworking.NewErrorWrapper().Wrap(connection) + for _, wrapper := range config.Wrappers { + wrappedConnection = wrapper.Wrap(wrappedConnection) + } + + client := &Client{ + connection: wrappedConnection, + router: rata.NewRequestGenerator(config.URL, internal.Routes), + url: config.URL, + userAgent: userAgent, + } + + return client +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/connection_wrapper.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/connection_wrapper.go new file mode 100644 index 0000000..0dd91f2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/connection_wrapper.go @@ -0,0 +1,17 @@ +package cfnetv1 + +import "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" + +//go:generate counterfeiter . ConnectionWrapper + +// ConnectionWrapper can wrap a given connection allowing the wrapper to modify +// all requests going in and out of the given connection. +type ConnectionWrapper interface { + cfnetworking.Connection + Wrap(innerconnection cfnetworking.Connection) cfnetworking.Connection +} + +// WrapConnection wraps the current Client connection in the wrapper. +func (client *Client) WrapConnection(wrapper ConnectionWrapper) { + client.connection = wrapper.Wrap(client.connection) +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/internal/routes.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/internal/routes.go new file mode 100644 index 0000000..69cf937 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/internal/routes.go @@ -0,0 +1,21 @@ +package internal + +import ( + "net/http" + + "github.com/tedsuo/rata" +) + +const ( + CreatePolicies = "PostPolicies" + DeletePolicies = "DeletePolicies" + ListPolicies = "ListPolicies" +) + +// Routes is a list of routes used by the rata library to construct request +// URLs. +var Routes = rata.Routes{ + {Path: "/policies", Method: http.MethodPost, Name: CreatePolicies}, + {Path: "/policies/delete", Method: http.MethodPost, Name: DeletePolicies}, + {Path: "/policies", Method: http.MethodGet, Name: ListPolicies}, +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/policy.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/policy.go new file mode 100644 index 0000000..e1ae1b4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/policy.go @@ -0,0 +1,105 @@ +package cfnetv1 + +import ( + "bytes" + "encoding/json" + + "strings" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/internal" +) + +type PolicyProtocol string + +const ( + PolicyProtocolTCP PolicyProtocol = "tcp" + PolicyProtocolUDP PolicyProtocol = "udp" +) + +type PolicyList struct { + TotalPolicies int `json:"total_policies,omitempty"` + Policies []Policy `json:"policies"` +} + +type Policy struct { + Source PolicySource `json:"source"` + Destination PolicyDestination `json:"destination"` +} + +type PolicySource struct { + ID string `json:"id"` +} + +type PolicyDestination struct { + ID string `json:"id"` + Protocol PolicyProtocol `json:"protocol"` + Ports Ports `json:"ports"` +} + +// CreatePolicies will create the network policy with the given parameters. +func (client Client) CreatePolicies(policies []Policy) error { + rawJSON, err := json.Marshal(PolicyList{Policies: policies}) + if err != nil { + return err + } + + request, err := client.newHTTPRequest(requestOptions{ + RequestName: internal.CreatePolicies, + Body: bytes.NewReader(rawJSON), + }) + if err != nil { + return err + } + + return client.connection.Make(request, &cfnetworking.Response{}) +} + +// ListPolicies will list the policies with the app guids in either the source or destination. +func (client Client) ListPolicies(appGUIDs ...string) ([]Policy, error) { + var request *cfnetworking.Request + var err error + if len(appGUIDs) == 0 { + request, err = client.newHTTPRequest(requestOptions{ + RequestName: internal.ListPolicies, + }) + } else { + request, err = client.newHTTPRequest(requestOptions{ + RequestName: internal.ListPolicies, + Query: map[string][]string{ + "id": {strings.Join(appGUIDs, ",")}, + }, + }) + } + if err != nil { + return []Policy{}, err + } + + policies := PolicyList{} + response := &cfnetworking.Response{} + + err = client.connection.Make(request, response) + if err != nil { + return []Policy{}, err + } + + err = json.Unmarshal(response.RawResponse, &policies) + if err != nil { + return []Policy{}, err + } + + return policies.Policies, nil +} + +// RemovePolicies will remove the network policy with the given parameters. +func (client Client) RemovePolicies(policies []Policy) error { + rawJSON, err := json.Marshal(PolicyList{Policies: policies}) + if err != nil { + return err + } + request, err := client.newHTTPRequest(requestOptions{ + RequestName: internal.DeletePolicies, + Body: bytes.NewReader(rawJSON), + }) + return client.connection.Make(request, &cfnetworking.Response{}) +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/ports.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/ports.go new file mode 100644 index 0000000..d684f64 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/ports.go @@ -0,0 +1,6 @@ +package cfnetv1 + +type Ports struct { + Start int `json:"start"` + End int `json:"end"` +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/request.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/request.go new file mode 100644 index 0000000..687f5e0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1/request.go @@ -0,0 +1,70 @@ +package cfnetv1 + +import ( + "fmt" + "io" + "net/http" + "net/url" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" +) + +// Params represents URI parameters for a request. +type Params map[string]string + +// requestOptions contains all the options to create an HTTP request. +type requestOptions struct { + // URIParams are the list URI route parameters + URIParams Params + + // Query is a list of HTTP query parameters + Query url.Values + + // RequestName is the name of the request (see routes) + RequestName string + + // URI is the URI of the request. + URI string + // Method is the HTTP method of the request. + Method string + + // Body is the request body + Body io.ReadSeeker +} + +// newHTTPRequest returns a constructed HTTP.Request with some defaults. +// Defaults are applied when Request fields are not filled in. +func (client Client) newHTTPRequest(passedRequest requestOptions) (*cfnetworking.Request, error) { + var request *http.Request + var err error + if passedRequest.URI != "" { + request, err = http.NewRequest( + passedRequest.Method, + fmt.Sprintf("%s%s", client.url, passedRequest.URI), + passedRequest.Body, + ) + } else { + request, err = client.router.CreateRequest( + passedRequest.RequestName, + map[string]string(passedRequest.URIParams), + passedRequest.Body, + ) + if err == nil { + request.URL.RawQuery = passedRequest.Query.Encode() + } + } + if err != nil { + return nil, err + } + + request.Header = http.Header{} + request.Header.Set("Accept", "application/json") + request.Header.Set("User-Agent", client.userAgent) + + if passedRequest.Body != nil { + request.Header.Set("Content-Type", "application/json") + } + + // Make sure the body is the same as the one in the request + return cfnetworking.NewRequest(request, passedRequest.Body), nil +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/connection.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/connection.go new file mode 100644 index 0000000..bcc6548 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/connection.go @@ -0,0 +1,8 @@ +package cfnetworking + +//go:generate counterfeiter . Connection + +// Connection creates and executes http requests +type Connection interface { + Make(request *Request, passedResponse *Response) error +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/errors.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/errors.go new file mode 100644 index 0000000..d8a332f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/errors.go @@ -0,0 +1,64 @@ +package cfnetworking + +import ( + "encoding/json" + "net/http" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror" +) + +// errorWrapper is the wrapper that converts responses with 4xx and 5xx status +// codes to an error. +type errorWrapper struct { + connection Connection +} + +func NewErrorWrapper() *errorWrapper { + return new(errorWrapper) +} + +// Wrap wraps a Cloud Controller connection in this error handling wrapper. +func (e *errorWrapper) Wrap(innerconnection Connection) Connection { + e.connection = innerconnection + return e +} + +// Make converts RawHTTPStatusError, which represents responses with 4xx and +// 5xx status codes, to specific errors. +func (e *errorWrapper) Make(request *Request, passedResponse *Response) error { + err := e.connection.Make(request, passedResponse) + + if rawHTTPStatusErr, ok := err.(networkerror.RawHTTPStatusError); ok { + return convert(rawHTTPStatusErr) + } + return err +} + +func convert(rawHTTPStatusErr networkerror.RawHTTPStatusError) error { + // Try to unmarshal the raw error into a CC error. If unmarshaling fails, + // return the raw error. + var errorResponse networkerror.ErrorResponse + err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) + if err != nil { + return rawHTTPStatusErr + } + + switch rawHTTPStatusErr.StatusCode { + case http.StatusBadRequest: // 400 + return networkerror.BadRequestError(errorResponse) + case http.StatusUnauthorized: // 401 + return networkerror.UnauthorizedError(errorResponse) + case http.StatusForbidden: // 403 + return networkerror.ForbiddenError(errorResponse) + case http.StatusNotAcceptable: // 406 + return networkerror.NotAcceptableError(errorResponse) + case http.StatusConflict: // 409 + return networkerror.ConflictError(errorResponse) + default: + return networkerror.UnexpectedResponseError{ + ErrorResponse: errorResponse, + RequestIDs: rawHTTPStatusErr.RequestIDs, + ResponseCode: rawHTTPStatusErr.StatusCode, + } + } +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/bad_request_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/bad_request_error.go new file mode 100644 index 0000000..16db7bd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/bad_request_error.go @@ -0,0 +1,9 @@ +package networkerror + +type BadRequestError struct { + Message string `json:"error"` +} + +func (e BadRequestError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/conflict_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/conflict_error.go new file mode 100644 index 0000000..807ac31 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/conflict_error.go @@ -0,0 +1,9 @@ +package networkerror + +type ConflictError struct { + Message string `json:"error"` +} + +func (e ConflictError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/error_response.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/error_response.go new file mode 100644 index 0000000..a3ff465 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/error_response.go @@ -0,0 +1,9 @@ +package networkerror + +type ErrorResponse struct { + Message string `json:"error"` +} + +func (e ErrorResponse) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/forbidden_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/forbidden_error.go new file mode 100644 index 0000000..d780a34 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/forbidden_error.go @@ -0,0 +1,9 @@ +package networkerror + +type ForbiddenError struct { + Message string `json:"error"` +} + +func (e ForbiddenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/invalid_auth_token_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/invalid_auth_token_error.go new file mode 100644 index 0000000..3e3178c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/invalid_auth_token_error.go @@ -0,0 +1,11 @@ +package networkerror + +// InvalidAuthTokenError is returned when the client has an invalid +// authorization header. +type InvalidAuthTokenError struct { + Message string +} + +func (e InvalidAuthTokenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_acceptable_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_acceptable_error.go new file mode 100644 index 0000000..002a73d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_acceptable_error.go @@ -0,0 +1,9 @@ +package networkerror + +type NotAcceptableError struct { + Message string `json:"error"` +} + +func (e NotAcceptableError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_found_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_found_error.go new file mode 100644 index 0000000..a69d303 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/not_found_error.go @@ -0,0 +1,10 @@ +package networkerror + +// NotFoundError wraps a generic 404 error. +type NotFoundError struct { + Message string +} + +func (e NotFoundError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/raw_http_status_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/raw_http_status_error.go new file mode 100644 index 0000000..fea62dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/raw_http_status_error.go @@ -0,0 +1,14 @@ +package networkerror + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + StatusCode int + RawResponse []byte + RequestIDs []string +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("Error Code: %d\nRaw Response: %s", r.StatusCode, r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/request_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/request_error.go new file mode 100644 index 0000000..7b0ff48 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/request_error.go @@ -0,0 +1,11 @@ +package networkerror + +// RequestError represents a generic error encountered while performing the +// HTTP request. This generic error occurs before a HTTP response is obtained. +type RequestError struct { + Err error +} + +func (e RequestError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/ssl_validation_hostname_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/ssl_validation_hostname_error.go new file mode 100644 index 0000000..a583abc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/ssl_validation_hostname_error.go @@ -0,0 +1,13 @@ +package networkerror + +import "fmt" + +// SSLValidationHostnameError replaces x509.HostnameError when the server has +// SSL certificate that does not match the hostname. +type SSLValidationHostnameError struct { + Message string +} + +func (e SSLValidationHostnameError) Error() string { + return fmt.Sprintf("Hostname does not match SSL Certificate (%s)", e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unauthorized_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unauthorized_error.go new file mode 100644 index 0000000..513c6de --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unauthorized_error.go @@ -0,0 +1,9 @@ +package networkerror + +type UnauthorizedError struct { + Message string `json:"error"` +} + +func (e UnauthorizedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unexpected_response_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unexpected_response_error.go new file mode 100644 index 0000000..e337d7a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unexpected_response_error.go @@ -0,0 +1,20 @@ +package networkerror + +import "fmt" + +// UnexpectedResponseError is returned when the client gets an error that has +// not been accounted for. +type UnexpectedResponseError struct { + ErrorResponse + + RequestIDs []string + ResponseCode int +} + +func (e UnexpectedResponseError) Error() string { + message := fmt.Sprintf("Unexpected Response\nResponse code: %d", e.ResponseCode) + for _, id := range e.RequestIDs { + message = fmt.Sprintf("%s\nRequest ID: %s", message, id) + } + return fmt.Sprintf("%s\nDescription: %s", message, e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unverified_server_error.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unverified_server_error.go new file mode 100644 index 0000000..59a8773 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror/unverified_server_error.go @@ -0,0 +1,11 @@ +package networkerror + +// UnverifiedServerError replaces x509.UnknownAuthorityError when the server +// has SSL but the client is unable to verify it's certificate +type UnverifiedServerError struct { + URL string +} + +func (UnverifiedServerError) Error() string { + return "x509: certificate signed by unknown authority" +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networking_connection.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networking_connection.go new file mode 100644 index 0000000..a18ec65 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networking_connection.go @@ -0,0 +1,126 @@ +package cfnetworking + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "encoding/json" + "io/ioutil" + "net" + "net/http" + "net/url" + "time" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror" +) + +// NetworkingConnection represents a connection to the Cloud Controller +// server. +type NetworkingConnection struct { + HTTPClient *http.Client + UserAgent string +} + +// Config is for configuring a NetworkingConnection. +type Config struct { + DialTimeout time.Duration + SkipSSLValidation bool +} + +// NewConnection returns a new NetworkingConnection with provided +// configuration. +func NewConnection(config Config) *NetworkingConnection { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: config.SkipSSLValidation, + }, + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + KeepAlive: 30 * time.Second, + Timeout: config.DialTimeout, + }).DialContext, + } + + return &NetworkingConnection{ + HTTPClient: &http.Client{Transport: tr}, + } +} + +// Make performs the request and parses the response. +func (connection *NetworkingConnection) Make(request *Request, passedResponse *Response) error { + // In case this function is called from a retry, passedResponse may already + // be populated with a previous response. We reset in case there's an HTTP + // error and we don't repopulate it in populateResponse. + passedResponse.reset() + + response, err := connection.HTTPClient.Do(request.Request) + if err != nil { + return connection.processRequestErrors(request.Request, err) + } + + return connection.populateResponse(response, passedResponse) +} + +func (*NetworkingConnection) processRequestErrors(request *http.Request, err error) error { + switch e := err.(type) { + case *url.Error: + switch urlErr := e.Err.(type) { + case x509.UnknownAuthorityError: + return networkerror.UnverifiedServerError{ + URL: request.URL.String(), + } + case x509.HostnameError: + return networkerror.SSLValidationHostnameError{ + Message: urlErr.Error(), + } + default: + return networkerror.RequestError{Err: e} + } + default: + return err + } +} + +func (connection *NetworkingConnection) populateResponse(response *http.Response, passedResponse *Response) error { + passedResponse.HTTPResponse = response + + if resourceLocationURL := response.Header.Get("Location"); resourceLocationURL != "" { + passedResponse.ResourceLocationURL = resourceLocationURL + } + + rawBytes, err := ioutil.ReadAll(response.Body) + defer response.Body.Close() + if err != nil { + return err + } + + passedResponse.RawResponse = rawBytes + + err = connection.handleStatusCodes(response, passedResponse) + if err != nil { + return err + } + + if passedResponse.Result != nil { + decoder := json.NewDecoder(bytes.NewBuffer(passedResponse.RawResponse)) + decoder.UseNumber() + err = decoder.Decode(passedResponse.Result) + if err != nil { + return err + } + } + + return nil +} + +func (*NetworkingConnection) handleStatusCodes(response *http.Response, passedResponse *Response) error { + if response.StatusCode >= 400 { + return networkerror.RawHTTPStatusError{ + StatusCode: response.StatusCode, + RawResponse: passedResponse.RawResponse, + RequestIDs: response.Header["X-Vcap-Request-Id"], + } + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/request.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/request.go new file mode 100644 index 0000000..84f42ed --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/request.go @@ -0,0 +1,35 @@ +package cfnetworking + +import ( + "io" + "net/http" +) + +//go:generate counterfeiter . ReadSeeker + +type ReadSeeker interface { + io.ReadSeeker +} + +// Request represents the request of the cloud controller. +type Request struct { + *http.Request + + body io.ReadSeeker +} + +func (r *Request) ResetBody() error { + if r.body == nil { + return nil + } + + _, err := r.body.Seek(0, 0) + return err +} + +func NewRequest(request *http.Request, body io.ReadSeeker) *Request { + return &Request{ + Request: request, + body: body, + } +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/response.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/response.go new file mode 100644 index 0000000..8d4de87 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/response.go @@ -0,0 +1,29 @@ +package cfnetworking + +import "net/http" + +// Response represents a Cloud Controller response object. +type Response struct { + // Result represents the resource entity type that is expected in the + // response JSON. + Result interface{} + + // RawResponse represents the response body. + RawResponse []byte + + // Warnings represents warnings parsed from the custom warnings headers of a + // Cloud Controller response. + Warnings []string + + // HTTPResponse represents the HTTP response object. + HTTPResponse *http.Response + + // ResourceLocationURL represents the Location header value + ResourceLocationURL string +} + +func (r *Response) reset() { + r.RawResponse = []byte{} + r.Warnings = []string{} + r.HTTPResponse = nil +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/request_logger.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/request_logger.go new file mode 100644 index 0000000..1336fc8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/request_logger.go @@ -0,0 +1,156 @@ +package wrapper + +import ( + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" + "time" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" +) + +//go:generate counterfeiter . RequestLoggerOutput + +// RequestLoggerOutput is the interface for displaying logs +type RequestLoggerOutput interface { + DisplayHeader(name string, value string) error + DisplayHost(name string) error + DisplayJSONBody(body []byte) error + DisplayMessage(msg string) error + DisplayRequestHeader(method string, uri string, httpProtocol string) error + DisplayResponseHeader(httpProtocol string, status string) error + DisplayType(name string, requestDate time.Time) error + HandleInternalError(err error) + Start() error + Stop() error +} + +// RequestLogger is the wrapper that logs requests to and responses from the +// Cloud Controller server +type RequestLogger struct { + connection cfnetworking.Connection + output RequestLoggerOutput +} + +// NewRequestLogger returns a pointer to a RequestLogger wrapper +func NewRequestLogger(output RequestLoggerOutput) *RequestLogger { + return &RequestLogger{ + output: output, + } +} + +// Wrap sets the connection on the RequestLogger and returns itself +func (logger *RequestLogger) Wrap(innerconnection cfnetworking.Connection) cfnetworking.Connection { + logger.connection = innerconnection + return logger +} + +// Make records the request and the response to UI +func (logger *RequestLogger) Make(request *cfnetworking.Request, passedResponse *cfnetworking.Response) error { + err := logger.displayRequest(request) + if err != nil { + logger.output.HandleInternalError(err) + } + + err = logger.connection.Make(request, passedResponse) + + if passedResponse.HTTPResponse != nil { + displayErr := logger.displayResponse(passedResponse) + if displayErr != nil { + logger.output.HandleInternalError(displayErr) + } + } + + return err +} + +func (logger *RequestLogger) displayRequest(request *cfnetworking.Request) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("REQUEST", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayRequestHeader(request.Method, request.URL.RequestURI(), request.Proto) + if err != nil { + return err + } + err = logger.output.DisplayHost(request.URL.Host) + if err != nil { + return err + } + err = logger.displaySortedHeaders(request.Header) + if err != nil { + return err + } + + contentType := request.Header.Get("Content-Type") + if request.Body != nil { + if strings.Contains(contentType, "json") { + rawRequestBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return err + } + + defer request.ResetBody() + + return logger.output.DisplayJSONBody(rawRequestBody) + } else if contentType != "" { + return logger.output.DisplayMessage(fmt.Sprintf("[%s Content Hidden]", strings.Split(contentType, ";")[0])) + } + } + return nil +} + +func (logger *RequestLogger) displayResponse(passedResponse *cfnetworking.Response) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("RESPONSE", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayResponseHeader(passedResponse.HTTPResponse.Proto, passedResponse.HTTPResponse.Status) + if err != nil { + return err + } + err = logger.displaySortedHeaders(passedResponse.HTTPResponse.Header) + if err != nil { + return err + } + return logger.output.DisplayJSONBody(passedResponse.RawResponse) +} + +func (logger *RequestLogger) displaySortedHeaders(headers http.Header) error { + keys := []string{} + for key, _ := range headers { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + for _, value := range headers[key] { + err := logger.output.DisplayHeader(key, redactHeaders(key, value)) + if err != nil { + return err + } + } + } + return nil +} + +func redactHeaders(key string, value string) string { + if key == "Authorization" { + return "[PRIVATE DATA HIDDEN]" + } + return value +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/retry_request.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/retry_request.go new file mode 100644 index 0000000..8ccf3b9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/retry_request.go @@ -0,0 +1,54 @@ +package wrapper + +import ( + "net/http" + + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" +) + +// RetryRequest is a wrapper that retries failed requests if they contain a 5XX +// status code. +type RetryRequest struct { + maxRetries int + connection cfnetworking.Connection +} + +// NewRetryRequest returns a pointer to a RetryRequest wrapper. +func NewRetryRequest(maxRetries int) *RetryRequest { + return &RetryRequest{ + maxRetries: maxRetries, + } +} + +// Wrap sets the connection in the RetryRequest and returns itself. +func (retry *RetryRequest) Wrap(innerconnection cfnetworking.Connection) cfnetworking.Connection { + retry.connection = innerconnection + return retry +} + +// Make retries the request if it comes back with certain status codes. +func (retry *RetryRequest) Make(request *cfnetworking.Request, passedResponse *cfnetworking.Response) error { + var err error + + for i := 0; i < retry.maxRetries+1; i += 1 { + err = retry.connection.Make(request, passedResponse) + if err == nil { + return nil + } + + if passedResponse.HTTPResponse != nil && + (passedResponse.HTTPResponse.StatusCode == http.StatusBadGateway || + passedResponse.HTTPResponse.StatusCode == http.StatusServiceUnavailable || + passedResponse.HTTPResponse.StatusCode == http.StatusGatewayTimeout || + (passedResponse.HTTPResponse.StatusCode >= 400 && passedResponse.HTTPResponse.StatusCode < 500)) { + break + } + + // Reset the request body prior to the next retry + resetErr := request.ResetBody() + if resetErr != nil { + return resetErr + } + } + return err +} diff --git a/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/uaa_authentication.go b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/uaa_authentication.go new file mode 100644 index 0000000..ee4cf72 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/wrapper/uaa_authentication.go @@ -0,0 +1,81 @@ +package wrapper + +import ( + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking" + "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/networkerror" + "code.cloudfoundry.org/cli/api/uaa" +) + +//go:generate counterfeiter . UAAClient + +// UAAClient is the interface for getting a valid access token +type UAAClient interface { + RefreshAccessToken(refreshToken string) (uaa.RefreshedTokens, error) +} + +//go:generate counterfeiter . TokenCache + +// TokenCache is where the UAA token information is stored. +type TokenCache interface { + AccessToken() string + RefreshToken() string + SetAccessToken(token string) + SetRefreshToken(token string) +} + +// UAAAuthentication wraps connections and adds authentication headers to all +// requests +type UAAAuthentication struct { + connection cfnetworking.Connection + client UAAClient + cache TokenCache +} + +// NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with +// the client and a token cache. +func NewUAAAuthentication(client UAAClient, cache TokenCache) *UAAAuthentication { + return &UAAAuthentication{ + client: client, + cache: cache, + } +} + +// Wrap sets the connection on the UAAAuthentication and returns itself +func (t *UAAAuthentication) Wrap(innerconnection cfnetworking.Connection) cfnetworking.Connection { + t.connection = innerconnection + return t +} + +// SetClient sets the UAA client that the wrapper will use. +func (t *UAAAuthentication) SetClient(client UAAClient) { + t.client = client +} + +// Make adds authentication headers to the passed in request and then calls the +// wrapped connection's Make. If the client is not set on the wrapper, it will +// not add any header or handle any authentication errors. +func (t *UAAAuthentication) Make(request *cfnetworking.Request, passedResponse *cfnetworking.Response) error { + request.Header.Set("Authorization", t.cache.AccessToken()) + + requestErr := t.connection.Make(request, passedResponse) + if _, ok := requestErr.(networkerror.InvalidAuthTokenError); ok { + tokens, err := t.client.RefreshAccessToken(t.cache.RefreshToken()) + if err != nil { + return err + } + + t.cache.SetAccessToken(tokens.AuthorizationToken()) + t.cache.SetRefreshToken(tokens.RefreshToken) + + if request.Body != nil { + err = request.ResetBody() + if err != nil { + return err + } + } + request.Header.Set("Authorization", t.cache.AccessToken()) + requestErr = t.connection.Make(request, passedResponse) + } + + return requestErr +} diff --git a/vendor/code.cloudfoundry.org/cli/LICENSE b/vendor/code.cloudfoundry.org/cli/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/vendor/code.cloudfoundry.org/cli/NOTICE b/vendor/code.cloudfoundry.org/cli/NOTICE new file mode 100644 index 0000000..4e6a3b3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/NOTICE @@ -0,0 +1,11 @@ +Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved. + +This project contains software that is Copyright (c) 2013-2015 Pivotal Software, Inc. + +This project is licensed to you under the Apache License, Version 2.0 (the "License"). + +You may not use this project except in compliance with the License. + +This project may include a number of subcomponents with separate copyright notices +and license terms. Your use of these subcomponents is subject to the terms and +conditions of the subcomponent's license, as noted in the LICENSE file. diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/add_plugin_repository_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/add_plugin_repository_error.go new file mode 100644 index 0000000..92b986b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/add_plugin_repository_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +type AddPluginRepositoryError struct { + Name string + URL string + Message string +} + +func (e AddPluginRepositoryError) Error() string { + return fmt.Sprintf("Could not add repository '%s' from %s: %s", e.Name, e.URL, e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/all_instances_crashed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/all_instances_crashed_error.go new file mode 100644 index 0000000..630a794 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/all_instances_crashed_error.go @@ -0,0 +1,8 @@ +package actionerror + +type AllInstancesCrashedError struct { +} + +func (e AllInstancesCrashedError) Error() string { + return "All instances crashed" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/ambiguous_user_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ambiguous_user_error.go new file mode 100644 index 0000000..f6e5817 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ambiguous_user_error.go @@ -0,0 +1,22 @@ +package actionerror + +import ( + "fmt" + "sort" + "strings" +) + +type AmbiguousUserError struct { + Username string + Origins []string +} + +func (e AmbiguousUserError) Error() string { + sort.Strings(e.Origins) + origins := strings.Join(e.Origins, ", ") + return fmt.Sprintf( + "Ambiguous user. User with username '%s' exists in the following origins: %s. Specify an origin to disambiguate.", + e.Username, + origins, + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/app_not_found_in_manifest_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/app_not_found_in_manifest_error.go new file mode 100644 index 0000000..0c20cb0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/app_not_found_in_manifest_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type AppNotFoundInManifestError struct { + Name string +} + +func (e AppNotFoundInManifestError) Error() string { + return fmt.Sprintf("specfied app: %s not found in manifest", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_manifest_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_manifest_error.go new file mode 100644 index 0000000..6ad8c76 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_manifest_error.go @@ -0,0 +1,10 @@ +package actionerror + +// ApplicationManifestError when applying the manifest fails +type ApplicationManifestError struct { + Message string +} + +func (a ApplicationManifestError) Error() string { + return a.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_found_error.go new file mode 100644 index 0000000..d298db8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_found_error.go @@ -0,0 +1,18 @@ +package actionerror + +import "fmt" + +// ApplicationNotFoundError is returned when a requested application is not +// found. +type ApplicationNotFoundError struct { + GUID string + Name string +} + +func (e ApplicationNotFoundError) Error() string { + if e.GUID != "" { + return fmt.Sprintf("Application with GUID '%s' not found.", e.GUID) + } + + return fmt.Sprintf("Application '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_started_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_started_error.go new file mode 100644 index 0000000..611eac3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/application_not_started_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +// ApplicationNotStartedError is returned when trying to ssh to an application that is not STARTED. +type ApplicationNotStartedError struct { + Name string +} + +func (e ApplicationNotStartedError) Error() string { + return fmt.Sprintf("Application '%s' is not in the STARTED state", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/applications_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/applications_not_found_error.go new file mode 100644 index 0000000..e34fb68 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/applications_not_found_error.go @@ -0,0 +1,10 @@ +package actionerror + +// ApplicationsNotFoundError is returned when requested applications are not +// found. +type ApplicationsNotFoundError struct { +} + +func (e ApplicationsNotFoundError) Error() string { + return "One or more applications were not found." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/assign_droplet_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/assign_droplet_error.go new file mode 100644 index 0000000..4b2a4c1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/assign_droplet_error.go @@ -0,0 +1,11 @@ +package actionerror + +// AssignDropletError is returned when assigning the current droplet of an app +// fails +type AssignDropletError struct { + Message string +} + +func (a AssignDropletError) Error() string { + return a.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_already_exists_for_stack_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_already_exists_for_stack_error.go new file mode 100644 index 0000000..dc26a96 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_already_exists_for_stack_error.go @@ -0,0 +1,9 @@ +package actionerror + +type BuildpackAlreadyExistsForStackError struct { + Message string +} + +func (e BuildpackAlreadyExistsForStackError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_name_taken_error.go new file mode 100644 index 0000000..2e15430 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_name_taken_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type BuildpackNameTakenError struct { + Name string +} + +func (e BuildpackNameTakenError) Error() string { + return fmt.Sprintf("Buildpack %s already exists", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_not_found_error.go new file mode 100644 index 0000000..88da77e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// BuildpackNotFoundError is returned when a requested buildpack is not found. +type BuildpackNotFoundError struct { + BuildpackName string + StackName string +} + +func (e BuildpackNotFoundError) Error() string { + return fmt.Sprintf("Buildpack not found - Name: '%s'; Stack: '%s'", e.BuildpackName, e.StackName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_stack_change_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_stack_change_error.go new file mode 100644 index 0000000..79cbc09 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/buildpack_stack_change_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +type BuildpackStackChangeError struct { + BuildpackName string + BinaryName string +} + +func (e BuildpackStackChangeError) Error() string { + return fmt.Sprintf("Buildpack %s already exists with a stack association", e.BuildpackName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_and_manifest_conflict_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_and_manifest_conflict_error.go new file mode 100644 index 0000000..44126b5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_and_manifest_conflict_error.go @@ -0,0 +1,17 @@ +package actionerror + +import ( + "fmt" + "strings" +) + +type CommandLineOptionsAndManifestConflictError struct { + ManifestAttribute string + CommandLineOptions []string +} + +func (e CommandLineOptionsAndManifestConflictError) Error() string { + return fmt.Sprintf("cannot use manifest attribute %s with command line options: %s", + e.ManifestAttribute, strings.Join(e.CommandLineOptions, ", "), + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_with_multiple_apps_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_with_multiple_apps_error.go new file mode 100644 index 0000000..234e00e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/command_line_options_with_multiple_apps_error.go @@ -0,0 +1,7 @@ +package actionerror + +type CommandLineOptionsWithMultipleAppsError struct{} + +func (CommandLineOptionsWithMultipleAppsError) Error() string { + return "cannot use command line flag with multiple apps" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/deployment_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/deployment_not_found_error.go new file mode 100644 index 0000000..97c5c58 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/deployment_not_found_error.go @@ -0,0 +1,11 @@ +package actionerror + +// ActiveDeploymentNotFoundError is an error wrapper that represents the case +// when the deployment is not found. +type ActiveDeploymentNotFoundError struct { +} + +// Error method to display the error message. +func (e ActiveDeploymentNotFoundError) Error() string { + return "No active deployment found for app." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/docker_password_not_set_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/docker_password_not_set_error.go new file mode 100644 index 0000000..ec813dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/docker_password_not_set_error.go @@ -0,0 +1,8 @@ +package actionerror + +type DockerPasswordNotSetError struct { +} + +func (DockerPasswordNotSetError) Error() string { + return "Docker password not set." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/domain_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/domain_not_found_error.go new file mode 100644 index 0000000..5a16867 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/domain_not_found_error.go @@ -0,0 +1,22 @@ +package actionerror + +import "fmt" + +// DomainNotFoundError is an error wrapper that represents the case +// when the domain is not found. +type DomainNotFoundError struct { + Name string + GUID string +} + +// Error method to display the error message. +func (e DomainNotFoundError) Error() string { + switch { + case e.Name != "": + return fmt.Sprintf("Domain '%s' not found.", e.Name) + case e.GUID != "": + return fmt.Sprintf("Domain with GUID '%s' not found.", e.GUID) + default: + return "Domain not found." + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/domains_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/domains_not_found_error.go new file mode 100644 index 0000000..3971d40 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/domains_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// NoDomainsFoundError is returned when there are no private or shared domains +// accessible to an organization. +type NoDomainsFoundError struct { + OrganizationGUID string +} + +func (e NoDomainsFoundError) Error() string { + return fmt.Sprintf("No private or shared domains found for organization (GUID: %s)", e.OrganizationGUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/droplet_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/droplet_not_found_error.go new file mode 100644 index 0000000..5cc39d7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/droplet_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// DropletNotFoundError is returned when a requested droplet from an +// application is not found. +type DropletNotFoundError struct { + AppGUID string +} + +func (e DropletNotFoundError) Error() string { + return fmt.Sprintf("Droplet from App GUID '%s' not found.", e.AppGUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_error.go new file mode 100644 index 0000000..e79cef0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_error.go @@ -0,0 +1,31 @@ +package actionerror + +import ( + "fmt" + "strings" +) + +type DuplicateServiceError struct { + Name string + ServiceBrokers []string +} + +func (e DuplicateServiceError) Error() string { + message := " Specify a broker by using the '-b' flag." + + if len(e.ServiceBrokers) != 0 { + message = fmt.Sprintf("\nSpecify a broker from available brokers %s by using the '-b' flag.", e.availableBrokers()) + } + + return fmt.Sprintf( + "Service '%s' is provided by multiple service brokers.%s", e.Name, message) +} + +func (e DuplicateServiceError) availableBrokers() string { + var quotedBrokers []string + for _, broker := range e.ServiceBrokers { + quotedBrokers = append(quotedBrokers, fmt.Sprintf("'%s'", broker)) + } + availableBrokers := strings.Join(quotedBrokers, ", ") + return availableBrokers +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_plan_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_plan_error.go new file mode 100644 index 0000000..7c0a191 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/duplicate_service_plan_error.go @@ -0,0 +1,20 @@ +package actionerror + +import "fmt" + +type DuplicateServicePlanError struct { + Name string + ServiceOfferingName string + ServiceBrokerName string +} + +func (e DuplicateServicePlanError) Error() string { + base := fmt.Sprintf("Service plan '%s' is provided by multiple service offerings", e.Name) + requiredFlag := "Specify an offering by using the '-e' flag" + if e.ServiceOfferingName != "" { + base = fmt.Sprintf("%s. "+ + "Service offering '%s' is provided by multiple service brokers", base, e.ServiceOfferingName) + requiredFlag = "Specify a broker name by using the '-b' flag" + } + return fmt.Sprintf("%s. %s.", base, requiredFlag) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_archive_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_archive_error.go new file mode 100644 index 0000000..a4dabf9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_archive_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type EmptyArchiveError struct { + Path string +} + +func (e EmptyArchiveError) Error() string { + return fmt.Sprint(e.Path, "is an empty archive") +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_buildpack_directory_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_buildpack_directory_error.go new file mode 100644 index 0000000..13e6220 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_buildpack_directory_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// EmptyBuildpackDirectoryError represents the error when a user tries to upload +// new buildpack bits but specifies an empty directory as the path to these bits. +type EmptyBuildpackDirectoryError struct { + Path string +} + +func (e EmptyBuildpackDirectoryError) Error() string { + return fmt.Sprint(e.Path, " is empty") +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_directory_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_directory_error.go new file mode 100644 index 0000000..0491c6b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/empty_directory_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type EmptyDirectoryError struct { + Path string +} + +func (e EmptyDirectoryError) Error() string { + return fmt.Sprint(e.Path, "is an empty directory") +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/enrich_api_errors.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/enrich_api_errors.go new file mode 100644 index 0000000..d372f41 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/enrich_api_errors.go @@ -0,0 +1,12 @@ +package actionerror + +import "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + +func EnrichAPIErrors(e error) error { + switch err := e.(type) { + case ccerror.ServiceOfferingNameAmbiguityError: + return ServiceOfferingNameAmbiguityError{err} + default: + return e + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/environment_variable_not_set_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/environment_variable_not_set_error.go new file mode 100644 index 0000000..3164652 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/environment_variable_not_set_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// EnvironmentVariableNotSetError is returned when trying to unset env variable +// that was not previously set. +type EnvironmentVariableNotSetError struct { + EnvironmentVariableName string +} + +func (e EnvironmentVariableNotSetError) Error() string { + return fmt.Sprintf("Env variable %s was not set.", e.EnvironmentVariableName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/feature_flag_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/feature_flag_not_found_error.go new file mode 100644 index 0000000..4ee6840 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/feature_flag_not_found_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +// FeatureFlagNotFoundError is returned when a requested feature flag is not found. +type FeatureFlagNotFoundError struct { + FeatureFlagName string +} + +func (e FeatureFlagNotFoundError) Error() string { + return fmt.Sprintf("Feature flag '%s' not found.", e.FeatureFlagName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/fetching_plugin_info_from_repository_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/fetching_plugin_info_from_repository_error.go new file mode 100644 index 0000000..1815d14 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/fetching_plugin_info_from_repository_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// FetchingPluginInfoFromRepositoryError is returned an error is encountered +// getting plugin info from a repository. +type FetchingPluginInfoFromRepositoryError struct { + RepositoryName string + Err error +} + +func (e FetchingPluginInfoFromRepositoryError) Error() string { + return fmt.Sprintf("Plugin repository %s returned %s.", e.RepositoryName, e.Err.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/file_changed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/file_changed_error.go new file mode 100644 index 0000000..ba5d0b2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/file_changed_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type FileChangedError struct { + Filename string +} + +func (e FileChangedError) Error() string { + return fmt.Sprint("SHA1 mismatch for:", e.Filename) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/getting_plugin_repository_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/getting_plugin_repository_error.go new file mode 100644 index 0000000..0f16221 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/getting_plugin_repository_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// GettingPluginRepositoryError is returned when there's an error +// accessing the plugin repository. +type GettingPluginRepositoryError struct { + Name string + Message string +} + +func (e GettingPluginRepositoryError) Error() string { + return fmt.Sprintf("Could not get plugin repository '%s'\n%s", e.Name, e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/hostname_with_tcp_domain_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/hostname_with_tcp_domain_error.go new file mode 100644 index 0000000..c392420 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/hostname_with_tcp_domain_error.go @@ -0,0 +1,8 @@ +package actionerror + +type HostnameWithTCPDomainError struct { +} + +func (HostnameWithTCPDomainError) Error() string { + return "cannot use provided hostname with a TCP domain" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/http_health_check_invalid_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/http_health_check_invalid_error.go new file mode 100644 index 0000000..101746d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/http_health_check_invalid_error.go @@ -0,0 +1,10 @@ +package actionerror + +// HTTPHealthCheckInvalidError is returned when an HTTP endpoint is used with a +// health check type that is not HTTP. +type HTTPHealthCheckInvalidError struct { +} + +func (e HTTPHealthCheckInvalidError) Error() string { + return "Health check type must be 'http' to set a health check HTTP endpoint" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_buildpacks_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_buildpacks_error.go new file mode 100644 index 0000000..1c9eb05 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_buildpacks_error.go @@ -0,0 +1,10 @@ +package actionerror + +import "fmt" + +type InvalidBuildpacksError struct { +} + +func (err InvalidBuildpacksError) Error() string { + return fmt.Sprintf("Multiple buildpacks flags cannot have null/default option.") +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_command_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_command_error.go new file mode 100644 index 0000000..2e6e2d4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_command_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// InvalidCommandError represents an error that happens when help is called +// with an invalid command. +type InvalidCommandError struct { + CommandName string +} + +func (err InvalidCommandError) Error() string { + return fmt.Sprintf("'%s' is not a registered command. See 'cf help -a'", err.CommandName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_http_route_settings.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_http_route_settings.go new file mode 100644 index 0000000..78905df --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_http_route_settings.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type InvalidHTTPRouteSettings struct { + Domain string +} + +func (e InvalidHTTPRouteSettings) Error() string { + return fmt.Sprintln("Invalid HTTP settings for", e.Domain) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_lifecycle_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_lifecycle_error.go new file mode 100644 index 0000000..34e1bfa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_lifecycle_error.go @@ -0,0 +1,15 @@ +package actionerror + +import ( + "fmt" +) + +// InvalidLifecycleError is returned when the lifecycle specified is neither +// running nor staging. +type InvalidLifecycleError struct { + Lifecycle string +} + +func (e InvalidLifecycleError) Error() string { + return fmt.Sprintf("Invalid lifecycle: %s", e.Lifecycle) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_route_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_route_error.go new file mode 100644 index 0000000..bb09f91 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_route_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// InvalidRouteError is returned when a route is provided that isn't properly +// formed URL. +type InvalidRouteError struct { + Route string +} + +func (err InvalidRouteError) Error() string { + return fmt.Sprintf("Route '%s' is not parsable by URI", err.Route) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_tcp_route_settings.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_tcp_route_settings.go new file mode 100644 index 0000000..efaac36 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/invalid_tcp_route_settings.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type InvalidTCPRouteSettings struct { + Domain string +} + +func (e InvalidTCPRouteSettings) Error() string { + return fmt.Sprintln("Invalid TCP settings for", e.Domain) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_already_exists_error.go new file mode 100644 index 0000000..488b903 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_already_exists_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// IsolationSegmentAlreadyExistsError gets returned when an isolation segment +// already exists. +type IsolationSegmentAlreadyExistsError struct { + Name string +} + +func (e IsolationSegmentAlreadyExistsError) Error() string { + return fmt.Sprintf("Isolation Segment '%s' already exists.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_not_found_error.go new file mode 100644 index 0000000..41b0b82 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/isolation_segment_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// IsolationSegmentNotFoundError represents the error that occurs when the +// isolation segment is not found. +type IsolationSegmentNotFoundError struct { + Name string +} + +func (e IsolationSegmentNotFoundError) Error() string { + return fmt.Sprintf("Isolation Segment '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/log_cache_timeout_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/log_cache_timeout_error.go new file mode 100644 index 0000000..57ba151 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/log_cache_timeout_error.go @@ -0,0 +1,7 @@ +package actionerror + +type LogCacheTimeoutError struct{} + +func (LogCacheTimeoutError) Error() string { + return "Timeout trying to connect to LogCache" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/missing_name_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/missing_name_error.go new file mode 100644 index 0000000..eb546a0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/missing_name_error.go @@ -0,0 +1,7 @@ +package actionerror + +type MissingNameError struct{} + +func (MissingNameError) Error() string { + return "name not specified for app" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_buildpacks_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_buildpacks_found_error.go new file mode 100644 index 0000000..4147eaa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_buildpacks_found_error.go @@ -0,0 +1,15 @@ +package actionerror + +import ( + "fmt" +) + +// MultipleBuildpacksFoundError represents the scenario when the cloud +// controller returns multiple buildpacks when filtering by name. +type MultipleBuildpacksFoundError struct { + BuildpackName string +} + +func (e MultipleBuildpacksFoundError) Error() string { + return fmt.Sprintf("Multiple buildpacks named %s found", e.BuildpackName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_uaa_users_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_uaa_users_found_error.go new file mode 100644 index 0000000..c17f89a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/multiple_uaa_users_found_error.go @@ -0,0 +1,16 @@ +package actionerror + +import ( + "fmt" + "strings" +) + +type MultipleUAAUsersFoundError struct { + Username string + Origins []string +} + +func (e MultipleUAAUsersFoundError) Error() string { + origins := strings.Join(e.Origins, ", ") + return fmt.Sprintf("The username '%s' is found in multiple origins: %s.", e.Username, origins) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_compatible_binary_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_compatible_binary_error.go new file mode 100644 index 0000000..324476a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_compatible_binary_error.go @@ -0,0 +1,10 @@ +package actionerror + +// NoCompatibleBinaryError is returned when a repository contains a specified +// plugin but not for the specified platform. +type NoCompatibleBinaryError struct { +} + +func (e NoCompatibleBinaryError) Error() string { + return "Plugin requested has no binary available for your platform." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_eligible_packages_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_eligible_packages_error.go new file mode 100644 index 0000000..73eee7e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_eligible_packages_error.go @@ -0,0 +1,18 @@ +package actionerror + +import "fmt" + +type NoEligiblePackagesError struct { + AppName string + BinaryName string +} + +func (e NoEligiblePackagesError) Error() string { + switch { + case e.AppName != "": + return fmt.Sprintf("App '%s' has no eligible packages.", e.AppName) + default: + return fmt.Sprintf("No eligible pacakges available for app.") + } + +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_hostname_and_shared_domain_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_hostname_and_shared_domain_error.go new file mode 100644 index 0000000..10553f4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_hostname_and_shared_domain_error.go @@ -0,0 +1,7 @@ +package actionerror + +type NoHostnameAndSharedDomainError struct{} + +func (NoHostnameAndSharedDomainError) Error() string { + return "hostname required for shared domains" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_matching_domain_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_matching_domain_error.go new file mode 100644 index 0000000..317ecb8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_matching_domain_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type NoMatchingDomainError struct { + Route string +} + +func (e NoMatchingDomainError) Error() string { + return fmt.Sprintln("Unable to find a matching domain for", e.Route) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_organization_targeted_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_organization_targeted_error.go new file mode 100644 index 0000000..25c8569 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_organization_targeted_error.go @@ -0,0 +1,12 @@ +package actionerror + +// NoOrganizationTargetedError represents the scenario when an org is not targeted. +type NoOrganizationTargetedError struct { + BinaryName string +} + +func (NoOrganizationTargetedError) Error() string { + // The error message will be replaced by a translated message, returning the + // empty string does not add to the translation files. + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_relationship_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_relationship_error.go new file mode 100644 index 0000000..54d62fc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_relationship_error.go @@ -0,0 +1,8 @@ +package actionerror + +type NoRelationshipError struct { +} + +func (e NoRelationshipError) Error() string { + return "No relationship found." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_space_targeted_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_space_targeted_error.go new file mode 100644 index 0000000..be278f0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/no_space_targeted_error.go @@ -0,0 +1,12 @@ +package actionerror + +// NoSpaceTargetedError represents the scenario when a space is not targeted. +type NoSpaceTargetedError struct { + BinaryName string +} + +func (NoSpaceTargetedError) Error() string { + // The error message will be replaced by a translated message, returning the + // empty string does not add to the translation files. + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/nonexistent_app_path_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/nonexistent_app_path_error.go new file mode 100644 index 0000000..3d45274 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/nonexistent_app_path_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type NonexistentAppPathError struct { + Path string +} + +func (e NonexistentAppPathError) Error() string { + return fmt.Sprint("app path not found:", e.Path) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/not_logged_in_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/not_logged_in_error.go new file mode 100644 index 0000000..f6185ca --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/not_logged_in_error.go @@ -0,0 +1,12 @@ +package actionerror + +// NotLoggedInError represents the scenario when the user is not logged in. +type NotLoggedInError struct { + BinaryName string +} + +func (NotLoggedInError) Error() string { + // The error message will be replaced by a translated message, returning the + // empty string does not add to the translation files. + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_not_found_error.go new file mode 100644 index 0000000..9132f07 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_not_found_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// OrganizationNotFoundError represents the error that occurs when the +// organization is not found. +type OrganizationNotFoundError struct { + GUID string + Name string +} + +func (e OrganizationNotFoundError) Error() string { + return fmt.Sprintf("Organization '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_error.go new file mode 100644 index 0000000..a055801 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type OrganizationQuotaNotFoundError struct { + GUID string +} + +func (e OrganizationQuotaNotFoundError) Error() string { + return fmt.Sprintf("Organization quota with GUID '%s' not found.", e.GUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_for_name_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_for_name_error.go new file mode 100644 index 0000000..7c2f74b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/organization_quota_not_found_for_name_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type OrganizationQuotaNotFoundForNameError struct { + Name string +} + +func (e OrganizationQuotaNotFoundForNameError) Error() string { + return fmt.Sprintf("Organization quota with name '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_not_found_in_app_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_not_found_in_app_error.go new file mode 100644 index 0000000..de835ab --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_not_found_in_app_error.go @@ -0,0 +1,21 @@ +package actionerror + +import "fmt" + +type PackageNotFoundInAppError struct { + GUID string + AppName string + BinaryName string +} + +func (e PackageNotFoundInAppError) Error() string { + switch { + case e.GUID != "" && e.AppName != "": + return fmt.Sprintf("Package with guid '%s' not found in app '%s'.", e.GUID, e.AppName) + case e.AppName != "": + return fmt.Sprintf("Package not found in app '%s'.", e.AppName) + default: + return fmt.Sprintf("Package not found.") + } + +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_expired_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_expired_error.go new file mode 100644 index 0000000..6d2fe29 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_expired_error.go @@ -0,0 +1,7 @@ +package actionerror + +type PackageProcessingExpiredError struct{} + +func (PackageProcessingExpiredError) Error() string { + return "Package expired after upload" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_failed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_failed_error.go new file mode 100644 index 0000000..c656d25 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/package_processing_failed_error.go @@ -0,0 +1,7 @@ +package actionerror + +type PackageProcessingFailedError struct{} + +func (PackageProcessingFailedError) Error() string { + return "Package failed to process correctly after upload" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/password_grant_type_logout_required.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/password_grant_type_logout_required.go new file mode 100644 index 0000000..d36b05f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/password_grant_type_logout_required.go @@ -0,0 +1,10 @@ +package actionerror + +// PasswordGrantTypeLogoutRequiredError is returned when a user tries to +// authenticate with the password grant type, but a previous user had +// authenticated with the client grant type +type PasswordGrantTypeLogoutRequiredError struct{} + +func (PasswordGrantTypeLogoutRequiredError) Error() string { + return "Service account currently logged in. Use 'cf logout' to log out service account and try again." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_binary_remove_failed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_binary_remove_failed_error.go new file mode 100644 index 0000000..7b730bd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_binary_remove_failed_error.go @@ -0,0 +1,10 @@ +package actionerror + +// PluginBinaryRemoveFailedError is returned when running the plugin binary fails. +type PluginBinaryRemoveFailedError struct { + Err error +} + +func (e PluginBinaryRemoveFailedError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_commands_conflict_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_commands_conflict_error.go new file mode 100644 index 0000000..0425b6f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_commands_conflict_error.go @@ -0,0 +1,14 @@ +package actionerror + +// PluginCommandsConflictError is returned when a plugin command name conflicts +// with a core or existing plugin command name. +type PluginCommandsConflictError struct { + PluginName string + PluginVersion string + CommandNames []string + CommandAliases []string +} + +func (PluginCommandsConflictError) Error() string { + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_execute_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_execute_error.go new file mode 100644 index 0000000..f57d6e6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_execute_error.go @@ -0,0 +1,10 @@ +package actionerror + +// PluginExecuteError is returned when running the plugin binary fails. +type PluginExecuteError struct { + Err error +} + +func (e PluginExecuteError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_error.go new file mode 100644 index 0000000..2260f48 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_error.go @@ -0,0 +1,11 @@ +package actionerror + +// PluginInvalidError is returned with a plugin is invalid because it is +// missing a name or has 0 commands. +type PluginInvalidError struct { + Err error +} + +func (PluginInvalidError) Error() string { + return "File is not a valid cf CLI plugin binary." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_library_version_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_library_version_error.go new file mode 100644 index 0000000..d405bf8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_invalid_library_version_error.go @@ -0,0 +1,10 @@ +package actionerror + +// PluginInvalidLibraryVersionError is returned with a plugin is invalid because it is +// compiled with an incompatible version of the library. +type PluginInvalidLibraryVersionError struct { +} + +func (PluginInvalidLibraryVersionError) Error() string { + return "This plugin is not compatible with this version of the CLI" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_error.go new file mode 100644 index 0000000..5e0aceb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// PluginNotFoundError is an error returned when a plugin is not found. +type PluginNotFoundError struct { + PluginName string +} + +// Error outputs a plugin not found error message. +func (e PluginNotFoundError) Error() string { + return fmt.Sprintf("Plugin name %s does not exist.", e.PluginName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_any_repository_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_any_repository_error.go new file mode 100644 index 0000000..0cf839c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_any_repository_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// PluginNotFoundInAnyRepositoryError is an error returned when a plugin cannot +// be found in any repositories. +type PluginNotFoundInAnyRepositoryError struct { + PluginName string +} + +// Error outputs that the plugin cannot be found in any repositories. +func (e PluginNotFoundInAnyRepositoryError) Error() string { + return fmt.Sprintf("Plugin %s not found in any registered repo", e.PluginName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_repository_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_repository_error.go new file mode 100644 index 0000000..cfa8442 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/plugin_not_found_in_repository_error.go @@ -0,0 +1,15 @@ +package actionerror + +import "fmt" + +// PluginNotFoundInRepositoryError is an error returned when a plugin is not +// found. +type PluginNotFoundInRepositoryError struct { + PluginName string + RepositoryName string +} + +// Error outputs the plugin not found in repository error message. +func (e PluginNotFoundInRepositoryError) Error() string { + return fmt.Sprintf("Plugin %s not found in repository %s", e.PluginName, e.RepositoryName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/policy_does_not_exist_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/policy_does_not_exist_error.go new file mode 100644 index 0000000..6ce4346 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/policy_does_not_exist_error.go @@ -0,0 +1,7 @@ +package actionerror + +type PolicyDoesNotExistError struct{} + +func (PolicyDoesNotExistError) Error() string { + return "policy does not exist." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_found_error.go new file mode 100644 index 0000000..0690bb3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// ProcessInstanceNotFoundError is returned when the process type or process instance cannot be found +type ProcessInstanceNotFoundError struct { + ProcessType string + InstanceIndex uint +} + +func (e ProcessInstanceNotFoundError) Error() string { + return fmt.Sprintf("Instance %d of process %s not found", e.InstanceIndex, e.ProcessType) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_running_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_running_error.go new file mode 100644 index 0000000..c44eb3a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_instance_not_running_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// ProcessInstanceNotRunningError is returned when trying to perform an action +// on an instance that is not running +type ProcessInstanceNotRunningError struct { + ProcessType string + InstanceIndex uint +} + +func (e ProcessInstanceNotRunningError) Error() string { + return fmt.Sprintf("Instance %d of process %s not running", e.InstanceIndex, e.ProcessType) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_not_found_error.go new file mode 100644 index 0000000..364da87 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/process_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// ProcessNotFoundError is returned when a requested application is not +// found. +type ProcessNotFoundError struct { + ProcessType string +} + +func (e ProcessNotFoundError) Error() string { + return fmt.Sprintf("Process %s not found", e.ProcessType) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/property_combination_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/property_combination_error.go new file mode 100644 index 0000000..f96598c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/property_combination_error.go @@ -0,0 +1,15 @@ +package actionerror + +import ( + "fmt" + "strings" +) + +type PropertyCombinationError struct { + AppName string + Properties []string +} + +func (e PropertyCombinationError) Error() string { + return fmt.Sprintln("Cannot use the following properties together:", strings.Join(e.Properties, ", ")) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/quota_not_found_for_name_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/quota_not_found_for_name_error.go new file mode 100644 index 0000000..51d236c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/quota_not_found_for_name_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type QuotaNotFoundForNameError struct { + Name string +} + +func (e QuotaNotFoundForNameError) Error() string { + return fmt.Sprintf("Organization quota with name '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_already_exists_error.go new file mode 100644 index 0000000..df15a33 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_already_exists_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +type RepositoryAlreadyExistsError struct { + Name string + URL string +} + +func (e RepositoryAlreadyExistsError) Error() string { + return fmt.Sprintf("%s already registered as %s.", e.URL, e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_name_taken_error.go new file mode 100644 index 0000000..e618d75 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_name_taken_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type RepositoryNameTakenError struct { + Name string +} + +func (e RepositoryNameTakenError) Error() string { + return fmt.Sprintf("Plugin repo named '%s' already exists, please use another name.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_not_registered_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_not_registered_error.go new file mode 100644 index 0000000..1739e15 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/repository_not_registered_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type RepositoryNotRegisteredError struct { + Name string +} + +func (e RepositoryNotRegisteredError) Error() string { + return fmt.Sprintf("Plugin repository %s not found", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/resource_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/resource_already_exists_error.go new file mode 100644 index 0000000..beaf695 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/resource_already_exists_error.go @@ -0,0 +1,10 @@ +package actionerror + +// ResourceAlreadyExistsError is returned when an identical resource already exists +type ResourceAlreadyExistsError struct { + Message string +} + +func (e ResourceAlreadyExistsError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_ambiguous.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_ambiguous.go new file mode 100644 index 0000000..6e9c3ad --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_ambiguous.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// RevisionAmbiguousError is returned when multiple revisions with the same +// version are returned +type RevisionAmbiguousError struct { + Version int +} + +func (e RevisionAmbiguousError) Error() string { + return fmt.Sprintf("More than one revision '%d' found", e.Version) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_not_found.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_not_found.go new file mode 100644 index 0000000..c1a8a0d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/revision_not_found.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// RevisionNotFoundError is returned when a requested revision is not +// found. +type RevisionNotFoundError struct { + Version int +} + +func (e RevisionNotFoundError) Error() string { + return fmt.Sprintf("Revision '%d' not found", e.Version) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_already_exists_error.go new file mode 100644 index 0000000..03d2d42 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_already_exists_error.go @@ -0,0 +1,16 @@ +package actionerror + +import "fmt" + +// RouteAlreadyExistsError is returned when a route already exists +type RouteAlreadyExistsError struct { + Route string + Err error +} + +func (e RouteAlreadyExistsError) Error() string { + if e.Err != nil { + return e.Err.Error() + } + return fmt.Sprintf("Route %s already exists.", e.Route) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_binding_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_binding_not_found_error.go new file mode 100644 index 0000000..92203f0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_binding_not_found_error.go @@ -0,0 +1,7 @@ +package actionerror + +type RouteBindingNotFoundError struct{} + +func (e RouteBindingNotFoundError) Error() string { + return "Route binding not found." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_bound_to_multiple_apps_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_bound_to_multiple_apps_error.go new file mode 100644 index 0000000..d3f0689 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_bound_to_multiple_apps_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// RouteBoundToMultipleAppsError is returned when a route is mapped to more than one app +type RouteBoundToMultipleAppsError struct { + AppName string + RouteURL string +} + +func (e RouteBoundToMultipleAppsError) Error() string { + return fmt.Sprintf("App '%s' was not deleted because route '%s' is mapped to more than one app.", e.AppName, e.RouteURL) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_destination_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_destination_not_found_error.go new file mode 100644 index 0000000..d5b157f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_destination_not_found_error.go @@ -0,0 +1,19 @@ +package actionerror + +import "fmt" + +// RouteDestinationNotFoundError is returned when a route destination cannot be found +type RouteDestinationNotFoundError struct { + AppGUID string + ProcessType string + RouteGUID string +} + +func (e RouteDestinationNotFoundError) Error() string { + return fmt.Sprintf( + "Destination with app guid '%s' and process type '%s' for route with guid '%s' not found.", + e.AppGUID, + e.ProcessType, + e.RouteGUID, + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_in_different_space_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_in_different_space_error.go new file mode 100644 index 0000000..8b3ea61 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_in_different_space_error.go @@ -0,0 +1,11 @@ +package actionerror + +// RouteInDifferentSpaceError is returned when the route exists in a different +// space than the one requesting it. +type RouteInDifferentSpaceError struct { + Route string +} + +func (RouteInDifferentSpaceError) Error() string { + return "route registered to another space" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_not_found_error.go new file mode 100644 index 0000000..94f40a0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_not_found_error.go @@ -0,0 +1,27 @@ +package actionerror + +import "fmt" + +// RouteNotFoundError is returned when a route cannot be found +type RouteNotFoundError struct { + Host string + DomainName string + Path string + Port int +} + +func (e RouteNotFoundError) Error() string { + switch e.Port { + case 0: + return fmt.Sprintf("Route with host '%s', domain '%s', and path '%s' not found.", e.Host, e.DomainName, e.path()) + default: + return fmt.Sprintf("Route with domain '%s' and port %d not found.", e.DomainName, e.Port) + } +} + +func (e RouteNotFoundError) path() string { + if e.Path == "" { + return "/" + } + return e.Path +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_path_with_tcp_domain_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_path_with_tcp_domain_error.go new file mode 100644 index 0000000..61478d6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/route_path_with_tcp_domain_error.go @@ -0,0 +1,8 @@ +package actionerror + +type RoutePathWithTCPDomainError struct { +} + +func (RoutePathWithTCPDomainError) Error() string { + return "cannot use provided route path with a TCP domain" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/router_group_not_found.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/router_group_not_found.go new file mode 100644 index 0000000..3795747 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/router_group_not_found.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type RouterGroupNotFoundError struct { + Name string +} + +func (err RouterGroupNotFoundError) Error() string { + return fmt.Sprintf("Router group '%s' not found.", err.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_json_syntax_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_json_syntax_error.go new file mode 100644 index 0000000..38096d0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_json_syntax_error.go @@ -0,0 +1,21 @@ +package actionerror + +import "fmt" + +type SecurityGroupJsonSyntaxError struct { + Path string +} + +func (e SecurityGroupJsonSyntaxError) Error() string { + return fmt.Sprintf(`Incorrect json format: %s + +Valid json file example: +[ + { + "protocol": "tcp", + "destination": "10.244.1.18", + "ports": "3306" + } +] +`, e.Path) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_bound_to_space_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_bound_to_space_error.go new file mode 100644 index 0000000..7714874 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_bound_to_space_error.go @@ -0,0 +1,19 @@ +package actionerror + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// SecurityGroupNotBoundToSpaceError is returned when a requested security group is +// not bound in the requested lifecycle phase to the requested space. +type SecurityGroupNotBoundToSpaceError struct { + Lifecycle constant.SecurityGroupLifecycle + Name string + Space string +} + +func (e SecurityGroupNotBoundToSpaceError) Error() string { + return fmt.Sprintf("Security group %s not bound to space %s for lifecycle phase '%s'.", e.Name, e.Space, e.Lifecycle) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_found_error.go new file mode 100644 index 0000000..9b519fe --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/security_group_not_found_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// SecurityGroupNotFoundError is returned when a requested security group is +// not found. +type SecurityGroupNotFoundError struct { + Name string +} + +func (e SecurityGroupNotFoundError) Error() string { + return fmt.Sprintf("Security group '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_binding_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_binding_not_found_error.go new file mode 100644 index 0000000..e7d8f12 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_binding_not_found_error.go @@ -0,0 +1,14 @@ +package actionerror + +import "fmt" + +// ServiceBindingNotFoundError is returned when a service binding cannot be +// found. +type ServiceBindingNotFoundError struct { + AppGUID string + ServiceInstanceGUID string +} + +func (e ServiceBindingNotFoundError) Error() string { + return fmt.Sprintf("Service binding for application GUID '%s', and service instance GUID '%s' not found.", e.AppGUID, e.ServiceInstanceGUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_name_required_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_name_required_error.go new file mode 100644 index 0000000..07ff885 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_name_required_error.go @@ -0,0 +1,16 @@ +package actionerror + +import ( + "fmt" +) + +type ServiceBrokerNameRequiredError struct { + ServiceOfferingName string +} + +func (e ServiceBrokerNameRequiredError) Error() string { + return fmt.Sprintf( + "Service offering '%s' is provided by multiple service brokers. Specify a broker name by using the '-b' flag.", + e.ServiceOfferingName, + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_not_found_error.go new file mode 100644 index 0000000..2137d71 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_broker_not_found_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type ServiceBrokerNotFoundError struct { + Name string +} + +func (e ServiceBrokerNotFoundError) Error() string { + return fmt.Sprintf("Service broker '%s' not found.\nTIP: Use 'cf service-brokers' to see a list of available brokers.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_found_error.go new file mode 100644 index 0000000..8c69b95 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_found_error.go @@ -0,0 +1,15 @@ +package actionerror + +import "fmt" + +type ServiceInstanceNotFoundError struct { + GUID string + Name string +} + +func (e ServiceInstanceNotFoundError) Error() string { + if e.Name == "" { + return fmt.Sprintf("Service instance (GUID: %s) not found.", e.GUID) + } + return fmt.Sprintf("Service instance '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shareable_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shareable_error.go new file mode 100644 index 0000000..e04ebfb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shareable_error.go @@ -0,0 +1,13 @@ +package actionerror + +// ServiceInstanceNotShareableError is returned when either the +// service_instance_sharing feature flag is disabled or the service broker has +// disabled sharing +type ServiceInstanceNotShareableError struct { + FeatureFlagEnabled bool + ServiceBrokerSharingEnabled bool +} + +func (e ServiceInstanceNotShareableError) Error() string { + return "Service instance sharing is not enabled" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shared_to_space_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shared_to_space_error.go new file mode 100644 index 0000000..dc6d212 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_not_shared_to_space_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +// ServiceInstanceNotSharedToSpaceError is returned when attempting to unshare a service instance from a space to which it is not shared. +type ServiceInstanceNotSharedToSpaceError struct { + ServiceInstanceName string +} + +func (e ServiceInstanceNotSharedToSpaceError) Error() string { + return fmt.Sprintf("Failed to unshare service instance '%s'. Ensure the space and specified org exist and that the service instance has been shared to this space.", e.ServiceInstanceName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_params_fetching_not_supported_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_params_fetching_not_supported_error.go new file mode 100644 index 0000000..bf15682 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_params_fetching_not_supported_error.go @@ -0,0 +1,11 @@ +package actionerror + +// ServiceInstanceParamsFetchingNotSupportedError is returned when +// service instance is user provided or +// service instance retrievable is false for a managed service instance +type ServiceInstanceParamsFetchingNotSupportedError struct { +} + +func (e ServiceInstanceParamsFetchingNotSupportedError) Error() string { + return "This service does not support fetching service instance parameters." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_type_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_type_error.go new file mode 100644 index 0000000..9021fcd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_type_error.go @@ -0,0 +1,16 @@ +package actionerror + +import ( + "fmt" + + "code.cloudfoundry.org/cli/resources" +) + +type ServiceInstanceTypeError struct { + Name string + RequiredType resources.ServiceInstanceType +} + +func (e ServiceInstanceTypeError) Error() string { + return fmt.Sprintf("The service instance '%s' is not %s", e.Name, e.RequiredType) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_update_is_noop.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_update_is_noop.go new file mode 100644 index 0000000..2191aac --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_instance_update_is_noop.go @@ -0,0 +1,7 @@ +package actionerror + +type ServiceInstanceUpdateIsNoop struct{} + +func (ServiceInstanceUpdateIsNoop) Error() string { + return "ServiceInstanceUpdateIsNoop" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_key_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_key_not_found_error.go new file mode 100644 index 0000000..870ea65 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_key_not_found_error.go @@ -0,0 +1,19 @@ +package actionerror + +import "fmt" + +type ServiceKeyNotFoundError struct { + KeyName string + ServiceInstanceName string +} + +func NewServiceKeyNotFoundError(keyName, serviceInstanceName string) error { + return ServiceKeyNotFoundError{ + KeyName: keyName, + ServiceInstanceName: serviceInstanceName, + } +} + +func (e ServiceKeyNotFoundError) Error() string { + return fmt.Sprintf("No service key %s found for service instance %s", e.KeyName, e.ServiceInstanceName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_not_found_error.go new file mode 100644 index 0000000..de770d2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_not_found_error.go @@ -0,0 +1,23 @@ +package actionerror + +import "fmt" + +type ServiceNotFoundError struct { + Name, Broker string +} + +func (e ServiceNotFoundError) Error() string { + if e.Name != "" && e.Broker != "" { + return fmt.Sprintf("Service offering '%s' for service broker '%s' not found.", e.Name, e.Broker) + } + + if e.Name != "" { + return fmt.Sprintf("Service offering '%s' not found.", e.Name) + } + + if e.Broker != "" { + return fmt.Sprintf("No service offerings found for service broker '%s'.", e.Broker) + } + + return "No service offerings found." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_offering_name_ambiguity_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_offering_name_ambiguity_error.go new file mode 100644 index 0000000..b7ec535 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_offering_name_ambiguity_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + +type ServiceOfferingNameAmbiguityError struct { + ccerror.ServiceOfferingNameAmbiguityError +} + +func (e ServiceOfferingNameAmbiguityError) Error() string { + return e.ServiceOfferingNameAmbiguityError.Error() + "\nSpecify a broker by using the '-b' flag." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_plan_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_plan_not_found_error.go new file mode 100644 index 0000000..34d38d0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_plan_not_found_error.go @@ -0,0 +1,28 @@ +package actionerror + +import "fmt" + +type ServicePlanNotFoundError struct { + PlanName string + OfferingName string + ServiceBrokerName string +} + +func (e ServicePlanNotFoundError) Error() string { + if e.OfferingName != "" && e.PlanName != "" { + if e.ServiceBrokerName != "" { + return fmt.Sprintf("The plan %s could not be found for service offering %s and broker %s.", e.PlanName, e.OfferingName, e.ServiceBrokerName) + } + return fmt.Sprintf("The plan %s could not be found for service offering %s.", e.PlanName, e.OfferingName) + } + + if e.PlanName != "" { + return fmt.Sprintf("Service plan '%s' not found.", e.PlanName) + } + + if e.OfferingName != "" { + return fmt.Sprintf("No service plans found for service offering '%s'.", e.OfferingName) + } + + return "No service plans found." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_upgrade_not_available_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_upgrade_not_available_error.go new file mode 100644 index 0000000..2fa641a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_upgrade_not_available_error.go @@ -0,0 +1,10 @@ +package actionerror + +// ServiceInstanceUpgradeNotAvailableError is returned when attempting to upgrade a single service instance, +// but there is no upgrade available on the current service plan, i.e., service instance is already +// up-to-date. +type ServiceInstanceUpgradeNotAvailableError struct{} + +func (e ServiceInstanceUpgradeNotAvailableError) Error() string { + return "No upgrade is available." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_visibility_type_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_visibility_type_error.go new file mode 100644 index 0000000..a21f6a3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/service_visibility_type_error.go @@ -0,0 +1,8 @@ +package actionerror + +type ServicePlanVisibilityTypeError struct { +} + +func (e ServicePlanVisibilityTypeError) Error() string { + return "You cannot change access for space-scoped service plans." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/shared_service_instance_not_found.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/shared_service_instance_not_found.go new file mode 100644 index 0000000..c1af418 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/shared_service_instance_not_found.go @@ -0,0 +1,9 @@ +package actionerror + +// SharedServiceInstanceNotFoundError is returned when a service instance is not found when performing a share service. +type SharedServiceInstanceNotFoundError struct { +} + +func (e SharedServiceInstanceNotFoundError) Error() string { + return "Specified instance not found or not a managed service instance. Sharing is not supported for user provided services." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_already_exists_error.go new file mode 100644 index 0000000..5e7c307 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_already_exists_error.go @@ -0,0 +1,16 @@ +package actionerror + +import "fmt" + +// SpaceAlreadyExistsError is returned when a space already exists +type SpaceAlreadyExistsError struct { + Space string + Err error +} + +func (e SpaceAlreadyExistsError) Error() string { + if e.Err != nil { + return e.Err.Error() + } + return fmt.Sprintf("Space '%s' already exists.", e.Space) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_not_found_error.go new file mode 100644 index 0000000..54c83ac --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_not_found_error.go @@ -0,0 +1,21 @@ +package actionerror + +import "fmt" + +// SpaceNotFoundError represents the scenario when the space searched for could +// not be found. +type SpaceNotFoundError struct { + GUID string + Name string +} + +func (e SpaceNotFoundError) Error() string { + switch { + case e.Name != "": + return fmt.Sprintf("Space '%s' not found.", e.Name) + case e.GUID != "": + return fmt.Sprintf("Space with GUID '%s' not found.", e.GUID) + default: + return fmt.Sprintf("Space '' not found.") + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_error.go new file mode 100644 index 0000000..291307e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type SpaceQuotaNotFoundError struct { + GUID string +} + +func (e SpaceQuotaNotFoundError) Error() string { + return fmt.Sprintf("Space quota with GUID '%s' not found.", e.GUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_for_name_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_for_name_error.go new file mode 100644 index 0000000..84516f2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_quota_not_found_for_name_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type SpaceQuotaNotFoundForNameError struct { + Name string +} + +func (e SpaceQuotaNotFoundForNameError) Error() string { + return fmt.Sprintf("Space quota with name '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_disabled_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_disabled_error.go new file mode 100644 index 0000000..d4e74ba --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_disabled_error.go @@ -0,0 +1,16 @@ +package actionerror + +import "fmt" + +// SpaceSSHAlreadyDisabledError is returned when ssh is already disabled on the space +type SpaceSSHAlreadyDisabledError struct { + Space string + Err error +} + +func (e SpaceSSHAlreadyDisabledError) Error() string { + if e.Err != nil { + return e.Err.Error() + } + return fmt.Sprintf("ssh support for space '%s' is already disabled.", e.Space) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_enabled_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_enabled_error.go new file mode 100644 index 0000000..8515182 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/space_ssh_already_enabled_error.go @@ -0,0 +1,16 @@ +package actionerror + +import "fmt" + +// SpaceSSHAlreadyEnabledError is returned when ssh is already enabled on the space +type SpaceSSHAlreadyEnabledError struct { + Space string + Err error +} + +func (e SpaceSSHAlreadyEnabledError) Error() string { + if e.Err != nil { + return e.Err.Error() + } + return fmt.Sprintf("ssh support for space '%s' is already enabled.", e.Space) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_endpoint_not_set_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_endpoint_not_set_error.go new file mode 100644 index 0000000..037ca1b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_endpoint_not_set_error.go @@ -0,0 +1,9 @@ +package actionerror + +// SSHEndpointNotSetError is returned when staging an application fails. +type SSHEndpointNotSetError struct { +} + +func (e SSHEndpointNotSetError) Error() string { + return "SSH endpoint not set" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_hostkey_fingerprint_not_set_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_hostkey_fingerprint_not_set_error.go new file mode 100644 index 0000000..dd9d2b6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/ssh_hostkey_fingerprint_not_set_error.go @@ -0,0 +1,9 @@ +package actionerror + +// SSHHostKeyFingerprintNotSetError is returned when staging an application fails. +type SSHHostKeyFingerprintNotSetError struct { +} + +func (e SSHHostKeyFingerprintNotSetError) Error() string { + return "SSH hostkey fingerprint not set" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/stack_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/stack_not_found_error.go new file mode 100644 index 0000000..4f91ee0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/stack_not_found_error.go @@ -0,0 +1,17 @@ +package actionerror + +import "fmt" + +// StackNotFoundError is returned when a requested stack is not found. +type StackNotFoundError struct { + GUID string + Name string +} + +func (e StackNotFoundError) Error() string { + if e.Name == "" { + return fmt.Sprintf("Stack with GUID '%s' not found.", e.GUID) + } + + return fmt.Sprintf("Stack '%s' not found.", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_error.go new file mode 100644 index 0000000..2f6706e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_error.go @@ -0,0 +1,10 @@ +package actionerror + +// StagingFailedError is returned when staging an application fails. +type StagingFailedError struct { + Reason string +} + +func (e StagingFailedError) Error() string { + return e.Reason +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_no_app_detected_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_no_app_detected_error.go new file mode 100644 index 0000000..98d3fbe --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_failed_no_app_detected_error.go @@ -0,0 +1,10 @@ +package actionerror + +// StagingFailedNoAppDetectedError is returned when staging an application fails. +type StagingFailedNoAppDetectedError struct { + Reason string +} + +func (e StagingFailedNoAppDetectedError) Error() string { + return e.Reason +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_timeout_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_timeout_error.go new file mode 100644 index 0000000..b5892ca --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/staging_timeout_error.go @@ -0,0 +1,17 @@ +package actionerror + +import ( + "fmt" + "time" +) + +// StagingTimeoutError is returned when staging timeout is reached waiting for +// an application to stage. +type StagingTimeoutError struct { + AppName string + Timeout time.Duration +} + +func (e StagingTimeoutError) Error() string { + return fmt.Sprintf("Timed out waiting for application '%s' to stage", e.AppName) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/startup_timeout_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/startup_timeout_error.go new file mode 100644 index 0000000..9f09596 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/startup_timeout_error.go @@ -0,0 +1,13 @@ +package actionerror + +import "fmt" + +// StartupTimeoutError is returned when startup timeout is reached waiting for +// an application to start. +type StartupTimeoutError struct { + Name string +} + +func (e StartupTimeoutError) Error() string { + return fmt.Sprintf("Timed out waiting for application '%s' to start", e.Name) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_not_found_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_not_found_error.go new file mode 100644 index 0000000..412a5b7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_not_found_error.go @@ -0,0 +1,12 @@ +package actionerror + +import "fmt" + +// TaskNotFoundError is returned when no tasks matching the filters are found. +type TaskNotFoundError struct { + SequenceID int +} + +func (e TaskNotFoundError) Error() string { + return fmt.Sprintf("Task sequence ID %d not found.", e.SequenceID) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_workers_unavailable_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_workers_unavailable_error.go new file mode 100644 index 0000000..449d34f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/task_workers_unavailable_error.go @@ -0,0 +1,11 @@ +package actionerror + +// TaskWorkersUnavailableError is returned when there are no workers to run a +// given task. +type TaskWorkersUnavailableError struct { + Message string +} + +func (e TaskWorkersUnavailableError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/tcp_route_options_not_provided_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/tcp_route_options_not_provided_error.go new file mode 100644 index 0000000..64e31a6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/tcp_route_options_not_provided_error.go @@ -0,0 +1,9 @@ +package actionerror + +type TCPRouteOptionsNotProvidedError struct { + Domain string +} + +func (e TCPRouteOptionsNotProvidedError) Error() string { + return "The route is invalid: For TCP routes you must specify a port or request a random one." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/trigger_legacy_push_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/trigger_legacy_push_error.go new file mode 100644 index 0000000..4e8e11e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/trigger_legacy_push_error.go @@ -0,0 +1,20 @@ +package actionerror + +import ( + "fmt" + "strings" +) + +type TriggerLegacyPushError struct { + DomainHostRelated []string + GlobalRelated []string + InheritanceRelated bool + RandomRouteRelated bool +} + +func (e TriggerLegacyPushError) Error() string { + if len(e.DomainHostRelated) > 0 || len(e.GlobalRelated) > 0 { + return fmt.Sprintf("Triggering legacy push due to - Inheritance: %t, Random Route: %t, and Found: %s", e.InheritanceRelated, e.RandomRouteRelated, strings.Join(append(e.DomainHostRelated, e.GlobalRelated...), ", ")) + } + return fmt.Sprintf("Triggering legacy push due to - Inheritance: %t and Random Route: %t", e.InheritanceRelated, e.RandomRouteRelated) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/upload_failed_error.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/upload_failed_error.go new file mode 100644 index 0000000..1f347b7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/upload_failed_error.go @@ -0,0 +1,9 @@ +package actionerror + +type UploadFailedError struct { + Err error +} + +func (UploadFailedError) Error() string { + return "upload failed" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/actionerror/user_not_found.go b/vendor/code.cloudfoundry.org/cli/actor/actionerror/user_not_found.go new file mode 100644 index 0000000..57f50c8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/actionerror/user_not_found.go @@ -0,0 +1,23 @@ +package actionerror + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// UserNotFoundError is an error wrapper that represents the case +// when the user is not found in UAA. +type UserNotFoundError struct { + Username string + Origin string +} + +// Error method to display the error message. +func (e UserNotFoundError) Error() string { + if e.Origin != "" && e.Origin != constant.DefaultOriginUaa { + return fmt.Sprintf("User '%s' with origin '%s' does not exist.", e.Username, e.Origin) + } + + return fmt.Sprintf("User '%s' does not exist.", e.Username) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/actor.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/actor.go new file mode 100644 index 0000000..11f7c31 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/actor.go @@ -0,0 +1,26 @@ +// Package sharedaction handles all operations that do not require a cloud +// controller +package sharedaction + +type AuthActor interface { + IsLoggedIn() bool +} + +// Actor handles all shared actions +type Actor struct { + Config Config + AuthActor +} + +// NewActor returns an Actor with default settings +func NewActor(config Config) *Actor { + var authActor AuthActor = NewDefaultAuthActor(config) + if config.IsCFOnK8s() { + authActor = NewK8sAuthActor(config) + } + + return &Actor{ + AuthActor: authActor, + Config: config, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/auth.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/auth.go new file mode 100644 index 0000000..f7f5910 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/auth.go @@ -0,0 +1,31 @@ +package sharedaction + +type DefaultAuthActor struct { + config Config +} + +func NewDefaultAuthActor(config Config) DefaultAuthActor { + return DefaultAuthActor{ + config: config, + } +} + +func (a DefaultAuthActor) IsLoggedIn() bool { + return a.config.AccessToken() != "" || a.config.RefreshToken() != "" +} + +type K8sAuthActor struct { + config Config +} + +func NewK8sAuthActor(config Config) K8sAuthActor { + return K8sAuthActor{ + config: config, + } +} + +func (a K8sAuthActor) IsLoggedIn() bool { + name, err := a.config.CurrentUserName() + + return err == nil && name != "" +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/check_target.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/check_target.go new file mode 100644 index 0000000..5621e84 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/check_target.go @@ -0,0 +1,51 @@ +package sharedaction + +import "code.cloudfoundry.org/cli/actor/actionerror" + +// CheckTarget confirms that the user is logged in. Optionally it will also +// check if an organization and space are targeted. +func (actor Actor) CheckTarget(targetedOrganizationRequired bool, targetedSpaceRequired bool) error { + if !actor.IsLoggedIn() { + return actionerror.NotLoggedInError{ + BinaryName: actor.Config.BinaryName(), + } + } + + if targetedOrganizationRequired { + if !actor.IsOrgTargeted() { + return actionerror.NoOrganizationTargetedError{ + BinaryName: actor.Config.BinaryName(), + } + } + + if targetedSpaceRequired { + if !actor.IsSpaceTargeted() { + return actionerror.NoSpaceTargetedError{ + BinaryName: actor.Config.BinaryName(), + } + } + } + } + + return nil +} + +func (actor Actor) RequireCurrentUser() (string, error) { + if !actor.IsLoggedIn() { + return "", actionerror.NotLoggedInError{ + BinaryName: actor.Config.BinaryName(), + } + } + + return actor.Config.CurrentUserName() +} + +func (actor Actor) RequireTargetedOrg() (string, error) { + if !actor.IsOrgTargeted() { + return "", actionerror.NoOrganizationTargetedError{ + BinaryName: actor.Config.BinaryName(), + } + } + + return actor.Config.TargetedOrganizationName(), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/config.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/config.go new file mode 100644 index 0000000..32be6d2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/config.go @@ -0,0 +1,16 @@ +package sharedaction + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Config + +// Config a way of getting basic CF configuration +type Config interface { + AccessToken() string + BinaryName() string + CurrentUserName() (string, error) + HasTargetedOrganization() bool + HasTargetedSpace() bool + IsCFOnK8s() bool + RefreshToken() string + TargetedOrganizationName() string + Verbose() (bool, []string) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_unix.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_unix.go new file mode 100644 index 0000000..680fe4c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_unix.go @@ -0,0 +1,12 @@ +//go:build !windows +// +build !windows + +package sharedaction + +import "os" + +// fixMode is unnecessary on UNIX systems, see windows version for more +// details. +func fixMode(mode os.FileMode) os.FileMode { + return mode +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_windows.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_windows.go new file mode 100644 index 0000000..2e726c7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/fix_mode_windows.go @@ -0,0 +1,12 @@ +//go:build windows +// +build windows + +package sharedaction + +import "os" + +// fixMode forces all files on windows to be executable because by default +// everything on windows is read/write only. Even executable files. +func fixMode(mode os.FileMode) os.FileMode { + return mode | 0700 +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/help.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/help.go new file mode 100644 index 0000000..a1120cd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/help.go @@ -0,0 +1,200 @@ +package sharedaction + +import ( + "reflect" + "sort" + "strings" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/util/sorting" +) + +const ( + CommonCommandsIndent string = " " + AllCommandsIndent string = " " + CommandIndent string = " " +) + +// CommandInfo contains the help details of a command +type CommandInfo struct { + // Name is the command name + Name string + + // Description is the command description + Description string + + // Alias is the command alias + Alias string + + // Usage is the command usage string + Usage string + + // Examples is the command examples string + Examples string + + // Resources is the types of object that the command applies to + Resources string + + // RelatedCommands is a list of commands related to the command + RelatedCommands []string + + // Flags contains the list of flags for this command + Flags []CommandFlag + + // Environment is a list of environment variables specific for this command + Environment []EnvironmentVariable +} + +// CommandFlag contains the help details of a command's flag +type CommandFlag struct { + // Short is the short form of the flag + Short string + + // Long is the long form of the flag + Long string + + // Description is the description of the flag + Description string + + // Default is the flag's default value + Default string +} + +// EnvironmentVariable contains env vars specific for this command +type EnvironmentVariable struct { + Name string + Description string + DefaultValue string +} + +// HasUsage is an interface that commands may implement if they want to define their usage +// text in a Usage() method, which gives them more flexibility than a struct tag. +type HasUsage interface { + Usage() string +} + +// HasExamples is an interface that commands may implement if they want to define their examples +// text in a Examples() method, which gives them more flexibility than a struct tag. +type HasExamples interface { + Examples() string +} + +// HasResources is an interface that commands may implement if they want to define their resources +// text in a Resources() method, which gives them more flexibility than a struct tag. +type HasResources interface { + Resources() string +} + +// CommandInfoByName returns the help information for a particular commandName in +// the commandList. +func (Actor) CommandInfoByName(commandList interface{}, commandName string) (CommandInfo, error) { + field, found := reflect.TypeOf(commandList).FieldByNameFunc( + func(fieldName string) bool { + field, _ := reflect.TypeOf(commandList).FieldByName(fieldName) + return field.Tag.Get("command") == commandName || field.Tag.Get("alias") == commandName + }, + ) + + if !found { + return CommandInfo{}, actionerror.InvalidCommandError{CommandName: commandName} + } + + tag := field.Tag + cmd := CommandInfo{ + Name: tag.Get("command"), + Description: tag.Get("description"), + Alias: tag.Get("alias"), + Flags: []CommandFlag{}, + Environment: []EnvironmentVariable{}, + } + + fieldValue := reflect.ValueOf(commandList).FieldByIndex(field.Index) + + if commandWithUsage, hasUsage := fieldValue.Interface().(HasUsage); hasUsage { + cmd.Usage = strings.ReplaceAll( + strings.TrimSpace(commandWithUsage.Usage()), + "\n", + "\n"+CommandIndent, + ) + } + + if commandWithExamples, hasExamples := fieldValue.Interface().(HasExamples); hasExamples { + cmd.Examples = strings.ReplaceAll( + strings.TrimSpace(commandWithExamples.Examples()), + "\n", + "\n"+CommandIndent, + ) + } + + if commandWithResources, hasResources := fieldValue.Interface().(HasResources); hasResources { + cmd.Resources = strings.ReplaceAll( + strings.TrimSpace(commandWithResources.Resources()), + "\n", + "\n"+CommandIndent, + ) + } + + command := field.Type + for i := 0; i < command.NumField(); i++ { + fieldTag := command.Field(i).Tag + + if fieldTag.Get("hidden") != "" { + continue + } + + if cmd.Usage == "" && fieldTag.Get("usage") != "" { + cmd.Usage = fieldTag.Get("usage") + continue + } + + if cmd.Examples == "" && fieldTag.Get("examples") != "" { + cmd.Examples = fieldTag.Get("examples") + continue + } + + if fieldTag.Get("related_commands") != "" { + relatedCommands := strings.Split(fieldTag.Get("related_commands"), ", ") + sort.Slice(relatedCommands, sorting.SortAlphabeticFunc(relatedCommands)) + cmd.RelatedCommands = relatedCommands + continue + } + + if fieldTag.Get("description") != "" { + cmd.Flags = append(cmd.Flags, CommandFlag{ + Short: fieldTag.Get("short"), + Long: fieldTag.Get("long"), + Description: fieldTag.Get("description"), + Default: fieldTag.Get("default"), + }) + } + + if fieldTag.Get("environmentName") != "" { + cmd.Environment = append(cmd.Environment, EnvironmentVariable{ + Name: fieldTag.Get("environmentName"), + DefaultValue: fieldTag.Get("environmentDefault"), + Description: fieldTag.Get("environmentDescription"), + }) + } + } + + return cmd, nil +} + +// CommandInfos returns a slice of CommandInfo that only fills in +// the Name and Description for all the commands in commandList +func (Actor) CommandInfos(commandList interface{}) map[string]CommandInfo { + handler := reflect.TypeOf(commandList) + + infos := make(map[string]CommandInfo, handler.NumField()) + for i := 0; i < handler.NumField(); i++ { + fieldTag := handler.Field(i).Tag + commandName := fieldTag.Get("command") + infos[commandName] = CommandInfo{ + Name: commandName, + Description: fieldTag.Get("description"), + Alias: fieldTag.Get("alias"), + } + } + + return infos +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_org_targeted.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_org_targeted.go new file mode 100644 index 0000000..b9a317b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_org_targeted.go @@ -0,0 +1,6 @@ +package sharedaction + +// IsOrgTargeted determines whether an org is being targeted by the CLI +func (actor Actor) IsOrgTargeted() bool { + return actor.Config.HasTargetedOrganization() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_space_targeted.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_space_targeted.go new file mode 100644 index 0000000..80a45ba --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/is_space_targeted.go @@ -0,0 +1,6 @@ +package sharedaction + +// IsSpaceTargeted determines whether a space is being targeted by the CLI +func (actor Actor) IsSpaceTargeted() bool { + return actor.Config.HasTargetedSpace() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/log_cache_client.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/log_cache_client.go new file mode 100644 index 0000000..ed3403a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/log_cache_client.go @@ -0,0 +1,21 @@ +package sharedaction + +import ( + "context" + "time" + + logcache "code.cloudfoundry.org/go-log-cache" + "code.cloudfoundry.org/go-loggregator/v8/rpc/loggregator_v2" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . LogCacheClient + +// LogCacheClient is a client for getting logs. +type LogCacheClient interface { + Read( + ctx context.Context, + sourceID string, + start time.Time, + opts ...logcache.ReadOption, + ) ([]*loggregator_v2.Envelope, error) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/logging.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/logging.go new file mode 100644 index 0000000..8207676 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/logging.go @@ -0,0 +1,261 @@ +package sharedaction + +import ( + "context" + "errors" + "fmt" + "log" + "strings" + "time" + + logcache "code.cloudfoundry.org/go-log-cache" + "code.cloudfoundry.org/go-log-cache/rpc/logcache_v1" + "code.cloudfoundry.org/go-loggregator/v8/rpc/loggregator_v2" + "github.com/sirupsen/logrus" +) + +const ( + StagingLog = "STG" + RecentLogsLines = 1000 + + retryCount = 5 + retryInterval = time.Millisecond * 250 +) + +type LogMessage struct { + message string + messageType string + timestamp time.Time + sourceType string + sourceInstance string +} + +func (log LogMessage) Message() string { + return log.message +} + +func (log LogMessage) Type() string { + return log.messageType +} + +func (log LogMessage) Staging() bool { + return log.sourceType == StagingLog +} + +func (log LogMessage) Timestamp() time.Time { + return log.timestamp +} + +func (log LogMessage) SourceType() string { + return log.sourceType +} + +func (log LogMessage) SourceInstance() string { + return log.sourceInstance +} + +func NewLogMessage(message string, messageType string, timestamp time.Time, sourceType string, sourceInstance string) *LogMessage { + return &LogMessage{ + message: message, + messageType: messageType, + timestamp: timestamp, + sourceType: sourceType, + sourceInstance: sourceInstance, + } +} + +type LogMessages []*LogMessage + +func (lm LogMessages) Len() int { return len(lm) } + +func (lm LogMessages) Less(i, j int) bool { + return lm[i].timestamp.Before(lm[j].timestamp) +} + +func (lm LogMessages) Swap(i, j int) { + lm[i], lm[j] = lm[j], lm[i] +} + +type channelWriter struct { + errChannel chan error +} + +func (c channelWriter) Write(bytes []byte) (n int, err error) { + c.errChannel <- errors.New(strings.Trim(string(bytes), "\n")) + + return len(bytes), nil +} + +// cliRetryBackoff returns true for OnErr after sleeping the given interval for a limited number of times, +// and returns true for OnEmpty always. +// Basically: retry x times on connection failures, and wait forever for logs to show up. +type cliRetryBackoff struct { + interval time.Duration + maxCount int + count int +} + +func newCliRetryBackoff(interval time.Duration, maxCount int) *cliRetryBackoff { + return &cliRetryBackoff{ + interval: interval, + maxCount: maxCount, + } +} + +func (b *cliRetryBackoff) OnErr(error) bool { + b.count++ + if b.count >= b.maxCount { + return false + } + + time.Sleep(b.interval) + return true +} + +func (b *cliRetryBackoff) OnEmpty() bool { + time.Sleep(b.interval) + return true +} + +func (b *cliRetryBackoff) Reset() { + b.count = 0 +} + +func GetStreamingLogs(appGUID string, client LogCacheClient) (<-chan LogMessage, <-chan error, context.CancelFunc) { + + logrus.Info("Start Tailing Logs") + + outgoingLogStream := make(chan LogMessage, 1000) + outgoingErrStream := make(chan error, 1000) + ctx, cancelFunc := context.WithCancel(context.Background()) + go func() { + defer close(outgoingLogStream) + defer close(outgoingErrStream) + + ts := latestEnvelopeTimestamp(client, outgoingErrStream, ctx, appGUID) + + // if the context was cancelled we may not have seen an envelope + if ts.IsZero() { + return + } + + const offset = 1 * time.Second + walkStartTime := ts.Add(-offset) + + logcache.Walk( + ctx, + appGUID, + logcache.Visitor(func(envelopes []*loggregator_v2.Envelope) bool { + logMessages := convertEnvelopesToLogMessages(envelopes) + for _, logMessage := range logMessages { + select { + case <-ctx.Done(): + return false + default: + outgoingLogStream <- *logMessage + } + } + return true + }), + client.Read, + logcache.WithWalkDelay(2*time.Second), + logcache.WithWalkStartTime(walkStartTime), + logcache.WithWalkEnvelopeTypes(logcache_v1.EnvelopeType_LOG), + logcache.WithWalkBackoff(newCliRetryBackoff(retryInterval, retryCount)), + logcache.WithWalkLogger(log.New(channelWriter{ + errChannel: outgoingErrStream, + }, "", 0)), + ) + }() + + return outgoingLogStream, outgoingErrStream, cancelFunc +} + +func latestEnvelopeTimestamp(client LogCacheClient, errs chan error, ctx context.Context, sourceID string) time.Time { + + // Fetching the most recent timestamp could be implemented with client.Read directly rather than using logcache.Walk + // We use Walk because we want the extra retry behavior provided through Walk + + // Wrap client.Read in our own function to allow us to specify our own read options + // https://github.com/cloudfoundry/go-log-cache/issues/27 + r := func(ctx context.Context, sourceID string, _ time.Time, opts ...logcache.ReadOption) ([]*loggregator_v2.Envelope, error) { + os := []logcache.ReadOption{ + logcache.WithLimit(1), + logcache.WithDescending(), + } + for _, o := range opts { + os = append(os, o) + } + return client.Read(ctx, sourceID, time.Time{}, os...) + } + + var timestamp time.Time + + logcache.Walk( + ctx, + sourceID, + logcache.Visitor(func(envelopes []*loggregator_v2.Envelope) bool { + timestamp = time.Unix(0, envelopes[0].Timestamp) + return false + }), + r, + logcache.WithWalkBackoff(newCliRetryBackoff(retryInterval, retryCount)), + logcache.WithWalkLogger(log.New(channelWriter{ + errChannel: errs, + }, "", 0)), + ) + + return timestamp +} + +func GetRecentLogs(appGUID string, client LogCacheClient) ([]LogMessage, error) { + logLineRequestCount := RecentLogsLines + var envelopes []*loggregator_v2.Envelope + var err error + + for logLineRequestCount >= 1 { + envelopes, err = client.Read( + context.Background(), + appGUID, + time.Time{}, + logcache.WithEnvelopeTypes(logcache_v1.EnvelopeType_LOG), + logcache.WithLimit(logLineRequestCount), + logcache.WithDescending(), + ) + if err == nil || err.Error() != "unexpected status code 429" { + break + } + logLineRequestCount /= 2 + } + if err != nil { + return nil, fmt.Errorf("Failed to retrieve logs from Log Cache: %s", err) + } + + logMessages := convertEnvelopesToLogMessages(envelopes) + var reorderedLogMessages []LogMessage + for i := len(logMessages) - 1; i >= 0; i-- { + reorderedLogMessages = append(reorderedLogMessages, *logMessages[i]) + } + + return reorderedLogMessages, nil +} + +func convertEnvelopesToLogMessages(envelopes []*loggregator_v2.Envelope) []*LogMessage { + var logMessages []*LogMessage + for _, envelope := range envelopes { + logEnvelope, ok := envelope.GetMessage().(*loggregator_v2.Envelope_Log) + if !ok { + continue + } + log := logEnvelope.Log + + logMessages = append(logMessages, NewLogMessage( + string(log.Payload), + loggregator_v2.Log_Type_name[int32(log.Type)], + time.Unix(0, envelope.GetTimestamp()), + envelope.GetTags()["source_type"], + envelope.GetInstanceId(), + )) + } + return logMessages +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/resource.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/resource.go new file mode 100644 index 0000000..944883b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/resource.go @@ -0,0 +1,516 @@ +package sharedaction + +import ( + "archive/zip" + "crypto/sha1" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/ykk" + ignore "github.com/sabhiram/go-gitignore" + log "github.com/sirupsen/logrus" +) + +const ( + DefaultFolderPermissions = 0755 + DefaultArchiveFilePermissions = 0744 + MaxResourceMatchChunkSize = 1000 +) + +var DefaultIgnoreLines = []string{ + ".cfignore", + ".DS_Store", + ".git", + ".gitignore", + ".hg", + ".svn", + "_darcs", + "manifest.yaml", + "manifest.yml", +} + +type Resource struct { + Filename string `json:"fn"` + Mode os.FileMode `json:"mode"` + SHA1 string `json:"sha1"` + Size int64 `json:"size"` +} + +type V3Resource ccv3.Resource + +// ToV3Resource converts a sharedaction Resource to V3 Resource format +func (r Resource) ToV3Resource() V3Resource { + return V3Resource{ + FilePath: r.Filename, + Mode: r.Mode, + Checksum: ccv3.Checksum{Value: r.SHA1}, + SizeInBytes: r.Size, + } +} + +// ToV2Resource converts a V3 Resource to V2 Resource format +func (r V3Resource) ToV2Resource() Resource { + return Resource{ + Filename: r.FilePath, + Mode: r.Mode, + SHA1: r.Checksum.Value, + Size: r.SizeInBytes, + } +} + +// GatherArchiveResources returns a list of resources for an archive. +func (actor Actor) GatherArchiveResources(archivePath string) ([]Resource, error) { + var resources []Resource + + archive, err := os.Open(archivePath) + if err != nil { + return nil, err + } + defer archive.Close() + + reader, err := actor.newArchiveReader(archive) + if err != nil { + return nil, err + } + + gitIgnore, err := actor.generateArchiveCFIgnoreMatcher(reader.File) + if err != nil { + log.Errorln("reading .cfignore file:", err) + return nil, err + } + + for _, archivedFile := range reader.File { + filename := filepath.ToSlash(archivedFile.Name) + if gitIgnore.MatchesPath(filename) { + continue + } + + resource := Resource{Filename: filename} + info := archivedFile.FileInfo() + + switch { + case info.IsDir(): + resource.Mode = DefaultFolderPermissions + case info.Mode()&os.ModeSymlink == os.ModeSymlink: + resource.Mode = info.Mode() + default: + fileReader, err := archivedFile.Open() + if err != nil { + return nil, err + } + defer fileReader.Close() + + hash := sha1.New() + + _, err = io.Copy(hash, fileReader) + if err != nil { + return nil, err + } + + resource.Mode = DefaultArchiveFilePermissions + resource.SHA1 = fmt.Sprintf("%x", hash.Sum(nil)) + resource.Size = archivedFile.FileInfo().Size() + } + + resources = append(resources, resource) + } + if len(resources) <= 1 { + return nil, actionerror.EmptyArchiveError{Path: archivePath} + } + return resources, nil +} + +// GatherDirectoryResources returns a list of resources for a directory. +func (actor Actor) GatherDirectoryResources(sourceDir string) ([]Resource, error) { + var ( + resources []Resource + gitIgnore *ignore.GitIgnore + ) + + gitIgnore, err := actor.generateDirectoryCFIgnoreMatcher(sourceDir) + if err != nil { + log.Errorln("reading .cfignore file:", err) + return nil, err + } + + evalDir, err := filepath.EvalSymlinks(sourceDir) + if err != nil { + log.Errorln("evaluating symlink:", err) + return nil, err + } + + walkErr := filepath.Walk(evalDir, func(fullPath string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + relPath, err := filepath.Rel(evalDir, fullPath) + if err != nil { + return err + } + + // if file ignored continue to the next file + if gitIgnore.MatchesPath(relPath) { + return nil + } + + if relPath == "." { + return nil + } + + resource := Resource{ + Filename: filepath.ToSlash(relPath), + } + + switch { + case info.IsDir(): + // If the file is a directory + resource.Mode = DefaultFolderPermissions + case info.Mode()&os.ModeSymlink == os.ModeSymlink: + // If the file is a Symlink we just set the mode of the file + // We won't be using any sha information since we don't do + // any resource matching on symlinks. + resource.Mode = fixMode(info.Mode()) + default: + // If the file is regular we want to open + // and calculate the sha of the file + file, err := os.Open(fullPath) + if err != nil { + return err + } + defer file.Close() + + sum := sha1.New() + _, err = io.Copy(sum, file) + if err != nil { + return err + } + + resource.Mode = fixMode(info.Mode()) + resource.SHA1 = fmt.Sprintf("%x", sum.Sum(nil)) + resource.Size = info.Size() + } + + resources = append(resources, resource) + return nil + }) + + if len(resources) == 0 { + return nil, actionerror.EmptyDirectoryError{Path: sourceDir} + } + + return resources, walkErr +} + +// ZipArchiveResources zips an archive and a sorted (based on full +// path/filename) list of resources and returns the location. On Windows, the +// filemode for user is forced to be readable and executable. +func (actor Actor) ZipArchiveResources(sourceArchivePath string, filesToInclude []Resource) (string, error) { + log.WithField("sourceArchive", sourceArchivePath).Info("zipping source files from archive") + zipFile, err := ioutil.TempFile("", "cf-cli-") + if err != nil { + return "", err + } + defer zipFile.Close() + zipPath := zipFile.Name() + + writer := zip.NewWriter(zipFile) + defer writer.Close() + + source, err := os.Open(sourceArchivePath) + if err != nil { + return zipPath, err + } + defer source.Close() + + reader, err := actor.newArchiveReader(source) + if err != nil { + return zipPath, err + } + + for _, archiveFile := range reader.File { + resource, ok := actor.findInResources(archiveFile.Name, filesToInclude) + if !ok { + log.WithField("archiveFileName", archiveFile.Name).Debug("skipping file") + continue + } + + log.WithField("archiveFileName", archiveFile.Name).Debug("zipping file") + // archiveFile.Open opens the symlink file, not the file it points too + reader, openErr := archiveFile.Open() + if openErr != nil { + log.WithField("archiveFile", archiveFile.Name).Errorln("opening path in dir:", openErr) + return zipPath, openErr + } + defer reader.Close() + + err = actor.addFileToZipFromFileSystem( + resource.Filename, reader, archiveFile.FileInfo(), + resource, writer, + ) + if err != nil { + log.WithField("archiveFileName", archiveFile.Name).Errorln("zipping file:", err) + return zipPath, err + } + reader.Close() + } + + log.WithFields(log.Fields{ + "zip_file_location": zipFile.Name(), + "zipped_file_count": len(filesToInclude), + }).Info("zip file created") + return zipPath, nil +} + +// ZipDirectoryResources zips a directory and a sorted (based on full +// path/filename) list of resources and returns the location. On Windows, the +// filemode for user is forced to be readable and executable. +func (actor Actor) ZipDirectoryResources(sourceDir string, filesToInclude []Resource) (string, error) { + log.WithField("sourceDir", sourceDir).Info("zipping source files from directory") + zipFile, err := ioutil.TempFile("", "cf-cli-") + if err != nil { + return "", err + } + defer zipFile.Close() + zipPath := zipFile.Name() + + writer := zip.NewWriter(zipFile) + defer writer.Close() + + for _, resource := range filesToInclude { + fullPath := filepath.Join(sourceDir, resource.Filename) + log.WithField("fullPath", fullPath).Debug("zipping file") + + fileInfo, err := os.Lstat(fullPath) + if err != nil { + log.WithField("fullPath", fullPath).Errorln("stat error in dir:", err) + return zipPath, err + } + + log.WithField("file-mode", fileInfo.Mode().String()).Debug("resource file info") + if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink { + // we need to user os.Readlink to read a symlink file from a directory + err = actor.addLinkToZipFromFileSystem(fullPath, fileInfo, resource, writer) + if err != nil { + log.WithField("fullPath", fullPath).Errorln("zipping file:", err) + return zipPath, err + } + } else { + srcFile, err := os.Open(fullPath) + if err != nil { + log.WithField("fullPath", fullPath).Errorln("opening path in dir:", err) + return zipPath, err + } + defer srcFile.Close() + + err = actor.addFileToZipFromFileSystem( + fullPath, srcFile, fileInfo, + resource, writer, + ) + srcFile.Close() + if err != nil { + log.WithField("fullPath", fullPath).Errorln("zipping file:", err) + return zipPath, err + } + } + } + + log.WithFields(log.Fields{ + "zip_file_location": zipFile.Name(), + "zipped_file_count": len(filesToInclude), + }).Info("zip file created") + return zipPath, nil +} + +func (Actor) addLinkToZipFromFileSystem(srcPath string, + fileInfo os.FileInfo, resource Resource, + zipFile *zip.Writer, +) error { + header, err := zip.FileInfoHeader(fileInfo) + if err != nil { + log.WithField("srcPath", srcPath).Errorln("getting file info in dir:", err) + return err + } + + header.Name = resource.Filename + header.Method = zip.Deflate + + log.WithFields(log.Fields{ + "srcPath": srcPath, + "destPath": header.Name, + "mode": header.Mode().String(), + }).Debug("setting mode for file") + + destFileWriter, err := zipFile.CreateHeader(header) + if err != nil { + log.Errorln("creating header:", err) + return err + } + + pathInSymlink, err := os.Readlink(srcPath) + if err != nil { + return err + } + log.WithField("path", pathInSymlink).Debug("resolving symlink") + symLinkContents := strings.NewReader(pathInSymlink) + if _, err := io.Copy(destFileWriter, symLinkContents); err != nil { + log.WithField("srcPath", srcPath).Errorln("copying data in dir:", err) + return err + } + + return nil +} + +func (Actor) addFileToZipFromFileSystem(srcPath string, + srcFile io.Reader, fileInfo os.FileInfo, resource Resource, + zipFile *zip.Writer, +) error { + header, err := zip.FileInfoHeader(fileInfo) + if err != nil { + log.WithField("srcPath", srcPath).Errorln("getting file info in dir:", err) + return err + } + + header.Name = resource.Filename + + // An extra '/' indicates that this file is a directory + if fileInfo.IsDir() && !strings.HasSuffix(resource.Filename, "/") { + header.Name += "/" + } + header.Method = zip.Deflate + header.SetMode(resource.Mode) + + log.WithFields(log.Fields{ + "srcPath": srcPath, + "destPath": header.Name, + "mode": header.Mode().String(), + }).Debug("setting mode for file") + + destFileWriter, err := zipFile.CreateHeader(header) + if err != nil { + log.Errorln("creating header:", err) + return err + } + + if fileInfo.Mode().IsRegular() { + sum := sha1.New() + multi := io.MultiWriter(sum, destFileWriter) + + if _, err := io.Copy(multi, srcFile); err != nil { + log.WithField("srcPath", srcPath).Errorln("copying data in dir:", err) + return err + } + + if currentSum := fmt.Sprintf("%x", sum.Sum(nil)); resource.SHA1 != currentSum { + log.WithFields(log.Fields{ + "expected": resource.SHA1, + "currentSum": currentSum, + }).Error("setting mode for file") + return actionerror.FileChangedError{Filename: srcPath} + } + } else if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink { + _, err = io.Copy(destFileWriter, srcFile) + if err != nil { + return err + } + } + + return nil +} + +func (Actor) generateArchiveCFIgnoreMatcher(files []*zip.File) (*ignore.GitIgnore, error) { + for _, item := range files { + if strings.HasSuffix(item.Name, ".cfignore") { + fileReader, err := item.Open() + if err != nil { + return nil, err + } + defer fileReader.Close() + + raw, err := ioutil.ReadAll(fileReader) + if err != nil { + return nil, err + } + s := append(DefaultIgnoreLines, strings.Split(string(raw), "\n")...) + return ignore.CompileIgnoreLines(s...) + } + } + return ignore.CompileIgnoreLines(DefaultIgnoreLines...) +} + +func (actor Actor) generateDirectoryCFIgnoreMatcher(sourceDir string) (*ignore.GitIgnore, error) { + pathToCFIgnore := filepath.Join(sourceDir, ".cfignore") + log.WithFields(log.Fields{ + "pathToCFIgnore": pathToCFIgnore, + "sourceDir": sourceDir, + }).Debug("using ignore file") + + additionalIgnoreLines := DefaultIgnoreLines + + // If verbose logging has files in the current dir, ignore them + _, traceFiles := actor.Config.Verbose() + for _, traceFilePath := range traceFiles { + if relPath, err := filepath.Rel(sourceDir, traceFilePath); err == nil { + additionalIgnoreLines = append(additionalIgnoreLines, relPath) + } + } + + log.Debugf("ignore rules: %v", additionalIgnoreLines) + + if _, err := os.Stat(pathToCFIgnore); !os.IsNotExist(err) { + return ignore.CompileIgnoreFileAndLines(pathToCFIgnore, additionalIgnoreLines...) + } + return ignore.CompileIgnoreLines(additionalIgnoreLines...) +} + +func (Actor) findInResources(path string, filesToInclude []Resource) (Resource, bool) { + for _, resource := range filesToInclude { + if resource.Filename == filepath.ToSlash(path) { + log.WithField("resource", resource.Filename).Debug("found resource in files to include") + return resource, true + } + } + + log.WithField("path", path).Debug("did not find resource in files to include") + return Resource{}, false +} + +func (Actor) newArchiveReader(archive *os.File) (*zip.Reader, error) { + info, err := archive.Stat() + if err != nil { + return nil, err + } + + return ykk.NewReader(archive, info.Size()) +} + +func (actor Actor) CreateArchive(bitsPath string, resources []Resource) (io.ReadCloser, int64, error) { + archivePath, err := actor.ZipDirectoryResources(bitsPath, resources) + _ = err + + return actor.ReadArchive(archivePath) +} + +func (Actor) ReadArchive(archivePath string) (io.ReadCloser, int64, error) { + archive, err := os.Open(archivePath) + if err != nil { + log.WithField("archivePath", archivePath).Errorln("opening temp archive:", err) + return nil, -1, err + } + + archiveInfo, err := archive.Stat() + if err != nil { + archive.Close() + log.WithField("archivePath", archivePath).Errorln("stat temp archive:", err) + return nil, -1, err + } + + return archive, archiveInfo.Size(), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/secure_shell_client.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/secure_shell_client.go new file mode 100644 index 0000000..af27600 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/secure_shell_client.go @@ -0,0 +1,13 @@ +package sharedaction + +import "code.cloudfoundry.org/cli/util/clissh" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SecureShellClient + +type SecureShellClient interface { + Connect(username string, passcode string, sshEndpoint string, sshHostKeyFingerprint string, skipHostValidation bool) error + Close() error + InteractiveSession(commands []string, terminalRequest clissh.TTYRequest) error + LocalPortForward(localPortForwardSpecs []clissh.LocalPortForward) error + Wait() error +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/sharedaction/ssh.go b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/ssh.go new file mode 100644 index 0000000..600d4cc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/sharedaction/ssh.go @@ -0,0 +1,56 @@ +package sharedaction + +import "code.cloudfoundry.org/cli/util/clissh" + +type TTYOption clissh.TTYRequest + +const ( + RequestTTYAuto TTYOption = iota + RequestTTYNo + RequestTTYYes + RequestTTYForce +) + +type LocalPortForward clissh.LocalPortForward + +type SSHOptions struct { + Commands []string + Username string + Passcode string + Endpoint string + HostKeyFingerprint string + SkipHostValidation bool + SkipRemoteExecution bool + TTYOption TTYOption + LocalPortForwardSpecs []LocalPortForward +} + +func (actor Actor) ExecuteSecureShell(sshClient SecureShellClient, sshOptions SSHOptions) error { + err := sshClient.Connect(sshOptions.Username, sshOptions.Passcode, sshOptions.Endpoint, sshOptions.HostKeyFingerprint, sshOptions.SkipHostValidation) + if err != nil { + return err + } + defer sshClient.Close() + + err = sshClient.LocalPortForward(convertActorToSSHPackageForwardingSpecs(sshOptions.LocalPortForwardSpecs)) + if err != nil { + return err + } + + if sshOptions.SkipRemoteExecution { + err = sshClient.Wait() + } else { + err = sshClient.InteractiveSession(sshOptions.Commands, clissh.TTYRequest(sshOptions.TTYOption)) + } + return err +} + +func convertActorToSSHPackageForwardingSpecs(actorSpecs []LocalPortForward) []clissh.LocalPortForward { + sshPackageSpecs := []clissh.LocalPortForward{} + + for _, spec := range actorSpecs { + sshPackageSpecs = append(sshPackageSpecs, clissh.LocalPortForward(spec)) + } + + return sshPackageSpecs +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/actor.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/actor.go new file mode 100644 index 0000000..6fb6cbe --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/actor.go @@ -0,0 +1,63 @@ +// Package v7action contains the business logic for the commands/v7 package +package v7action + +import ( + "code.cloudfoundry.org/cli/api/uaa/constant" + "code.cloudfoundry.org/cli/cf/configuration/coreconfig" + "code.cloudfoundry.org/cli/util/configv3" + "code.cloudfoundry.org/clock" +) + +// SortOrder is used for sorting. +type SortOrder string + +const ( + Ascending SortOrder = "Ascending" + Descending SortOrder = "Descending" +) + +// Warnings is a list of warnings returned back from the cloud controller +type Warnings []string + +type AuthActor interface { + Authenticate(credentials map[string]string, origin string, grantType constant.GrantType) error + GetLoginPrompts() (map[string]coreconfig.AuthPrompt, error) + GetCurrentUser() (configv3.User, error) +} + +// Actor represents a V7 actor. +type Actor struct { + CloudControllerClient CloudControllerClient + Config Config + SharedActor SharedActor + UAAClient UAAClient + RoutingClient RoutingClient + Clock clock.Clock + + AuthActor +} + +// NewActor returns a new V7 actor. +func NewActor( + client CloudControllerClient, + config Config, + sharedActor SharedActor, + uaaClient UAAClient, + routingClient RoutingClient, + clk clock.Clock, +) *Actor { + authActor := NewDefaultAuthActor(config, uaaClient) + if config != nil && config.IsCFOnK8s() { + authActor = NewKubernetesAuthActor(config, NewDefaultKubernetesConfigGetter(), client) + } + + return &Actor{ + CloudControllerClient: client, + Config: config, + SharedActor: sharedActor, + UAAClient: uaaClient, + RoutingClient: routingClient, + Clock: clk, + AuthActor: authActor, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/application.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/application.go new file mode 100644 index 0000000..95f1abb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/application.go @@ -0,0 +1,464 @@ +package v7action + +import ( + "errors" + "fmt" + "time" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/batcher" + "code.cloudfoundry.org/cli/util/unique" +) + +func (actor Actor) DeleteApplicationByNameAndSpace(name, spaceGUID string, deleteRoutes bool) (Warnings, error) { + var allWarnings Warnings + var jobQueue []ccv3.JobURL + + app, getAppWarnings, err := actor.GetApplicationByNameAndSpace(name, spaceGUID) + allWarnings = append(allWarnings, getAppWarnings...) + if err != nil { + return allWarnings, err + } + + var routes []resources.Route + if deleteRoutes { + var getRoutesWarnings Warnings + routes, getRoutesWarnings, err = actor.GetApplicationRoutes(app.GUID) + allWarnings = append(allWarnings, getRoutesWarnings...) + if err != nil { + return allWarnings, err + } + + for _, route := range routes { + if len(route.Destinations) > 1 { + for _, destination := range route.Destinations { + guid := destination.App.GUID + if guid != app.GUID { + return allWarnings, actionerror.RouteBoundToMultipleAppsError{AppName: app.Name, RouteURL: route.URL} + } + } + } + } + } + + appDeleteJobURL, deleteAppWarnings, err := actor.CloudControllerClient.DeleteApplication(app.GUID) + allWarnings = append(allWarnings, deleteAppWarnings...) + if err != nil { + return allWarnings, err + } + + pollWarnings, err := actor.CloudControllerClient.PollJob(appDeleteJobURL) + allWarnings = append(allWarnings, pollWarnings...) + if err != nil { + return allWarnings, err + } + + if deleteRoutes { + for _, route := range routes { + jobURL, deleteRouteWarnings, err := actor.CloudControllerClient.DeleteRoute(route.GUID) + allWarnings = append(allWarnings, deleteRouteWarnings...) + if err != nil { + if _, ok := err.(ccerror.ResourceNotFoundError); ok { + continue + } + return allWarnings, err + } + + jobQueue = append(jobQueue, jobURL) + } + } + + for _, job := range jobQueue { + pollWarnings, err := actor.CloudControllerClient.PollJob(job) + allWarnings = append(allWarnings, pollWarnings...) + if err != nil { + return allWarnings, err + } + } + + return allWarnings, err +} + +func (actor Actor) GetApplicationsByGUIDs(appGUIDs []string) ([]resources.Application, Warnings, error) { + uniqueAppGUIDs := unique.StringSlice(appGUIDs) + + var apps []resources.Application + warnings, err := batcher.RequestByGUID(appGUIDs, func(guids []string) (ccv3.Warnings, error) { + batch, warnings, err := actor.CloudControllerClient.GetApplications( + ccv3.Query{Key: ccv3.GUIDFilter, Values: guids}, + ) + apps = append(apps, batch...) + return warnings, err + }) + + if err != nil { + return nil, Warnings(warnings), err + } + + if len(apps) < len(uniqueAppGUIDs) { + return nil, Warnings(warnings), actionerror.ApplicationsNotFoundError{} + } + + return apps, Warnings(warnings), nil +} + +func (actor Actor) GetApplicationsByNamesAndSpace(appNames []string, spaceGUID string) ([]resources.Application, Warnings, error) { + uniqueAppNames := unique.StringSlice(appNames) + + apps, warnings, err := actor.CloudControllerClient.GetApplications( + ccv3.Query{Key: ccv3.NameFilter, Values: appNames}, + ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + ) + + if err != nil { + return nil, Warnings(warnings), err + } + + if len(apps) < len(uniqueAppNames) { + return nil, Warnings(warnings), actionerror.ApplicationsNotFoundError{} + } + + return apps, Warnings(warnings), nil +} + +// GetApplicationByNameAndSpace returns the application with the given +// name in the given space. +func (actor Actor) GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, Warnings, error) { + apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{appName}, spaceGUID) + + if err != nil { + if _, ok := err.(actionerror.ApplicationsNotFoundError); ok { + return resources.Application{}, warnings, actionerror.ApplicationNotFoundError{Name: appName} + } + return resources.Application{}, warnings, err + } + + return apps[0], warnings, nil +} + +// GetApplicationsBySpace returns all applications in a space. +func (actor Actor) GetApplicationsBySpace(spaceGUID string) ([]resources.Application, Warnings, error) { + apps, warnings, err := actor.CloudControllerClient.GetApplications( + ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + ) + + if err != nil { + return []resources.Application{}, Warnings(warnings), err + } + + return apps, Warnings(warnings), nil +} + +// CreateApplicationInSpace creates and returns the application with the given +// name in the given space. +func (actor Actor) CreateApplicationInSpace(app resources.Application, spaceGUID string) (resources.Application, Warnings, error) { + createdApp, warnings, err := actor.CloudControllerClient.CreateApplication( + resources.Application{ + LifecycleType: app.LifecycleType, + LifecycleBuildpacks: app.LifecycleBuildpacks, + StackName: app.StackName, + Name: app.Name, + SpaceGUID: spaceGUID, + }) + + if err != nil { + return resources.Application{}, Warnings(warnings), err + } + + return createdApp, Warnings(warnings), nil +} + +// SetApplicationProcessHealthCheckTypeByNameAndSpace sets the health check +// information of the provided processType for an application with the given +// name and space GUID. +func (actor Actor) SetApplicationProcessHealthCheckTypeByNameAndSpace( + appName string, + spaceGUID string, + healthCheckType constant.HealthCheckType, + httpEndpoint string, + processType string, + invocationTimeout int64, +) (resources.Application, Warnings, error) { + + app, getWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return resources.Application{}, getWarnings, err + } + + setWarnings, err := actor.UpdateProcessByTypeAndApplication( + processType, + app.GUID, + resources.Process{ + HealthCheckType: healthCheckType, + HealthCheckEndpoint: httpEndpoint, + HealthCheckInvocationTimeout: invocationTimeout, + }) + return app, append(getWarnings, setWarnings...), err +} + +// StopApplication stops an application. +func (actor Actor) StopApplication(appGUID string) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.UpdateApplicationStop(appGUID) + + return Warnings(warnings), err +} + +// StartApplication starts an application. +func (actor Actor) StartApplication(appGUID string) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.UpdateApplicationStart(appGUID) + return Warnings(warnings), err +} + +// RestartApplication restarts an application and waits for it to start. +func (actor Actor) RestartApplication(appGUID string, noWait bool) (Warnings, error) { + // var allWarnings Warnings + _, warnings, err := actor.CloudControllerClient.UpdateApplicationRestart(appGUID) + return Warnings(warnings), err +} + +func (actor Actor) GetUnstagedNewestPackageGUID(appGUID string) (string, Warnings, error) { + var err error + var allWarnings Warnings + packages, warnings, err := actor.CloudControllerClient.GetPackages( + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, + ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}}) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", allWarnings, err + } + if len(packages) == 0 { + return "", allWarnings, nil + } + + newestPackage := packages[0] + + droplets, warnings, err := actor.CloudControllerClient.GetPackageDroplets( + newestPackage.GUID, + ccv3.Query{Key: ccv3.StatesFilter, Values: []string{"STAGED"}}, + ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}}, + ) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", allWarnings, err + } + + if len(droplets) == 0 { + return newestPackage.GUID, allWarnings, nil + } + + return "", allWarnings, nil +} + +// PollStart polls an application's processes until some are started. If noWait is false, +// it waits for at least one instance of all processes to be running. If noWait is true, +// it only waits for an instance of the web process to be running. +func (actor Actor) PollStart(app resources.Application, noWait bool, handleInstanceDetails func(string)) (Warnings, error) { + var allWarnings Warnings + processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(app.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + var filteredProcesses []resources.Process + if noWait { + for _, process := range processes { + if process.Type == constant.ProcessTypeWeb { + filteredProcesses = append(filteredProcesses, process) + } + } + } else { + filteredProcesses = processes + } + + timer := actor.Clock.NewTimer(time.Millisecond) + defer timer.Stop() + timeout := actor.Clock.After(actor.Config.StartupTimeout()) + + for { + select { + case <-timeout: + return allWarnings, actionerror.StartupTimeoutError{Name: app.Name} + case <-timer.C(): + stopPolling, warnings, err := actor.PollProcesses(filteredProcesses, handleInstanceDetails) + allWarnings = append(allWarnings, warnings...) + if stopPolling || err != nil { + return allWarnings, err + } + + timer.Reset(actor.Config.PollingInterval()) + } + } +} + +// PollStartForRolling polls a deploying application's processes until some are started. It does the same thing as PollStart, except it accounts for rolling deployments and whether +// they have failed or been canceled during polling. +func (actor Actor) PollStartForRolling(app resources.Application, deploymentGUID string, noWait bool, handleInstanceDetails func(string)) (Warnings, error) { + var ( + deployment resources.Deployment + processes []resources.Process + allWarnings Warnings + ) + + timer := actor.Clock.NewTimer(time.Millisecond) + defer timer.Stop() + timeout := actor.Clock.After(actor.Config.StartupTimeout()) + + for { + select { + case <-timeout: + warnings, err := actor.CancelDeployment(deploymentGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + return allWarnings, actionerror.StartupTimeoutError{Name: app.Name} + case <-timer.C(): + if !isDeployed(deployment) { + ccDeployment, warnings, err := actor.getDeployment(deploymentGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + deployment = ccDeployment + processes, warnings, err = actor.getProcesses(deployment, app.GUID, noWait) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + } + + if noWait || isDeployed(deployment) { + stopPolling, warnings, err := actor.PollProcesses(processes, handleInstanceDetails) + allWarnings = append(allWarnings, warnings...) + if stopPolling || err != nil { + return allWarnings, err + } + } + + timer.Reset(actor.Config.PollingInterval()) + } + } +} + +func isDeployed(d resources.Deployment) bool { + return d.StatusValue == constant.DeploymentStatusValueFinalized && d.StatusReason == constant.DeploymentStatusReasonDeployed +} + +// PollProcesses - return true if there's no need to keep polling +func (actor Actor) PollProcesses(processes []resources.Process, handleInstanceDetails func(string)) (bool, Warnings, error) { + numProcesses := len(processes) + numStableProcesses := 0 + var allWarnings Warnings + for _, process := range processes { + ccInstances, ccWarnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID) + instances := ProcessInstances(ccInstances) + allWarnings = append(allWarnings, ccWarnings...) + if err != nil { + return true, allWarnings, err + } + + handleInstanceDetails(formatInstanceDetails(instances)) + + if instances.Empty() || instances.AnyRunning() { + numStableProcesses += 1 + continue + } + + if instances.AllCrashed() { + return true, allWarnings, actionerror.AllInstancesCrashedError{} + } + + //precondition: !instances.Empty() && no instances are running + // do not increment numStableProcesses + return false, allWarnings, nil + } + return numStableProcesses == numProcesses, allWarnings, nil +} + +// UpdateApplication updates the buildpacks on an application +func (actor Actor) UpdateApplication(app resources.Application) (resources.Application, Warnings, error) { + ccApp := resources.Application{ + GUID: app.GUID, + StackName: app.StackName, + LifecycleType: app.LifecycleType, + LifecycleBuildpacks: app.LifecycleBuildpacks, + Metadata: app.Metadata, + Name: app.Name, + } + + updatedApp, warnings, err := actor.CloudControllerClient.UpdateApplication(ccApp) + if err != nil { + return resources.Application{}, Warnings(warnings), err + } + + return updatedApp, Warnings(warnings), nil +} + +func (actor Actor) getDeployment(deploymentGUID string) (resources.Deployment, Warnings, error) { + deployment, warnings, err := actor.CloudControllerClient.GetDeployment(deploymentGUID) + if err != nil { + return deployment, Warnings(warnings), err + } + + if deployment.StatusValue == constant.DeploymentStatusValueFinalized { + switch deployment.StatusReason { + case constant.DeploymentStatusReasonCanceled: + return deployment, Warnings(warnings), errors.New("Deployment has been canceled") + case constant.DeploymentStatusReasonSuperseded: + return deployment, Warnings(warnings), errors.New("Deployment has been superseded") + } + } + + return deployment, Warnings(warnings), err +} + +func (actor Actor) getProcesses(deployment resources.Deployment, appGUID string, noWait bool) ([]resources.Process, Warnings, error) { + if noWait { + // these are only web processes for now so we can just use these + return deployment.NewProcesses, nil, nil + } + + // if the deployment is deployed we know web are all running and PollProcesses will see those as stable + // so just getting all processes is equivalent to just getting non-web ones and polling those + if isDeployed(deployment) { + processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID) + if err != nil { + return processes, Warnings(warnings), err + } + return processes, Warnings(warnings), nil + } + + return nil, nil, nil +} + +func (actor Actor) RenameApplicationByNameAndSpaceGUID(appName, newAppName, spaceGUID string) (resources.Application, Warnings, error) { + allWarnings := Warnings{} + application, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Application{}, allWarnings, err + } + application.Name = newAppName + application, warnings, err = actor.UpdateApplication(application) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Application{}, allWarnings, err + } + + return application, allWarnings, nil +} + +func formatInstanceDetails(instances ProcessInstances) string { + for _, instance := range instances { + if instance.Details != "" { + return fmt.Sprintf("Error starting instances: '%s'", instance.Details) + } + } + return "Instances starting..." +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/application_feature.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_feature.go new file mode 100644 index 0000000..24c00e7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_feature.go @@ -0,0 +1,40 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) GetAppFeature(appGUID string, featureName string) (resources.ApplicationFeature, Warnings, error) { + appFeature, warnings, err := actor.CloudControllerClient.GetAppFeature(appGUID, featureName) + + return appFeature, Warnings(warnings), err +} + +func (actor Actor) GetSSHEnabled(appGUID string) (ccv3.SSHEnabled, Warnings, error) { + sshEnabled, warnings, err := actor.CloudControllerClient.GetSSHEnabled(appGUID) + return sshEnabled, Warnings(warnings), err +} + +func (actor Actor) GetSSHEnabledByAppName(appName string, spaceGUID string) (ccv3.SSHEnabled, Warnings, error) { + var allWarnings Warnings + + app, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return ccv3.SSHEnabled{}, allWarnings, err + } + + sshEnabled, warnings, err := actor.CloudControllerClient.GetSSHEnabled(app.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return ccv3.SSHEnabled{}, allWarnings, err + } + + return sshEnabled, allWarnings, nil +} + +func (actor Actor) UpdateAppFeature(app resources.Application, enabled bool, featureName string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.UpdateAppFeature(app.GUID, enabled, featureName) + return Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/application_manifest.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_manifest.go new file mode 100644 index 0000000..9e23a1e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_manifest.go @@ -0,0 +1,70 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ManifestParser + +type ManifestParser interface { + AppNames() []string + RawAppManifest(name string) ([]byte, error) +} + +// ApplyApplicationManifest reads in the manifest from the path and provides it +// to the cloud controller. +func (actor Actor) ApplyApplicationManifest(parser ManifestParser, spaceGUID string) (Warnings, error) { + var allWarnings Warnings + + for _, appName := range parser.AppNames() { + rawManifest, err := parser.RawAppManifest(appName) + if err != nil { + return allWarnings, err + } + + app, getAppWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + + allWarnings = append(allWarnings, getAppWarnings...) + if err != nil { + return allWarnings, err + } + + applyManifestWarnings, err := actor.SetApplicationManifest(app.GUID, rawManifest) + allWarnings = append(allWarnings, applyManifestWarnings...) + if err != nil { + return allWarnings, err + } + } + + return allWarnings, nil +} + +func (actor Actor) SetApplicationManifest(appGUID string, rawManifest []byte) (Warnings, error) { + var allWarnings Warnings + jobURL, applyManifestWarnings, err := actor.CloudControllerClient.UpdateApplicationApplyManifest(appGUID, rawManifest) + allWarnings = append(allWarnings, applyManifestWarnings...) + if err != nil { + return allWarnings, err + } + + pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollWarnings...) + if err != nil { + if newErr, ok := err.(ccerror.V3JobFailedError); ok { + return allWarnings, actionerror.ApplicationManifestError{Message: newErr.Detail} + } + return allWarnings, err + } + return allWarnings, nil +} + +func (actor Actor) GetRawApplicationManifestByNameAndSpace(appName string, spaceGUID string) ([]byte, Warnings, error) { + app, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return nil, warnings, err + } + + rawManifest, manifestWarnings, err := actor.CloudControllerClient.GetApplicationManifest(app.GUID) + return rawManifest, append(warnings, manifestWarnings...), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/application_summary.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_summary.go new file mode 100644 index 0000000..42776cf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/application_summary.go @@ -0,0 +1,193 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/batcher" +) + +type ApplicationSummary struct { + resources.Application + ProcessSummaries ProcessSummaries + Routes []resources.Route +} + +// v7action.DetailedApplicationSummary represents an application with its processes and droplet. +type DetailedApplicationSummary struct { + ApplicationSummary + CurrentDroplet resources.Droplet +} + +func (a ApplicationSummary) GetIsolationSegmentName() (string, bool) { + if a.hasIsolationSegment() { + return a.ProcessSummaries[0].InstanceDetails[0].IsolationSegment, true + } + return "", false +} + +func (a ApplicationSummary) hasIsolationSegment() bool { + return len(a.ProcessSummaries) > 0 && + len(a.ProcessSummaries[0].InstanceDetails) > 0 && + len(a.ProcessSummaries[0].InstanceDetails[0].IsolationSegment) > 0 +} + +func (actor Actor) GetAppSummariesForSpace(spaceGUID string, labelSelector string) ([]ApplicationSummary, Warnings, error) { + var allWarnings Warnings + var allSummaries []ApplicationSummary + + keys := []ccv3.Query{ + {Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + {Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}}, + } + if len(labelSelector) > 0 { + keys = append(keys, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + apps, warnings, err := actor.CloudControllerClient.GetApplications(keys...) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + var processes []resources.Process + + warnings, err = batcher.RequestByGUID(toAppGUIDs(apps), func(guids []string) (ccv3.Warnings, error) { + batch, warnings, err := actor.CloudControllerClient.GetProcesses(ccv3.Query{ + Key: ccv3.AppGUIDFilter, Values: guids, + }) + processes = append(processes, batch...) + return warnings, err + }) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + processSummariesByAppGUID := make(map[string]ProcessSummaries, len(apps)) + for _, process := range processes { + instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID) + allWarnings = append(allWarnings, Warnings(warnings)...) + if err != nil { + return nil, allWarnings, err + } + + var instanceDetails []ProcessInstance + for _, instance := range instances { + instanceDetails = append(instanceDetails, ProcessInstance(instance)) + } + + processSummary := ProcessSummary{ + Process: resources.Process(process), + InstanceDetails: instanceDetails, + } + + processSummariesByAppGUID[process.AppGUID] = append(processSummariesByAppGUID[process.AppGUID], processSummary) + } + + var routes []resources.Route + + warnings, err = batcher.RequestByGUID(toAppGUIDs(apps), func(guids []string) (ccv3.Warnings, error) { + batch, warnings, err := actor.CloudControllerClient.GetRoutes(ccv3.Query{ + Key: ccv3.AppGUIDFilter, Values: guids, + }) + routes = append(routes, batch...) + return warnings, err + }) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + routesByAppGUID := make(map[string][]resources.Route) + + for _, route := range routes { + for _, dest := range route.Destinations { + routesByAppGUID[dest.App.GUID] = append(routesByAppGUID[dest.App.GUID], route) + } + } + + for _, app := range apps { + processSummariesByAppGUID[app.GUID].Sort() + + summary := ApplicationSummary{ + Application: app, + ProcessSummaries: processSummariesByAppGUID[app.GUID], + Routes: routesByAppGUID[app.GUID], + } + + allSummaries = append(allSummaries, summary) + } + + return allSummaries, allWarnings, nil +} + +func (actor Actor) GetDetailedAppSummary(appName, spaceGUID string, withObfuscatedValues bool) (DetailedApplicationSummary, Warnings, error) { + var allWarnings Warnings + + app, actorWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, actorWarnings...) + if err != nil { + return DetailedApplicationSummary{}, actorWarnings, err + } + + summary, warnings, err := actor.createSummary(app, withObfuscatedValues) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return DetailedApplicationSummary{}, allWarnings, err + } + + detailedSummary, warnings, err := actor.addDroplet(summary) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return DetailedApplicationSummary{}, allWarnings, err + } + + return detailedSummary, allWarnings, err +} + +func (actor Actor) createSummary(app resources.Application, withObfuscatedValues bool) (ApplicationSummary, Warnings, error) { + var allWarnings Warnings + + processSummaries, processWarnings, err := actor.getProcessSummariesForApp(app.GUID, withObfuscatedValues) + allWarnings = append(allWarnings, processWarnings...) + if err != nil { + return ApplicationSummary{}, allWarnings, err + } + + routes, warnings, err := actor.GetApplicationRoutes(app.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return ApplicationSummary{}, allWarnings, err + } + + return ApplicationSummary{ + Application: app, + ProcessSummaries: processSummaries, + Routes: routes, + }, allWarnings, nil +} + +func (actor Actor) addDroplet(summary ApplicationSummary) (DetailedApplicationSummary, Warnings, error) { + var allWarnings Warnings + + droplet, warnings, err := actor.GetCurrentDropletByApplication(summary.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + if _, ok := err.(actionerror.DropletNotFoundError); !ok { + return DetailedApplicationSummary{}, allWarnings, err + } + } + return DetailedApplicationSummary{ + ApplicationSummary: summary, + CurrentDroplet: droplet, + }, allWarnings, nil +} + +func toAppGUIDs(apps []resources.Application) []string { + guids := make([]string, len(apps)) + + for i, app := range apps { + guids[i] = app.GUID + } + + return guids +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/auth.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/auth.go new file mode 100644 index 0000000..c69d483 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/auth.go @@ -0,0 +1,113 @@ +package v7action + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "strings" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/uaa/constant" + "code.cloudfoundry.org/cli/cf/configuration/coreconfig" + "code.cloudfoundry.org/cli/util/configv3" +) + +type defaultAuthActor struct { + config Config + uaaClient UAAClient +} + +func NewDefaultAuthActor(config Config, uaaClient UAAClient) AuthActor { + return &defaultAuthActor{ + config: config, + uaaClient: uaaClient, + } +} + +func (actor defaultAuthActor) Authenticate(credentials map[string]string, origin string, grantType constant.GrantType) error { + if grantType == constant.GrantTypePassword && actor.config.UAAGrantType() == string(constant.GrantTypeClientCredentials) { + return actionerror.PasswordGrantTypeLogoutRequiredError{} + } + + actor.config.UnsetOrganizationAndSpaceInformation() + accessToken, refreshToken, err := actor.uaaClient.Authenticate(credentials, origin, grantType) + if err != nil { + actor.config.SetTokenInformation("", "", "") + return err + } + + accessToken = fmt.Sprintf("bearer %s", accessToken) + actor.config.SetTokenInformation(accessToken, refreshToken, "") + + if grantType == constant.GrantTypePassword { + actor.config.SetUAAGrantType("") + } else { + actor.config.SetUAAGrantType(string(grantType)) + } + + if grantType == constant.GrantTypeClientCredentials { + actor.config.SetUAAClientCredentials(credentials["client_id"], "") + } + + return nil +} + +func (actor defaultAuthActor) GetLoginPrompts() (map[string]coreconfig.AuthPrompt, error) { + rawPrompts, err := actor.uaaClient.GetLoginPrompts() + if err != nil { + return nil, err + } + + prompts := make(map[string]coreconfig.AuthPrompt) + for key, val := range rawPrompts { + prompts[key] = coreconfig.AuthPrompt{ + Type: knownAuthPromptTypes[val[0]], + DisplayName: val[1], + } + } + + return prompts, nil +} + +func (actor defaultAuthActor) GetCurrentUser() (configv3.User, error) { + return actor.config.CurrentUser() +} + +// TODO: error check this in future stories +func (actor Actor) RevokeAccessAndRefreshTokens() error { + accessToken := actor.Config.AccessToken() + if actor.isTokenRevocable(accessToken) { + refreshToken := actor.Config.RefreshToken() + _ = actor.UAAClient.Revoke(refreshToken) + _ = actor.UAAClient.Revoke(accessToken) + } + return nil +} + +func (actor Actor) isTokenRevocable(token string) bool { + segments := strings.Split(token, ".") + + if len(segments) < 2 { + return false + } + + jsonPayload, err := base64.RawURLEncoding.DecodeString(segments[1]) + if err != nil { + return false + } + + payload := make(map[string]interface{}) + json.Unmarshal(jsonPayload, &payload) + revocable, ok := payload["revocable"].(bool) + + if !ok { + return false + } + + return revocable +} + +var knownAuthPromptTypes = map[string]coreconfig.AuthPromptType{ + "text": coreconfig.AuthPromptTypeText, + "password": coreconfig.AuthPromptTypePassword, +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/build.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/build.go new file mode 100644 index 0000000..a6aeda4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/build.go @@ -0,0 +1,177 @@ +package v7action + +import ( + "errors" + "strings" + "time" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + + log "github.com/sirupsen/logrus" +) + +func (actor Actor) StagePackage(packageGUID, appName, spaceGUID string) (<-chan resources.Droplet, <-chan Warnings, <-chan error) { + dropletStream := make(chan resources.Droplet) + warningsStream := make(chan Warnings) + errorStream := make(chan error) + go func() { + defer close(dropletStream) + defer close(warningsStream) + defer close(errorStream) + + apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{appName}, spaceGUID) + warningsStream <- warnings + if err != nil { + if _, ok := err.(actionerror.ApplicationsNotFoundError); ok { + err = actionerror.ApplicationNotFoundError{Name: appName} + } + errorStream <- err + return + } + app := apps[0] + + pkgs, allWarnings, err := actor.CloudControllerClient.GetPackages(ccv3.Query{ + Key: ccv3.AppGUIDFilter, Values: []string{app.GUID}, + }) + warningsStream <- Warnings(allWarnings) + if err != nil { + errorStream <- err + return + } + + if !packageInPackages(packageGUID, pkgs) { + err = actionerror.PackageNotFoundInAppError{GUID: packageGUID, AppName: appName} + errorStream <- err + return + } + + build := resources.Build{PackageGUID: packageGUID} + build, allWarnings, err = actor.CloudControllerClient.CreateBuild(build) + warningsStream <- Warnings(allWarnings) + + if err != nil { + errorStream <- err + return + } + + timer := actor.Clock.NewTimer(time.Millisecond) + defer timer.Stop() + timeout := actor.Clock.After(actor.Config.StagingTimeout()) + + for { + select { + case <-timeout: + errorStream <- actionerror.StagingTimeoutError{AppName: appName, Timeout: actor.Config.StagingTimeout()} + return + case <-timer.C(): + var warnings ccv3.Warnings + build, warnings, err = actor.CloudControllerClient.GetBuild(build.GUID) + warningsStream <- Warnings(warnings) + if err != nil { + errorStream <- err + return + } + + switch build.State { + case constant.BuildFailed: + if strings.Contains(build.Error, "NoAppDetectedError") { + errorStream <- actionerror.StagingFailedNoAppDetectedError{Reason: build.Error} + } else { + errorStream <- actionerror.StagingFailedError{Reason: build.Error} + } + return + case constant.BuildStaging: + timer.Reset(actor.Config.PollingInterval()) + default: + + //TODO: uncomment after #150569020 + // droplet, warnings, err := actor.CloudControllerClient.GetDroplet(build.DropletGUID) + // warningsStream <- Warnings(warnings) + // if err != nil { + // errorStream <- err + // return + // } + + droplet := resources.Droplet{ + GUID: build.DropletGUID, + State: constant.DropletState(build.State), + CreatedAt: build.CreatedAt, + } + + dropletStream <- droplet + return + } + } + } + }() + + return dropletStream, warningsStream, errorStream +} + +func (actor Actor) StageApplicationPackage(packageGUID string) (resources.Build, Warnings, error) { + var allWarnings Warnings + + build := resources.Build{PackageGUID: packageGUID} + build, warnings, err := actor.CloudControllerClient.CreateBuild(build) + log.Debug("created build") + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Build{}, allWarnings, err + } + + log.Debug("no errors creating build") + return resources.Build{GUID: build.GUID}, allWarnings, nil +} + +func (actor Actor) PollBuild(buildGUID string, appName string) (resources.Droplet, Warnings, error) { + var allWarnings Warnings + + timeout := actor.Clock.After(actor.Config.StagingTimeout()) + interval := actor.Clock.NewTimer(time.Millisecond) + + for { + select { + case <-interval.C(): + build, warnings, err := actor.CloudControllerClient.GetBuild(buildGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Droplet{}, allWarnings, err + } + + switch build.State { + case constant.BuildFailed: + return resources.Droplet{}, allWarnings, errors.New(build.Error) + + case constant.BuildStaged: + droplet, warnings, err := actor.CloudControllerClient.GetDroplet(build.DropletGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Droplet{}, allWarnings, err + } + + return resources.Droplet{ + GUID: droplet.GUID, + State: droplet.State, + CreatedAt: droplet.CreatedAt, + }, allWarnings, nil + } + + interval.Reset(actor.Config.PollingInterval()) + + case <-timeout: + return resources.Droplet{}, allWarnings, actionerror.StagingTimeoutError{AppName: appName, Timeout: actor.Config.StagingTimeout()} + } + } +} + +func packageInPackages(targetPkgGUID string, pkgs []resources.Package) bool { + for i := range pkgs { + if pkgs[i].GUID == targetPkgGUID { + return true + } + } + return false +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/buildpack.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/buildpack.go new file mode 100644 index 0000000..0fc3eab --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/buildpack.go @@ -0,0 +1,271 @@ +package v7action + +import ( + "archive/zip" + "io" + "os" + "path/filepath" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util" +) + +type JobURL ccv3.JobURL + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Downloader + +type Downloader interface { + Download(url string, tmpDirPath string) (string, error) +} + +func (actor Actor) GetBuildpacks(labelSelector string) ([]resources.Buildpack, Warnings, error) { + queries := []ccv3.Query{ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.PositionOrder}}} + if labelSelector != "" { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + + buildpacks, warnings, err := actor.CloudControllerClient.GetBuildpacks(queries...) + + return buildpacks, Warnings(warnings), err +} + +// GetBuildpackByNameAndStack returns a buildpack with the provided name and +// stack. If `buildpackStack` is not specified, and there are multiple +// buildpacks with the same name, it will return the one with no stack, if +// present. +func (actor Actor) GetBuildpackByNameAndStack(buildpackName string, buildpackStack string) (resources.Buildpack, Warnings, error) { + var ( + buildpacks []resources.Buildpack + warnings ccv3.Warnings + err error + ) + + if buildpackStack == "" { + buildpacks, warnings, err = actor.CloudControllerClient.GetBuildpacks(ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{buildpackName}, + }) + } else { + buildpacks, warnings, err = actor.CloudControllerClient.GetBuildpacks( + ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{buildpackName}, + }, + ccv3.Query{ + Key: ccv3.StackFilter, + Values: []string{buildpackStack}, + }, + ) + } + + if err != nil { + return resources.Buildpack{}, Warnings(warnings), err + } + + if len(buildpacks) == 0 { + return resources.Buildpack{}, Warnings(warnings), actionerror.BuildpackNotFoundError{BuildpackName: buildpackName, StackName: buildpackStack} + } + + if len(buildpacks) > 1 { + for _, buildpack := range buildpacks { + if buildpack.Stack == "" { + return buildpack, Warnings(warnings), nil + } + } + return resources.Buildpack{}, Warnings(warnings), actionerror.MultipleBuildpacksFoundError{BuildpackName: buildpackName} + } + + return buildpacks[0], Warnings(warnings), err +} + +func (actor Actor) CreateBuildpack(buildpack resources.Buildpack) (resources.Buildpack, Warnings, error) { + buildpack, warnings, err := actor.CloudControllerClient.CreateBuildpack(buildpack) + + return buildpack, Warnings(warnings), err +} + +func (actor Actor) UpdateBuildpackByNameAndStack(buildpackName string, buildpackStack string, buildpack resources.Buildpack) (resources.Buildpack, Warnings, error) { + var warnings Warnings + foundBuildpack, getWarnings, err := actor.GetBuildpackByNameAndStack(buildpackName, buildpackStack) + warnings = append(warnings, getWarnings...) + + if err != nil { + return resources.Buildpack{}, warnings, err + } + + buildpack.GUID = foundBuildpack.GUID + + updatedBuildpack, updateWarnings, err := actor.CloudControllerClient.UpdateBuildpack(resources.Buildpack(buildpack)) + warnings = append(warnings, updateWarnings...) + if err != nil { + return resources.Buildpack{}, warnings, err + } + + return updatedBuildpack, warnings, nil +} + +func (actor Actor) UploadBuildpack(guid string, pathToBuildpackBits string, progressBar SimpleProgressBar) (ccv3.JobURL, Warnings, error) { + wrappedReader, size, err := progressBar.Initialize(pathToBuildpackBits) + if err != nil { + return "", Warnings{}, err + } + + defer progressBar.Terminate() + + jobURL, warnings, err := actor.CloudControllerClient.UploadBuildpack(guid, pathToBuildpackBits, wrappedReader, size) + if err != nil { + // TODO: Do we actually want to convert this error? Is this the right place? + if e, ok := err.(ccerror.BuildpackAlreadyExistsForStackError); ok { + return "", Warnings(warnings), actionerror.BuildpackAlreadyExistsForStackError{Message: e.Message} + } + return "", Warnings(warnings), err + } + + return jobURL, Warnings(warnings), nil +} + +func (actor *Actor) PrepareBuildpackBits(inputPath string, tmpDirPath string, downloader Downloader) (string, error) { + if util.IsHTTPScheme(inputPath) { + pathToDownloadedBits, err := downloader.Download(inputPath, tmpDirPath) + if err != nil { + return "", err + } + return pathToDownloadedBits, nil + } + + if filepath.Ext(inputPath) == ".zip" { + return inputPath, nil + } + + info, err := os.Stat(inputPath) + if err != nil { + return "", err + } + + if info.IsDir() { + var empty bool + empty, err = isEmptyDirectory(inputPath) + if err != nil { + return "", err + } + if empty { + return "", actionerror.EmptyBuildpackDirectoryError{Path: inputPath} + } + archive := filepath.Join(tmpDirPath, filepath.Base(inputPath)) + ".zip" + + err = Zipit(inputPath, archive, "") + if err != nil { + return "", err + } + return archive, nil + } + + return inputPath, nil +} + +func isEmptyDirectory(name string) (bool, error) { + f, err := os.Open(name) + if err != nil { + return false, err + } + defer f.Close() + + _, err = f.Readdirnames(1) + if err == io.EOF { + return true, nil + } + return false, err +} + +// Zipit zips the source into a .zip file in the target dir +func Zipit(source, target, prefix string) error { + // Thanks to Svett Ralchev + // http://blog.ralch.com/tutorial/golang-working-with-zip/ + + zipfile, err := os.Create(target) + if err != nil { + return err + } + defer zipfile.Close() + + if prefix != "" { + _, err = io.WriteString(zipfile, prefix) + if err != nil { + return err + } + } + + archive := zip.NewWriter(zipfile) + defer archive.Close() + + err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if path == source { + return nil + } + + header, err := zip.FileInfoHeader(info) + if err != nil { + return err + } + header.Name, err = filepath.Rel(source, path) + if err != nil { + return err + } + + header.Name = filepath.ToSlash(header.Name) + if info.IsDir() { + header.Name += "/" + header.SetMode(info.Mode()) + } else { + header.Method = zip.Deflate + header.SetMode(fixMode(info.Mode())) + } + + writer, err := archive.CreateHeader(header) + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + _, err = io.Copy(writer, file) + return err + }) + + return err +} + +func (actor Actor) DeleteBuildpackByNameAndStack(buildpackName string, buildpackStack string) (Warnings, error) { + var allWarnings Warnings + buildpack, getBuildpackWarnings, err := actor.GetBuildpackByNameAndStack(buildpackName, buildpackStack) + allWarnings = append(allWarnings, getBuildpackWarnings...) + if err != nil { + return allWarnings, err + } + + jobURL, deleteBuildpackWarnings, err := actor.CloudControllerClient.DeleteBuildpack(buildpack.GUID) + allWarnings = append(allWarnings, deleteBuildpackWarnings...) + if err != nil { + return allWarnings, err + } + + pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollWarnings...) + + return allWarnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/cloud_controller_client.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/cloud_controller_client.go new file mode 100644 index 0000000..5bca12c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/cloud_controller_client.go @@ -0,0 +1,201 @@ +package v7action + +import ( + "io" + "net/http" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . CloudControllerClient + +// CloudControllerClient is the interface to the cloud controller V3 API. +type CloudControllerClient interface { + ApplyOrganizationQuota(quotaGUID string, orgGUID string) (resources.RelationshipList, ccv3.Warnings, error) + ApplySpaceQuota(quotaGUID string, spaceGUID string) (resources.RelationshipList, ccv3.Warnings, error) + CheckRoute(domainGUID string, hostname string, path string, port int) (bool, ccv3.Warnings, error) + CancelDeployment(deploymentGUID string) (ccv3.Warnings, error) + CopyPackage(sourcePackageGUID string, targetAppGUID string) (resources.Package, ccv3.Warnings, error) + CreateApplication(app resources.Application) (resources.Application, ccv3.Warnings, error) + CreateApplicationDeployment(appGUID string, dropletGUID string) (string, ccv3.Warnings, error) + CreateApplicationDeploymentByRevision(appGUID string, revisionGUID string) (string, ccv3.Warnings, error) + CreateApplicationProcessScale(appGUID string, process resources.Process) (resources.Process, ccv3.Warnings, error) + CreateApplicationTask(appGUID string, task resources.Task) (resources.Task, ccv3.Warnings, error) + CreateBuild(build resources.Build) (resources.Build, ccv3.Warnings, error) + CreateBuildpack(bp resources.Buildpack) (resources.Buildpack, ccv3.Warnings, error) + CreateDomain(domain resources.Domain) (resources.Domain, ccv3.Warnings, error) + CreateDroplet(appGUID string) (resources.Droplet, ccv3.Warnings, error) + CreateIsolationSegment(isolationSegment resources.IsolationSegment) (resources.IsolationSegment, ccv3.Warnings, error) + CreateOrganization(orgName string) (resources.Organization, ccv3.Warnings, error) + CreateOrganizationQuota(orgQuota resources.OrganizationQuota) (resources.OrganizationQuota, ccv3.Warnings, error) + CreatePackage(pkg resources.Package) (resources.Package, ccv3.Warnings, error) + CreateRole(role resources.Role) (resources.Role, ccv3.Warnings, error) + CreateRoute(route resources.Route) (resources.Route, ccv3.Warnings, error) + CreateRouteBinding(binding resources.RouteBinding) (ccv3.JobURL, ccv3.Warnings, error) + CreateServiceBroker(serviceBroker resources.ServiceBroker) (ccv3.JobURL, ccv3.Warnings, error) + CreateServiceCredentialBinding(binding resources.ServiceCredentialBinding) (ccv3.JobURL, ccv3.Warnings, error) + CreateServiceInstance(serviceInstance resources.ServiceInstance) (ccv3.JobURL, ccv3.Warnings, error) + CreateSecurityGroup(securityGroup resources.SecurityGroup) (resources.SecurityGroup, ccv3.Warnings, error) + CreateSpace(space resources.Space) (resources.Space, ccv3.Warnings, error) + CreateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, ccv3.Warnings, error) + CreateUser(userGUID string) (resources.User, ccv3.Warnings, error) + DeleteApplication(guid string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteApplicationProcessInstance(appGUID string, processType string, instanceIndex int) (ccv3.Warnings, error) + DeleteBuildpack(buildpackGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteDomain(domainGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteIsolationSegment(guid string) (ccv3.Warnings, error) + DeleteIsolationSegmentOrganization(isolationSegmentGUID string, organizationGUID string) (ccv3.Warnings, error) + DeleteOrganization(orgGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteOrganizationQuota(quotaGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteOrphanedRoutes(spaceGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteRole(roleGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteRoute(routeGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteRouteBinding(guid string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteSecurityGroup(securityGroupGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteServiceCredentialBinding(guid string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteServiceBroker(serviceBrokerGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteServiceInstance(serviceInstanceGUID string, query ...ccv3.Query) (ccv3.JobURL, ccv3.Warnings, error) + DeleteSpaceQuota(spaceQuotaGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteSpace(guid string) (ccv3.JobURL, ccv3.Warnings, error) + DeleteUser(userGUID string) (ccv3.JobURL, ccv3.Warnings, error) + DownloadDroplet(dropletGUID string) ([]byte, ccv3.Warnings, error) + EntitleIsolationSegmentToOrganizations(isoGUID string, orgGUIDs []string) (resources.RelationshipList, ccv3.Warnings, error) + GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, ccv3.Warnings, error) + GetApplicationDropletCurrent(appGUID string) (resources.Droplet, ccv3.Warnings, error) + GetApplicationEnvironment(appGUID string) (ccv3.Environment, ccv3.Warnings, error) + GetApplicationManifest(appGUID string) ([]byte, ccv3.Warnings, error) + GetApplicationProcessByType(appGUID string, processType string) (resources.Process, ccv3.Warnings, error) + GetApplicationProcesses(appGUID string) ([]resources.Process, ccv3.Warnings, error) + GetApplicationRevisions(appGUID string, query ...ccv3.Query) ([]resources.Revision, ccv3.Warnings, error) + GetApplicationRevisionsDeployed(appGUID string) ([]resources.Revision, ccv3.Warnings, error) + GetApplicationRoutes(appGUID string) ([]resources.Route, ccv3.Warnings, error) + GetApplicationTasks(appGUID string, query ...ccv3.Query) ([]resources.Task, ccv3.Warnings, error) + GetApplications(query ...ccv3.Query) ([]resources.Application, ccv3.Warnings, error) + GetBuild(guid string) (resources.Build, ccv3.Warnings, error) + GetBuildpacks(query ...ccv3.Query) ([]resources.Buildpack, ccv3.Warnings, error) + GetDefaultDomain(orgGuid string) (resources.Domain, ccv3.Warnings, error) + GetDeployment(guid string) (resources.Deployment, ccv3.Warnings, error) + GetDeployments(query ...ccv3.Query) ([]resources.Deployment, ccv3.Warnings, error) + GetDomain(GUID string) (resources.Domain, ccv3.Warnings, error) + GetDomains(query ...ccv3.Query) ([]resources.Domain, ccv3.Warnings, error) + GetDroplet(guid string) (resources.Droplet, ccv3.Warnings, error) + GetDroplets(query ...ccv3.Query) ([]resources.Droplet, ccv3.Warnings, error) + GetEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName) (resources.EnvironmentVariables, ccv3.Warnings, error) + GetEvents(query ...ccv3.Query) ([]ccv3.Event, ccv3.Warnings, error) + GetFeatureFlag(featureFlagName string) (resources.FeatureFlag, ccv3.Warnings, error) + GetFeatureFlags() ([]resources.FeatureFlag, ccv3.Warnings, error) + GetInfo() (ccv3.Info, ccv3.Warnings, error) + GetIsolationSegment(guid string) (resources.IsolationSegment, ccv3.Warnings, error) + GetIsolationSegmentOrganizations(isolationSegmentGUID string) ([]resources.Organization, ccv3.Warnings, error) + GetIsolationSegments(query ...ccv3.Query) ([]resources.IsolationSegment, ccv3.Warnings, error) + GetNewApplicationProcesses(appGUID string, deploymentGUID string) ([]resources.Process, ccv3.Warnings, error) + GetOrganization(orgGUID string) (resources.Organization, ccv3.Warnings, error) + GetOrganizationDefaultIsolationSegment(orgGUID string) (resources.Relationship, ccv3.Warnings, error) + GetOrganizationDomains(orgGUID string, query ...ccv3.Query) ([]resources.Domain, ccv3.Warnings, error) + GetOrganizationQuota(quotaGUID string) (resources.OrganizationQuota, ccv3.Warnings, error) + GetOrganizationQuotas(query ...ccv3.Query) ([]resources.OrganizationQuota, ccv3.Warnings, error) + GetOrganizations(query ...ccv3.Query) ([]resources.Organization, ccv3.Warnings, error) + GetPackage(guid string) (resources.Package, ccv3.Warnings, error) + GetPackages(query ...ccv3.Query) ([]resources.Package, ccv3.Warnings, error) + GetPackageDroplets(packageGUID string, query ...ccv3.Query) ([]resources.Droplet, ccv3.Warnings, error) + GetProcess(processGUID string) (resources.Process, ccv3.Warnings, error) + GetProcesses(query ...ccv3.Query) ([]resources.Process, ccv3.Warnings, error) + GetProcessInstances(processGUID string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) + GetProcessSidecars(processGUID string) ([]resources.Sidecar, ccv3.Warnings, error) + GetRoles(query ...ccv3.Query) ([]resources.Role, ccv3.IncludedResources, ccv3.Warnings, error) + GetRouteBindings(query ...ccv3.Query) ([]resources.RouteBinding, ccv3.IncludedResources, ccv3.Warnings, error) + GetRouteDestinations(routeGUID string) ([]resources.RouteDestination, ccv3.Warnings, error) + GetRoutes(query ...ccv3.Query) ([]resources.Route, ccv3.Warnings, error) + GetRunningSecurityGroups(spaceGUID string, queries ...ccv3.Query) ([]resources.SecurityGroup, ccv3.Warnings, error) + GetSecurityGroups(query ...ccv3.Query) ([]resources.SecurityGroup, ccv3.Warnings, error) + GetServiceBrokers(query ...ccv3.Query) ([]resources.ServiceBroker, ccv3.Warnings, error) + GetServiceCredentialBindings(query ...ccv3.Query) ([]resources.ServiceCredentialBinding, ccv3.Warnings, error) + GetServiceCredentialBindingDetails(guid string) (resources.ServiceCredentialBindingDetails, ccv3.Warnings, error) + GetServiceInstanceByNameAndSpace(name, spaceGUID string, query ...ccv3.Query) (resources.ServiceInstance, ccv3.IncludedResources, ccv3.Warnings, error) + GetServiceInstanceParameters(serviceInstanceGUID string) (types.JSONObject, ccv3.Warnings, error) + GetServiceInstanceSharedSpaces(serviceInstanceGUID string) ([]ccv3.SpaceWithOrganization, ccv3.Warnings, error) + GetServiceInstanceUsageSummary(serviceInstanceGUID string) ([]resources.ServiceInstanceUsageSummary, ccv3.Warnings, error) + GetServiceInstances(query ...ccv3.Query) ([]resources.ServiceInstance, ccv3.IncludedResources, ccv3.Warnings, error) + GetServiceOfferingByGUID(guid string) (resources.ServiceOffering, ccv3.Warnings, error) + GetServiceOfferings(query ...ccv3.Query) ([]resources.ServiceOffering, ccv3.Warnings, error) + GetServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName string) (resources.ServiceOffering, ccv3.Warnings, error) + GetServicePlanByGUID(guid string) (resources.ServicePlan, ccv3.Warnings, error) + GetServicePlans(query ...ccv3.Query) ([]resources.ServicePlan, ccv3.Warnings, error) + GetServicePlansWithOfferings(query ...ccv3.Query) ([]ccv3.ServiceOfferingWithPlans, ccv3.Warnings, error) + GetServicePlansWithSpaceAndOrganization(query ...ccv3.Query) ([]ccv3.ServicePlanWithSpaceAndOrganization, ccv3.Warnings, error) + GetSpaceFeature(spaceGUID string, featureName string) (bool, ccv3.Warnings, error) + GetSpaceIsolationSegment(spaceGUID string) (resources.Relationship, ccv3.Warnings, error) + GetSpaceManifestDiff(spaceGUID string, rawManifest []byte) (resources.ManifestDiff, ccv3.Warnings, error) + GetSpaceQuota(spaceQuotaGUID string) (resources.SpaceQuota, ccv3.Warnings, error) + GetSpaces(query ...ccv3.Query) ([]resources.Space, ccv3.IncludedResources, ccv3.Warnings, error) + GetSpaceQuotas(query ...ccv3.Query) ([]resources.SpaceQuota, ccv3.Warnings, error) + GetSSHEnabled(appGUID string) (ccv3.SSHEnabled, ccv3.Warnings, error) + GetAppFeature(appGUID string, featureName string) (resources.ApplicationFeature, ccv3.Warnings, error) + GetStacks(query ...ccv3.Query) ([]resources.Stack, ccv3.Warnings, error) + GetStagingSecurityGroups(spaceGUID string, queries ...ccv3.Query) ([]resources.SecurityGroup, ccv3.Warnings, error) + GetUser(userGUID string) (resources.User, ccv3.Warnings, error) + GetUsers(query ...ccv3.Query) ([]resources.User, ccv3.Warnings, error) + MakeRequestSendReceiveRaw(Method string, URL string, headers http.Header, requestBody []byte) ([]byte, *http.Response, error) + MapRoute(routeGUID string, appGUID string, destinationProtocol string) (ccv3.Warnings, error) + PollJob(jobURL ccv3.JobURL) (ccv3.Warnings, error) + PollJobForState(jobURL ccv3.JobURL, state constant.JobState) (ccv3.Warnings, error) + PollJobToEventStream(jobURL ccv3.JobURL) chan ccv3.PollJobEvent + PurgeServiceOffering(serviceOfferingGUID string) (ccv3.Warnings, error) + ResourceMatch(resources []ccv3.Resource) ([]ccv3.Resource, ccv3.Warnings, error) + RootResponse() (ccv3.Info, ccv3.Warnings, error) + SetApplicationDroplet(appGUID string, dropletGUID string) (resources.Relationship, ccv3.Warnings, error) + SharePrivateDomainToOrgs(domainGuid string, sharedOrgs ccv3.SharedOrgs) (ccv3.Warnings, error) + ShareServiceInstanceToSpaces(serviceInstanceGUID string, spaceGUIDs []string) (resources.RelationshipList, ccv3.Warnings, error) + TargetCF(settings ccv3.TargetSettings) + UnbindSecurityGroupRunningSpace(securityGroupGUID string, spaceGUID string) (ccv3.Warnings, error) + UnbindSecurityGroupStagingSpace(securityGroupGUID string, spaceGUID string) (ccv3.Warnings, error) + UnmapRoute(routeGUID string, destinationGUID string) (ccv3.Warnings, error) + UnsharePrivateDomainFromOrg(domainGUID string, sharedOrgGUID string) (ccv3.Warnings, error) + UnshareServiceInstanceFromSpace(serviceInstanceGUID string, sharedToSpaceGUID string) (ccv3.Warnings, error) + UpdateAppFeature(appGUID string, enabled bool, featureName string) (ccv3.Warnings, error) + UpdateApplication(app resources.Application) (resources.Application, ccv3.Warnings, error) + UpdateApplicationApplyManifest(appGUID string, rawManifest []byte) (ccv3.JobURL, ccv3.Warnings, error) + UpdateApplicationEnvironmentVariables(appGUID string, envVars resources.EnvironmentVariables) (resources.EnvironmentVariables, ccv3.Warnings, error) + UpdateApplicationRestart(appGUID string) (resources.Application, ccv3.Warnings, error) + UpdateApplicationStart(appGUID string) (resources.Application, ccv3.Warnings, error) + UpdateApplicationStop(appGUID string) (resources.Application, ccv3.Warnings, error) + UpdateDestination(routeGUID string, destinationGUID string, protocol string) (ccv3.Warnings, error) + UpdateBuildpack(buildpack resources.Buildpack) (resources.Buildpack, ccv3.Warnings, error) + UpdateEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName, envVars resources.EnvironmentVariables) (resources.EnvironmentVariables, ccv3.Warnings, error) + UpdateFeatureFlag(flag resources.FeatureFlag) (resources.FeatureFlag, ccv3.Warnings, error) + UpdateOrganization(org resources.Organization) (resources.Organization, ccv3.Warnings, error) + UpdateOrganizationDefaultIsolationSegmentRelationship(orgGUID string, isolationSegmentGUID string) (resources.Relationship, ccv3.Warnings, error) + UpdateOrganizationQuota(orgQuota resources.OrganizationQuota) (resources.OrganizationQuota, ccv3.Warnings, error) + UpdateProcess(process resources.Process) (resources.Process, ccv3.Warnings, error) + UpdateResourceMetadata(resource string, resourceGUID string, metadata resources.Metadata) (ccv3.JobURL, ccv3.Warnings, error) + UpdateSecurityGroupRunningSpace(securityGroupGUID string, spaceGUIDs []string) (ccv3.Warnings, error) + UpdateSecurityGroupStagingSpace(securityGroupGUID string, spaceGUIDs []string) (ccv3.Warnings, error) + UpdateSecurityGroup(securityGroup resources.SecurityGroup) (resources.SecurityGroup, ccv3.Warnings, error) + UpdateServiceInstance(serviceInstanceGUID string, serviceInstanceUpdates resources.ServiceInstance) (ccv3.JobURL, ccv3.Warnings, error) + UpdateSpace(space resources.Space) (resources.Space, ccv3.Warnings, error) + UpdateSpaceApplyManifest(spaceGUID string, rawManifest []byte) (ccv3.JobURL, ccv3.Warnings, error) + UpdateSpaceFeature(spaceGUID string, enabled bool, featureName string) (ccv3.Warnings, error) + UpdateSpaceIsolationSegmentRelationship(spaceGUID string, isolationSegmentGUID string) (resources.Relationship, ccv3.Warnings, error) + UpdateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, ccv3.Warnings, error) + UnsetSpaceQuota(spaceQuotaGUID, spaceGUID string) (ccv3.Warnings, error) + UpdateServiceBroker(serviceBrokerGUID string, serviceBroker resources.ServiceBroker) (ccv3.JobURL, ccv3.Warnings, error) + UpdateTaskCancel(taskGUID string) (resources.Task, ccv3.Warnings, error) + UploadBitsPackage(pkg resources.Package, matchedResources []ccv3.Resource, newResources io.Reader, newResourcesLength int64) (resources.Package, ccv3.Warnings, error) + UploadBuildpack(buildpackGUID string, buildpackPath string, buildpack io.Reader, buildpackLength int64) (ccv3.JobURL, ccv3.Warnings, error) + UploadDropletBits(dropletGUID string, dropletPath string, droplet io.Reader, dropletLength int64) (ccv3.JobURL, ccv3.Warnings, error) + UploadPackage(pkg resources.Package, zipFilepath string) (resources.Package, ccv3.Warnings, error) + WhoAmI() (resources.K8sUser, ccv3.Warnings, error) + + servicePlanVisibilityClient +} + +type servicePlanVisibilityClient interface { + GetServicePlanVisibility(servicePlanGUID string) (resources.ServicePlanVisibility, ccv3.Warnings, error) + UpdateServicePlanVisibility(servicePlanGUID string, visibility resources.ServicePlanVisibility) (resources.ServicePlanVisibility, ccv3.Warnings, error) + DeleteServicePlanVisibility(servicePlanGUID, organizationGUID string) (ccv3.Warnings, error) +} + +// TODO: Split this enormous interface diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/config.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/config.go new file mode 100644 index 0000000..8c4eb01 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/config.go @@ -0,0 +1,33 @@ +package v7action + +import ( + "time" + + "code.cloudfoundry.org/cli/util/configv3" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Config + +type Config interface { + AccessToken() string + APIVersion() string + CurrentUser() (configv3.User, error) + DialTimeout() time.Duration + PollingInterval() time.Duration + RefreshToken() string + SSHOAuthClient() string + SetAccessToken(token string) + SetRefreshToken(token string) + SetTargetInformation(args configv3.TargetInformationArgs) + SetTokenInformation(accessToken string, refreshToken string, token string) + SetUAAClientCredentials(client string, clientSecret string) + SetUAAGrantType(grantType string) + SkipSSLValidation() bool + StagingTimeout() time.Duration + StartupTimeout() time.Duration + Target() string + UAAGrantType() string + UnsetOrganizationAndSpaceInformation() + SetKubernetesAuthInfo(authInfo string) + IsCFOnK8s() bool +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/curl.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/curl.go new file mode 100644 index 0000000..7e82c96 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/curl.go @@ -0,0 +1,69 @@ +package v7action + +import ( + "bufio" + "fmt" + "io/ioutil" + "net/http" + "net/textproto" + "strings" + + "code.cloudfoundry.org/cli/command/translatableerror" +) + +func (actor Actor) MakeCurlRequest( + method string, + path string, + customHeaders []string, + data string, + failOnHTTPError bool, +) ([]byte, *http.Response, error) { + url := fmt.Sprintf("%s/%s", actor.Config.Target(), strings.TrimLeft(path, "/")) + + requestHeaders, err := buildRequestHeaders(customHeaders) + if err != nil { + return nil, nil, translatableerror.RequestCreationError{Err: err} + } + + if method == "" && data != "" { + method = "POST" + } + + requestBodyBytes := []byte(data) + + trimmedData := strings.Trim(string(data), `"'`) + if strings.HasPrefix(trimmedData, "@") { + trimmedData = strings.Trim(trimmedData[1:], `"'`) + requestBodyBytes, err = ioutil.ReadFile(trimmedData) + if err != nil { + return nil, nil, translatableerror.RequestCreationError{Err: err} + } + } + + responseBody, httpResponse, err := actor.CloudControllerClient.MakeRequestSendReceiveRaw( + method, + url, + requestHeaders, + requestBodyBytes, + ) + + if err != nil && failOnHTTPError { + return nil, nil, translatableerror.CurlExit22Error{StatusCode: httpResponse.StatusCode} + } + + return responseBody, httpResponse, nil +} + +func buildRequestHeaders(customHeaders []string) (http.Header, error) { + headerString := strings.Join(customHeaders, "\n") + headerString = strings.TrimSpace(headerString) + headerString += "\n\n" + + headerReader := bufio.NewReader(strings.NewReader(headerString)) + parsedCustomHeaders, err := textproto.NewReader(headerReader).ReadMIMEHeader() + if err != nil { + return nil, err + } + + return http.Header(parsedCustomHeaders), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/deployment.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/deployment.go new file mode 100644 index 0000000..c532df8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/deployment.go @@ -0,0 +1,44 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) CreateDeploymentByApplicationAndDroplet(appGUID string, dropletGUID string) (string, Warnings, error) { + deploymentGUID, warnings, err := actor.CloudControllerClient.CreateApplicationDeployment(appGUID, dropletGUID) + + return deploymentGUID, Warnings(warnings), err +} + +func (actor Actor) CreateDeploymentByApplicationAndRevision(appGUID string, revisionGUID string) (string, Warnings, error) { + deploymentGUID, warnings, err := actor.CloudControllerClient.CreateApplicationDeploymentByRevision(appGUID, revisionGUID) + + return deploymentGUID, Warnings(warnings), err +} + +func (actor Actor) GetLatestActiveDeploymentForApp(appGUID string) (resources.Deployment, Warnings, error) { + ccDeployments, warnings, err := actor.CloudControllerClient.GetDeployments( + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, + ccv3.Query{Key: ccv3.StatusValueFilter, Values: []string{string(constant.DeploymentStatusValueActive)}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, + ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}}, + ) + + if err != nil { + return resources.Deployment{}, Warnings(warnings), err + } + + if len(ccDeployments) == 0 { + return resources.Deployment{}, Warnings(warnings), actionerror.ActiveDeploymentNotFoundError{} + } + + return resources.Deployment(ccDeployments[0]), Warnings(warnings), nil +} + +func (actor Actor) CancelDeployment(deploymentGUID string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.CancelDeployment(deploymentGUID) + return Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/domain.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/domain.go new file mode 100644 index 0000000..d9ed8c9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/domain.go @@ -0,0 +1,184 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" +) + +type SharedOrgs ccv3.SharedOrgs + +func (actor Actor) CheckRoute(domainName string, hostname string, path string, port int) (bool, Warnings, error) { + var allWarnings Warnings + + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return false, allWarnings, err + } + + matches, checkRouteWarnings, err := actor.CloudControllerClient.CheckRoute(domain.GUID, hostname, path, port) + allWarnings = append(allWarnings, checkRouteWarnings...) + + return matches, allWarnings, err +} + +func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGroupName string) (Warnings, error) { + allWarnings := Warnings{} + routerGroupGUID := "" + + if routerGroupName != "" { + routerGroup, err := actor.GetRouterGroupByName(routerGroupName) + if err != nil { + return allWarnings, err + } + + routerGroupGUID = routerGroup.GUID + } + + _, warnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{ + Name: domainName, + Internal: types.NullBool{IsSet: true, Value: internal}, + RouterGroup: routerGroupGUID, + }) + allWarnings = append(allWarnings, Warnings(warnings)...) + + return allWarnings, err +} + +func (actor Actor) CreatePrivateDomain(domainName string, orgName string) (Warnings, error) { + allWarnings := Warnings{} + organization, warnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return allWarnings, err + } + _, apiWarnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{ + Name: domainName, + OrganizationGUID: organization.GUID, + }) + + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + return allWarnings, err +} + +func (actor Actor) DeleteDomain(domain resources.Domain) (Warnings, error) { + allWarnings := Warnings{} + + jobURL, apiWarnings, err := actor.CloudControllerClient.DeleteDomain(domain.GUID) + + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + if err != nil { + return allWarnings, err + } + + pollJobWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(pollJobWarnings)...) + + return allWarnings, err +} + +func (actor Actor) GetOrganizationDomains(orgGuid string, labelSelector string) ([]resources.Domain, Warnings, error) { + keys := []ccv3.Query{} + if labelSelector != "" { + keys = append(keys, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + ccv3Domains, warnings, err := actor.CloudControllerClient.GetOrganizationDomains(orgGuid, keys...) + + if err != nil { + return nil, Warnings(warnings), err + } + + var domains []resources.Domain + for _, domain := range ccv3Domains { + domains = append(domains, resources.Domain(domain)) + } + + return domains, Warnings(warnings), nil +} + +func (actor Actor) GetDomain(domainGUID string) (resources.Domain, Warnings, error) { + domain, warnings, err := actor.CloudControllerClient.GetDomain(domainGUID) + + if err != nil { + return resources.Domain{}, Warnings(warnings), err + } + + return resources.Domain(domain), Warnings(warnings), nil +} + +func (actor Actor) GetDomainByName(domainName string) (resources.Domain, Warnings, error) { + domain, warnings, err := actor.getDomainByName(domainName) + return domain, Warnings(warnings), err +} + +func (actor Actor) SharePrivateDomain(domainName string, orgName string) (Warnings, error) { + orgGUID, domainGUID, warnings, err := actor.GetDomainAndOrgGUIDsByName(domainName, orgName) + + if err != nil { + return warnings, err + } + + apiWarnings, err := actor.CloudControllerClient.SharePrivateDomainToOrgs( + domainGUID, + ccv3.SharedOrgs{GUIDs: []string{orgGUID}}, + ) + + allWarnings := append(warnings, Warnings(apiWarnings)...) + + return allWarnings, err +} + +func (actor Actor) UnsharePrivateDomain(domainName string, orgName string) (Warnings, error) { + orgGUID, domainGUID, warnings, err := actor.GetDomainAndOrgGUIDsByName(domainName, orgName) + + if err != nil { + return warnings, err + } + + apiWarnings, err := actor.CloudControllerClient.UnsharePrivateDomainFromOrg( + domainGUID, + orgGUID, + ) + + allWarnings := append(warnings, Warnings(apiWarnings)...) + + return allWarnings, err +} + +func (actor Actor) GetDomainAndOrgGUIDsByName(domainName string, orgName string) (string, string, Warnings, error) { + org, getOrgWarnings, err := actor.GetOrganizationByName(orgName) + + if err != nil { + return "", "", getOrgWarnings, err + } + + domain, getDomainWarnings, err := actor.GetDomainByName(domainName) + allWarnings := append(getOrgWarnings, getDomainWarnings...) + + if err != nil { + return "", "", allWarnings, err + } + + return org.GUID, domain.GUID, allWarnings, nil +} + +func (actor Actor) getDomainByName(domainName string) (resources.Domain, ccv3.Warnings, error) { + domains, warnings, err := actor.CloudControllerClient.GetDomains( + ccv3.Query{Key: ccv3.NameFilter, Values: []string{domainName}}, + ) + switch { + case err != nil: + return resources.Domain{}, warnings, err + case len(domains) == 0: + return resources.Domain{}, warnings, actionerror.DomainNotFoundError{Name: domainName} + default: + return domains[0], warnings, nil + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/droplet.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/droplet.go new file mode 100644 index 0000000..e9ec793 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/droplet.go @@ -0,0 +1,176 @@ +package v7action + +import ( + "io" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +// CreateApplicationDroplet creates a new droplet without a package for the app with +// guid appGUID. +func (actor Actor) CreateApplicationDroplet(appGUID string) (resources.Droplet, Warnings, error) { + ccDroplet, warnings, err := actor.CloudControllerClient.CreateDroplet(appGUID) + + return ccDroplet, Warnings(warnings), err +} + +// SetApplicationDropletByApplicationNameAndSpace sets the droplet for an application. +func (actor Actor) SetApplicationDropletByApplicationNameAndSpace(appName string, spaceGUID string, dropletGUID string) (Warnings, error) { + allWarnings := Warnings{} + application, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + _, apiWarnings, err := actor.CloudControllerClient.SetApplicationDroplet(application.GUID, dropletGUID) + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + if newErr, ok := err.(ccerror.UnprocessableEntityError); ok { + return allWarnings, actionerror.AssignDropletError{Message: newErr.Message} + } + + return allWarnings, err +} + +func (actor Actor) SetApplicationDroplet(appGUID string, dropletGUID string) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.SetApplicationDroplet(appGUID, dropletGUID) + + if newErr, ok := err.(ccerror.UnprocessableEntityError); ok { + return Warnings(warnings), actionerror.AssignDropletError{Message: newErr.Message} + } + + return Warnings(warnings), err +} + +// GetApplicationDroplets returns the list of droplets that belong to application. +func (actor Actor) GetApplicationDroplets(appName string, spaceGUID string) ([]resources.Droplet, Warnings, error) { + allWarnings := Warnings{} + application, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + droplets, apiWarnings, err := actor.CloudControllerClient.GetDroplets( + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{application.GUID}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, + ) + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + if err != nil { + return nil, allWarnings, err + } + + if len(droplets) == 0 { + return []resources.Droplet{}, allWarnings, nil + } + + currentDroplet, apiWarnings, err := actor.CloudControllerClient.GetApplicationDropletCurrent(application.GUID) + allWarnings = append(allWarnings, apiWarnings...) + if err != nil { + if _, ok := err.(ccerror.DropletNotFoundError); ok { + return droplets, allWarnings, nil + } + return []resources.Droplet{}, allWarnings, err + } + + for i, droplet := range droplets { + if droplet.GUID == currentDroplet.GUID { + droplets[i].IsCurrent = true + } + } + + return droplets, allWarnings, err +} + +func (actor Actor) GetCurrentDropletByApplication(appGUID string) (resources.Droplet, Warnings, error) { + droplet, warnings, err := actor.CloudControllerClient.GetApplicationDropletCurrent(appGUID) + switch err.(type) { + case ccerror.ApplicationNotFoundError: + return resources.Droplet{}, Warnings(warnings), actionerror.ApplicationNotFoundError{GUID: appGUID} + case ccerror.DropletNotFoundError: + return resources.Droplet{}, Warnings(warnings), actionerror.DropletNotFoundError{AppGUID: appGUID} + } + return droplet, Warnings(warnings), err +} + +func (actor Actor) UploadDroplet(dropletGUID string, dropletPath string, progressReader io.Reader, size int64) (Warnings, error) { + var allWarnings Warnings + + jobURL, uploadWarnings, err := actor.CloudControllerClient.UploadDropletBits(dropletGUID, dropletPath, progressReader, size) + allWarnings = append(allWarnings, uploadWarnings...) + if err != nil { + return allWarnings, err + } + + jobWarnings, jobErr := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, jobWarnings...) + if jobErr != nil { + return allWarnings, jobErr + } + + return allWarnings, nil +} + +func (actor Actor) DownloadCurrentDropletByAppName(appName string, spaceGUID string) ([]byte, string, Warnings, error) { + var allWarnings Warnings + + app, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return []byte{}, "", allWarnings, err + } + + droplet, ccWarnings, err := actor.CloudControllerClient.GetApplicationDropletCurrent(app.GUID) + allWarnings = append(allWarnings, ccWarnings...) + + if err != nil { + if _, ok := err.(ccerror.DropletNotFoundError); ok { + return []byte{}, "", allWarnings, actionerror.DropletNotFoundError{} + } + return []byte{}, "", allWarnings, err + } + + rawDropletBytes, ccWarnings, err := actor.CloudControllerClient.DownloadDroplet(droplet.GUID) + allWarnings = append(allWarnings, ccWarnings...) + if err != nil { + return []byte{}, "", allWarnings, err + } + + return rawDropletBytes, droplet.GUID, allWarnings, nil +} + +func (actor Actor) DownloadDropletByGUIDAndAppName(dropletGUID string, appName string, spaceGUID string) ([]byte, Warnings, error) { + var allWarnings Warnings + + app, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return []byte{}, allWarnings, err + } + + droplets, getDropletWarnings, err := actor.CloudControllerClient.GetDroplets( + ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{dropletGUID}}, + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{app.GUID}}, + ) + allWarnings = append(allWarnings, getDropletWarnings...) + if err != nil { + return []byte{}, allWarnings, err + } + + if len(droplets) == 0 { + return []byte{}, allWarnings, actionerror.DropletNotFoundError{} + } + + rawDropletBytes, ccWarnings, err := actor.CloudControllerClient.DownloadDroplet(dropletGUID) + allWarnings = append(allWarnings, ccWarnings...) + if err != nil { + return []byte{}, allWarnings, err + } + + return rawDropletBytes, allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/environment_variable.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/environment_variable.go new file mode 100644 index 0000000..a5588b5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/environment_variable.go @@ -0,0 +1,110 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" +) + +// EnvironmentVariableGroups represents all environment variables for application +type EnvironmentVariableGroups ccv3.Environment + +// EnvironmentVariableGroup represents a CC environment variable group (e.g. staging or running) +type EnvironmentVariableGroup resources.EnvironmentVariables + +// EnvironmentVariablePair represents an environment variable and its value +// on an application +type EnvironmentVariablePair struct { + Key string + Value string +} + +// GetEnvironmentVariableGroup returns the values of an environment variable group. +func (actor *Actor) GetEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName) (EnvironmentVariableGroup, Warnings, error) { + ccEnvGroup, warnings, err := actor.CloudControllerClient.GetEnvironmentVariableGroup(group) + return EnvironmentVariableGroup(ccEnvGroup), Warnings(warnings), err +} + +// GetEnvironmentVariablesByApplicationNameAndSpace returns the environment +// variables for an application. +func (actor *Actor) GetEnvironmentVariablesByApplicationNameAndSpace(appName string, spaceGUID string) (EnvironmentVariableGroups, Warnings, error) { + app, warnings, appErr := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if appErr != nil { + return EnvironmentVariableGroups{}, warnings, appErr + } + + ccEnvGroups, v3Warnings, apiErr := actor.CloudControllerClient.GetApplicationEnvironment(app.GUID) + warnings = append(warnings, v3Warnings...) + return EnvironmentVariableGroups(ccEnvGroups), warnings, apiErr +} + +// SetEnvironmentVariableByApplicationNameAndSpace adds an +// EnvironmentVariablePair to an application. It must be restarted for changes +// to take effect. +func (actor *Actor) SetEnvironmentVariableByApplicationNameAndSpace(appName string, spaceGUID string, envPair EnvironmentVariablePair) (Warnings, error) { + app, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return warnings, err + } + + _, v3Warnings, apiErr := actor.CloudControllerClient.UpdateApplicationEnvironmentVariables( + app.GUID, + resources.EnvironmentVariables{ + envPair.Key: {Value: envPair.Value, IsSet: true}, + }) + warnings = append(warnings, v3Warnings...) + return warnings, apiErr +} + +// SetEnvironmentVariableGroup sets a given environment variable group according to the given +// keys and values. Any existing variables that are not present in the given set of variables +// will be unset. +func (actor *Actor) SetEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName, newEnvVars resources.EnvironmentVariables) (Warnings, error) { + var allWarnings Warnings + + existingEnvVars, warnings, err := actor.CloudControllerClient.GetEnvironmentVariableGroup(group) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + for k := range existingEnvVars { + if _, ok := newEnvVars[k]; !ok { + newEnvVars[k] = types.FilteredString{IsSet: false} + } + } + + _, warnings, err = actor.CloudControllerClient.UpdateEnvironmentVariableGroup(group, newEnvVars) + allWarnings = append(allWarnings, warnings...) + + return allWarnings, err +} + +// UnsetEnvironmentVariableByApplicationNameAndSpace removes an environment +// variable from an application. It must be restarted for changes to take +// effect. +func (actor *Actor) UnsetEnvironmentVariableByApplicationNameAndSpace(appName string, spaceGUID string, environmentVariableName string) (Warnings, error) { + app, warnings, appErr := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if appErr != nil { + return warnings, appErr + } + envGroups, getWarnings, getErr := actor.CloudControllerClient.GetApplicationEnvironment(app.GUID) + warnings = append(warnings, getWarnings...) + if getErr != nil { + return warnings, getErr + } + + if _, ok := envGroups.EnvironmentVariables[environmentVariableName]; !ok { + return warnings, actionerror.EnvironmentVariableNotSetError{EnvironmentVariableName: environmentVariableName} + } + + _, patchWarnings, patchErr := actor.CloudControllerClient.UpdateApplicationEnvironmentVariables( + app.GUID, + resources.EnvironmentVariables{ + environmentVariableName: {Value: "", IsSet: false}, + }) + warnings = append(warnings, patchWarnings...) + return warnings, patchErr +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/event.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/event.go new file mode 100644 index 0000000..36b1726 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/event.go @@ -0,0 +1,104 @@ +package v7action + +import ( + "fmt" + "strconv" + "strings" + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/util/generic" +) + +type Event struct { + GUID string + Time time.Time + Type string + ActorName string + Description string +} + +func (actor Actor) GetRecentEventsByApplicationNameAndSpace(appName string, spaceGUID string) ([]Event, Warnings, error) { + var allWarnings Warnings + + app, appWarnings, appErr := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, appWarnings...) + if appErr != nil { + return nil, allWarnings, appErr + } + + ccEvents, warnings, err := actor.CloudControllerClient.GetEvents( + ccv3.Query{Key: ccv3.TargetGUIDFilter, Values: []string{app.GUID}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, + ) + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return nil, allWarnings, err + } + + var events []Event + for _, ccEvent := range ccEvents { + events = append(events, Event{ + GUID: ccEvent.GUID, + Time: ccEvent.CreatedAt, + Type: ccEvent.Type, + ActorName: ccEvent.ActorName, + Description: generateDescription(ccEvent.Data), + }) + + } + + return events, allWarnings, nil +} + +var knownMetadataKeys = []string{ + "index", + "reason", + "cell_id", + "instance", + "exit_description", + "exit_status", + "recursive", + "disk_quota", + "instances", + "memory", + "state", + "command", + "environment_json", +} + +func generateDescription(data map[string]interface{}) string { + mappedData := generic.NewMap(data) + if mappedData.Has("request") { + mappedData = generic.NewMap(mappedData.Get("request")) + } + return formatDescription(mappedData, knownMetadataKeys) +} + +func formatDescription(metadata generic.Map, keys []string) string { + parts := []string{} + for _, key := range keys { + value := metadata.Get(key) + if value != nil { + parts = append(parts, fmt.Sprintf("%s: %s", key, formatDescriptionPart(value))) + } + } + return strings.Join(parts, ", ") +} + +func formatDescriptionPart(val interface{}) string { + switch val := val.(type) { + case string: + return val + case float64: + return strconv.FormatFloat(val, byte('f'), -1, 64) + case bool: + if val { + return "true" + } + return "false" + default: + return fmt.Sprintf("%s", val) + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/feature_flag.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/feature_flag.go new file mode 100644 index 0000000..00b9740 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/feature_flag.go @@ -0,0 +1,48 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/resources" +) + +// GetFeatureFlagByName returns a featureFlag with the provided name. +func (actor Actor) GetFeatureFlagByName(featureFlagName string) (resources.FeatureFlag, Warnings, error) { + featureFlag, warnings, err := actor.CloudControllerClient.GetFeatureFlag(featureFlagName) + + if err != nil { + if _, ok := err.(ccerror.FeatureFlagNotFoundError); ok { + return resources.FeatureFlag{}, Warnings(warnings), actionerror.FeatureFlagNotFoundError{FeatureFlagName: featureFlagName} + } + return resources.FeatureFlag{}, Warnings(warnings), err + } + + return featureFlag, Warnings(warnings), err +} + +func (actor Actor) GetFeatureFlags() ([]resources.FeatureFlag, Warnings, error) { + featureFlags, warnings, err := actor.CloudControllerClient.GetFeatureFlags() + + if err != nil { + return nil, Warnings(warnings), err + } + + return featureFlags, Warnings(warnings), nil +} + +func (actor Actor) EnableFeatureFlag(flagName string) (Warnings, error) { + return actor.updateFeatureFlag(resources.FeatureFlag{Name: flagName, Enabled: true}) +} + +func (actor Actor) DisableFeatureFlag(flagName string) (Warnings, error) { + return actor.updateFeatureFlag(resources.FeatureFlag{Name: flagName, Enabled: false}) +} + +func (actor Actor) updateFeatureFlag(flag resources.FeatureFlag) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.UpdateFeatureFlag(flag) + + if _, ok := err.(ccerror.FeatureFlagNotFoundError); ok { + err = actionerror.FeatureFlagNotFoundError{FeatureFlagName: flag.Name} + } + return Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_unix.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_unix.go new file mode 100644 index 0000000..5a3e9de --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_unix.go @@ -0,0 +1,12 @@ +//go:build !windows +// +build !windows + +package v7action + +import "os" + +// fixMode is unnecessary on UNIX systems, see windows version for more +// details. +func fixMode(mode os.FileMode) os.FileMode { + return mode +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_windows.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_windows.go new file mode 100644 index 0000000..2ad56de --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/fix_mode_windows.go @@ -0,0 +1,12 @@ +//go:build windows +// +build windows + +package v7action + +import "os" + +// fixMode forces all files on windows to be executable because by default +// everything on windows is read/write only. Even executable files. +func fixMode(mode os.FileMode) os.FileMode { + return mode | 0700 +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/info.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/info.go new file mode 100644 index 0000000..723c1b5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/info.go @@ -0,0 +1,13 @@ +package v7action + +import "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + +type Info ccv3.Info + +func (actor Actor) GetRootResponse() (Info, Warnings, error) { + info, warnings, err := actor.CloudControllerClient.GetInfo() + if err != nil { + return Info{}, Warnings(warnings), err + } + return Info(info), Warnings(warnings), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/isolation_segment.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/isolation_segment.go new file mode 100644 index 0000000..1ca9e76 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/isolation_segment.go @@ -0,0 +1,197 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +type IsolationSegmentSummary struct { + Name string + EntitledOrgs []string +} + +// GetEffectiveIsolationSegmentBySpace returns the space's effective isolation +// segment. +// +// If the space has its own isolation segment, that will be returned. +// +// If the space does not have one, the organization's default isolation segment +// (GUID passed in) will be returned. +// +// If the space does not have one and the passed in organization default +// isolation segment GUID is empty, a NoRelationshipError will be returned. +func (actor Actor) GetEffectiveIsolationSegmentBySpace(spaceGUID string, orgDefaultIsolationSegmentGUID string) (resources.IsolationSegment, Warnings, error) { + relationship, warnings, err := actor.CloudControllerClient.GetSpaceIsolationSegment(spaceGUID) + allWarnings := append(Warnings{}, warnings...) + if err != nil { + return resources.IsolationSegment{}, allWarnings, err + } + + effectiveGUID := relationship.GUID + if effectiveGUID == "" { + if orgDefaultIsolationSegmentGUID != "" { + effectiveGUID = orgDefaultIsolationSegmentGUID + } else { + return resources.IsolationSegment{}, allWarnings, actionerror.NoRelationshipError{} + } + } + + isolationSegment, warnings, err := actor.CloudControllerClient.GetIsolationSegment(effectiveGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.IsolationSegment{}, allWarnings, err + } + + return resources.IsolationSegment(isolationSegment), allWarnings, err +} + +// CreateIsolationSegmentByName creates a given isolation segment. +func (actor Actor) CreateIsolationSegmentByName(isolationSegment resources.IsolationSegment) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.CreateIsolationSegment(resources.IsolationSegment(isolationSegment)) + if _, ok := err.(ccerror.UnprocessableEntityError); ok { + return Warnings(warnings), actionerror.IsolationSegmentAlreadyExistsError{Name: isolationSegment.Name} + } + return Warnings(warnings), err +} + +// DeleteIsolationSegmentByName deletes the given isolation segment. +func (actor Actor) DeleteIsolationSegmentByName(name string) (Warnings, error) { + isolationSegment, warnings, err := actor.GetIsolationSegmentByName(name) + allWarnings := append(Warnings{}, warnings...) + if err != nil { + return allWarnings, err + } + + apiWarnings, err := actor.CloudControllerClient.DeleteIsolationSegment(isolationSegment.GUID) + return append(allWarnings, apiWarnings...), err +} + +// EntitleIsolationSegmentToOrganizationByName entitles the given organization +// to use the specified isolation segment +func (actor Actor) EntitleIsolationSegmentToOrganizationByName(isolationSegmentName string, orgName string) (Warnings, error) { + isolationSegment, warnings, err := actor.GetIsolationSegmentByName(isolationSegmentName) + allWarnings := append(Warnings{}, warnings...) + if err != nil { + return allWarnings, err + } + + organization, warnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + _, apiWarnings, err := actor.CloudControllerClient.EntitleIsolationSegmentToOrganizations(isolationSegment.GUID, []string{organization.GUID}) + return append(allWarnings, apiWarnings...), err +} + +func (actor Actor) AssignIsolationSegmentToSpaceByNameAndSpace(isolationSegmentName string, spaceGUID string) (Warnings, error) { + seg, warnings, err := actor.GetIsolationSegmentByName(isolationSegmentName) + if err != nil { + return warnings, err + } + + _, apiWarnings, err := actor.CloudControllerClient.UpdateSpaceIsolationSegmentRelationship(spaceGUID, seg.GUID) + return append(warnings, apiWarnings...), err +} + +// GetIsolationSegmentByName returns the requested isolation segment. +func (actor Actor) GetIsolationSegmentByName(name string) (resources.IsolationSegment, Warnings, error) { + isolationSegments, warnings, err := actor.CloudControllerClient.GetIsolationSegments( + ccv3.Query{Key: ccv3.NameFilter, Values: []string{name}}, + ) + if err != nil { + return resources.IsolationSegment{}, Warnings(warnings), err + } + + if len(isolationSegments) == 0 { + return resources.IsolationSegment{}, Warnings(warnings), actionerror.IsolationSegmentNotFoundError{Name: name} + } + + return resources.IsolationSegment(isolationSegments[0]), Warnings(warnings), nil +} + +// GetIsolationSegmentSummaries returns all isolation segments and their entitled orgs +func (actor Actor) GetIsolationSegmentSummaries() ([]IsolationSegmentSummary, Warnings, error) { + isolationSegments, warnings, err := actor.CloudControllerClient.GetIsolationSegments() + allWarnings := append(Warnings{}, warnings...) + if err != nil { + return nil, allWarnings, err + } + + var isolationSegmentSummaries []IsolationSegmentSummary + + for _, isolationSegment := range isolationSegments { + isolationSegmentSummary := IsolationSegmentSummary{ + Name: isolationSegment.Name, + EntitledOrgs: []string{}, + } + + orgs, warnings, err := actor.CloudControllerClient.GetIsolationSegmentOrganizations(isolationSegment.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + for _, org := range orgs { + isolationSegmentSummary.EntitledOrgs = append(isolationSegmentSummary.EntitledOrgs, org.Name) + } + + isolationSegmentSummaries = append(isolationSegmentSummaries, isolationSegmentSummary) + } + return isolationSegmentSummaries, allWarnings, nil +} + +func (actor Actor) GetIsolationSegmentsByOrganization(orgGUID string) ([]resources.IsolationSegment, Warnings, error) { + isolationSegments, warnings, err := actor.CloudControllerClient.GetIsolationSegments( + ccv3.Query{Key: ccv3.OrganizationGUIDFilter, Values: []string{orgGUID}}, + ) + if err != nil { + return []resources.IsolationSegment{}, Warnings(warnings), err + } + + return isolationSegments, Warnings(warnings), nil +} + +func (actor Actor) DeleteIsolationSegmentOrganizationByName(isolationSegmentName string, orgName string) (Warnings, error) { + segment, warnings, err := actor.GetIsolationSegmentByName(isolationSegmentName) + allWarnings := append(Warnings{}, warnings...) + if err != nil { + return allWarnings, err + } + + org, warnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return allWarnings, err + } + + apiWarnings, err := actor.CloudControllerClient.DeleteIsolationSegmentOrganization(segment.GUID, org.GUID) + + allWarnings = append(allWarnings, apiWarnings...) + return allWarnings, err +} + +// GetOrganizationDefaultIsolationSegment gets a default isolation segment on +// an organization. +func (actor Actor) GetOrganizationDefaultIsolationSegment(orgGUID string) (string, Warnings, error) { + defaultIsoSegRelationship, apiWarnings, err := actor.CloudControllerClient.GetOrganizationDefaultIsolationSegment(orgGUID) + return defaultIsoSegRelationship.GUID, Warnings(apiWarnings), err +} + +// SetOrganizationDefaultIsolationSegment sets a default isolation segment on +// an organization. +func (actor Actor) SetOrganizationDefaultIsolationSegment(orgGUID string, isoSegGUID string) (Warnings, error) { + _, apiWarnings, err := actor.CloudControllerClient.UpdateOrganizationDefaultIsolationSegmentRelationship(orgGUID, isoSegGUID) + return Warnings(apiWarnings), err +} + +// ResetOrganizationDefaultIsolationSegment resets the default isolation segment fon +// an organization. +func (actor Actor) ResetOrganizationDefaultIsolationSegment(orgGUID string) (Warnings, error) { + _, apiWarnings, err := actor.CloudControllerClient.UpdateOrganizationDefaultIsolationSegmentRelationship(orgGUID, "") + return Warnings(apiWarnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/job.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/job.go new file mode 100644 index 0000000..0324477 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/job.go @@ -0,0 +1,48 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +type JobState constant.JobState + +const ( + JobPolling = JobState(constant.JobPolling) + JobComplete = JobState(constant.JobComplete) + JobFailed = JobState(constant.JobFailed) + JobProcessing = JobState(constant.JobProcessing) +) + +type PollJobEvent struct { + State JobState + Err error + Warnings Warnings +} + +func (actor Actor) PollUploadBuildpackJob(jobURL ccv3.JobURL) (Warnings, error) { + warnings, err := actor.CloudControllerClient.PollJob(jobURL) + return Warnings(warnings), err +} + +func (actor Actor) PollJobToEventStream(jobURL ccv3.JobURL) chan PollJobEvent { + input := actor.CloudControllerClient.PollJobToEventStream(jobURL) + if input == nil { + return nil + } + + output := make(chan PollJobEvent) + + go func() { + for event := range input { + output <- PollJobEvent{ + State: JobState(event.State), + Err: event.Err, + Warnings: Warnings(event.Warnings), + } + } + close(output) + }() + + return output +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/k8s_auth.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/k8s_auth.go new file mode 100644 index 0000000..bbbfadb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/k8s_auth.go @@ -0,0 +1,89 @@ +package v7action + +import ( + "errors" + "fmt" + "sort" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/uaa/constant" + "code.cloudfoundry.org/cli/cf/configuration/coreconfig" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/configv3" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . KubernetesConfigGetter + +type KubernetesConfigGetter interface { + Get() (*clientcmdapi.Config, error) +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . WhoAmIer + +type WhoAmIer interface { + WhoAmI() (resources.K8sUser, ccv3.Warnings, error) +} + +type DefaultKubernetesConfigGetter struct{} + +func NewDefaultKubernetesConfigGetter() DefaultKubernetesConfigGetter { + return DefaultKubernetesConfigGetter{} +} + +func (c DefaultKubernetesConfigGetter) Get() (*clientcmdapi.Config, error) { + pathOpts := clientcmd.NewDefaultPathOptions() + return pathOpts.GetStartingConfig() +} + +type kubernetesAuthActor struct { + config Config + k8sConfigGetter KubernetesConfigGetter + whoAmIer WhoAmIer +} + +func NewKubernetesAuthActor(config Config, k8sConfigGetter KubernetesConfigGetter, whoAmIer WhoAmIer) AuthActor { + return &kubernetesAuthActor{ + config: config, + k8sConfigGetter: k8sConfigGetter, + whoAmIer: whoAmIer, + } +} + +func (actor kubernetesAuthActor) Authenticate(credentials map[string]string, origin string, grantType constant.GrantType) error { + actor.config.SetKubernetesAuthInfo(credentials["k8s-auth-info"]) + return nil +} + +func (actor kubernetesAuthActor) GetLoginPrompts() (map[string]coreconfig.AuthPrompt, error) { + conf, err := actor.k8sConfigGetter.Get() + if err != nil { + return nil, err + } + + if len(conf.AuthInfos) == 0 { + return nil, errors.New("no kubernetes authentication infos configured") + } + + var prompts []string + for authInfo := range conf.AuthInfos { + prompts = append(prompts, authInfo) + } + sort.Strings(prompts) + + return map[string]coreconfig.AuthPrompt{"k8s-auth-info": { + Type: coreconfig.AuthPromptTypeMenu, + Entries: prompts, + DisplayName: "Choose your Kubernetes authentication info", + }}, nil +} + +func (actor kubernetesAuthActor) GetCurrentUser() (configv3.User, error) { + user, _, err := actor.whoAmIer.WhoAmI() + if err != nil { + return configv3.User{}, fmt.Errorf("calling /whoami endpoint failed: %w", err) + } + + return configv3.User{Name: user.Name}, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/label.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/label.go new file mode 100644 index 0000000..5ed9845 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/label.go @@ -0,0 +1,180 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" +) + +func (actor *Actor) GetApplicationLabels(appName string, spaceGUID string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + return actor.extractLabels((*resources.Metadata)(resource.Metadata), warnings, err) +} + +func (actor *Actor) GetDomainLabels(domainName string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetDomainByName(domainName) + return actor.extractLabels(resource.Metadata, warnings, err) +} + +func (actor *Actor) GetOrganizationLabels(orgName string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetOrganizationByName(orgName) + return actor.extractLabels(resource.Metadata, warnings, err) +} + +func (actor *Actor) GetRouteLabels(routeName string, spaceGUID string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetRoute(routeName, spaceGUID) + return actor.extractLabels((*resources.Metadata)(resource.Metadata), warnings, err) +} + +func (actor *Actor) GetServiceBrokerLabels(serviceBrokerName string) (map[string]types.NullString, Warnings, error) { + serviceBroker, warnings, err := actor.GetServiceBrokerByName(serviceBrokerName) + return actor.extractLabels(serviceBroker.Metadata, warnings, err) +} + +func (actor *Actor) GetServiceInstanceLabels(serviceInstanceName, spaceGUID string) (map[string]types.NullString, Warnings, error) { + serviceInstance, warnings, err := actor.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return actor.extractLabels(serviceInstance.Metadata, warnings, err) +} + +func (actor *Actor) GetServiceOfferingLabels(serviceOfferingName, serviceBrokerName string) (map[string]types.NullString, Warnings, error) { + serviceOffering, warnings, err := actor.CloudControllerClient.GetServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName) + return actor.extractLabels(serviceOffering.Metadata, Warnings(warnings), actionerror.EnrichAPIErrors(err)) +} + +func (actor *Actor) GetServicePlanLabels(servicePlanName, serviceOfferingName, serviceBrokerName string) (map[string]types.NullString, Warnings, error) { + servicePlan, warnings, err := actor.GetServicePlanByNameOfferingAndBroker(servicePlanName, serviceOfferingName, serviceBrokerName) + return actor.extractLabels(servicePlan.Metadata, warnings, err) +} + +func (actor *Actor) GetSpaceLabels(spaceName string, orgGUID string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, orgGUID) + return actor.extractLabels(resource.Metadata, warnings, err) +} + +func (actor *Actor) GetStackLabels(stackName string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetStackByName(stackName) + return actor.extractLabels(resource.Metadata, warnings, err) +} + +func (actor *Actor) GetBuildpackLabels(buildpackName string, buildpackStack string) (map[string]types.NullString, Warnings, error) { + resource, warnings, err := actor.GetBuildpackByNameAndStack(buildpackName, buildpackStack) + return actor.extractLabels(resource.Metadata, warnings, err) +} + +func (actor *Actor) extractLabels(metadata *resources.Metadata, warnings Warnings, err error) (map[string]types.NullString, Warnings, error) { + var labels map[string]types.NullString + + if err != nil { + return labels, warnings, err + } + if metadata != nil { + labels = metadata.Labels + } + return labels, warnings, nil +} + +func (actor *Actor) UpdateApplicationLabelsByApplicationName(appName string, spaceGUID string, labels map[string]types.NullString) (Warnings, error) { + app, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("app", app.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateBuildpackLabelsByBuildpackNameAndStack(buildpackName string, stack string, labels map[string]types.NullString) (Warnings, error) { + buildpack, warnings, err := actor.GetBuildpackByNameAndStack(buildpackName, stack) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("buildpack", buildpack.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateDomainLabelsByDomainName(domainName string, labels map[string]types.NullString) (Warnings, error) { + domain, warnings, err := actor.GetDomainByName(domainName) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("domain", domain.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateOrganizationLabelsByOrganizationName(orgName string, labels map[string]types.NullString) (Warnings, error) { + org, warnings, err := actor.GetOrganizationByName(orgName) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("org", org.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateRouteLabels(routeName string, spaceGUID string, labels map[string]types.NullString) (Warnings, error) { + route, warnings, err := actor.GetRoute(routeName, spaceGUID) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("route", route.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateSpaceLabelsBySpaceName(spaceName string, orgGUID string, labels map[string]types.NullString) (Warnings, error) { + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, orgGUID) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("space", space.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateStackLabelsByStackName(stackName string, labels map[string]types.NullString) (Warnings, error) { + stack, warnings, err := actor.GetStackByName(stackName) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("stack", stack.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateServiceBrokerLabelsByServiceBrokerName(serviceBrokerName string, labels map[string]types.NullString) (Warnings, error) { + serviceBroker, warnings, err := actor.GetServiceBrokerByName(serviceBrokerName) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("service-broker", serviceBroker.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateServiceInstanceLabels(serviceInstanceName, spaceGUID string, labels map[string]types.NullString) (Warnings, error) { + serviceInstance, warnings, err := actor.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("service-instance", serviceInstance.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) UpdateServiceOfferingLabels(serviceOfferingName string, serviceBrokerName string, labels map[string]types.NullString) (Warnings, error) { + serviceOffering, warnings, err := actor.CloudControllerClient.GetServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName) + if err != nil { + return Warnings(warnings), actionerror.EnrichAPIErrors(err) + } + return actor.updateResourceMetadata("service-offering", serviceOffering.GUID, resources.Metadata{Labels: labels}, Warnings(warnings)) +} + +func (actor *Actor) UpdateServicePlanLabels(servicePlanName string, serviceOfferingName string, serviceBrokerName string, labels map[string]types.NullString) (Warnings, error) { + servicePlan, warnings, err := actor.GetServicePlanByNameOfferingAndBroker(servicePlanName, serviceOfferingName, serviceBrokerName) + if err != nil { + return warnings, err + } + return actor.updateResourceMetadata("service-plan", servicePlan.GUID, resources.Metadata{Labels: labels}, warnings) +} + +func (actor *Actor) updateResourceMetadata(resourceType string, resourceGUID string, payload resources.Metadata, warnings Warnings) (Warnings, error) { + jobURL, updateWarnings, err := actor.CloudControllerClient.UpdateResourceMetadata(resourceType, resourceGUID, payload) + warnings = append(warnings, updateWarnings...) + if err != nil { + return warnings, err + } + + if jobURL != "" { + pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + warnings = append(warnings, pollWarnings...) + if err != nil { + return warnings, err + } + } + + return warnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/logging.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/logging.go new file mode 100644 index 0000000..5c77b2d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/logging.go @@ -0,0 +1,128 @@ +package v7action + +import ( + "context" + "errors" + "strings" + "time" + + "code.cloudfoundry.org/cli/actor/sharedaction" + "github.com/SermoDigital/jose/jws" +) + +func (actor Actor) GetStreamingLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client sharedaction.LogCacheClient) (<-chan sharedaction.LogMessage, <-chan error, context.CancelFunc, Warnings, error) { + app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return nil, nil, nil, allWarnings, err + } + + messages, logErrs, cancelFunc := sharedaction.GetStreamingLogs(app.GUID, client) + + return messages, logErrs, cancelFunc, allWarnings, err +} + +func (actor Actor) GetRecentLogsForApplicationByNameAndSpace(appName string, spaceGUID string, client sharedaction.LogCacheClient) ([]sharedaction.LogMessage, Warnings, error) { + app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return nil, allWarnings, err + } + + logCacheMessages, err := sharedaction.GetRecentLogs(app.GUID, client) + if err != nil { + return nil, allWarnings, err + } + + var logMessages []sharedaction.LogMessage + + for _, message := range logCacheMessages { + logMessages = append(logMessages, *sharedaction.NewLogMessage( + message.Message(), + message.Type(), + message.Timestamp(), + message.SourceType(), + message.SourceInstance(), + )) + } + + return logMessages, allWarnings, nil +} + +func (actor Actor) ScheduleTokenRefresh( + after func(time.Duration) <-chan time.Time, + stop chan struct{}, + stoppedRefreshingToken chan struct{}) (<-chan error, error) { + + timeToRefresh, err := actor.refreshAccessTokenIfNecessary() + if err != nil { + close(stoppedRefreshingToken) + return nil, err + } + + refreshErrs := make(chan error) + + go func() { + defer close(stoppedRefreshingToken) + for { + select { + case <-after(*timeToRefresh): + d, err := actor.refreshAccessTokenIfNecessary() + if err == nil { + timeToRefresh = d + } else { + refreshErrs <- err + } + case <-stop: + return + } + } + }() + + return refreshErrs, nil +} + +func (actor Actor) refreshAccessTokenIfNecessary() (*time.Duration, error) { + accessToken := actor.Config.AccessToken() + + duration, err := actor.tokenExpiryTime(accessToken) + if err != nil || *duration < time.Minute { + accessToken, err = actor.RefreshAccessToken() + if err != nil { + return nil, err + } + } + + accessToken = strings.TrimPrefix(accessToken, "bearer ") + token, err := jws.ParseJWT([]byte(accessToken)) + if err != nil { + return nil, err + } + + var timeToRefresh time.Duration + expiration, ok := token.Claims().Expiration() + if !ok { + return nil, errors.New("Failed to get an expiry time from the current access token") + } + expiresIn := time.Until(expiration) + if expiresIn >= 2*time.Minute { + timeToRefresh = expiresIn - time.Minute + } else { + timeToRefresh = expiresIn * 9 / 10 + } + return &timeToRefresh, nil +} + +func (actor Actor) tokenExpiryTime(accessToken string) (*time.Duration, error) { + var expiresIn time.Duration + + accessTokenString := strings.TrimPrefix(accessToken, "bearer ") + token, err := jws.ParseJWT([]byte(accessTokenString)) + if err != nil { + return nil, err + } + + expiration, ok := token.Claims().Expiration() + if ok { + expiresIn = time.Until(expiration) + } + return &expiresIn, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/marketplace.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/marketplace.go new file mode 100644 index 0000000..cc6f3a3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/marketplace.go @@ -0,0 +1,56 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" +) + +type ServiceOfferingWithPlans ccv3.ServiceOfferingWithPlans + +type MarketplaceFilter struct { + SpaceGUID, ServiceOfferingName, ServiceBrokerName string + ShowUnavailable bool +} + +func (actor Actor) Marketplace(filter MarketplaceFilter) ([]ServiceOfferingWithPlans, Warnings, error) { + query := []ccv3.Query{{Key: ccv3.PerPage, Values: []string{ccv3.MaxPerPage}}} + + if filter.SpaceGUID != "" { + query = append(query, ccv3.Query{ + Key: ccv3.SpaceGUIDFilter, + Values: []string{filter.SpaceGUID}, + }) + } + + if filter.ServiceOfferingName != "" { + query = append(query, ccv3.Query{ + Key: ccv3.ServiceOfferingNamesFilter, + Values: []string{filter.ServiceOfferingName}, + }) + } + + if filter.ServiceBrokerName != "" { + query = append(query, ccv3.Query{ + Key: ccv3.ServiceBrokerNamesFilter, + Values: []string{filter.ServiceBrokerName}, + }) + } + + if !filter.ShowUnavailable { + query = append(query, ccv3.Query{ + Key: ccv3.AvailableFilter, + Values: []string{"true"}, + }) + } + + serviceOffering, warnings, err := actor.CloudControllerClient.GetServicePlansWithOfferings(query...) + if err != nil { + return nil, Warnings(warnings), err + } + + result := make([]ServiceOfferingWithPlans, len(serviceOffering)) + for i := range serviceOffering { + result[i] = ServiceOfferingWithPlans(serviceOffering[i]) + } + + return result, Warnings(warnings), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/organization.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization.go new file mode 100644 index 0000000..dbe432e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization.go @@ -0,0 +1,113 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) GetOrganizations(labelSelector string) ([]resources.Organization, Warnings, error) { + queries := []ccv3.Query{ + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}}, + } + if len(labelSelector) > 0 { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + orgs, warnings, err := actor.CloudControllerClient.GetOrganizations(queries...) + if err != nil { + return []resources.Organization{}, Warnings(warnings), err + } + + return orgs, Warnings(warnings), nil +} + +// GetOrganizationByGUID returns the organization with the given guid. +func (actor Actor) GetOrganizationByGUID(orgGUID string) (resources.Organization, Warnings, error) { + ccOrg, warnings, err := actor.CloudControllerClient.GetOrganization(orgGUID) + if err != nil { + return resources.Organization{}, Warnings(warnings), err + } + + return resources.Organization(ccOrg), Warnings(warnings), err +} + +// GetOrganizationByName returns the organization with the given name. +func (actor Actor) GetOrganizationByName(name string) (resources.Organization, Warnings, error) { + orgs, warnings, err := actor.CloudControllerClient.GetOrganizations( + ccv3.Query{Key: ccv3.NameFilter, Values: []string{name}}, + ) + if err != nil { + return resources.Organization{}, Warnings(warnings), err + } + + if len(orgs) == 0 { + return resources.Organization{}, Warnings(warnings), actionerror.OrganizationNotFoundError{Name: name} + } + + return resources.Organization(orgs[0]), Warnings(warnings), nil +} + +// CreateOrganization creates a new organization with the given name +func (actor Actor) CreateOrganization(orgName string) (resources.Organization, Warnings, error) { + allWarnings := Warnings{} + + organization, apiWarnings, err := actor.CloudControllerClient.CreateOrganization(orgName) + allWarnings = append(allWarnings, apiWarnings...) + + return organization, allWarnings, err +} + +// updateOrganization updates the name and/or labels of an organization +func (actor Actor) updateOrganization(org resources.Organization) (resources.Organization, Warnings, error) { + updatedOrg, warnings, err := actor.CloudControllerClient.UpdateOrganization(org) + if err != nil { + return resources.Organization{}, Warnings(warnings), err + } + + return updatedOrg, Warnings(warnings), nil +} + +func (actor Actor) RenameOrganization(oldOrgName, newOrgName string) (resources.Organization, Warnings, error) { + var allWarnings Warnings + + org, warnings, err := actor.GetOrganizationByName(oldOrgName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Organization{}, allWarnings, err + } + + org.Name = newOrgName + org, warnings, err = actor.updateOrganization(org) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Organization{}, allWarnings, err + } + return org, allWarnings, nil +} + +func (actor Actor) DeleteOrganization(name string) (Warnings, error) { + var allWarnings Warnings + + org, warnings, err := actor.GetOrganizationByName(name) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + jobURL, deleteWarnings, err := actor.CloudControllerClient.DeleteOrganization(org.GUID) + allWarnings = append(allWarnings, Warnings(deleteWarnings)...) + if err != nil { + return allWarnings, err + } + + ccWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(ccWarnings)...) + + return allWarnings, err +} + +func (actor Actor) GetDefaultDomain(orgGUID string) (resources.Domain, Warnings, error) { + domain, warnings, err := actor.CloudControllerClient.GetDefaultDomain(orgGUID) + + return resources.Domain(domain), Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_quota.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_quota.go new file mode 100644 index 0000000..1352d43 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_quota.go @@ -0,0 +1,180 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" +) + +type QuotaLimits struct { + TotalMemoryInMB *types.NullInt + PerProcessMemoryInMB *types.NullInt + TotalInstances *types.NullInt + PaidServicesAllowed *bool + TotalServiceInstances *types.NullInt + TotalRoutes *types.NullInt + TotalReservedPorts *types.NullInt +} + +func (actor Actor) ApplyOrganizationQuotaByName(quotaName string, orgGUID string) (Warnings, error) { + var allWarnings Warnings + + quota, warnings, err := actor.GetOrganizationQuotaByName(quotaName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + _, ccWarnings, err := actor.CloudControllerClient.ApplyOrganizationQuota(quota.GUID, orgGUID) + allWarnings = append(allWarnings, ccWarnings...) + + return allWarnings, err +} + +// CreateOrganization creates a new organization with the given name +func (actor Actor) CreateOrganizationQuota(name string, limits QuotaLimits) (Warnings, error) { + orgQuota := createQuotaStruct(name, limits) + setZeroDefaultsForQuotaCreation(&orgQuota.Apps, &orgQuota.Routes, &orgQuota.Services) + convertUnlimitedToNil(&orgQuota.Apps, &orgQuota.Routes, &orgQuota.Services) + + _, apiWarnings, err := actor.CloudControllerClient.CreateOrganizationQuota(orgQuota) + + return Warnings(apiWarnings), err +} + +func (actor Actor) DeleteOrganizationQuota(quotaName string) (Warnings, error) { + var allWarnings Warnings + + quota, warnings, err := actor.GetOrganizationQuotaByName(quotaName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + jobURL, ccWarnings, err := actor.CloudControllerClient.DeleteOrganizationQuota(quota.GUID) + allWarnings = append(allWarnings, ccWarnings...) + if err != nil { + return allWarnings, err + } + + ccWarnings, err = actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, ccWarnings...) + + return allWarnings, err +} + +func (actor Actor) GetOrganizationQuotas() ([]resources.OrganizationQuota, Warnings, error) { + orgQuotas, warnings, err := actor.CloudControllerClient.GetOrganizationQuotas() + if err != nil { + return []resources.OrganizationQuota{}, Warnings(warnings), err + } + + return orgQuotas, Warnings(warnings), nil +} + +func (actor Actor) GetOrganizationQuotaByName(orgQuotaName string) (resources.OrganizationQuota, Warnings, error) { + ccv3OrgQuotas, warnings, err := actor.CloudControllerClient.GetOrganizationQuotas( + ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{orgQuotaName}, + }, + ) + if err != nil { + return resources.OrganizationQuota{}, Warnings(warnings), err + + } + + if len(ccv3OrgQuotas) == 0 { + return resources.OrganizationQuota{}, Warnings(warnings), actionerror.OrganizationQuotaNotFoundForNameError{Name: orgQuotaName} + } + + return ccv3OrgQuotas[0], Warnings(warnings), nil +} + +func (actor Actor) UpdateOrganizationQuota(quotaName string, newName string, limits QuotaLimits) (Warnings, error) { + var allWarnings Warnings + + quota, warnings, err := actor.GetOrganizationQuotaByName(quotaName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + if newName == "" { + newName = quotaName + } + newQuota := createQuotaStruct(newName, limits) + newQuota.GUID = quota.GUID + convertUnlimitedToNil(&newQuota.Apps, &newQuota.Routes, &newQuota.Services) + + _, ccWarnings, err := actor.CloudControllerClient.UpdateOrganizationQuota(newQuota) + allWarnings = append(allWarnings, ccWarnings...) + + return allWarnings, err +} + +func createQuotaStruct(name string, limits QuotaLimits) resources.OrganizationQuota { + AppLimit := resources.AppLimit{ + TotalMemory: limits.TotalMemoryInMB, + InstanceMemory: limits.PerProcessMemoryInMB, + TotalAppInstances: limits.TotalInstances, + } + ServiceLimit := resources.ServiceLimit{ + TotalServiceInstances: limits.TotalServiceInstances, + PaidServicePlans: limits.PaidServicesAllowed, + } + RouteLimit := resources.RouteLimit{ + TotalRoutes: limits.TotalRoutes, + TotalReservedPorts: limits.TotalReservedPorts, + } + + quota := resources.OrganizationQuota{ + Quota: resources.Quota{ + Name: name, + Apps: AppLimit, + Services: ServiceLimit, + Routes: RouteLimit, + }, + } + + return quota +} + +func setZeroDefaultsForQuotaCreation(apps *resources.AppLimit, routes *resources.RouteLimit, services *resources.ServiceLimit) { + if apps.TotalMemory == nil { + apps.TotalMemory = &types.NullInt{IsSet: true, Value: 0} + } + + if routes.TotalRoutes == nil { + routes.TotalRoutes = &types.NullInt{IsSet: true, Value: 0} + } + + if routes.TotalReservedPorts == nil { + routes.TotalReservedPorts = &types.NullInt{IsSet: true, Value: 0} + } + + if services.TotalServiceInstances == nil { + services.TotalServiceInstances = &types.NullInt{IsSet: true, Value: 0} + } +} + +func convertUnlimitedToNil(apps *resources.AppLimit, routes *resources.RouteLimit, services *resources.ServiceLimit) { + flags := []*types.NullInt{ + apps.TotalMemory, + apps.InstanceMemory, + apps.TotalAppInstances, + services.TotalServiceInstances, + routes.TotalRoutes, + routes.TotalReservedPorts, + } + + for i := 0; i < len(flags); i++ { + if flags[i] != nil { + if flags[i].Value == -1 { + flags[i].IsSet = false + flags[i].Value = 0 + } + } + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_summary.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_summary.go new file mode 100644 index 0000000..2fdc28c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/organization_summary.go @@ -0,0 +1,75 @@ +package v7action + +import ( + "sort" + + "code.cloudfoundry.org/cli/resources" +) + +type OrganizationSummary struct { + resources.Organization + DomainNames []string + QuotaName string + SpaceNames []string + + // DefaultIsolationSegmentGUID is the unique identifier of the isolation + // segment this organization is tagged with. + DefaultIsolationSegmentGUID string +} + +func (actor Actor) GetOrganizationSummaryByName(orgName string) (OrganizationSummary, Warnings, error) { + var allWarnings Warnings + + org, warnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return OrganizationSummary{}, allWarnings, err + } + + domains, warnings, err := actor.GetOrganizationDomains(org.GUID, "") + allWarnings = append(allWarnings, warnings...) + if err != nil { + return OrganizationSummary{}, allWarnings, err + } + + quota, ccv3Warnings, err := actor.CloudControllerClient.GetOrganizationQuota(org.QuotaGUID) + allWarnings = append(allWarnings, ccv3Warnings...) + if err != nil { + return OrganizationSummary{}, allWarnings, err + } + + spaces, warnings, err := actor.GetOrganizationSpaces(org.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return OrganizationSummary{}, allWarnings, err + } + + isoSegGUID, warnings, err := actor.GetOrganizationDefaultIsolationSegment(org.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return OrganizationSummary{}, allWarnings, err + } + + domainNames := []string{} + for _, domain := range domains { + domainNames = append(domainNames, domain.Name) + } + + spaceNames := []string{} + for _, space := range spaces { + spaceNames = append(spaceNames, space.Name) + } + + sort.Strings(domainNames) + sort.Strings(spaceNames) + + organizationSummary := OrganizationSummary{ + Organization: org, + DomainNames: domainNames, + QuotaName: quota.Name, + SpaceNames: spaceNames, + DefaultIsolationSegmentGUID: isoSegGUID, + } + + return organizationSummary, allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/package.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/package.go new file mode 100644 index 0000000..38f080d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/package.go @@ -0,0 +1,259 @@ +package v7action + +import ( + "io" + "os" + "time" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/actor/sharedaction" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + log "github.com/sirupsen/logrus" +) + +const ( + DefaultFolderPermissions = 0755 + DefaultArchiveFilePermissions = 0744 +) + +type DockerImageCredentials struct { + Path string + Username string + Password string +} + +func (actor Actor) CreateDockerPackageByApplication(appGUID string, dockerImageCredentials DockerImageCredentials) (resources.Package, Warnings, error) { + inputPackage := resources.Package{ + Type: constant.PackageTypeDocker, + Relationships: resources.Relationships{ + constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}, + }, + DockerImage: dockerImageCredentials.Path, + DockerUsername: dockerImageCredentials.Username, + DockerPassword: dockerImageCredentials.Password, + } + pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage) + return resources.Package(pkg), Warnings(warnings), err +} + +func (actor Actor) CreateDockerPackageByApplicationNameAndSpace(appName string, spaceGUID string, dockerImageCredentials DockerImageCredentials) (resources.Package, Warnings, error) { + app, getWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return resources.Package{}, getWarnings, err + } + pkg, warnings, err := actor.CreateDockerPackageByApplication(app.GUID, dockerImageCredentials) + return pkg, append(getWarnings, warnings...), err +} + +func (actor Actor) CreateAndUploadBitsPackageByApplicationNameAndSpace(appName string, spaceGUID string, bitsPath string) (resources.Package, Warnings, error) { + app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return resources.Package{}, allWarnings, err + } + + if bitsPath == "" { + bitsPath, err = os.Getwd() + if err != nil { + return resources.Package{}, allWarnings, err + } + } + + info, err := os.Stat(bitsPath) + if err != nil { + return resources.Package{}, allWarnings, err + } + + var fileResources []sharedaction.Resource + if info.IsDir() { + fileResources, err = actor.SharedActor.GatherDirectoryResources(bitsPath) + } else { + fileResources, err = actor.SharedActor.GatherArchiveResources(bitsPath) + } + if err != nil { + return resources.Package{}, allWarnings, err + } + + // potentially match resources here in the future + + var archivePath string + if info.IsDir() { + archivePath, err = actor.SharedActor.ZipDirectoryResources(bitsPath, fileResources) + } else { + archivePath, err = actor.SharedActor.ZipArchiveResources(bitsPath, fileResources) + } + if err != nil { + os.RemoveAll(archivePath) + return resources.Package{}, allWarnings, err + } + defer os.RemoveAll(archivePath) + + inputPackage := resources.Package{ + Type: constant.PackageTypeBits, + Relationships: resources.Relationships{ + constant.RelationshipTypeApplication: resources.Relationship{GUID: app.GUID}, + }, + } + + pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + + _, warnings, err = actor.CloudControllerClient.UploadPackage(pkg, archivePath) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + + for pkg.State != constant.PackageReady && + pkg.State != constant.PackageFailed && + pkg.State != constant.PackageExpired { + time.Sleep(actor.Config.PollingInterval()) + pkg, warnings, err = actor.CloudControllerClient.GetPackage(pkg.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + } + + if pkg.State == constant.PackageFailed { + return resources.Package{}, allWarnings, actionerror.PackageProcessingFailedError{} + } else if pkg.State == constant.PackageExpired { + return resources.Package{}, allWarnings, actionerror.PackageProcessingExpiredError{} + } + + updatedPackage, updatedWarnings, err := actor.PollPackage(resources.Package(pkg)) + return updatedPackage, append(allWarnings, updatedWarnings...), err +} + +func (actor Actor) GetNewestReadyPackageForApplication(app resources.Application) (resources.Package, Warnings, error) { + ccv3Packages, warnings, err := actor.CloudControllerClient.GetPackages( + ccv3.Query{ + Key: ccv3.AppGUIDFilter, + Values: []string{app.GUID}, + }, + ccv3.Query{ + Key: ccv3.StatesFilter, + Values: []string{string(constant.PackageReady)}, + }, + ccv3.Query{ + Key: ccv3.OrderBy, + Values: []string{ccv3.CreatedAtDescendingOrder}, + }, + ) + + if err != nil { + return resources.Package{}, Warnings(warnings), err + } + + if len(ccv3Packages) == 0 { + return resources.Package{}, Warnings(warnings), actionerror.NoEligiblePackagesError{AppName: app.Name} + } + + return resources.Package(ccv3Packages[0]), Warnings(warnings), nil +} + +// GetApplicationPackages returns a list of package of an app. +func (actor *Actor) GetApplicationPackages(appName string, spaceGUID string) ([]resources.Package, Warnings, error) { + app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return nil, allWarnings, err + } + + ccv3Packages, warnings, err := actor.CloudControllerClient.GetPackages( + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{app.GUID}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, + ) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + var packages []resources.Package + for _, ccv3Package := range ccv3Packages { + packages = append(packages, resources.Package(ccv3Package)) + } + + return packages, allWarnings, nil +} + +func (actor Actor) CreateBitsPackageByApplication(appGUID string) (resources.Package, Warnings, error) { + inputPackage := resources.Package{ + Type: constant.PackageTypeBits, + Relationships: resources.Relationships{ + constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}, + }, + } + + pkg, warnings, err := actor.CloudControllerClient.CreatePackage(inputPackage) + if err != nil { + return resources.Package{}, Warnings(warnings), err + } + + return resources.Package(pkg), Warnings(warnings), err +} + +func (actor Actor) UploadBitsPackage(pkg resources.Package, matchedResources []sharedaction.V3Resource, newResources io.Reader, newResourcesLength int64) (resources.Package, Warnings, error) { + apiResources := make([]ccv3.Resource, 0, len(matchedResources)) // Explicitly done to prevent nils + + for _, resource := range matchedResources { + apiResources = append(apiResources, ccv3.Resource(resource)) + } + + appPkg, warnings, err := actor.CloudControllerClient.UploadBitsPackage(resources.Package(pkg), apiResources, newResources, newResourcesLength) + return resources.Package(appPkg), Warnings(warnings), err +} + +// PollPackage returns a package of an app. +func (actor Actor) PollPackage(pkg resources.Package) (resources.Package, Warnings, error) { + var allWarnings Warnings + + for pkg.State != constant.PackageReady && pkg.State != constant.PackageFailed && pkg.State != constant.PackageExpired { + time.Sleep(actor.Config.PollingInterval()) + ccPkg, warnings, err := actor.CloudControllerClient.GetPackage(pkg.GUID) + log.WithFields(log.Fields{ + "package_guid": pkg.GUID, + "state": pkg.State, + }).Debug("polling package state") + + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + + pkg = resources.Package(ccPkg) + } + + if pkg.State == constant.PackageFailed { + return resources.Package{}, allWarnings, actionerror.PackageProcessingFailedError{} + } else if pkg.State == constant.PackageExpired { + return resources.Package{}, allWarnings, actionerror.PackageProcessingExpiredError{} + } + + return pkg, allWarnings, nil +} + +func (actor Actor) CopyPackage(sourceApp resources.Application, targetApp resources.Application) (resources.Package, Warnings, error) { + var allWarnings Warnings + sourcePkg, warnings, err := actor.GetNewestReadyPackageForApplication(sourceApp) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + targetPkg, ccv3Warnings, err := actor.CloudControllerClient.CopyPackage(sourcePkg.GUID, targetApp.GUID) + allWarnings = append(allWarnings, ccv3Warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + + readyPackage, warnings, err := actor.PollPackage(resources.Package(targetPkg)) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Package{}, allWarnings, err + } + + return readyPackage, allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/process.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/process.go new file mode 100644 index 0000000..c25884e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/process.go @@ -0,0 +1,62 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) GetProcess(processGUID string) (resources.Process, Warnings, error) { + process, warnings, err := actor.CloudControllerClient.GetProcess(processGUID) + + return resources.Process(process), Warnings(warnings), err +} + +// GetProcessByTypeAndApplication returns a process for the given application +// and type. +func (actor Actor) GetProcessByTypeAndApplication(processType string, appGUID string) (resources.Process, Warnings, error) { + process, warnings, err := actor.CloudControllerClient.GetApplicationProcessByType(appGUID, processType) + if _, ok := err.(ccerror.ProcessNotFoundError); ok { + return resources.Process{}, Warnings(warnings), actionerror.ProcessNotFoundError{ProcessType: processType} + } + return resources.Process(process), Warnings(warnings), err +} + +func (actor Actor) ScaleProcessByApplication(appGUID string, process resources.Process) (Warnings, error) { + _, warnings, err := actor.CloudControllerClient.CreateApplicationProcessScale(appGUID, resources.Process(process)) + allWarnings := Warnings(warnings) + if err != nil { + if _, ok := err.(ccerror.ProcessNotFoundError); ok { + return allWarnings, actionerror.ProcessNotFoundError{ProcessType: process.Type} + } + return allWarnings, err + } + + return allWarnings, nil +} + +func (actor Actor) UpdateProcessByTypeAndApplication(processType string, appGUID string, updatedProcess resources.Process) (Warnings, error) { + if updatedProcess.HealthCheckType != constant.HTTP { + if updatedProcess.HealthCheckEndpoint != constant.ProcessHealthCheckEndpointDefault && updatedProcess.HealthCheckEndpoint != "" { + return nil, actionerror.HTTPHealthCheckInvalidError{} + } + + updatedProcess.HealthCheckEndpoint = "" + } + + process, warnings, err := actor.GetProcessByTypeAndApplication(processType, appGUID) + allWarnings := warnings + if err != nil { + return allWarnings, err + } + + updatedProcess.GUID = process.GUID + _, updateWarnings, err := actor.CloudControllerClient.UpdateProcess(resources.Process(updatedProcess)) + allWarnings = append(allWarnings, Warnings(updateWarnings)...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/process_health_check.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_health_check.go new file mode 100644 index 0000000..51f2edb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_health_check.go @@ -0,0 +1,70 @@ +package v7action + +import ( + "sort" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +type ProcessHealthCheck struct { + ProcessType string + HealthCheckType constant.HealthCheckType + Endpoint string + InvocationTimeout int64 +} + +type ProcessHealthChecks []ProcessHealthCheck + +func (phs ProcessHealthChecks) Sort() { + sort.Slice(phs, func(i int, j int) bool { + var iScore int + var jScore int + + switch phs[i].ProcessType { + case constant.ProcessTypeWeb: + iScore = 0 + default: + iScore = 1 + } + + switch phs[j].ProcessType { + case constant.ProcessTypeWeb: + jScore = 0 + default: + jScore = 1 + } + + if iScore == 1 && jScore == 1 { + return phs[i].ProcessType < phs[j].ProcessType + } + return iScore < jScore + }) +} + +func (actor Actor) GetApplicationProcessHealthChecksByNameAndSpace(appName string, spaceGUID string) ([]ProcessHealthCheck, Warnings, error) { + app, allWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + if err != nil { + return nil, allWarnings, err + } + + ccv3Processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(app.GUID) + allWarnings = append(allWarnings, Warnings(warnings)...) + if err != nil { + return nil, allWarnings, err + } + + var processHealthChecks ProcessHealthChecks + for _, ccv3Process := range ccv3Processes { + processHealthCheck := ProcessHealthCheck{ + ProcessType: ccv3Process.Type, + HealthCheckType: ccv3Process.HealthCheckType, + Endpoint: ccv3Process.HealthCheckEndpoint, + InvocationTimeout: ccv3Process.HealthCheckInvocationTimeout, + } + processHealthChecks = append(processHealthChecks, processHealthCheck) + } + + processHealthChecks.Sort() + + return processHealthChecks, allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/process_instance.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_instance.go new file mode 100644 index 0000000..5393899 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_instance.go @@ -0,0 +1,77 @@ +package v7action + +import ( + "time" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +type ProcessInstance ccv3.ProcessInstance + +// Running will return true if the instance is running. +func (instance ProcessInstance) Running() bool { + return instance.State == constant.ProcessInstanceRunning +} + +// StartTime returns the time that the instance started. +func (instance *ProcessInstance) StartTime() time.Time { + return time.Now().Add(-instance.Uptime) +} + +type ProcessInstances []ccv3.ProcessInstance + +func (pi ProcessInstances) AllCrashed() bool { + for _, instance := range pi { + if instance.State != constant.ProcessInstanceCrashed { + return false + } + } + return true +} + +func (pi ProcessInstances) AnyRunning() bool { + for _, instance := range pi { + if instance.State == constant.ProcessInstanceRunning { + return true + } + } + return false +} + +func (pi ProcessInstances) Empty() bool { + return len(pi) == 0 +} + +func (actor Actor) DeleteInstanceByApplicationNameSpaceProcessTypeAndIndex(appName string, spaceGUID string, processType string, instanceIndex int) (Warnings, error) { + var allWarnings Warnings + app, appWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, appWarnings...) + if err != nil { + return allWarnings, err + } + + deleteWarnings, err := actor.CloudControllerClient.DeleteApplicationProcessInstance(app.GUID, processType, instanceIndex) + allWarnings = append(allWarnings, deleteWarnings...) + + if err != nil { + switch err.(type) { + case ccerror.ProcessNotFoundError: + return allWarnings, actionerror.ProcessNotFoundError{ + ProcessType: processType, + } + case ccerror.InstanceNotFoundError: + return allWarnings, actionerror.ProcessInstanceNotFoundError{ + ProcessType: processType, + InstanceIndex: uint(instanceIndex), + } + default: + return allWarnings, err + } + } + + return allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/process_summary.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_summary.go new file mode 100644 index 0000000..72f1e9a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/process_summary.go @@ -0,0 +1,136 @@ +package v7action + +import ( + "fmt" + "sort" + "strings" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + log "github.com/sirupsen/logrus" +) + +// ProcessSummary represents a process with instance details. +type ProcessSummary struct { + resources.Process + + Sidecars []resources.Sidecar + + InstanceDetails []ProcessInstance +} + +type ProcessSummaries []ProcessSummary + +func (p ProcessSummary) TotalInstanceCount() int { + return len(p.InstanceDetails) +} + +func (p ProcessSummary) HealthyInstanceCount() int { + count := 0 + for _, instance := range p.InstanceDetails { + if instance.State == constant.ProcessInstanceRunning { + count++ + } + } + return count +} + +func (ps ProcessSummaries) Sort() { + sort.Slice(ps, func(i int, j int) bool { + var iScore int + var jScore int + + switch ps[i].Type { + case constant.ProcessTypeWeb: + iScore = 0 + default: + iScore = 1 + } + + switch ps[j].Type { + case constant.ProcessTypeWeb: + jScore = 0 + default: + jScore = 1 + } + + if iScore == 1 && jScore == 1 { + return ps[i].Type < ps[j].Type + } + return iScore < jScore + }) +} + +func (ps ProcessSummaries) String() string { + ps.Sort() + + var summaries []string + for _, p := range ps { + summaries = append(summaries, fmt.Sprintf("%s:%d/%d", p.Type, p.HealthyInstanceCount(), p.TotalInstanceCount())) + } + + return strings.Join(summaries, ", ") +} + +func (actor Actor) getProcessSummariesForApp(appGUID string, withObfuscatedValues bool) (ProcessSummaries, Warnings, error) { + log.WithFields(log.Fields{ + "appGUID": appGUID, + "withObfuscatedValues": withObfuscatedValues, + }).Info("retrieving process information") + + ccv3Processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID) + allWarnings := Warnings(warnings) + if err != nil { + return nil, allWarnings, err + } + + var processSummaries ProcessSummaries + for _, ccv3Process := range ccv3Processes { + process := resources.Process(ccv3Process) + if withObfuscatedValues { + fullProcess, warnings, err := actor.GetProcess(ccv3Process.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + process = fullProcess + } + + processSummary, warnings, err := actor.getProcessSummary(process) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + processSummaries = append(processSummaries, processSummary) + } + processSummaries.Sort() + + return processSummaries, allWarnings, nil +} + +func (actor Actor) getProcessSummary(process resources.Process) (ProcessSummary, Warnings, error) { + sidecars, warnings, err := actor.CloudControllerClient.GetProcessSidecars(process.GUID) + allWarnings := Warnings(warnings) + if err != nil { + return ProcessSummary{}, allWarnings, err + } + + instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID) + allWarnings = append(allWarnings, Warnings(warnings)...) + if err != nil { + return ProcessSummary{}, allWarnings, err + } + + processSummary := ProcessSummary{ + Process: process, + } + for _, sidecar := range sidecars { + processSummary.Sidecars = append(processSummary.Sidecars, resources.Sidecar(sidecar)) + } + for _, instance := range instances { + processSummary.InstanceDetails = append(processSummary.InstanceDetails, ProcessInstance(instance)) + } + + return processSummary, allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/progress_bar.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/progress_bar.go new file mode 100644 index 0000000..3b1951c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/progress_bar.go @@ -0,0 +1,48 @@ +package v7action + +import ( + "io" + "os" + "time" + + "gopkg.in/cheggaaa/pb.v1" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SimpleProgressBar + +type SimpleProgressBar interface { + Initialize(path string) (io.Reader, int64, error) + Terminate() +} + +type ProgressBar struct { + bar *pb.ProgressBar +} + +func NewProgressBar() *ProgressBar { + return &ProgressBar{} +} + +func (p *ProgressBar) Initialize(path string) (io.Reader, int64, error) { + file, err := os.Open(path) + if err != nil { + return nil, 0, err + } + + fileInfo, err := file.Stat() + if err != nil { + return nil, 0, err + } + + p.bar = pb.New(int(fileInfo.Size())).SetUnits(pb.U_BYTES) + p.bar.ShowTimeLeft = false + p.bar.Start() + return p.bar.NewProxyReader(file), fileInfo.Size(), nil + +} + +func (p *ProgressBar) Terminate() { + // Adding sleep to ensure UI has finished drawing + time.Sleep(time.Second) + p.bar.Finish() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/resource_match.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/resource_match.go new file mode 100644 index 0000000..dc5db1c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/resource_match.go @@ -0,0 +1,59 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/sharedaction" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + log "github.com/sirupsen/logrus" +) + +func (actor Actor) ResourceMatch(resources []sharedaction.V3Resource) ([]sharedaction.V3Resource, Warnings, error) { + resourceChunks := actor.chunkResources(resources) + + log.WithFields(log.Fields{ + "total_resources": len(resources), + "chunks": len(resourceChunks), + }).Debug("sending resource match stats") + + var ( + allWarnings Warnings + matchedAPIResources []ccv3.Resource + ) + + for _, chunk := range resourceChunks { + newMatchedAPIResources, warnings, err := actor.CloudControllerClient.ResourceMatch(chunk) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + matchedAPIResources = append(matchedAPIResources, newMatchedAPIResources...) + } + + var matchedResources []sharedaction.V3Resource + for _, resource := range matchedAPIResources { + matchedResources = append(matchedResources, sharedaction.V3Resource(resource)) + } + + log.WithFields(log.Fields{ + "matchedResources": len(matchedResources), + }).Debug("number of resources matched by CC") + + return matchedResources, allWarnings, nil +} + +func (Actor) chunkResources(resources []sharedaction.V3Resource) [][]ccv3.Resource { + var chunkedResources [][]ccv3.Resource + var currentSet []ccv3.Resource + + for index, resource := range resources { + if resource.SizeInBytes != 0 { + currentSet = append(currentSet, ccv3.Resource(resource)) + } + + if len(currentSet) == constant.MaxNumberOfResourcesForMatching || index+1 == len(resources) { + chunkedResources = append(chunkedResources, currentSet) + currentSet = []ccv3.Resource{} + } + } + return chunkedResources +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/revisions.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/revisions.go new file mode 100644 index 0000000..47b7920 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/revisions.go @@ -0,0 +1,104 @@ +package v7action + +import ( + "strconv" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/actor/versioncheck" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +const MinimumCCAPIVersionForDeployable = "3.86.0" + +// GetRevisionsByApplicationNameAndSpace returns revisions for application. +func (actor *Actor) GetRevisionsByApplicationNameAndSpace(appName string, spaceGUID string) ([]resources.Revision, Warnings, error) { + var warnings Warnings + app, appWarnings, appErr := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + warnings = append(warnings, appWarnings...) + if appErr != nil { + return []resources.Revision{}, warnings, appErr + } + revisions, apiWarnings, apiErr := actor.CloudControllerClient.GetApplicationRevisions( + app.GUID, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{"-created_at"}}, + ) + warnings = append(warnings, apiWarnings...) + if apiErr != nil { + return []resources.Revision{}, warnings, apiErr + } + versionRequirementMet, versionErr := versioncheck.IsMinimumAPIVersionMet(actor.Config.APIVersion(), MinimumCCAPIVersionForDeployable) + if versionErr != nil { + return []resources.Revision{}, warnings, versionErr + } + if versionRequirementMet == false { + _, deployableWarnings, deployableErr := actor.setRevisionsDeployableByDropletStateForApp(app.GUID, revisions) + warnings = append(warnings, deployableWarnings...) + if deployableErr != nil { + return []resources.Revision{}, warnings, deployableErr + } + } + return revisions, warnings, nil +} + +func (actor Actor) GetRevisionByApplicationAndVersion(appGUID string, revisionVersion int) (resources.Revision, Warnings, error) { + query := ccv3.Query{ + Key: ccv3.VersionsFilter, + Values: []string{strconv.Itoa(revisionVersion)}, + } + revisions, warnings, apiErr := actor.CloudControllerClient.GetApplicationRevisions(appGUID, query) + if apiErr != nil { + return resources.Revision{}, Warnings(warnings), apiErr + } + + if len(revisions) > 1 { + return resources.Revision{}, Warnings(warnings), actionerror.RevisionAmbiguousError{Version: revisionVersion} + } + + if len(revisions) == 0 { + return resources.Revision{}, Warnings(warnings), actionerror.RevisionNotFoundError{Version: revisionVersion} + } + + versionRequirementMet, versionErr := versioncheck.IsMinimumAPIVersionMet(actor.Config.APIVersion(), MinimumCCAPIVersionForDeployable) + if versionErr != nil { + return resources.Revision{}, Warnings(warnings), versionErr + } + if versionRequirementMet == false { + _, deployableWarnings, deployableErr := actor.setRevisionsDeployableByDropletStateForApp(appGUID, revisions) + warnings = append(warnings, deployableWarnings...) + if deployableErr != nil { + return resources.Revision{}, Warnings(warnings), deployableErr + } + } + + return revisions[0], Warnings(warnings), nil +} + +func (actor Actor) setRevisionsDeployableByDropletStateForApp(appGUID string, revisions []resources.Revision) ([]resources.Revision, Warnings, error) { + droplets, warnings, err := actor.CloudControllerClient.GetDroplets( + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, + ) + if err != nil { + return []resources.Revision{}, Warnings(warnings), err + } + for i := range revisions { + for _, droplet := range droplets { + if revisions[i].Droplet.GUID == droplet.GUID { + revisions[i].Deployable = (droplet.State == constant.DropletStaged) + } + } + } + return revisions, Warnings(warnings), nil +} + +func (actor Actor) GetApplicationRevisionsDeployed(appGUID string) ([]resources.Revision, Warnings, error) { + + revisions, warnings, apiErr := actor.CloudControllerClient.GetApplicationRevisionsDeployed(appGUID) + + if apiErr != nil { + return []resources.Revision{}, Warnings(warnings), apiErr + } + + return revisions, Warnings(warnings), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/role.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/role.go new file mode 100644 index 0000000..437d324 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/role.go @@ -0,0 +1,227 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) CreateOrgRole(roleType constant.RoleType, orgGUID string, userNameOrGUID string, userOrigin string, isClient bool) (Warnings, error) { + roleToCreate := resources.Role{ + Type: roleType, + OrgGUID: orgGUID, + } + + if isClient { + err := actor.UAAClient.ValidateClientUser(userNameOrGUID) + if err != nil { + return Warnings{}, err + } + + roleToCreate.UserGUID = userNameOrGUID + } else { + roleToCreate.Username = userNameOrGUID + roleToCreate.Origin = userOrigin + } + + _, warnings, err := actor.CloudControllerClient.CreateRole(roleToCreate) + + return Warnings(warnings), err +} + +func (actor Actor) CreateSpaceRole(roleType constant.RoleType, orgGUID string, spaceGUID string, userNameOrGUID string, userOrigin string, isClient bool) (Warnings, error) { + roleToCreate := resources.Role{ + Type: roleType, + SpaceGUID: spaceGUID, + } + + if isClient { + roleToCreate.UserGUID = userNameOrGUID + } else { + roleToCreate.Username = userNameOrGUID + roleToCreate.Origin = userOrigin + } + + warnings, err := actor.CreateOrgRole(constant.OrgUserRole, orgGUID, userNameOrGUID, userOrigin, isClient) + if err != nil { + _, isIdempotentError := err.(ccerror.RoleAlreadyExistsError) + _, isForbiddenError := err.(ccerror.ForbiddenError) + _, isUserNotFoundError := err.(actionerror.UserNotFoundError) + + if !isIdempotentError && !isForbiddenError && !isUserNotFoundError { + return warnings, err + } + } + + _, ccv3Warnings, err := actor.CloudControllerClient.CreateRole(roleToCreate) + warnings = append(warnings, ccv3Warnings...) + + return warnings, err +} + +func (actor Actor) DeleteOrgRole(roleType constant.RoleType, orgGUID string, userNameOrGUID string, userOrigin string, isClient bool) (Warnings, error) { + var userGUID string + var allWarnings Warnings + userGUID, warnings, err := actor.getUserGuidForDeleteRole(isClient, userNameOrGUID, userOrigin, allWarnings) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + roleGUID, warnings, err := actor.GetRoleGUID(ccv3.OrganizationGUIDFilter, orgGUID, userGUID, roleType) + allWarnings = append(allWarnings, warnings...) + if err != nil || roleGUID == "" { + return allWarnings, err + } + + jobURL, deleteRoleWarnings, err := actor.CloudControllerClient.DeleteRole(roleGUID) + allWarnings = append(allWarnings, deleteRoleWarnings...) + if err != nil { + return allWarnings, err + } + + pollJobWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollJobWarnings...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} + +func (actor Actor) DeleteSpaceRole(roleType constant.RoleType, spaceGUID string, userNameOrGUID string, userOrigin string, isClient bool) (Warnings, error) { + var userGUID string + var allWarnings Warnings + userGUID, userWarnings, err := actor.getUserGuidForDeleteRole(isClient, userNameOrGUID, userOrigin, allWarnings) + allWarnings = append(allWarnings, userWarnings...) + if err != nil { + return allWarnings, err + } + + roleGUID, roleWarnings, err := actor.GetRoleGUID(ccv3.SpaceGUIDFilter, spaceGUID, userGUID, roleType) + allWarnings = append(allWarnings, roleWarnings...) + if err != nil || roleGUID == "" { + return allWarnings, err + } + + jobURL, deleteRoleWarnings, err := actor.CloudControllerClient.DeleteRole(roleGUID) + allWarnings = append(allWarnings, deleteRoleWarnings...) + if err != nil { + return allWarnings, err + } + + pollJobWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollJobWarnings...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} + +func (actor Actor) getUserGuidForDeleteRole(isClient bool, userNameOrGUID string, userOrigin string, allWarnings Warnings) (string, Warnings, error) { + var userGUID string + if isClient { + user, warnings, err := actor.CloudControllerClient.GetUser(userNameOrGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + if _, ok := err.(ccerror.UserNotFoundError); ok { + err = actionerror.UserNotFoundError{Username: userNameOrGUID} + } + return "", allWarnings, err + } + userGUID = user.GUID + } else { + queries := []ccv3.Query{{ + Key: ccv3.UsernamesFilter, + Values: []string{userNameOrGUID}, + }} + if userOrigin != "" { + queries = append(queries, ccv3.Query{ + Key: ccv3.OriginsFilter, + Values: []string{userOrigin}, + }) + } + + ccv3Users, warnings, err := actor.CloudControllerClient.GetUsers(queries...) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", allWarnings, err + } + if len(ccv3Users) == 0 { + return "", allWarnings, actionerror.UserNotFoundError{Username: userNameOrGUID, Origin: userOrigin} + } + if len(ccv3Users) > 1 { + origins := []string{} + for _, user := range ccv3Users { + origins = append(origins, user.Origin) + } + return "", allWarnings, actionerror.AmbiguousUserError{Username: userNameOrGUID, Origins: origins} + } + userGUID = ccv3Users[0].GUID + } + return userGUID, allWarnings, nil +} + +func (actor Actor) GetRoleGUID(queryKey ccv3.QueryKey, orgOrSpaceGUID string, userGUID string, roleType constant.RoleType) (string, Warnings, error) { + ccv3Roles, _, warnings, err := actor.CloudControllerClient.GetRoles( + ccv3.Query{ + Key: ccv3.UserGUIDFilter, + Values: []string{userGUID}, + }, + ccv3.Query{ + Key: ccv3.RoleTypesFilter, + Values: []string{string(roleType)}, + }, + ccv3.Query{ + Key: queryKey, + Values: []string{orgOrSpaceGUID}, + }, + ) + + if err != nil { + return "", Warnings(warnings), err + } + + if len(ccv3Roles) == 0 { + return "", Warnings(warnings), nil + } + + return ccv3Roles[0].GUID, Warnings(warnings), nil +} + +func (actor Actor) GetOrgUsersByRoleType(orgGuid string) (map[constant.RoleType][]resources.User, Warnings, error) { + return actor.getUsersByRoleType(orgGuid, ccv3.OrganizationGUIDFilter) +} + +func (actor Actor) GetSpaceUsersByRoleType(spaceGuid string) (map[constant.RoleType][]resources.User, Warnings, error) { + return actor.getUsersByRoleType(spaceGuid, ccv3.SpaceGUIDFilter) +} + +func (actor Actor) getUsersByRoleType(guid string, filterKey ccv3.QueryKey) (map[constant.RoleType][]resources.User, Warnings, error) { + ccv3Roles, includes, ccWarnings, err := actor.CloudControllerClient.GetRoles( + ccv3.Query{ + Key: filterKey, + Values: []string{guid}, + }, + ccv3.Query{ + Key: ccv3.Include, + Values: []string{"user"}, + }, + ) + if err != nil { + return nil, Warnings(ccWarnings), err + } + usersByGuids := make(map[string]resources.User) + for _, user := range includes.Users { + usersByGuids[user.GUID] = user + } + usersByRoleType := make(map[constant.RoleType][]resources.User) + for _, role := range ccv3Roles { + user := resources.User(usersByGuids[role.UserGUID]) + usersByRoleType[role.Type] = append(usersByRoleType[role.Type], user) + } + return usersByRoleType, Warnings(ccWarnings), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/route.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/route.go new file mode 100644 index 0000000..e91d543 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/route.go @@ -0,0 +1,437 @@ +package v7action + +import ( + "sort" + "strconv" + "strings" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/batcher" + "code.cloudfoundry.org/cli/util/extract" + "code.cloudfoundry.org/cli/util/lookuptable" + "code.cloudfoundry.org/cli/util/railway" + "code.cloudfoundry.org/cli/util/sorting" +) + +type RouteSummary struct { + resources.Route + AppNames []string + AppProtocols []string + DomainName string + SpaceName string + ServiceInstanceName string +} + +func (actor Actor) CreateRoute(spaceGUID, domainName, hostname, path string, port int) (resources.Route, Warnings, error) { + allWarnings := Warnings{} + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return resources.Route{}, allWarnings, err + } + + route, apiWarnings, err := actor.CloudControllerClient.CreateRoute(resources.Route{ + SpaceGUID: spaceGUID, + DomainGUID: domain.GUID, + Host: hostname, + Path: path, + Port: port, + }) + + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + if _, ok := err.(ccerror.RouteNotUniqueError); ok { + return resources.Route{}, allWarnings, actionerror.RouteAlreadyExistsError{Err: err} + } + + return route, allWarnings, err +} + +func (actor Actor) GetRouteDestinations(routeGUID string) ([]resources.RouteDestination, Warnings, error) { + destinations, warnings, err := actor.CloudControllerClient.GetRouteDestinations(routeGUID) + + var actorDestinations []resources.RouteDestination + for _, dst := range destinations { + actorDestinations = append(actorDestinations, resources.RouteDestination{ + GUID: dst.GUID, + App: resources.RouteDestinationApp(dst.App), + }) + } + + return actorDestinations, Warnings(warnings), err +} + +func (actor Actor) GetRouteDestinationByAppGUID(route resources.Route, appGUID string) (resources.RouteDestination, error) { + for _, destination := range route.Destinations { + if destination.App.GUID == appGUID && destination.App.Process.Type == constant.ProcessTypeWeb { + return destination, nil + } + } + + return resources.RouteDestination{}, actionerror.RouteDestinationNotFoundError{ + AppGUID: appGUID, + ProcessType: constant.ProcessTypeWeb, + RouteGUID: route.GUID, + } +} + +func (actor Actor) GetRoutesBySpace(spaceGUID string, labelSelector string) ([]resources.Route, Warnings, error) { + allWarnings := Warnings{} + queries := []ccv3.Query{ + ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + } + if len(labelSelector) > 0 { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + + routes, warnings, err := actor.CloudControllerClient.GetRoutes(queries...) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + return routes, allWarnings, nil +} + +func (actor Actor) parseRoutePath(routePath string) (string, string, string, resources.Domain, Warnings, error) { + var ( + warnings Warnings + host string + path string + port string + ) + + routeParts := strings.SplitN(routePath, "/", 2) + domainAndPort := routeParts[0] + if len(routeParts) > 1 { + path = "/" + routeParts[1] + } + + domainAndPortParts := strings.SplitN(domainAndPort, ":", 2) + domainName := domainAndPortParts[0] + if len(domainAndPortParts) > 1 { + port = domainAndPortParts[1] + } + + domain, allWarnings, err := actor.GetDomainByName(domainName) + + if err != nil { + _, domainNotFound := err.(actionerror.DomainNotFoundError) + domainParts := strings.SplitN(domainName, ".", 2) + needToCheckForHost := domainNotFound && len(domainParts) > 1 + + if !needToCheckForHost { + return "", "", "", resources.Domain{}, allWarnings, err + } + + host = domainParts[0] + domainName = domainParts[1] + domain, warnings, err = actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", "", resources.Domain{}, allWarnings, err + } + } + + return host, path, port, domain, allWarnings, err +} + +func (actor Actor) GetRoute(routePath string, spaceGUID string) (resources.Route, Warnings, error) { + filters := []ccv3.Query{ + { + Key: ccv3.SpaceGUIDFilter, + Values: []string{spaceGUID}, + }, + } + + host, path, port, domain, allWarnings, err := actor.parseRoutePath(routePath) + if err != nil { + return resources.Route{}, allWarnings, err + } + + filters = append(filters, ccv3.Query{Key: ccv3.DomainGUIDFilter, + Values: []string{domain.GUID}, + }) + filters = append(filters, ccv3.Query{Key: ccv3.HostsFilter, + Values: []string{host}, + }) + filters = append(filters, ccv3.Query{Key: ccv3.PathsFilter, + Values: []string{path}, + }) + + if domain.IsTCP() { + filters = append(filters, ccv3.Query{Key: ccv3.PortsFilter, + Values: []string{port}, + }) + } + + routes, warnings, err := actor.CloudControllerClient.GetRoutes(filters...) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return resources.Route{}, allWarnings, err + } + if len(routes) == 0 { + return resources.Route{}, allWarnings, actionerror.RouteNotFoundError{ + Host: host, + DomainName: domain.Name, + Path: path, + } + } + + return routes[0], allWarnings, nil +} + +func (actor Actor) GetRoutesByOrg(orgGUID string, labelSelector string) ([]resources.Route, Warnings, error) { + allWarnings := Warnings{} + queries := []ccv3.Query{ + ccv3.Query{Key: ccv3.OrganizationGUIDFilter, Values: []string{orgGUID}}, + } + if len(labelSelector) > 0 { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + + routes, warnings, err := actor.CloudControllerClient.GetRoutes(queries...) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + return routes, allWarnings, nil +} + +func (actor Actor) GetApplicationMapForRoute(route resources.Route) (map[string]resources.Application, Warnings, error) { + var v7Warning Warnings + apps, v7Warning, err := actor.GetApplicationsByGUIDs(extract.UniqueList("Destinations.App.GUID", route)) + + appMap := make(map[string]resources.Application) + for _, a := range apps { + appMap[a.GUID] = a + } + return appMap, v7Warning, err +} + +func (actor Actor) GetRouteSummaries(routes []resources.Route) ([]RouteSummary, Warnings, error) { + var ( + spaces []resources.Space + apps []resources.Application + routeBindings []resources.RouteBinding + serviceInstances []resources.ServiceInstance + ) + + warnings, err := railway.Sequentially( + func() (ccv3.Warnings, error) { + return batcher.RequestByGUID( + extract.UniqueList("SpaceGUID", routes), + func(guids []string) (ccv3.Warnings, error) { + batch, _, warnings, err := actor.CloudControllerClient.GetSpaces(ccv3.Query{ + Key: ccv3.GUIDFilter, + Values: guids, + }) + spaces = append(spaces, batch...) + return warnings, err + }, + ) + }, + func() (warnings ccv3.Warnings, err error) { + var v7Warning Warnings + apps, v7Warning, err = actor.GetApplicationsByGUIDs(extract.UniqueList("Destinations.App.GUID", routes)) + return ccv3.Warnings(v7Warning), err + }, + func() (warnings ccv3.Warnings, err error) { + return batcher.RequestByGUID( + extract.UniqueList("GUID", routes), + func(guids []string) (ccv3.Warnings, error) { + batch, included, warnings, err := actor.CloudControllerClient.GetRouteBindings( + ccv3.Query{Key: ccv3.Include, Values: []string{"service_instance"}}, + ccv3.Query{Key: ccv3.RouteGUIDFilter, Values: guids}, + ) + routeBindings = append(routeBindings, batch...) + serviceInstances = append(serviceInstances, included.ServiceInstances...) + return warnings, err + }, + ) + }, + ) + + if err != nil { + return nil, Warnings(warnings), err + } + + spaceNamesByGUID := lookuptable.NameFromGUID(spaces) + appNamesByGUID := lookuptable.NameFromGUID(apps) + serviceInstanceNameByGUID := lookuptable.NameFromGUID(serviceInstances) + + serviceInstanceNameByRouteGUID := make(map[string]string) + for _, routeBinding := range routeBindings { + serviceInstanceNameByRouteGUID[routeBinding.RouteGUID] = serviceInstanceNameByGUID[routeBinding.ServiceInstanceGUID] + } + + var routeSummaries []RouteSummary + for _, route := range routes { + var appNames []string + + protocolSet := map[string]bool{} + for _, destination := range route.Destinations { + appNames = append(appNames, appNamesByGUID[destination.App.GUID]) + protocolSet[destination.Protocol] = true + } + + var appProtocols []string + if len(protocolSet) > 0 { + appProtocols = make([]string, 0, len(protocolSet)) + for key := range protocolSet { + appProtocols = append(appProtocols, key) + } + sort.Strings(appProtocols) + } + + routeSummaries = append(routeSummaries, RouteSummary{ + Route: route, + AppNames: appNames, + AppProtocols: appProtocols, + SpaceName: spaceNamesByGUID[route.SpaceGUID], + DomainName: getDomainName(route.URL, route.Host, route.Path, route.Port), + ServiceInstanceName: serviceInstanceNameByRouteGUID[route.GUID], + }) + } + + sort.Slice(routeSummaries, func(i, j int) bool { + return sorting.LessIgnoreCase(routeSummaries[i].SpaceName, routeSummaries[j].SpaceName) + }) + + return routeSummaries, Warnings(warnings), nil +} + +func (actor Actor) DeleteOrphanedRoutes(spaceGUID string) (Warnings, error) { + var allWarnings Warnings + + jobURL, warnings, err := actor.CloudControllerClient.DeleteOrphanedRoutes(spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + warnings, err = actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, warnings...) + + return allWarnings, err +} + +func (actor Actor) DeleteRoute(domainName, hostname, path string, port int) (Warnings, error) { + allWarnings := Warnings{} + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + + if _, ok := err.(actionerror.DomainNotFoundError); ok { + allWarnings = append(allWarnings, err.Error()) + return allWarnings, nil + } + + if err != nil { + return allWarnings, err + } + + route, actorWarnings, err := actor.GetRouteByAttributes(domain, hostname, path, port) + + allWarnings = append(allWarnings, actorWarnings...) + + if err != nil { + return allWarnings, err + } + + jobURL, apiWarnings, err := actor.CloudControllerClient.DeleteRoute(route.GUID) + actorWarnings = Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + if err != nil { + return allWarnings, err + } + + pollJobWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(pollJobWarnings)...) + + return allWarnings, err +} + +func (actor Actor) GetRouteByAttributes(domain resources.Domain, hostname string, path string, port int) (resources.Route, Warnings, error) { + var ( + routes []resources.Route + ccWarnings ccv3.Warnings + err error + ) + + queries := []ccv3.Query{ + {Key: ccv3.DomainGUIDFilter, Values: []string{domain.GUID}}, + {Key: ccv3.HostsFilter, Values: []string{hostname}}, + {Key: ccv3.PathsFilter, Values: []string{path}}, + } + + if domain.IsTCP() { + queries = append(queries, ccv3.Query{Key: ccv3.PortsFilter, Values: []string{strconv.Itoa(port)}}) + } + + routes, ccWarnings, err = actor.CloudControllerClient.GetRoutes(queries...) + if err != nil { + return resources.Route{}, Warnings(ccWarnings), err + } + + if len(routes) < 1 { + return resources.Route{}, Warnings(ccWarnings), actionerror.RouteNotFoundError{ + DomainName: domain.Name, + Host: hostname, + Path: path, + Port: port, + } + } + + return routes[0], Warnings(ccWarnings), nil +} + +func (actor Actor) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID, destinationProtocol) + return Warnings(warnings), err +} + +func (actor Actor) UpdateDestination(routeGUID string, destinationGUID string, protocol string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.UpdateDestination(routeGUID, destinationGUID, protocol) + return Warnings(warnings), err +} +func (actor Actor) UnmapRoute(routeGUID string, destinationGUID string) (Warnings, error) { + warnings, err := actor.CloudControllerClient.UnmapRoute(routeGUID, destinationGUID) + return Warnings(warnings), err +} + +func (actor Actor) GetApplicationRoutes(appGUID string) ([]resources.Route, Warnings, error) { + allWarnings := Warnings{} + + routes, warnings, err := actor.CloudControllerClient.GetApplicationRoutes(appGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + if len(routes) == 0 { + return nil, allWarnings, err + } + + return routes, allWarnings, nil +} + +func getDomainName(fullURL, host, path string, port int) string { + domainWithoutHost := strings.TrimPrefix(fullURL, host+".") + domainWithoutPath := strings.TrimSuffix(domainWithoutHost, path) + + if port > 0 { + portString := strconv.Itoa(port) + domainWithoutPort := strings.TrimSuffix(domainWithoutPath, ":"+portString) + return domainWithoutPort + } + + return domainWithoutPath +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/route_binding.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/route_binding.go new file mode 100644 index 0000000..6d2d278 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/route_binding.go @@ -0,0 +1,176 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/railway" +) + +type CreateRouteBindingParams struct { + SpaceGUID string + ServiceInstanceName string + DomainName string + Hostname string + Path string + Parameters types.OptionalObject +} + +type DeleteRouteBindingParams struct { + SpaceGUID string + ServiceInstanceName string + DomainName string + Hostname string + Path string +} + +type getRouteForBindingParams struct { + SpaceGUID string + DomainName string + Hostname string + Path string +} + +func (actor Actor) CreateRouteBinding(params CreateRouteBindingParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + route resources.Route + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(params.ServiceInstanceName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + route, warnings, err = actor.getRouteForBinding(getRouteForBindingParams{ + SpaceGUID: params.SpaceGUID, + DomainName: params.DomainName, + Hostname: params.Hostname, + Path: params.Path, + }) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.createRouteBinding(serviceInstance.GUID, route.GUID, params.Parameters) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + return stream, Warnings(warnings), err +} + +func (actor Actor) DeleteRouteBinding(params DeleteRouteBindingParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + route resources.Route + binding resources.RouteBinding + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(params.ServiceInstanceName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + route, warnings, err = actor.getRouteForBinding(getRouteForBindingParams{ + SpaceGUID: params.SpaceGUID, + DomainName: params.DomainName, + Hostname: params.Hostname, + Path: params.Path, + }) + return + }, + func() (warnings ccv3.Warnings, err error) { + binding, warnings, err = actor.getRouteBinding(serviceInstance.GUID, route.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.DeleteRouteBinding(binding.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + return stream, Warnings(warnings), err +} + +func (actor Actor) createRouteBinding(serviceInstanceGUID, routeGUID string, parameters types.OptionalObject) (ccv3.JobURL, ccv3.Warnings, error) { + jobURL, warnings, err := actor.CloudControllerClient.CreateRouteBinding(resources.RouteBinding{ + ServiceInstanceGUID: serviceInstanceGUID, + RouteGUID: routeGUID, + Parameters: parameters, + }) + switch err.(type) { + case nil: + return jobURL, warnings, nil + case ccerror.ResourceAlreadyExistsError: + return "", warnings, actionerror.ResourceAlreadyExistsError{Message: err.Error()} + default: + return "", warnings, err + } +} + +func (actor Actor) getRouteBinding(serviceInstanceGUID, routeGUID string) (resources.RouteBinding, ccv3.Warnings, error) { + bindings, _, warnings, err := actor.CloudControllerClient.GetRouteBindings( + ccv3.Query{Key: ccv3.RouteGUIDFilter, Values: []string{routeGUID}}, + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}}, + ) + + switch { + case err != nil: + return resources.RouteBinding{}, warnings, err + case len(bindings) == 0: + return resources.RouteBinding{}, warnings, actionerror.RouteBindingNotFoundError{} + default: + return bindings[0], warnings, nil + } +} + +func (actor Actor) getRouteForBinding(params getRouteForBindingParams) (resources.Route, ccv3.Warnings, error) { + var ( + domain resources.Domain + routes []resources.Route + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + domain, warnings, err = actor.getDomainByName(params.DomainName) + return + }, + func() (warnings ccv3.Warnings, err error) { + routes, warnings, err = actor.CloudControllerClient.GetRoutes( + ccv3.Query{Key: ccv3.DomainGUIDFilter, Values: []string{domain.GUID}}, + ccv3.Query{Key: ccv3.HostsFilter, Values: []string{params.Hostname}}, + ccv3.Query{Key: ccv3.PathsFilter, Values: []string{params.Path}}, + ) + return + }, + ) + + switch { + case err != nil: + return resources.Route{}, warnings, err + case len(routes) == 0: + return resources.Route{}, warnings, actionerror.RouteNotFoundError{ + Host: params.Hostname, + DomainName: domain.Name, + Path: params.Path, + } + default: + return routes[0], warnings, nil + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/router_group.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/router_group.go new file mode 100644 index 0000000..2be81f3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/router_group.go @@ -0,0 +1,37 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/router" + "code.cloudfoundry.org/cli/api/router/routererror" +) + +type RouterGroup router.RouterGroup + +func (actor Actor) GetRouterGroups() ([]RouterGroup, error) { + var routerGroups []RouterGroup + + apiRouterGroups, err := actor.RoutingClient.GetRouterGroups() + if err != nil { + return nil, err + } + + for _, group := range apiRouterGroups { + routerGroups = append(routerGroups, RouterGroup(group)) + } + + return routerGroups, err +} + +func (actor Actor) GetRouterGroupByName(name string) (RouterGroup, error) { + apiRouterGroup, err := actor.RoutingClient.GetRouterGroupByName(name) + if err != nil { + if _, ok := err.(routererror.ResourceNotFoundError); ok { + return RouterGroup{}, actionerror.RouterGroupNotFoundError{Name: name} + } + + return RouterGroup{}, err + } + + return RouterGroup(apiRouterGroup), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/routing_client.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/routing_client.go new file mode 100644 index 0000000..2922959 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/routing_client.go @@ -0,0 +1,10 @@ +package v7action + +import "code.cloudfoundry.org/cli/api/router" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RoutingClient + +type RoutingClient interface { + GetRouterGroups() ([]router.RouterGroup, error) + GetRouterGroupByName(name string) (router.RouterGroup, error) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/security_group.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/security_group.go new file mode 100644 index 0000000..73099a3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/security_group.go @@ -0,0 +1,386 @@ +package v7action + +import ( + "encoding/json" + "io/ioutil" + "os" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/batcher" + "code.cloudfoundry.org/cli/util/lookuptable" +) + +type SecurityGroupSummary struct { + Name string + Rules []resources.Rule + SecurityGroupSpaces []SecurityGroupSpace +} + +type SecurityGroupSpace struct { + SpaceName string + OrgName string + Lifecycle string +} + +func (actor Actor) BindSecurityGroupToSpaces(securityGroupGUID string, spaces []resources.Space, lifecycle constant.SecurityGroupLifecycle) (Warnings, error) { + var ( + warnings ccv3.Warnings + err error + spaceGUIDs []string + ) + + for _, space := range spaces { + spaceGUIDs = append(spaceGUIDs, space.GUID) + } + + switch lifecycle { + case constant.SecurityGroupLifecycleRunning: + warnings, err = actor.CloudControllerClient.UpdateSecurityGroupRunningSpace(securityGroupGUID, spaceGUIDs) + case constant.SecurityGroupLifecycleStaging: + warnings, err = actor.CloudControllerClient.UpdateSecurityGroupStagingSpace(securityGroupGUID, spaceGUIDs) + default: + err = actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} + } + + return Warnings(warnings), err +} + +func (actor Actor) CreateSecurityGroup(name, filePath string) (Warnings, error) { + allWarnings := Warnings{} + bytes, err := parsePath(filePath) + if err != nil { + return allWarnings, err + } + + var rules []resources.Rule + err = json.Unmarshal(bytes, &rules) + if err != nil { + return allWarnings, err + } + + securityGroup := resources.SecurityGroup{Name: name, Rules: rules} + + _, warnings, err := actor.CloudControllerClient.CreateSecurityGroup(securityGroup) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + return allWarnings, nil +} + +func (actor Actor) GetSecurityGroup(securityGroupName string) (resources.SecurityGroup, Warnings, error) { + allWarnings := Warnings{} + + securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{securityGroupName}}) + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return resources.SecurityGroup{}, allWarnings, err + } + + if len(securityGroups) == 0 { + return resources.SecurityGroup{}, allWarnings, actionerror.SecurityGroupNotFoundError{Name: securityGroupName} + } + + return securityGroups[0], allWarnings, err +} + +func (actor Actor) GetSecurityGroupSummary(securityGroupName string) (SecurityGroupSummary, Warnings, error) { + allWarnings := Warnings{} + securityGroupSummary := SecurityGroupSummary{} + securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{securityGroupName}}) + + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return securityGroupSummary, allWarnings, err + } + if len(securityGroups) == 0 { + return securityGroupSummary, allWarnings, actionerror.SecurityGroupNotFoundError{Name: securityGroupName} + } + + securityGroupSummary.Name = securityGroupName + securityGroupSummary.Rules = securityGroups[0].Rules + + var noSecurityGroupSpaces = len(securityGroups[0].StagingSpaceGUIDs) == 0 && len(securityGroups[0].RunningSpaceGUIDs) == 0 + if noSecurityGroupSpaces { + securityGroupSummary.SecurityGroupSpaces = []SecurityGroupSpace{} + } else { + secGroupSpaces, warnings, err := getSecurityGroupSpaces(actor, securityGroups[0].StagingSpaceGUIDs, securityGroups[0].RunningSpaceGUIDs) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return securityGroupSummary, allWarnings, err + } + securityGroupSummary.SecurityGroupSpaces = secGroupSpaces + } + + return securityGroupSummary, allWarnings, nil +} + +func (actor Actor) GetSecurityGroups() ([]SecurityGroupSummary, Warnings, error) { + allWarnings := Warnings{} + securityGroupSummaries := []SecurityGroupSummary{} + securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups() + + allWarnings = append(allWarnings, warnings...) + + if err != nil { + return securityGroupSummaries, allWarnings, err + } + + for _, securityGroup := range securityGroups { + var securityGroupSummary SecurityGroupSummary + securityGroupSummary.Name = securityGroup.Name + securityGroupSummary.Rules = securityGroup.Rules + + var securityGroupSpaces []SecurityGroupSpace + var noSecurityGroupSpaces = !*securityGroup.StagingGloballyEnabled && !*securityGroup.RunningGloballyEnabled && len(securityGroup.StagingSpaceGUIDs) == 0 && len(securityGroup.RunningSpaceGUIDs) == 0 + if noSecurityGroupSpaces { + securityGroupSpaces = []SecurityGroupSpace{} + } + + if *securityGroup.StagingGloballyEnabled { + securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ + SpaceName: "", + OrgName: "", + Lifecycle: "staging", + }) + } + + if *securityGroup.RunningGloballyEnabled { + securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ + SpaceName: "", + OrgName: "", + Lifecycle: "running", + }) + } + + secGroupSpaces, warnings, err := getSecurityGroupSpaces(actor, securityGroup.StagingSpaceGUIDs, securityGroup.RunningSpaceGUIDs) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return securityGroupSummaries, allWarnings, err + } + securityGroupSpaces = append(securityGroupSpaces, secGroupSpaces...) + securityGroupSummary.SecurityGroupSpaces = securityGroupSpaces + + securityGroupSummaries = append(securityGroupSummaries, securityGroupSummary) + } + + return securityGroupSummaries, allWarnings, nil +} + +func (actor Actor) UnbindSecurityGroup(securityGroupName string, orgName string, spaceName string, lifecycle constant.SecurityGroupLifecycle) (Warnings, error) { + var allWarnings Warnings + + org, warnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, org.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + var ccv3Warnings ccv3.Warnings + switch lifecycle { + case constant.SecurityGroupLifecycleRunning: + ccv3Warnings, err = actor.CloudControllerClient.UnbindSecurityGroupRunningSpace(securityGroup.GUID, space.GUID) + case constant.SecurityGroupLifecycleStaging: + ccv3Warnings, err = actor.CloudControllerClient.UnbindSecurityGroupStagingSpace(securityGroup.GUID, space.GUID) + default: + return allWarnings, actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} + } + + allWarnings = append(allWarnings, ccv3Warnings...) + + if err != nil { + if _, isNotBoundError := err.(ccerror.SecurityGroupNotBound); isNotBoundError { + return allWarnings, actionerror.SecurityGroupNotBoundToSpaceError{ + Name: securityGroupName, + Space: spaceName, + Lifecycle: lifecycle, + } + } + } + + return allWarnings, err +} + +func (actor Actor) GetGlobalStagingSecurityGroups() ([]resources.SecurityGroup, Warnings, error) { + stagingSecurityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.GloballyEnabledStaging, Values: []string{"true"}}) + + return stagingSecurityGroups, Warnings(warnings), err +} + +func (actor Actor) GetGlobalRunningSecurityGroups() ([]resources.SecurityGroup, Warnings, error) { + runningSecurityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.GloballyEnabledRunning, Values: []string{"true"}}) + + return runningSecurityGroups, Warnings(warnings), err +} + +func (actor Actor) UpdateSecurityGroup(name, filePath string) (Warnings, error) { + allWarnings := Warnings{} + + // parse input file + bytes, err := parsePath(filePath) + if err != nil { + return allWarnings, err + } + + var rules []resources.Rule + err = json.Unmarshal(bytes, &rules) + if err != nil { + return allWarnings, err + } + + // fetch security group from API + securityGroups, warnings, err := actor.CloudControllerClient.GetSecurityGroups(ccv3.Query{Key: ccv3.NameFilter, Values: []string{name}}) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + if len(securityGroups) == 0 { + return allWarnings, actionerror.SecurityGroupNotFoundError{Name: name} + } + + securityGroup := resources.SecurityGroup{ + Name: name, + GUID: securityGroups[0].GUID, + Rules: rules, + } + + // update security group + _, warnings, err = actor.CloudControllerClient.UpdateSecurityGroup(securityGroup) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} + +func (actor Actor) UpdateSecurityGroupGloballyEnabled(securityGroupName string, lifecycle constant.SecurityGroupLifecycle, enabled bool) (Warnings, error) { + var allWarnings Warnings + + securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + requestBody := resources.SecurityGroup{GUID: securityGroup.GUID} + switch lifecycle { + case constant.SecurityGroupLifecycleRunning: + requestBody.RunningGloballyEnabled = &enabled + case constant.SecurityGroupLifecycleStaging: + requestBody.StagingGloballyEnabled = &enabled + default: + return allWarnings, actionerror.InvalidLifecycleError{Lifecycle: string(lifecycle)} + } + + _, ccv3Warnings, err := actor.CloudControllerClient.UpdateSecurityGroup(requestBody) + allWarnings = append(allWarnings, ccv3Warnings...) + + return allWarnings, err +} + +func (actor Actor) DeleteSecurityGroup(securityGroupName string) (Warnings, error) { + var allWarnings Warnings + + securityGroup, warnings, err := actor.GetSecurityGroup(securityGroupName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + jobURL, ccv3Warnings, err := actor.CloudControllerClient.DeleteSecurityGroup(securityGroup.GUID) + allWarnings = append(allWarnings, ccv3Warnings...) + if err != nil { + return allWarnings, err + } + + pollingWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollingWarnings...) + return allWarnings, err +} + +func getSecurityGroupSpaces(actor Actor, stagingSpaceGUIDs []string, runningSpaceGUIDs []string) ([]SecurityGroupSpace, ccv3.Warnings, error) { + var warnings ccv3.Warnings + associatedSpaceGuids := runningSpaceGUIDs + associatedSpaceGuids = append(associatedSpaceGuids, stagingSpaceGUIDs...) + + var securityGroupSpaces []SecurityGroupSpace + var spaces []resources.Space + var includes ccv3.IncludedResources + + if len(associatedSpaceGuids) > 0 { + ccv3Warnings, err := batcher.RequestByGUID(associatedSpaceGuids, func(guids []string) (ccv3.Warnings, error) { + batchSpaces, batchIncludes, newWarnings, err := actor.CloudControllerClient.GetSpaces(ccv3.Query{ + Key: ccv3.GUIDFilter, + Values: guids, + }, ccv3.Query{ + Key: ccv3.Include, + Values: []string{"organization"}, + }) + spaces = append(spaces, batchSpaces...) + includes.Organizations = append(includes.Organizations, batchIncludes.Organizations...) + return newWarnings, err + }) + warnings = ccv3Warnings + if err != nil { + return securityGroupSpaces, warnings, err + } + + orgsByGuid := lookuptable.OrgFromGUID(includes.Organizations) + spacesByGuid := lookuptable.SpaceFromGUID(spaces) + + for _, runningSpaceGUID := range runningSpaceGUIDs { + space := spacesByGuid[runningSpaceGUID] + orgGuid := space.Relationships[constant.RelationshipTypeOrganization].GUID + securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ + SpaceName: space.Name, + OrgName: orgsByGuid[orgGuid].Name, + Lifecycle: "running", + }) + } + + for _, stagingSpaceGUID := range stagingSpaceGUIDs { + space := spacesByGuid[stagingSpaceGUID] + orgGuid := space.Relationships[constant.RelationshipTypeOrganization].GUID + securityGroupSpaces = append(securityGroupSpaces, SecurityGroupSpace{ + SpaceName: space.Name, + OrgName: orgsByGuid[orgGuid].Name, + Lifecycle: "staging", + }) + } + } + return securityGroupSpaces, warnings, nil +} + +func parsePath(path string) ([]byte, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + + bytes, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + return bytes, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_access.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_access.go new file mode 100644 index 0000000..7f32b77 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_access.go @@ -0,0 +1,343 @@ +package v7action + +import ( + "errors" + "fmt" + "sort" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +type ServicePlanWithSpaceAndOrganization ccv3.ServicePlanWithSpaceAndOrganization + +type ServicePlanAccess struct { + BrokerName string + ServiceOfferingName string + ServicePlanName string + VisibilityType resources.ServicePlanVisibilityType + VisibilityDetails []string +} + +type SkippedPlans []string + +type offeringDetails struct{ offeringName, brokerName string } + +func (actor *Actor) GetServiceAccess(offeringName, brokerName, orgName string) ([]ServicePlanAccess, Warnings, error) { + var orgGUID string + var allWarnings Warnings + if orgName != "" { + org, orgWarnings, err := actor.GetOrganizationByName(orgName) + if err != nil { + return nil, orgWarnings, err + } + allWarnings = append(allWarnings, orgWarnings...) + + orgGUID = org.GUID + } + + plansQuery := buildPlansFilterForGet(offeringName, brokerName, orgGUID) + + offerings, offeringsWarnings, err := actor.getServiceOfferings(offeringName, brokerName) + allWarnings = append(allWarnings, offeringsWarnings...) + if err != nil { + return nil, allWarnings, err + } + + plans, plansWarnings, err := actor.CloudControllerClient.GetServicePlansWithSpaceAndOrganization(plansQuery...) + allWarnings = append(allWarnings, plansWarnings...) + if err != nil { + return nil, allWarnings, err + } + + var result []ServicePlanAccess + for _, plan := range plans { + if offering, ok := offerings[plan.ServiceOfferingGUID]; ok { + visibilityDetails, warnings, err := actor.getServicePlanVisibilityDetails(ServicePlanWithSpaceAndOrganization(plan)) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + result = append(result, ServicePlanAccess{ + ServicePlanName: plan.Name, + VisibilityType: plan.VisibilityType, + VisibilityDetails: visibilityDetails, + ServiceOfferingName: offering.offeringName, + BrokerName: offering.brokerName, + }) + } + } + + sort.Slice(result, func(i, j int) bool { + if result[i].BrokerName != result[j].BrokerName { + return result[i].BrokerName < result[j].BrokerName + } + if result[i].ServiceOfferingName != result[j].ServiceOfferingName { + return result[i].ServiceOfferingName < result[j].ServiceOfferingName + } + return result[i].ServicePlanName < result[j].ServicePlanName + }) + + return result, allWarnings, err +} + +func (actor *Actor) EnableServiceAccess(offeringName, brokerName, orgName, planName string) (SkippedPlans, Warnings, error) { + var allWarnings Warnings + + offering, offeringWarnings, err := actor.CloudControllerClient.GetServiceOfferingByNameAndBroker(offeringName, brokerName) + allWarnings = append(allWarnings, offeringWarnings...) + if err != nil { + return nil, allWarnings, actionerror.EnrichAPIErrors(err) + } + + plansQuery := buildPlansFilterForUpdate(offering.GUID, planName) + plans, planWarnings, err := actor.CloudControllerClient.GetServicePlans(plansQuery...) + allWarnings = append(allWarnings, planWarnings...) + if err != nil { + return nil, allWarnings, err + } + + if len(plans) == 0 { + return nil, allWarnings, actionerror.ServicePlanNotFoundError{ + PlanName: planName, + OfferingName: offeringName, + } + } + + if offeringIsSpaceScoped(plans) { + return nil, allWarnings, actionerror.ServicePlanVisibilityTypeError{} + } + + visibility := resources.ServicePlanVisibility{Type: resources.ServicePlanVisibilityPublic} + if orgName != "" { + org, orgWarnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, orgWarnings...) + if err != nil { + return nil, allWarnings, err + } + + visibility.Type = resources.ServicePlanVisibilityOrganization + visibility.Organizations = []resources.ServicePlanVisibilityDetail{{GUID: org.GUID}} + } + + var skipped SkippedPlans + for _, plan := range plans { + if plan.VisibilityType == resources.ServicePlanVisibilityPublic && visibility.Type == resources.ServicePlanVisibilityOrganization { + skipped = append(skipped, plan.Name) + continue + } + + _, visibilityWarnings, err := actor.CloudControllerClient.UpdateServicePlanVisibility( + plan.GUID, + visibility, + ) + allWarnings = append(allWarnings, visibilityWarnings...) + if err != nil { + return nil, allWarnings, err + } + } + + return skipped, allWarnings, nil +} + +func (actor *Actor) DisableServiceAccess(offeringName, brokerName, orgName, planName string) (SkippedPlans, Warnings, error) { + var allWarnings Warnings + + offering, offeringWarnings, err := actor.CloudControllerClient.GetServiceOfferingByNameAndBroker(offeringName, brokerName) + allWarnings = append(allWarnings, offeringWarnings...) + if err != nil { + return SkippedPlans{}, allWarnings, actionerror.EnrichAPIErrors(err) + } + + plansQuery := buildPlansFilterForUpdate(offering.GUID, planName) + plans, planWarnings, err := actor.CloudControllerClient.GetServicePlans(plansQuery...) + allWarnings = append(allWarnings, planWarnings...) + if err != nil { + return SkippedPlans{}, allWarnings, err + } + + if len(plans) == 0 { + return SkippedPlans{}, allWarnings, actionerror.ServicePlanNotFoundError{ + PlanName: planName, + OfferingName: offeringName, + } + } + + if offeringIsSpaceScoped(plans) { + return SkippedPlans{}, allWarnings, actionerror.ServicePlanVisibilityTypeError{} + } + + var ( + disableWarnings Warnings + skipped SkippedPlans + ) + + if orgName != "" { + skipped, disableWarnings, err = actor.disableOrganizationServiceAccess(plans, orgName) + } else { + skipped, disableWarnings, err = actor.disableAllServiceAccess(plans) + } + + allWarnings = append(allWarnings, disableWarnings...) + return skipped, allWarnings, err +} + +func (actor *Actor) disableAllServiceAccess(plans []resources.ServicePlan) (SkippedPlans, Warnings, error) { + var ( + allWarnings Warnings + skipped SkippedPlans + ) + + visibility := resources.ServicePlanVisibility{Type: resources.ServicePlanVisibilityAdmin} + for _, plan := range plans { + if plan.VisibilityType == resources.ServicePlanVisibilityAdmin { + skipped = append(skipped, plan.Name) + continue + } + + _, visibilityWarnings, err := actor.CloudControllerClient.UpdateServicePlanVisibility( + plan.GUID, + visibility, + ) + allWarnings = append(allWarnings, visibilityWarnings...) + if err != nil { + return skipped, allWarnings, err + } + } + return skipped, allWarnings, nil +} + +func (actor *Actor) disableOrganizationServiceAccess(plans []resources.ServicePlan, orgName string) (SkippedPlans, Warnings, error) { + var allWarnings Warnings + + org, orgWarnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, orgWarnings...) + if err != nil { + return nil, allWarnings, err + } + + for _, plan := range plans { + if plan.VisibilityType == resources.ServicePlanVisibilityPublic { + return nil, allWarnings, errors.New("Cannot remove organization level access for public plans.") + } + } + + var skipped SkippedPlans + for _, plan := range plans { + if plan.VisibilityType == resources.ServicePlanVisibilityAdmin { + skipped = append(skipped, plan.Name) + continue + } + + deleteWarnings, err := actor.CloudControllerClient.DeleteServicePlanVisibility(plan.GUID, org.GUID) + allWarnings = append(allWarnings, deleteWarnings...) + if err != nil { + return skipped, allWarnings, err + } + } + + return skipped, allWarnings, nil +} + +func (actor *Actor) getServiceOfferings(service, broker string) (map[string]offeringDetails, Warnings, error) { + var offeringsQuery []ccv3.Query + + if broker != "" { + offeringsQuery = append(offeringsQuery, ccv3.Query{ + Key: ccv3.ServiceBrokerNamesFilter, + Values: []string{broker}, + }) + } + + if service != "" { + offeringsQuery = append(offeringsQuery, ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{service}, + }) + } + + serviceOfferings, warnings, err := actor.CloudControllerClient.GetServiceOfferings(offeringsQuery...) + if err != nil { + return nil, Warnings(warnings), err + } + if len(serviceOfferings) == 0 && len(offeringsQuery) > 0 { + return nil, Warnings(warnings), actionerror.ServiceNotFoundError{Name: service, Broker: broker} + } + + offerings := make(map[string]offeringDetails) + for _, o := range serviceOfferings { + offerings[o.GUID] = offeringDetails{ + offeringName: o.Name, + brokerName: o.ServiceBrokerName, + } + } + return offerings, Warnings(warnings), err +} + +func (actor *Actor) getServicePlanVisibilityDetails(plan ServicePlanWithSpaceAndOrganization) (names []string, warnings Warnings, err error) { + if plan.VisibilityType == resources.ServicePlanVisibilityOrganization { + result, vwarn, err := actor.CloudControllerClient.GetServicePlanVisibility(plan.GUID) + warnings = Warnings(vwarn) + if err != nil { + return nil, warnings, err + } + + for _, organization := range result.Organizations { + names = append(names, organization.Name) + } + } + + if plan.VisibilityType == resources.ServicePlanVisibilitySpace { + names = []string{fmt.Sprintf("%s (org: %s)", plan.SpaceName, plan.OrganizationName)} + } + + return names, warnings, nil +} + +func buildPlansFilterForGet(offeringName, brokerName, orgGUID string) (query []ccv3.Query) { + if offeringName != "" { + query = append(query, ccv3.Query{ + Key: ccv3.ServiceOfferingNamesFilter, + Values: []string{offeringName}, + }) + } + + if brokerName != "" { + query = append(query, ccv3.Query{ + Key: ccv3.ServiceBrokerNamesFilter, + Values: []string{brokerName}, + }) + } + + if orgGUID != "" { + query = append(query, ccv3.Query{ + Key: ccv3.OrganizationGUIDFilter, + Values: []string{orgGUID}, + }) + } + + return query +} + +func buildPlansFilterForUpdate(offeringGUID, planName string) []ccv3.Query { + plansQuery := []ccv3.Query{{ + Key: ccv3.ServiceOfferingGUIDsFilter, + Values: []string{offeringGUID}, + }} + + if planName != "" { + plansQuery = append(plansQuery, ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{planName}, + }) + } + + return plansQuery +} + +func offeringIsSpaceScoped(plans []resources.ServicePlan) bool { + // All plans from a space scoped offering will have the same visibility type + return plans[0].VisibilityType == resources.ServicePlanVisibilitySpace +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_app_binding.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_app_binding.go new file mode 100644 index 0000000..0ff5779 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_app_binding.go @@ -0,0 +1,141 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/railway" +) + +type CreateServiceAppBindingParams struct { + SpaceGUID string + ServiceInstanceName string + AppName string + BindingName string + Parameters types.OptionalObject +} + +type DeleteServiceAppBindingParams struct { + SpaceGUID string + ServiceInstanceName string + AppName string +} + +func (actor Actor) CreateServiceAppBinding(params CreateServiceAppBindingParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + app resources.Application + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(params.ServiceInstanceName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + app, warnings, err = actor.CloudControllerClient.GetApplicationByNameAndSpace(params.AppName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.createServiceAppBinding(serviceInstance.GUID, app.GUID, params.BindingName, params.Parameters) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + switch err.(type) { + case nil: + return stream, Warnings(warnings), nil + case ccerror.ApplicationNotFoundError: + return nil, Warnings(warnings), actionerror.ApplicationNotFoundError{Name: params.AppName} + default: + return nil, Warnings(warnings), err + } +} + +func (actor Actor) DeleteServiceAppBinding(params DeleteServiceAppBindingParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + app resources.Application + binding resources.ServiceCredentialBinding + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(params.ServiceInstanceName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + app, warnings, err = actor.CloudControllerClient.GetApplicationByNameAndSpace(params.AppName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + binding, warnings, err = actor.getServiceAppBinding(serviceInstance.GUID, app.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.DeleteServiceCredentialBinding(binding.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + switch err.(type) { + case nil: + return stream, Warnings(warnings), nil + case ccerror.ApplicationNotFoundError: + return nil, Warnings(warnings), actionerror.ApplicationNotFoundError{Name: params.AppName} + default: + return nil, Warnings(warnings), err + } +} + +func (actor Actor) createServiceAppBinding(serviceInstanceGUID, appGUID, bindingName string, parameters types.OptionalObject) (ccv3.JobURL, ccv3.Warnings, error) { + jobURL, warnings, err := actor.CloudControllerClient.CreateServiceCredentialBinding(resources.ServiceCredentialBinding{ + Type: resources.AppBinding, + Name: bindingName, + ServiceInstanceGUID: serviceInstanceGUID, + AppGUID: appGUID, + Parameters: parameters, + }) + switch err.(type) { + case nil: + return jobURL, warnings, nil + case ccerror.ResourceAlreadyExistsError: + return "", warnings, actionerror.ResourceAlreadyExistsError{Message: err.Error()} + default: + return "", warnings, err + } +} + +func (actor Actor) getServiceAppBinding(serviceInstanceGUID, appGUID string) (resources.ServiceCredentialBinding, ccv3.Warnings, error) { + bindings, warnings, err := actor.CloudControllerClient.GetServiceCredentialBindings( + ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"app"}}, + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}}, + ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, + ) + + switch { + case err != nil: + return resources.ServiceCredentialBinding{}, warnings, err + case len(bindings) == 0: + return resources.ServiceCredentialBinding{}, warnings, actionerror.ServiceBindingNotFoundError{ + AppGUID: appGUID, + ServiceInstanceGUID: serviceInstanceGUID, + } + default: + return bindings[0], warnings, nil + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_broker.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_broker.go new file mode 100644 index 0000000..620ddce --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_broker.go @@ -0,0 +1,69 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/railway" +) + +func (actor Actor) GetServiceBrokers() ([]resources.ServiceBroker, Warnings, error) { + serviceBrokers, warnings, err := actor.CloudControllerClient.GetServiceBrokers() + if err != nil { + return nil, Warnings(warnings), err + } + + return serviceBrokers, Warnings(warnings), nil +} + +func (actor Actor) GetServiceBrokerByName(serviceBrokerName string) (resources.ServiceBroker, Warnings, error) { + query := []ccv3.Query{ + { + Key: ccv3.NameFilter, + Values: []string{serviceBrokerName}, + }, + } + serviceBrokers, warnings, err := actor.CloudControllerClient.GetServiceBrokers(query...) + if err != nil { + return resources.ServiceBroker{}, Warnings(warnings), err + } + + if len(serviceBrokers) == 0 { + return resources.ServiceBroker{}, Warnings(warnings), actionerror.ServiceBrokerNotFoundError{Name: serviceBrokerName} + } + + return serviceBrokers[0], Warnings(warnings), nil +} + +func (actor Actor) CreateServiceBroker(model resources.ServiceBroker) (Warnings, error) { + return actor.performAndPoll(func() (ccv3.JobURL, ccv3.Warnings, error) { + return actor.CloudControllerClient.CreateServiceBroker(model) + }) +} + +func (actor Actor) UpdateServiceBroker(serviceBrokerGUID string, model resources.ServiceBroker) (Warnings, error) { + return actor.performAndPoll(func() (ccv3.JobURL, ccv3.Warnings, error) { + return actor.CloudControllerClient.UpdateServiceBroker(serviceBrokerGUID, model) + }) +} + +func (actor Actor) DeleteServiceBroker(serviceBrokerGUID string) (Warnings, error) { + return actor.performAndPoll(func() (ccv3.JobURL, ccv3.Warnings, error) { + return actor.CloudControllerClient.DeleteServiceBroker(serviceBrokerGUID) + }) +} + +func (actor Actor) performAndPoll(callback func() (ccv3.JobURL, ccv3.Warnings, error)) (Warnings, error) { + var jobURL ccv3.JobURL + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = callback() + return + }, + func() (ccv3.Warnings, error) { + return actor.CloudControllerClient.PollJob(jobURL) + }, + ) + return Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance.go new file mode 100644 index 0000000..7ac5c7b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance.go @@ -0,0 +1,374 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/railway" +) + +type UpdateManagedServiceInstanceParams struct { + ServiceInstanceName string + ServicePlanName string + SpaceGUID string + Tags types.OptionalStringSlice + Parameters types.OptionalObject +} + +type CreateManagedServiceInstanceParams struct { + ServiceOfferingName string + ServicePlanName string + ServiceInstanceName string + ServiceBrokerName string + SpaceGUID string + Tags types.OptionalStringSlice + Parameters types.OptionalObject +} + +func (actor Actor) GetServiceInstanceByNameAndSpace(serviceInstanceName string, spaceGUID string) (resources.ServiceInstance, Warnings, error) { + serviceInstance, _, warnings, err := actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return serviceInstance, Warnings(warnings), err +} + +func (actor Actor) CreateUserProvidedServiceInstance(serviceInstance resources.ServiceInstance) (Warnings, error) { + serviceInstance.Type = resources.UserProvidedServiceInstance + _, warnings, err := actor.CloudControllerClient.CreateServiceInstance(serviceInstance) + return Warnings(warnings), err +} + +func (actor Actor) UpdateUserProvidedServiceInstance(serviceInstanceName, spaceGUID string, serviceInstanceUpdates resources.ServiceInstance) (Warnings, error) { + var original resources.ServiceInstance + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + original, _, warnings, err = actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + err = assertServiceInstanceType(resources.UserProvidedServiceInstance, original) + return + }, + func() (warnings ccv3.Warnings, err error) { + _, warnings, err = actor.CloudControllerClient.UpdateServiceInstance(original.GUID, serviceInstanceUpdates) + return + }, + ) + + return Warnings(warnings), err +} + +func (actor Actor) CreateManagedServiceInstance(params CreateManagedServiceInstanceParams) (chan PollJobEvent, Warnings, error) { + var ( + servicePlan resources.ServicePlan + jobURL ccv3.JobURL + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + var v7Warnings Warnings + servicePlan, v7Warnings, err = actor.GetServicePlanByNameOfferingAndBroker( + params.ServicePlanName, + params.ServiceOfferingName, + params.ServiceBrokerName, + ) + return ccv3.Warnings(v7Warnings), err + }, + func() (warnings ccv3.Warnings, err error) { + serviceInstance := resources.ServiceInstance{ + Type: resources.ManagedServiceInstance, + Name: params.ServiceInstanceName, + ServicePlanGUID: servicePlan.GUID, + SpaceGUID: params.SpaceGUID, + Tags: params.Tags, + Parameters: params.Parameters, + } + + jobURL, warnings, err = actor.CloudControllerClient.CreateServiceInstance(serviceInstance) + return + }, + ) + switch e := err.(type) { + case nil: + return actor.PollJobToEventStream(jobURL), Warnings(warnings), nil + case actionerror.DuplicateServicePlanError: + return nil, Warnings(warnings), actionerror.ServiceBrokerNameRequiredError{ + ServiceOfferingName: e.ServiceOfferingName, + } + default: + return nil, Warnings(warnings), err + } +} + +func (actor Actor) UpdateManagedServiceInstance(params UpdateManagedServiceInstanceParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + serviceOffering resources.ServiceOffering + serviceBroker resources.ServiceBroker + newPlanGUID string + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + planChangeRequested := params.ServicePlanName != "" + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, serviceOffering, serviceBroker, warnings, err = actor.getServiceInstanceForUpdate( + params.ServiceInstanceName, + params.SpaceGUID, + planChangeRequested, + ) + return + }, + func() (warnings ccv3.Warnings, err error) { + err = assertServiceInstanceType(resources.ManagedServiceInstance, serviceInstance) + return + }, + func() (warnings ccv3.Warnings, err error) { + if planChangeRequested { + newPlanGUID, warnings, err = actor.getPlanForInstanceUpdate(params.ServicePlanName, serviceOffering, serviceBroker) + } + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.updateManagedServiceInstance(serviceInstance, newPlanGUID, params) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + return stream, Warnings(warnings), err +} + +func (actor Actor) UpgradeManagedServiceInstance(serviceInstanceName string, spaceGUID string) (Warnings, error) { + var serviceInstance resources.ServiceInstance + var servicePlan resources.ServicePlan + var jobURL ccv3.JobURL + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + if serviceInstance.UpgradeAvailable.Value != true { + err = actionerror.ServiceInstanceUpgradeNotAvailableError{} + } + return + }, + func() (warnings ccv3.Warnings, err error) { + servicePlan, warnings, err = actor.CloudControllerClient.GetServicePlanByGUID(serviceInstance.ServicePlanGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.UpdateServiceInstance(serviceInstance.GUID, resources.ServiceInstance{ + MaintenanceInfoVersion: servicePlan.MaintenanceInfoVersion, + }) + return + }, + func() (warnings ccv3.Warnings, err error) { + return actor.CloudControllerClient.PollJobForState(jobURL, constant.JobPolling) + }, + ) + + return Warnings(warnings), err +} + +func (actor Actor) RenameServiceInstance(currentServiceInstanceName, spaceGUID, newServiceInstanceName string) (Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + jobURL ccv3.JobURL + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(currentServiceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.UpdateServiceInstance( + serviceInstance.GUID, + resources.ServiceInstance{Name: newServiceInstanceName}, + ) + return + }, + func() (warnings ccv3.Warnings, err error) { + return actor.CloudControllerClient.PollJobForState(jobURL, constant.JobPolling) + }, + ) + + return Warnings(warnings), err +} + +func (actor Actor) DeleteServiceInstance(serviceInstanceName, spaceGUID string) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + jobURL ccv3.JobURL + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.DeleteServiceInstance(serviceInstance.GUID) + return + }, + ) + + switch err.(type) { + case nil: + case ccerror.ServiceInstanceNotFoundError: + return nil, Warnings(warnings), actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName} + default: + return nil, Warnings(warnings), err + } + + switch jobURL { + case "": + return nil, Warnings(warnings), nil + default: + return actor.PollJobToEventStream(jobURL), Warnings(warnings), nil + } +} + +func (actor Actor) PurgeServiceInstance(serviceInstanceName, spaceGUID string) (Warnings, error) { + var serviceInstance resources.ServiceInstance + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + _, warnings, err = actor.CloudControllerClient.DeleteServiceInstance( + serviceInstance.GUID, + ccv3.Query{Key: ccv3.Purge, Values: []string{"true"}}, + ) + return + }, + ) + + switch err.(type) { + case nil: + return Warnings(warnings), nil + case ccerror.ServiceInstanceNotFoundError: + return Warnings(warnings), actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName} + default: + return Warnings(warnings), err + } +} + +func (actor Actor) pollJob(jobURL ccv3.JobURL, wait bool) (ccv3.Warnings, error) { + switch { + case jobURL == "": + return ccv3.Warnings{}, nil + case wait: + return actor.CloudControllerClient.PollJob(jobURL) + default: + return actor.CloudControllerClient.PollJobForState(jobURL, constant.JobPolling) + } +} + +func (actor Actor) getServiceInstanceByNameAndSpace(serviceInstanceName string, spaceGUID string, query ...ccv3.Query) (resources.ServiceInstance, ccv3.IncludedResources, ccv3.Warnings, error) { + serviceInstance, includedResources, warnings, err := actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID, query...) + switch e := err.(type) { + case ccerror.ServiceInstanceNotFoundError: + return serviceInstance, ccv3.IncludedResources{}, warnings, actionerror.ServiceInstanceNotFoundError{Name: e.Name} + default: + return serviceInstance, includedResources, warnings, err + } +} + +func (actor Actor) getServiceInstanceForUpdate(serviceInstanceName string, spaceGUID string, includePlan bool) (resources.ServiceInstance, resources.ServiceOffering, resources.ServiceBroker, ccv3.Warnings, error) { + var query []ccv3.Query + if includePlan { + query = append( + query, + ccv3.Query{Key: ccv3.FieldsServicePlanServiceOffering, Values: []string{"name", "guid"}}, + ccv3.Query{Key: ccv3.FieldsServicePlanServiceOfferingServiceBroker, Values: []string{"name"}}, + ) + } + + serviceInstance, includedResources, warnings, err := actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID, query...) + + var ( + serviceOffering resources.ServiceOffering + serviceBroker resources.ServiceBroker + ) + if len(includedResources.ServiceOfferings) != 0 { + serviceOffering = includedResources.ServiceOfferings[0] + } + if len(includedResources.ServiceBrokers) != 0 { + serviceBroker = includedResources.ServiceBrokers[0] + } + + return serviceInstance, serviceOffering, serviceBroker, warnings, err +} + +func (actor Actor) getPlanForInstanceUpdate(planName string, serviceOffering resources.ServiceOffering, serviceBroker resources.ServiceBroker) (string, ccv3.Warnings, error) { + plans, warnings, err := actor.CloudControllerClient.GetServicePlans([]ccv3.Query{ + {Key: ccv3.ServiceOfferingGUIDsFilter, Values: []string{serviceOffering.GUID}}, + {Key: ccv3.NameFilter, Values: []string{planName}}, + }...) + + switch { + case err != nil: + return "", warnings, err + case len(plans) == 0: + return "", warnings, actionerror.ServicePlanNotFoundError{ + PlanName: planName, + OfferingName: serviceOffering.Name, + ServiceBrokerName: serviceBroker.Name, + } + default: + return plans[0].GUID, warnings, nil + } +} + +func (actor Actor) updateManagedServiceInstance(serviceInstance resources.ServiceInstance, newServicePlanGUID string, params UpdateManagedServiceInstanceParams) (ccv3.JobURL, ccv3.Warnings, error) { + if newServicePlanGUID == serviceInstance.ServicePlanGUID { + newServicePlanGUID = "" + } + + update := resources.ServiceInstance{ + ServicePlanGUID: newServicePlanGUID, + Tags: params.Tags, + Parameters: params.Parameters, + } + + if update.ServicePlanGUID == "" && !update.Tags.IsSet && !update.Parameters.IsSet { + return "", nil, actionerror.ServiceInstanceUpdateIsNoop{} + } + + return actor.CloudControllerClient.UpdateServiceInstance(serviceInstance.GUID, update) +} + +func assertServiceInstanceType(requiredType resources.ServiceInstanceType, instance resources.ServiceInstance) error { + if instance.Type != requiredType { + return actionerror.ServiceInstanceTypeError{ + Name: instance.Name, + RequiredType: requiredType, + } + } + + return nil +} + +func handleServiceInstanceErrors(warnings ccv3.Warnings, err error) (Warnings, error) { + switch e := err.(type) { + case nil: + return Warnings(warnings), nil + case ccerror.ServiceInstanceNotFoundError: + return Warnings(warnings), actionerror.ServiceInstanceNotFoundError{Name: e.Name} + default: + return Warnings(warnings), err + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_details.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_details.go new file mode 100644 index 0000000..80597c0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_details.go @@ -0,0 +1,300 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/extract" + "code.cloudfoundry.org/cli/util/railway" +) + +const featureFlagServiceInstanceSharing string = "service_instance_sharing" + +type ServiceInstanceBoundAppCount struct { + OrgName string + SpaceName string + BoundAppCount int +} + +type UsageSummaryWithSpaceAndOrg struct { + SpaceName string + OrganizationName string + BoundAppCount int +} + +type SharedStatus struct { + FeatureFlagIsDisabled bool + OfferingDisablesSharing bool + IsSharedToOtherSpaces bool + IsSharedFromOriginalSpace bool + UsageSummary []UsageSummaryWithSpaceAndOrg +} + +type ServiceInstanceParameters map[string]interface{} + +type ServiceInstanceUpgradeState int + +type ServiceInstanceUpgradeStatus struct { + State ServiceInstanceUpgradeState + Description string +} + +const ( + ServiceInstanceUpgradeNotSupported ServiceInstanceUpgradeState = iota + ServiceInstanceUpgradeAvailable + ServiceInstanceUpgradeNotAvailable +) + +type ServiceInstanceDetails struct { + resources.ServiceInstance + SpaceName string + OrganizationName string + ServiceOffering resources.ServiceOffering + ServicePlan resources.ServicePlan + ServiceBrokerName string + SharedStatus SharedStatus + UpgradeStatus ServiceInstanceUpgradeStatus + BoundApps []resources.ServiceCredentialBinding +} + +func (actor Actor) GetServiceInstanceDetails(serviceInstanceName string, spaceGUID string, omitApps bool) (ServiceInstanceDetails, Warnings, error) { + var serviceInstanceDetails ServiceInstanceDetails + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstanceDetails, warnings, err = actor.getServiceInstanceDetails(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + serviceInstanceDetails.SharedStatus, warnings, err = actor.getServiceInstanceSharedStatus(serviceInstanceDetails, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + serviceInstanceDetails.UpgradeStatus, warnings, err = actor.getServiceInstanceUpgradeStatus(serviceInstanceDetails) + return + }, + func() (warnings ccv3.Warnings, err error) { + if !omitApps { + serviceInstanceDetails.BoundApps, warnings, err = actor.getServiceInstanceBoundApps(serviceInstanceDetails.GUID) + } + return + }, + ) + if err != nil { + return ServiceInstanceDetails{}, Warnings(warnings), err + } + + return serviceInstanceDetails, Warnings(warnings), nil +} + +func (actor Actor) GetServiceInstanceParameters(serviceInstanceName string, spaceGUID string) (ServiceInstanceParameters, Warnings, error) { + var serviceInstance resources.ServiceInstance + var parameters ServiceInstanceParameters + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + parameters, warnings, err = actor.getServiceInstanceParameters(serviceInstance.GUID) + return + }, + ) + if err != nil { + return ServiceInstanceParameters{}, Warnings(warnings), err + } + + return parameters, Warnings(warnings), nil +} + +func (actor Actor) getServiceInstanceDetails(serviceInstanceName string, spaceGUID string) (ServiceInstanceDetails, ccv3.Warnings, error) { + query := []ccv3.Query{ + { + Key: ccv3.FieldsServicePlan, + Values: []string{"name", "guid"}, + }, + { + Key: ccv3.FieldsServicePlanServiceOffering, + Values: []string{"name", "guid", "description", "tags", "documentation_url"}, + }, + { + Key: ccv3.FieldsServicePlanServiceOfferingServiceBroker, + Values: []string{"name", "guid"}, + }, + { + Key: ccv3.FieldsSpace, + Values: []string{"name", "guid"}, + }, + { + Key: ccv3.FieldsSpaceOrganization, + Values: []string{"name", "guid"}, + }, + } + + serviceInstance, included, warnings, err := actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID, query...) + switch err.(type) { + case nil: + case ccerror.ServiceInstanceNotFoundError: + return ServiceInstanceDetails{}, warnings, actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName} + default: + return ServiceInstanceDetails{}, warnings, err + } + + result := ServiceInstanceDetails{ + ServiceInstance: serviceInstance, + ServicePlan: extractServicePlan(included), + ServiceOffering: extractServiceOffering(included), + ServiceBrokerName: extract.First("Name", included.ServiceBrokers), + SpaceName: extract.First("Name", included.Spaces), + OrganizationName: extract.First("Name", included.Organizations), + } + + return result, warnings, nil +} + +func (actor Actor) getServiceInstanceParameters(serviceInstanceGUID string) (ServiceInstanceParameters, ccv3.Warnings, error) { + params, warnings, err := actor.CloudControllerClient.GetServiceInstanceParameters(serviceInstanceGUID) + + switch err := err.(type) { + case nil: + return ServiceInstanceParameters(params), warnings, nil + case ccerror.ResourceNotFoundError, + ccerror.ServiceInstanceParametersFetchNotSupportedError: + return ServiceInstanceParameters{}, warnings, actionerror.ServiceInstanceParamsFetchingNotSupportedError{} + default: + return ServiceInstanceParameters{}, warnings, err + } +} + +func (actor Actor) getServiceInstanceSharedStatus(serviceInstanceDetails ServiceInstanceDetails, targetedSpace string) (SharedStatus, ccv3.Warnings, error) { + if serviceInstanceDetails.Type != resources.ManagedServiceInstance { + return SharedStatus{}, nil, nil + } + + if targetedSpace != serviceInstanceDetails.SpaceGUID { + return SharedStatus{IsSharedFromOriginalSpace: true}, nil, nil + } + + var ( + featureFlag resources.FeatureFlag + offeringDisablesSharing bool + sharedSpaces []ccv3.SpaceWithOrganization + usageSummaries []resources.ServiceInstanceUsageSummary + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + featureFlag, warnings, err = actor.CloudControllerClient.GetFeatureFlag(featureFlagServiceInstanceSharing) + return + }, + func() (warnings ccv3.Warnings, err error) { + offeringDisablesSharing, warnings, err = actor.getOfferingSharingDetails(serviceInstanceDetails.ServiceOffering.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + sharedSpaces, warnings, err = actor.CloudControllerClient.GetServiceInstanceSharedSpaces(serviceInstanceDetails.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + if len(sharedSpaces) > 0 { + usageSummaries, warnings, err = actor.CloudControllerClient.GetServiceInstanceUsageSummary(serviceInstanceDetails.GUID) + } + return + }, + ) + if err != nil { + return SharedStatus{}, warnings, err + } + + sharedStatus := SharedStatus{ + IsSharedToOtherSpaces: len(sharedSpaces) > 0, + OfferingDisablesSharing: offeringDisablesSharing, + FeatureFlagIsDisabled: !featureFlag.Enabled, + UsageSummary: buildUsageSummary(sharedSpaces, usageSummaries), + } + + return sharedStatus, warnings, nil +} + +func (actor Actor) getOfferingSharingDetails(serviceOfferingGUID string) (bool, ccv3.Warnings, error) { + serviceOffering, serviceOfferingWarning, err := + actor.CloudControllerClient.GetServiceOfferingByGUID(serviceOfferingGUID) + + switch err := err.(type) { + case nil: + return !serviceOffering.AllowsInstanceSharing, serviceOfferingWarning, nil + case ccerror.ServiceOfferingNotFoundError: + return false, serviceOfferingWarning, nil + default: + return false, serviceOfferingWarning, err + } +} + +func (actor Actor) getServiceInstanceUpgradeStatus(serviceInstanceDetails ServiceInstanceDetails) (ServiceInstanceUpgradeStatus, ccv3.Warnings, error) { + if !serviceInstanceDetails.UpgradeAvailable.Value { + if serviceInstanceDetails.MaintenanceInfoVersion == "" { + return ServiceInstanceUpgradeStatus{State: ServiceInstanceUpgradeNotSupported}, nil, nil + } + return ServiceInstanceUpgradeStatus{State: ServiceInstanceUpgradeNotAvailable}, nil, nil + } + + servicePlan, warnings, err := actor.CloudControllerClient.GetServicePlanByGUID(serviceInstanceDetails.ServicePlanGUID) + switch err.(type) { + case nil: + return ServiceInstanceUpgradeStatus{ + State: ServiceInstanceUpgradeAvailable, + Description: servicePlan.MaintenanceInfoDescription, + }, warnings, nil + case ccerror.ServicePlanNotFound: + return ServiceInstanceUpgradeStatus{ + State: ServiceInstanceUpgradeAvailable, + Description: "No upgrade details where found", + }, warnings, nil + default: + return ServiceInstanceUpgradeStatus{}, warnings, err + } +} + +func (actor Actor) getServiceInstanceBoundApps(serviceInstanceGUID string) ([]resources.ServiceCredentialBinding, ccv3.Warnings, error) { + return actor.CloudControllerClient.GetServiceCredentialBindings( + ccv3.Query{Key: ccv3.Include, Values: []string{"app"}}, + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}}, + ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"app"}}, + ) +} + +func extractServicePlan(included ccv3.IncludedResources) resources.ServicePlan { + if len(included.ServicePlans) == 1 { + return included.ServicePlans[0] + } + + return resources.ServicePlan{} +} + +func extractServiceOffering(included ccv3.IncludedResources) resources.ServiceOffering { + if len(included.ServiceOfferings) == 1 { + return included.ServiceOfferings[0] + } + + return resources.ServiceOffering{} +} + +func buildUsageSummary(sharedSpaces []ccv3.SpaceWithOrganization, usageSummaries []resources.ServiceInstanceUsageSummary) []UsageSummaryWithSpaceAndOrg { + var spaceGUIDToNames = make(map[string]ccv3.SpaceWithOrganization) + var sharedSpacesUsage []UsageSummaryWithSpaceAndOrg + + for _, sharedSpace := range sharedSpaces { + spaceGUIDToNames[sharedSpace.SpaceGUID] = sharedSpace + } + for _, usageSummary := range usageSummaries { + summary := UsageSummaryWithSpaceAndOrg{ + SpaceName: spaceGUIDToNames[usageSummary.SpaceGUID].SpaceName, + OrganizationName: spaceGUIDToNames[usageSummary.SpaceGUID].OrganizationName, + BoundAppCount: usageSummary.BoundAppCount, + } + sharedSpacesUsage = append(sharedSpacesUsage, summary) + } + return sharedSpacesUsage +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_list.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_list.go new file mode 100644 index 0000000..d090b6b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_list.go @@ -0,0 +1,131 @@ +package v7action + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/batcher" + "code.cloudfoundry.org/cli/util/extract" + "code.cloudfoundry.org/cli/util/lookuptable" + "code.cloudfoundry.org/cli/util/railway" +) + +type ServiceInstance struct { + Type resources.ServiceInstanceType + Name string + ServicePlanName string + ServiceOfferingName string + ServiceBrokerName string + BoundApps []string + LastOperation string + UpgradeAvailable types.OptionalBoolean +} + +type planDetails struct { + plan, offering, broker string +} + +func (actor Actor) GetServiceInstancesForSpace(spaceGUID string, omitApps bool) ([]ServiceInstance, Warnings, error) { + var ( + instances []resources.ServiceInstance + bindings []resources.ServiceCredentialBinding + included ccv3.IncludedResources + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + instances, included, warnings, err = actor.CloudControllerClient.GetServiceInstances( + ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + ccv3.Query{Key: ccv3.FieldsServicePlan, Values: []string{"guid", "name", "relationships.service_offering"}}, + ccv3.Query{Key: ccv3.FieldsServicePlanServiceOffering, Values: []string{"guid", "name", "relationships.service_broker"}}, + ccv3.Query{Key: ccv3.FieldsServicePlanServiceOfferingServiceBroker, Values: []string{"guid", "name"}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}}, + ccv3.Query{Key: ccv3.PerPage, Values: []string{ccv3.MaxPerPage}}, + ) + return + }, + func() (warnings ccv3.Warnings, err error) { + if !omitApps { + return batcher.RequestByGUID( + extract.UniqueList("GUID", instances), + func(guids []string) (ccv3.Warnings, error) { + batch, warnings, err := actor.CloudControllerClient.GetServiceCredentialBindings( + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: guids}, + ccv3.Query{Key: ccv3.Include, Values: []string{"app"}}, + ) + bindings = append(bindings, batch...) + return warnings, err + }, + ) + } + return + }, + ) + if err != nil { + return nil, Warnings(warnings), err + } + + planDetailsFromPlanGUIDLookup := buildPlanDetailsLookup(included) + boundAppsNamesFromInstanceGUIDLookup := buildBoundAppsLookup(bindings, spaceGUID) + + result := make([]ServiceInstance, len(instances)) + for i, instance := range instances { + names := planDetailsFromPlanGUIDLookup[instance.ServicePlanGUID] + result[i] = ServiceInstance{ + Name: instance.Name, + Type: instance.Type, + UpgradeAvailable: instance.UpgradeAvailable, + ServicePlanName: names.plan, + ServiceOfferingName: names.offering, + ServiceBrokerName: names.broker, + BoundApps: boundAppsNamesFromInstanceGUIDLookup[instance.GUID], + LastOperation: lastOperation(instance.LastOperation), + } + } + + return result, Warnings(warnings), nil +} + +func lastOperation(lo resources.LastOperation) string { + if lo.Type != "" && lo.State != "" { + return fmt.Sprintf("%s %s", lo.Type, lo.State) + } + return "" +} + +func buildPlanDetailsLookup(included ccv3.IncludedResources) map[string]planDetails { + brokerLookup := lookuptable.NameFromGUID(included.ServiceBrokers) + + type twoNames struct{ broker, offering string } + offeringLookup := make(map[string]twoNames) + for _, o := range included.ServiceOfferings { + brokerName := brokerLookup[o.ServiceBrokerGUID] + offeringLookup[o.GUID] = twoNames{ + broker: brokerName, + offering: o.Name, + } + } + + planLookup := make(map[string]planDetails) + for _, p := range included.ServicePlans { + names := offeringLookup[p.ServiceOfferingGUID] + planLookup[p.GUID] = planDetails{ + broker: names.broker, + offering: names.offering, + plan: p.Name, + } + } + return planLookup +} + +func buildBoundAppsLookup(bindings []resources.ServiceCredentialBinding, spaceGUID string) map[string][]string { + appsBoundLookup := make(map[string][]string) + for _, binding := range bindings { + if binding.Type == resources.AppBinding && binding.AppSpaceGUID == spaceGUID { + appsBoundLookup[binding.ServiceInstanceGUID] = append(appsBoundLookup[binding.ServiceInstanceGUID], binding.AppName) + } + } + return appsBoundLookup +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_sharing.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_sharing.go new file mode 100644 index 0000000..d021185 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_instance_sharing.go @@ -0,0 +1,97 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/railway" +) + +type ServiceInstanceSharingParams struct { + SpaceName string + OrgName types.OptionalString +} + +func (actor Actor) ShareServiceInstanceToSpaceAndOrg( + serviceInstanceName, targetedSpaceGUID, targetedOrgGUID string, + sharedToDetails ServiceInstanceSharingParams, +) (Warnings, error) { + var serviceInstance resources.ServiceInstance + var shareSpace resources.Space + + return handleServiceInstanceErrors(railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, shareSpace, warnings, err = actor.validateSharingDetails(serviceInstanceName, targetedSpaceGUID, targetedOrgGUID, sharedToDetails) + return + }, + func() (warnings ccv3.Warnings, err error) { + _, warnings, err = actor.CloudControllerClient.ShareServiceInstanceToSpaces(serviceInstance.GUID, []string{shareSpace.GUID}) + return + }, + )) +} + +func (actor Actor) UnshareServiceInstanceFromSpaceAndOrg( + serviceInstanceName, targetedSpaceGUID, targetedOrgGUID string, + sharedToDetails ServiceInstanceSharingParams, +) (Warnings, error) { + var serviceInstance resources.ServiceInstance + var unshareSpace resources.Space + + return handleServiceInstanceErrors(railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, unshareSpace, warnings, err = actor.validateSharingDetails( + serviceInstanceName, + targetedSpaceGUID, + targetedOrgGUID, + sharedToDetails, + ) + return + }, + func() (warnings ccv3.Warnings, err error) { + warnings, err = actor.CloudControllerClient.UnshareServiceInstanceFromSpace(serviceInstance.GUID, unshareSpace.GUID) + return + }, + )) +} + +func (actor Actor) validateSharingDetails( + serviceInstanceName, targetedSpaceGUID, targetedOrgGUID string, + sharedToDetails ServiceInstanceSharingParams, +) (resources.ServiceInstance, resources.Space, ccv3.Warnings, error) { + var serviceInstance resources.ServiceInstance + var shareSpace resources.Space + var shareToOrgGUID = targetedOrgGUID + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.CloudControllerClient.GetServiceInstanceByNameAndSpace(serviceInstanceName, targetedSpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + if sharedToDetails.OrgName.IsSet { + var ( + orgWarnings Warnings + organization resources.Organization + ) + + organization, orgWarnings, err = actor.GetOrganizationByName(sharedToDetails.OrgName.Value) + warnings = ccv3.Warnings(orgWarnings) + shareToOrgGUID = organization.GUID + } + return + }, + func() (warnings ccv3.Warnings, err error) { + var spaceWarnings Warnings + shareSpace, spaceWarnings, err = actor.GetSpaceByNameAndOrganization(sharedToDetails.SpaceName, shareToOrgGUID) + warnings = ccv3.Warnings(spaceWarnings) + return + }, + ) + + if err != nil { + return resources.ServiceInstance{}, resources.Space{}, warnings, err + } + + return serviceInstance, shareSpace, warnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_key.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_key.go new file mode 100644 index 0000000..0a31563 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_key.go @@ -0,0 +1,170 @@ +package v7action + +import ( + "fmt" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/railway" +) + +type CreateServiceKeyParams struct { + SpaceGUID string + ServiceInstanceName string + ServiceKeyName string + Parameters types.OptionalObject +} + +func (actor Actor) CreateServiceKey(params CreateServiceKeyParams) (chan PollJobEvent, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(params.ServiceInstanceName, params.SpaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.createServiceKey(serviceInstance.GUID, params.ServiceKeyName, params.Parameters) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + if err != nil { + return nil, Warnings(warnings), err + } + + return stream, Warnings(warnings), nil +} + +func (actor Actor) GetServiceKeysByServiceInstance(serviceInstanceName, spaceGUID string) ([]resources.ServiceCredentialBinding, Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + keys []resources.ServiceCredentialBinding + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + keys, warnings, err = actor.CloudControllerClient.GetServiceCredentialBindings( + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstance.GUID}}, + ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}}, + ) + return + }, + ) + + return keys, Warnings(warnings), err +} + +func (actor Actor) GetServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID string) (resources.ServiceCredentialBinding, Warnings, error) { + key, warnings, err := actor.getServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID) + return key, Warnings(warnings), err +} + +func (actor Actor) GetServiceKeyDetailsByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID string) (resources.ServiceCredentialBindingDetails, Warnings, error) { + var ( + key resources.ServiceCredentialBinding + details resources.ServiceCredentialBindingDetails + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + key, warnings, err = actor.getServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + details, warnings, err = actor.CloudControllerClient.GetServiceCredentialBindingDetails(key.GUID) + return + }, + ) + + return details, Warnings(warnings), err +} + +func (actor Actor) DeleteServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID string) (chan PollJobEvent, Warnings, error) { + var ( + key resources.ServiceCredentialBinding + jobURL ccv3.JobURL + stream chan PollJobEvent + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + key, warnings, err = actor.getServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + jobURL, warnings, err = actor.CloudControllerClient.DeleteServiceCredentialBinding(key.GUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + stream = actor.PollJobToEventStream(jobURL) + return + }, + ) + + return stream, Warnings(warnings), err +} + +func (actor Actor) createServiceKey(serviceInstanceGUID, serviceKeyName string, parameters types.OptionalObject) (ccv3.JobURL, ccv3.Warnings, error) { + jobURL, warnings, err := actor.CloudControllerClient.CreateServiceCredentialBinding(resources.ServiceCredentialBinding{ + Type: resources.KeyBinding, + Name: serviceKeyName, + ServiceInstanceGUID: serviceInstanceGUID, + Parameters: parameters, + }) + switch err.(type) { + case nil: + return jobURL, warnings, nil + case ccerror.ServiceKeyTakenError: + return "", warnings, actionerror.ResourceAlreadyExistsError{ + Message: fmt.Sprintf("Service key %s already exists", serviceKeyName), + } + default: + return "", warnings, err + } +} + +func (actor Actor) getServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID string) (resources.ServiceCredentialBinding, ccv3.Warnings, error) { + var ( + serviceInstance resources.ServiceInstance + keys []resources.ServiceCredentialBinding + ) + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceInstance, _, warnings, err = actor.getServiceInstanceByNameAndSpace(serviceInstanceName, spaceGUID) + return + }, + func() (warnings ccv3.Warnings, err error) { + keys, warnings, err = actor.CloudControllerClient.GetServiceCredentialBindings( + ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstance.GUID}}, + ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}}, + ccv3.Query{Key: ccv3.NameFilter, Values: []string{serviceKeyName}}, + ) + return + }, + ) + switch { + case err != nil: + return resources.ServiceCredentialBinding{}, warnings, err + case len(keys) == 0: + return resources.ServiceCredentialBinding{}, warnings, actionerror.NewServiceKeyNotFoundError(serviceKeyName, serviceInstanceName) + default: + return keys[0], warnings, nil + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_offering.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_offering.go new file mode 100644 index 0000000..0b61ec4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_offering.go @@ -0,0 +1,25 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/railway" +) + +func (actor Actor) PurgeServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName string) (Warnings, error) { + var serviceOffering resources.ServiceOffering + + warnings, err := railway.Sequentially( + func() (warnings ccv3.Warnings, err error) { + serviceOffering, warnings, err = actor.CloudControllerClient.GetServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName) + err = actionerror.EnrichAPIErrors(err) + return + }, + func() (ccv3.Warnings, error) { + return actor.CloudControllerClient.PurgeServiceOffering(serviceOffering.GUID) + }, + ) + + return Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/service_plan.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_plan.go new file mode 100644 index 0000000..0fcd237 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/service_plan.go @@ -0,0 +1,39 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) GetServicePlanByNameOfferingAndBroker(servicePlanName, serviceOfferingName, serviceBrokerName string) (resources.ServicePlan, Warnings, error) { + query := []ccv3.Query{{Key: ccv3.NameFilter, Values: []string{servicePlanName}}} + if serviceBrokerName != "" { + query = append(query, ccv3.Query{Key: ccv3.ServiceBrokerNamesFilter, Values: []string{serviceBrokerName}}) + } + if serviceOfferingName != "" { + query = append(query, ccv3.Query{Key: ccv3.ServiceOfferingNamesFilter, Values: []string{serviceOfferingName}}) + } + + servicePlans, warnings, err := actor.CloudControllerClient.GetServicePlans(query...) + if err != nil { + return resources.ServicePlan{}, Warnings(warnings), err + } + + switch len(servicePlans) { + case 0: + return resources.ServicePlan{}, Warnings(warnings), actionerror.ServicePlanNotFoundError{ + PlanName: servicePlanName, + OfferingName: serviceOfferingName, + ServiceBrokerName: serviceBrokerName, + } + case 1: + return servicePlans[0], Warnings(warnings), nil + default: + return resources.ServicePlan{}, Warnings(warnings), actionerror.DuplicateServicePlanError{ + Name: servicePlanName, + ServiceOfferingName: serviceOfferingName, + ServiceBrokerName: serviceBrokerName, + } + } +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/shared_actor.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/shared_actor.go new file mode 100644 index 0000000..95dab5a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/shared_actor.go @@ -0,0 +1,12 @@ +package v7action + +import "code.cloudfoundry.org/cli/actor/sharedaction" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SharedActor + +type SharedActor interface { + GatherArchiveResources(archivePath string) ([]sharedaction.Resource, error) + GatherDirectoryResources(sourceDir string) ([]sharedaction.Resource, error) + ZipArchiveResources(sourceArchivePath string, filesToInclude []sharedaction.Resource) (string, error) + ZipDirectoryResources(sourceDir string, filesToInclude []sharedaction.Resource) (string, error) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/space.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/space.go new file mode 100644 index 0000000..449c18d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/space.go @@ -0,0 +1,283 @@ +package v7action + +import ( + "fmt" + "sort" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +type SpaceSummary struct { + Space resources.Space + Name string + OrgName string + AppNames []string + ServiceInstanceNames []string + IsolationSegmentName string + QuotaName string + RunningSecurityGroups []resources.SecurityGroup + StagingSecurityGroups []resources.SecurityGroup +} + +func (actor Actor) CreateSpace(spaceName, orgGUID string) (resources.Space, Warnings, error) { + allWarnings := Warnings{} + + space, apiWarnings, err := actor.CloudControllerClient.CreateSpace(resources.Space{ + Name: spaceName, + Relationships: resources.Relationships{ + constant.RelationshipTypeOrganization: resources.Relationship{GUID: orgGUID}, + }, + }) + + actorWarnings := Warnings(apiWarnings) + allWarnings = append(allWarnings, actorWarnings...) + + if _, ok := err.(ccerror.NameNotUniqueInOrgError); ok { + return resources.Space{}, allWarnings, actionerror.SpaceAlreadyExistsError{Space: spaceName} + } + return resources.Space{ + GUID: space.GUID, + Name: spaceName, + }, allWarnings, err +} + +// ResetSpaceIsolationSegment disassociates a space from an isolation segment. +// +// If the space's organization has a default isolation segment, return its +// name. Otherwise return the empty string. +func (actor Actor) ResetSpaceIsolationSegment(orgGUID string, spaceGUID string) (string, Warnings, error) { + var allWarnings Warnings + + _, apiWarnings, err := actor.CloudControllerClient.UpdateSpaceIsolationSegmentRelationship(spaceGUID, "") + allWarnings = append(allWarnings, apiWarnings...) + if err != nil { + return "", allWarnings, err + } + + isoSegRelationship, apiWarnings, err := actor.CloudControllerClient.GetOrganizationDefaultIsolationSegment(orgGUID) + allWarnings = append(allWarnings, apiWarnings...) + if err != nil { + return "", allWarnings, err + } + + var isoSegName string + if isoSegRelationship.GUID != "" { + isolationSegment, apiWarnings, err := actor.CloudControllerClient.GetIsolationSegment(isoSegRelationship.GUID) + allWarnings = append(allWarnings, apiWarnings...) + if err != nil { + return "", allWarnings, err + } + isoSegName = isolationSegment.Name + } + + return isoSegName, allWarnings, nil +} + +func (actor Actor) GetSpaceByNameAndOrganization(spaceName string, orgGUID string) (resources.Space, Warnings, error) { + ccv3Spaces, _, warnings, err := actor.CloudControllerClient.GetSpaces( + ccv3.Query{Key: ccv3.NameFilter, Values: []string{spaceName}}, + ccv3.Query{Key: ccv3.OrganizationGUIDFilter, Values: []string{orgGUID}}, + ) + + if err != nil { + return resources.Space{}, Warnings(warnings), err + } + + if len(ccv3Spaces) == 0 { + return resources.Space{}, Warnings(warnings), actionerror.SpaceNotFoundError{Name: spaceName} + } + + return resources.Space(ccv3Spaces[0]), Warnings(warnings), nil +} + +func (actor Actor) GetSpaceSummaryByNameAndOrganization(spaceName string, orgGUID string) (SpaceSummary, Warnings, error) { + var allWarnings Warnings + + org, warnings, err := actor.GetOrganizationByGUID(orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, org.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + apps, warnings, err := actor.GetApplicationsBySpace(space.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + appNames := make([]string, len(apps)) + for i, app := range apps { + appNames[i] = app.Name + } + sort.Strings(appNames) + + serviceInstances, _, ccv3Warnings, err := actor.CloudControllerClient.GetServiceInstances( + ccv3.Query{ + Key: ccv3.SpaceGUIDFilter, + Values: []string{space.GUID}, + }) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + serviceInstanceNames := make([]string, len(serviceInstances)) + for i, instance := range serviceInstances { + serviceInstanceNames[i] = instance.Name + } + sort.Strings(serviceInstanceNames) + + isoSegRelationship, ccv3Warnings, err := actor.CloudControllerClient.GetSpaceIsolationSegment(space.GUID) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + isoSegName := "" + isoSegGUID := isoSegRelationship.GUID + isDefaultIsoSeg := false + + if isoSegGUID == "" { + defaultIsoSeg, ccv3Warnings, err := actor.CloudControllerClient.GetOrganizationDefaultIsolationSegment(org.GUID) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + isoSegGUID = defaultIsoSeg.GUID + if isoSegGUID != "" { + isDefaultIsoSeg = true + } + } + + if isoSegGUID != "" { + isoSeg, ccv3warnings, err := actor.CloudControllerClient.GetIsolationSegment(isoSegGUID) + allWarnings = append(allWarnings, Warnings(ccv3warnings)...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + if isDefaultIsoSeg { + isoSegName = fmt.Sprintf("%s (org default)", isoSeg.Name) + } else { + isoSegName = isoSeg.Name + } + } + + appliedQuotaRelationshipGUID := space.Relationships[constant.RelationshipTypeQuota].GUID + + var spaceQuota resources.SpaceQuota + if appliedQuotaRelationshipGUID != "" { + spaceQuota, ccv3Warnings, err = actor.CloudControllerClient.GetSpaceQuota(space.Relationships[constant.RelationshipTypeQuota].GUID) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + + if err != nil { + return SpaceSummary{}, allWarnings, err + } + } + + runningSecurityGroups, ccv3Warnings, err := actor.CloudControllerClient.GetRunningSecurityGroups(space.GUID) + allWarnings = append(allWarnings, ccv3Warnings...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + stagingSecurityGroups, ccv3Warnings, err := actor.CloudControllerClient.GetStagingSecurityGroups(space.GUID) + allWarnings = append(allWarnings, ccv3Warnings...) + if err != nil { + return SpaceSummary{}, allWarnings, err + } + + spaceSummary := SpaceSummary{ + OrgName: org.Name, + Name: space.Name, + Space: space, + AppNames: appNames, + ServiceInstanceNames: serviceInstanceNames, + IsolationSegmentName: isoSegName, + QuotaName: spaceQuota.Name, + RunningSecurityGroups: runningSecurityGroups, + StagingSecurityGroups: stagingSecurityGroups, + } + + return spaceSummary, allWarnings, nil +} + +// GetOrganizationSpacesWithLabelSelector returns a list of spaces in the specified org +func (actor Actor) GetOrganizationSpacesWithLabelSelector(orgGUID string, labelSelector string) ([]resources.Space, Warnings, error) { + + queries := []ccv3.Query{ + ccv3.Query{Key: ccv3.OrganizationGUIDFilter, Values: []string{orgGUID}}, + ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}}, + } + if len(labelSelector) > 0 { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + + ccv3Spaces, _, warnings, err := actor.CloudControllerClient.GetSpaces(queries...) + if err != nil { + return []resources.Space{}, Warnings(warnings), err + } + + spaces := make([]resources.Space, len(ccv3Spaces)) + for i, ccv3Space := range ccv3Spaces { + spaces[i] = resources.Space(ccv3Space) + } + + return spaces, Warnings(warnings), nil +} + +// GetOrganizationSpaces returns a list of spaces in the specified org +func (actor Actor) GetOrganizationSpaces(orgGUID string) ([]resources.Space, Warnings, error) { + return actor.GetOrganizationSpacesWithLabelSelector(orgGUID, "") +} + +func (actor Actor) DeleteSpaceByNameAndOrganizationName(spaceName string, orgName string) (Warnings, error) { + var allWarnings Warnings + + org, actorWarnings, err := actor.GetOrganizationByName(orgName) + allWarnings = append(allWarnings, actorWarnings...) + if err != nil { + return allWarnings, err + } + + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, org.GUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + jobURL, deleteWarnings, err := actor.CloudControllerClient.DeleteSpace(space.GUID) + allWarnings = append(allWarnings, Warnings(deleteWarnings)...) + if err != nil { + return allWarnings, err + } + + ccWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(ccWarnings)...) + + return allWarnings, err +} + +func (actor Actor) RenameSpaceByNameAndOrganizationGUID(oldSpaceName, newSpaceName, orgGUID string) (resources.Space, Warnings, error) { + var allWarnings Warnings + + space, getWarnings, err := actor.GetSpaceByNameAndOrganization(oldSpaceName, orgGUID) + allWarnings = append(allWarnings, getWarnings...) + if err != nil { + return resources.Space{}, allWarnings, err + } + + ccSpace, updateWarnings, err := actor.CloudControllerClient.UpdateSpace(resources.Space{GUID: space.GUID, Name: newSpaceName}) + allWarnings = append(allWarnings, Warnings(updateWarnings)...) + + return resources.Space(ccSpace), allWarnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/space_feature.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_feature.go new file mode 100644 index 0000000..d60a8d8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_feature.go @@ -0,0 +1,49 @@ +package v7action + +import "code.cloudfoundry.org/cli/actor/actionerror" + +func (actor Actor) UpdateSpaceFeature(spaceName string, orgGUID string, enabled bool, feature string) (Warnings, error) { + var allWarnings Warnings + + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + previousValue, ccv3Warnings, err := actor.CloudControllerClient.GetSpaceFeature(space.GUID, feature) + + allWarnings = append(allWarnings, ccv3Warnings...) + + if err != nil { + return allWarnings, err + } + + if (previousValue == enabled) && (feature == "ssh") { + if enabled { + return allWarnings, actionerror.SpaceSSHAlreadyEnabledError{Space: space.Name} + } else { + return allWarnings, actionerror.SpaceSSHAlreadyDisabledError{Space: space.Name} + } + } + + ccv3Warnings, err = actor.CloudControllerClient.UpdateSpaceFeature(space.GUID, enabled, feature) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + + return allWarnings, err +} + +func (actor Actor) GetSpaceFeature(spaceName string, orgGUID string, feature string) (bool, Warnings, error) { + var allWarnings Warnings + + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return false, allWarnings, err + } + + enabled, ccv3Warnings, err := actor.CloudControllerClient.GetSpaceFeature(space.GUID, feature) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + + return enabled, allWarnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/space_manifest.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_manifest.go new file mode 100644 index 0000000..763ccfc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_manifest.go @@ -0,0 +1,38 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) DiffSpaceManifest(spaceGUID string, rawManifest []byte) (resources.ManifestDiff, Warnings, error) { + diff, warnings, err := actor.CloudControllerClient.GetSpaceManifestDiff( + spaceGUID, + rawManifest, + ) + + return diff, Warnings(warnings), err +} + +func (actor Actor) SetSpaceManifest(spaceGUID string, rawManifest []byte) (Warnings, error) { + var allWarnings Warnings + jobURL, applyManifestWarnings, err := actor.CloudControllerClient.UpdateSpaceApplyManifest( + spaceGUID, + rawManifest, + ) + allWarnings = append(allWarnings, applyManifestWarnings...) + if err != nil { + return allWarnings, err + } + + pollWarnings, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, pollWarnings...) + if err != nil { + if newErr, ok := err.(ccerror.V3JobFailedError); ok { + return allWarnings, actionerror.ApplicationManifestError{Message: newErr.Detail} + } + return allWarnings, err + } + return allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/space_quota.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_quota.go new file mode 100644 index 0000000..78f5acc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/space_quota.go @@ -0,0 +1,181 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +func (actor Actor) ApplySpaceQuotaByName(quotaName, spaceGUID, orgGUID string) (Warnings, error) { + var allWarnings Warnings + + spaceQuota, warnings, err := actor.GetSpaceQuotaByName(quotaName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + _, ccWarnings, err := actor.CloudControllerClient.ApplySpaceQuota(spaceQuota.GUID, spaceGUID) + allWarnings = append(allWarnings, ccWarnings...) + + return allWarnings, err +} + +func (actor Actor) CreateSpaceQuota(spaceQuotaName string, orgGuid string, limits QuotaLimits) (Warnings, error) { + allWarnings := Warnings{} + + spaceQuota := resources.SpaceQuota{ + Quota: resources.Quota{ + Name: spaceQuotaName, + Apps: resources.AppLimit{ + TotalMemory: limits.TotalMemoryInMB, + InstanceMemory: limits.PerProcessMemoryInMB, + TotalAppInstances: limits.TotalInstances, + }, + Services: resources.ServiceLimit{ + TotalServiceInstances: limits.TotalServiceInstances, + PaidServicePlans: limits.PaidServicesAllowed, + }, + Routes: resources.RouteLimit{ + TotalRoutes: limits.TotalRoutes, + TotalReservedPorts: limits.TotalReservedPorts, + }, + }, + OrgGUID: orgGuid, + SpaceGUIDs: nil, + } + + setZeroDefaultsForQuotaCreation(&spaceQuota.Apps, &spaceQuota.Routes, &spaceQuota.Services) + convertUnlimitedToNil(&spaceQuota.Apps, &spaceQuota.Routes, &spaceQuota.Services) + + _, warnings, err := actor.CloudControllerClient.CreateSpaceQuota(spaceQuota) + allWarnings = append(allWarnings, warnings...) + + return allWarnings, err +} + +func (actor Actor) DeleteSpaceQuotaByName(quotaName string, orgGUID string) (Warnings, error) { + var allWarnings Warnings + + quota, warnings, err := actor.GetSpaceQuotaByName(quotaName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + jobURL, ccv3Warnings, err := actor.CloudControllerClient.DeleteSpaceQuota(quota.GUID) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + if err != nil { + return allWarnings, err + } + + ccv3Warnings, err = actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(ccv3Warnings)...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} + +func (actor Actor) GetSpaceQuotaByName(spaceQuotaName string, orgGUID string) (resources.SpaceQuota, Warnings, error) { + ccv3Quotas, warnings, err := actor.CloudControllerClient.GetSpaceQuotas( + ccv3.Query{ + Key: ccv3.OrganizationGUIDFilter, + Values: []string{orgGUID}, + }, + ccv3.Query{ + Key: ccv3.NameFilter, + Values: []string{spaceQuotaName}, + }, + ) + + if err != nil { + return resources.SpaceQuota{}, Warnings(warnings), err + } + + if len(ccv3Quotas) == 0 { + return resources.SpaceQuota{}, Warnings(warnings), actionerror.SpaceQuotaNotFoundForNameError{Name: spaceQuotaName} + } + + return ccv3Quotas[0], Warnings(warnings), nil +} + +func (actor Actor) GetSpaceQuotasByOrgGUID(orgGUID string) ([]resources.SpaceQuota, Warnings, error) { + spaceQuotas, warnings, err := actor.CloudControllerClient.GetSpaceQuotas( + ccv3.Query{ + Key: ccv3.OrganizationGUIDFilter, + Values: []string{orgGUID}, + }, + ) + + if err != nil { + return []resources.SpaceQuota{}, Warnings(warnings), err + } + + return spaceQuotas, Warnings(warnings), nil +} + +func (actor Actor) UpdateSpaceQuota(currentName, orgGUID, newName string, limits QuotaLimits) (Warnings, error) { + var allWarnings Warnings + + oldSpaceQuota, warnings, err := actor.GetSpaceQuotaByName(currentName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + if newName == "" { + newName = currentName + } + + newSpaceQuota := resources.SpaceQuota{ + Quota: resources.Quota{ + GUID: oldSpaceQuota.GUID, + Name: newName, + Apps: resources.AppLimit{ + TotalMemory: limits.TotalMemoryInMB, + InstanceMemory: limits.PerProcessMemoryInMB, + TotalAppInstances: limits.TotalInstances, + }, + Services: resources.ServiceLimit{ + TotalServiceInstances: limits.TotalServiceInstances, + PaidServicePlans: limits.PaidServicesAllowed, + }, + Routes: resources.RouteLimit{ + TotalRoutes: limits.TotalRoutes, + TotalReservedPorts: limits.TotalReservedPorts, + }, + }, + } + + convertUnlimitedToNil(&newSpaceQuota.Apps, &newSpaceQuota.Routes, &newSpaceQuota.Services) + + _, ccWarnings, err := actor.CloudControllerClient.UpdateSpaceQuota(newSpaceQuota) + allWarnings = append(allWarnings, ccWarnings...) + + return allWarnings, err +} + +func (actor Actor) UnsetSpaceQuota(spaceQuotaName, spaceName, orgGUID string) (Warnings, error) { + var allWarnings Warnings + space, warnings, err := actor.GetSpaceByNameAndOrganization(spaceName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + spaceQuota, warnings, err := actor.GetSpaceQuotaByName(spaceQuotaName, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + ccWarnings, err := actor.CloudControllerClient.UnsetSpaceQuota(spaceQuota.GUID, space.GUID) + allWarnings = append(allWarnings, ccWarnings...) + if err != nil { + return allWarnings, err + } + + return allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh.go new file mode 100644 index 0000000..30fcc6f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh.go @@ -0,0 +1,108 @@ +package v7action + +import ( + "fmt" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/resources" +) + +type SSHAuthentication struct { + Endpoint string + HostKeyFingerprint string + Passcode string + Username string +} + +func (actor Actor) GetSSHPasscode() (string, error) { + return actor.UAAClient.GetSSHPasscode(actor.Config.AccessToken(), actor.Config.SSHOAuthClient()) +} + +// GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex returns +// back the SSH authentication information for the SSH session. +func (actor Actor) GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex( + appName string, spaceGUID string, processType string, processIndex uint, +) (SSHAuthentication, Warnings, error) { + var allWarnings Warnings + + rootInfo, warnings, err := actor.CloudControllerClient.GetInfo() + allWarnings = append(allWarnings, warnings...) + if err != nil { + return SSHAuthentication{}, allWarnings, err + } + + endpoint := rootInfo.AppSSHEndpoint() + if endpoint == "" { + return SSHAuthentication{}, nil, actionerror.SSHEndpointNotSetError{} + } + + fingerprint := rootInfo.AppSSHHostKeyFingerprint() + if fingerprint == "" { + return SSHAuthentication{}, nil, actionerror.SSHHostKeyFingerprintNotSetError{} + } + + passcode, err := actor.UAAClient.GetSSHPasscode(actor.Config.AccessToken(), actor.Config.SSHOAuthClient()) + if err != nil { + return SSHAuthentication{}, Warnings{}, err + } + + application, appWarnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID) + allWarnings = append(allWarnings, appWarnings...) + if err != nil { + return SSHAuthentication{}, allWarnings, err + } + + if !application.Started() { + return SSHAuthentication{}, allWarnings, actionerror.ApplicationNotStartedError{Name: appName} + } + + username, processWarnings, err := actor.getUsername(application, processType, processIndex) + allWarnings = append(allWarnings, processWarnings...) + if err != nil { + return SSHAuthentication{}, allWarnings, err + } + + return SSHAuthentication{ + Endpoint: endpoint, + HostKeyFingerprint: fingerprint, + Passcode: passcode, + Username: username, + }, allWarnings, err +} + +func (actor Actor) getUsername(application resources.Application, processType string, processIndex uint) (string, Warnings, error) { + processSummaries, processWarnings, err := actor.getProcessSummariesForApp(application.GUID, false) + if err != nil { + return "", processWarnings, err + } + + var processSummary ProcessSummary + for _, appProcessSummary := range processSummaries { + if appProcessSummary.Type == processType { + processSummary = appProcessSummary + break + } + } + + if processSummary.GUID == "" { + return "", processWarnings, actionerror.ProcessNotFoundError{ProcessType: processType} + } + + var processInstance ProcessInstance + for _, instance := range processSummary.InstanceDetails { + if uint(instance.Index) == processIndex { + processInstance = instance + break + } + } + + if processInstance == (ProcessInstance{}) { + return "", processWarnings, actionerror.ProcessInstanceNotFoundError{ProcessType: processType, InstanceIndex: processIndex} + } + + if !processInstance.Running() { + return "", processWarnings, actionerror.ProcessInstanceNotRunningError{ProcessType: processType, InstanceIndex: processIndex} + } + + return fmt.Sprintf("cf:%s/%d", processSummary.GUID, processIndex), processWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh_actor.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh_actor.go new file mode 100644 index 0000000..84fd260 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/ssh_actor.go @@ -0,0 +1,9 @@ +package v7action + +import "code.cloudfoundry.org/cli/actor/sharedaction" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SSHActor + +type SSHActor interface { + ExecuteSecureShell(sshOptions sharedaction.SSHOptions) error +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/stack.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/stack.go new file mode 100644 index 0000000..29ed497 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/stack.go @@ -0,0 +1,46 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +func (actor *Actor) GetStackByName(stackName string) (resources.Stack, Warnings, error) { + stacks, warnings, err := actor.CloudControllerClient.GetStacks( + ccv3.Query{Key: ccv3.NameFilter, Values: []string{stackName}}, + ) + + if err != nil { + return resources.Stack{}, Warnings(warnings), err + } + + if len(stacks) == 0 { + return resources.Stack{}, Warnings(warnings), actionerror.StackNotFoundError{Name: stackName} + } + + return resources.Stack(stacks[0]), Warnings(warnings), nil +} + +func (actor Actor) GetStacks(labelSelector string) ([]resources.Stack, Warnings, error) { + var ( + stacks []resources.Stack + warnings ccv3.Warnings + err error + ) + if len(labelSelector) > 0 { + queries := []ccv3.Query{ + ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}, + } + + stacks, warnings, err = actor.CloudControllerClient.GetStacks(queries...) + } else { + stacks, warnings, err = actor.CloudControllerClient.GetStacks() + } + + if err != nil { + return nil, Warnings(warnings), err + } + + return stacks, Warnings(warnings), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/target.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/target.go new file mode 100644 index 0000000..a63a027 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/target.go @@ -0,0 +1,48 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/util/configv3" +) + +type TargetSettings ccv3.TargetSettings + +// SetTarget targets the Cloud Controller using the client and sets target +// information in the config based on the response. +func (actor Actor) SetTarget(settings TargetSettings) (Warnings, error) { + var allWarnings Warnings + + actor.CloudControllerClient.TargetCF(ccv3.TargetSettings(settings)) + + rootInfo, warnings, err := actor.CloudControllerClient.GetInfo() + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + actor.Config.SetTargetInformation(configv3.TargetInformationArgs{ + Api: settings.URL, + ApiVersion: rootInfo.CloudControllerAPIVersion(), + Auth: rootInfo.Login(), + MinCLIVersion: "", // Oldest supported V3 version should be OK + Doppler: rootInfo.Logging(), + LogCache: rootInfo.LogCache(), + NetworkPolicyV1: rootInfo.NetworkPolicyV1(), + Routing: rootInfo.Routing(), + SkipSSLValidation: settings.SkipSSLValidation, + UAA: rootInfo.UAA(), + CFOnK8s: rootInfo.CFOnK8s, + }) + + actor.Config.SetTokenInformation("", "", "") + actor.Config.SetKubernetesAuthInfo("") + + return allWarnings, nil +} + +// ClearTarget clears target information from the config. +func (actor Actor) ClearTarget() { + actor.Config.SetTargetInformation(configv3.TargetInformationArgs{}) + actor.Config.SetTokenInformation("", "", "") + actor.Config.SetKubernetesAuthInfo("") +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/task.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/task.go new file mode 100644 index 0000000..fd255bf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/task.go @@ -0,0 +1,69 @@ +package v7action + +import ( + "strconv" + + "sort" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/resources" +) + +// Run resources.Task runs the provided command in the application environment associated +// with the provided application GUID. +func (actor Actor) RunTask(appGUID string, task resources.Task) (resources.Task, Warnings, error) { + createdTask, warnings, err := actor.CloudControllerClient.CreateApplicationTask(appGUID, resources.Task(task)) + if err != nil { + if e, ok := err.(ccerror.TaskWorkersUnavailableError); ok { + return resources.Task{}, Warnings(warnings), actionerror.TaskWorkersUnavailableError{Message: e.Error()} + } + } + + return resources.Task(createdTask), Warnings(warnings), err +} + +// GetApplicationTasks returns a list of tasks associated with the provided +// appplication GUID. +func (actor Actor) GetApplicationTasks(appGUID string, sortOrder SortOrder) ([]resources.Task, Warnings, error) { + tasks, warnings, err := actor.CloudControllerClient.GetApplicationTasks(appGUID) + actorWarnings := Warnings(warnings) + if err != nil { + return nil, actorWarnings, err + } + + allTasks := []resources.Task{} + for _, task := range tasks { + allTasks = append(allTasks, resources.Task(task)) + } + + if sortOrder == Descending { + sort.Slice(allTasks, func(i int, j int) bool { return allTasks[i].SequenceID > allTasks[j].SequenceID }) + } else { + sort.Slice(allTasks, func(i int, j int) bool { return allTasks[i].SequenceID < allTasks[j].SequenceID }) + } + + return allTasks, actorWarnings, nil +} + +func (actor Actor) GetTaskBySequenceIDAndApplication(sequenceID int, appGUID string) (resources.Task, Warnings, error) { + tasks, warnings, err := actor.CloudControllerClient.GetApplicationTasks( + appGUID, + ccv3.Query{Key: ccv3.SequenceIDFilter, Values: []string{strconv.Itoa(sequenceID)}}, + ) + if err != nil { + return resources.Task{}, Warnings(warnings), err + } + + if len(tasks) == 0 { + return resources.Task{}, Warnings(warnings), actionerror.TaskNotFoundError{SequenceID: sequenceID} + } + + return resources.Task(tasks[0]), Warnings(warnings), nil +} + +func (actor Actor) TerminateTask(taskGUID string) (resources.Task, Warnings, error) { + task, warnings, err := actor.CloudControllerClient.UpdateTaskCancel(taskGUID) + return resources.Task(task), Warnings(warnings), err +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/token.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/token.go new file mode 100644 index 0000000..158ea98 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/token.go @@ -0,0 +1,43 @@ +package v7action + +import ( + "strings" + "time" + + "github.com/SermoDigital/jose/jws" + "github.com/SermoDigital/jose/jwt" +) + +func (actor Actor) RefreshAccessToken() (string, error) { + var expiresIn time.Duration + + refreshToken := actor.Config.RefreshToken() + + accessTokenString := strings.TrimPrefix(actor.Config.AccessToken(), "bearer ") + token, err := jws.ParseJWT([]byte(accessTokenString)) + + if err == nil { + expiration, ok := token.Claims().Expiration() + if ok { + expiresIn = time.Until(expiration) + } + } + + if err != nil || expiresIn < time.Minute { + tokens, err := actor.UAAClient.RefreshAccessToken(refreshToken) + if err != nil { + return "", err + } + + actor.Config.SetAccessToken(tokens.AuthorizationToken()) + actor.Config.SetRefreshToken(tokens.RefreshToken) + + return tokens.AuthorizationToken(), nil + } + return actor.Config.AccessToken(), nil +} + +func (actor Actor) ParseAccessToken(accessToken string) (jwt.JWT, error) { + tokenStr := strings.TrimPrefix(accessToken, "bearer ") + return jws.ParseJWT([]byte(tokenStr)) +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/uaa_client.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/uaa_client.go new file mode 100644 index 0000000..e11903e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/uaa_client.go @@ -0,0 +1,22 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/api/uaa" + "code.cloudfoundry.org/cli/api/uaa/constant" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UAAClient + +type UAAClient interface { + Authenticate(credentials map[string]string, origin string, grantType constant.GrantType) (string, string, error) + CreateUser(username string, password string, origin string) (uaa.User, error) + DeleteUser(userGuid string) (uaa.User, error) + GetAPIVersion() (string, error) + GetLoginPrompts() (map[string][]string, error) + GetSSHPasscode(accessToken string, sshOAuthClient string) (string, error) + ListUsers(userName, origin string) ([]uaa.User, error) + RefreshAccessToken(refreshToken string) (uaa.RefreshedTokens, error) + UpdatePassword(userGUID string, oldPassword string, newPassword string) error + ValidateClientUser(clientID string) error + Revoke(token string) error +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/user.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/user.go new file mode 100644 index 0000000..ceee43a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/user.go @@ -0,0 +1,106 @@ +package v7action + +import ( + "sort" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/resources" +) + +// CreateUser creates a new user in UAA and registers it with cloud controller. +func (actor Actor) CreateUser(username string, password string, origin string) (resources.User, Warnings, error) { + uaaUser, err := actor.UAAClient.CreateUser(username, password, origin) + if err != nil { + return resources.User{}, nil, err + } + + ccUser, ccWarnings, err := actor.CloudControllerClient.CreateUser(uaaUser.ID) + + return resources.User(ccUser), Warnings(ccWarnings), err +} + +// GetUser gets a user in UAA with the given username and (if provided) origin. +// It returns an error if no matching user is found. +// It returns an error if multiple matching users are found. +// NOTE: The UAA /Users endpoint used here requires admin scopes. +func (actor Actor) GetUser(username, origin string) (resources.User, error) { + uaaUsers, err := actor.UAAClient.ListUsers(username, origin) + if err != nil { + return resources.User{}, err + } + + if len(uaaUsers) == 0 { + return resources.User{}, actionerror.UserNotFoundError{Username: username, Origin: origin} + } + + if len(uaaUsers) > 1 { + var origins []string + for _, user := range uaaUsers { + origins = append(origins, user.Origin) + } + return resources.User{}, actionerror.MultipleUAAUsersFoundError{Username: username, Origins: origins} + } + + uaaUser := uaaUsers[0] + + v7actionUser := resources.User{ + GUID: uaaUser.ID, + Origin: uaaUser.Origin, + } + return v7actionUser, nil +} + +// DeleteUser +func (actor Actor) DeleteUser(userGuid string) (Warnings, error) { + var allWarnings Warnings + jobURL, ccWarningsDelete, err := actor.CloudControllerClient.DeleteUser(userGuid) + allWarnings = Warnings(ccWarningsDelete) + + // If there is an error that is not a ResourceNotFoundError + if _, ok := err.(ccerror.ResourceNotFoundError); !ok && err != nil { + return allWarnings, err + } + + ccWarningsPoll, err := actor.CloudControllerClient.PollJob(jobURL) + allWarnings = append(allWarnings, Warnings(ccWarningsPoll)...) + if err != nil { + return allWarnings, err + } + + _, err = actor.UAAClient.DeleteUser(userGuid) + + return allWarnings, err +} + +func (actor Actor) UpdateUserPassword(userGUID string, oldPassword string, newPassword string) error { + return actor.UAAClient.UpdatePassword(userGUID, oldPassword, newPassword) +} + +func SortUsers(users []resources.User) { + sort.Slice(users, func(i, j int) bool { + if users[i].PresentationName == users[j].PresentationName { + + if users[i].Origin == constant.DefaultOriginUaa || users[j].Origin == "" { + return true + } + + if users[j].Origin == constant.DefaultOriginUaa || users[i].Origin == "" { + return false + } + + return users[i].Origin < users[j].Origin + } + + return users[i].PresentationName < users[j].PresentationName + }) +} + +func GetHumanReadableOrigin(user resources.User) string { + if user.Origin == "" { + return "client" + } + + return user.Origin +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/v7action/version.go b/vendor/code.cloudfoundry.org/cli/actor/v7action/version.go new file mode 100644 index 0000000..59ff1e2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/v7action/version.go @@ -0,0 +1,11 @@ +package v7action + +// GetUAAAPIVersion returns the UAA API version. +func (actor Actor) GetUAAAPIVersion() (string, error) { + // NOTE: We are making a request here because this method is currently only + // used in one branch of one command. However, we could probably do a refactor + // to store the UAA version in the config file upon login, like we do with the + // UAA URL, so we could just read from there instead of making a request here. + + return actor.UAAClient.GetAPIVersion() +} diff --git a/vendor/code.cloudfoundry.org/cli/actor/versioncheck/minimum_version_check.go b/vendor/code.cloudfoundry.org/cli/actor/versioncheck/minimum_version_check.go new file mode 100644 index 0000000..2d9e3eb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/actor/versioncheck/minimum_version_check.go @@ -0,0 +1,27 @@ +package versioncheck + +import ( + "github.com/blang/semver" +) + +func IsMinimumAPIVersionMet(current string, minimum string) (bool, error) { + if minimum == "" { + return true, nil + } + + currentSemver, err := semver.Make(current) + if err != nil { + return false, err + } + + minimumSemver, err := semver.Make(minimum) + if err != nil { + return false, err + } + + if currentSemver.GTE(minimumSemver) { + return true, nil + } + + return false, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/api_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/api_not_found_error.go new file mode 100644 index 0000000..a11b532 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/api_not_found_error.go @@ -0,0 +1,12 @@ +package ccerror + +import "fmt" + +// APINotFoundError is returned when the API endpoint is not found. +type APINotFoundError struct { + URL string +} + +func (e APINotFoundError) Error() string { + return fmt.Sprintf("Unable to find API at %s", e.URL) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_not_found_error.go new file mode 100644 index 0000000..21b3cea --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_not_found_error.go @@ -0,0 +1,17 @@ +package ccerror + +import "fmt" + +// ApplicationNotFoundError is returned when an endpoint cannot find the +// specified application +type ApplicationNotFoundError struct { + Name string +} + +func (e ApplicationNotFoundError) Error() string { + if e.Name != "" { + return fmt.Sprintf("App '%s' not found.", e.Name) + } + + return "Application not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_stopped_stats_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_stopped_stats_error.go new file mode 100644 index 0000000..4a0334a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/application_stopped_stats_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ApplicationStoppedStatsError is returned when requesting instance +// information from a stopped app. +type ApplicationStoppedStatsError struct { + Message string +} + +func (e ApplicationStoppedStatsError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/bad_request_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/bad_request_error.go new file mode 100644 index 0000000..5b708ca --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/bad_request_error.go @@ -0,0 +1,10 @@ +package ccerror + +// BadRequestError is returned when the server says the request was bad. +type BadRequestError struct { + Message string +} + +func (e BadRequestError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_already_exists_for_stack_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_already_exists_for_stack_error.go new file mode 100644 index 0000000..c92fb80 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_already_exists_for_stack_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackAlreadyExistsForStackError struct { + Message string +} + +func (e BuildpackAlreadyExistsForStackError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_invalid_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_invalid_error.go new file mode 100644 index 0000000..4f8f5f0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_invalid_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackInvalidError struct { + Message string +} + +func (e BuildpackInvalidError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_name_taken_error.go new file mode 100644 index 0000000..019d6dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_name_taken_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackNameTakenError struct { + Message string +} + +func (e BuildpackNameTakenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stack_does_not_exist_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stack_does_not_exist_error.go new file mode 100644 index 0000000..cb77113 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stack_does_not_exist_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackStackDoesNotExistError struct { + Message string +} + +func (e BuildpackStackDoesNotExistError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stacks_dont_match_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stacks_dont_match_error.go new file mode 100644 index 0000000..e0b2001 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_stacks_dont_match_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackStacksDontMatchError struct { + Message string +} + +func (e BuildpackStacksDontMatchError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_zip_invalid_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_zip_invalid_error.go new file mode 100644 index 0000000..fc0533c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/buildpack_zip_invalid_error.go @@ -0,0 +1,9 @@ +package ccerror + +type BuildpackZipInvalidError struct { + Message string +} + +func (e BuildpackZipInvalidError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/deployment_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/deployment_not_found_error.go new file mode 100644 index 0000000..b542c0b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/deployment_not_found_error.go @@ -0,0 +1,10 @@ +package ccerror + +// DeploymentNotFoundError is returned when an endpoint cannot find the +// specified deployment +type DeploymentNotFoundError struct { +} + +func (e DeploymentNotFoundError) Error() string { + return "Deployment not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/droplet_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/droplet_not_found_error.go new file mode 100644 index 0000000..8fd73bf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/droplet_not_found_error.go @@ -0,0 +1,10 @@ +package ccerror + +// DropletNotFoundError is returned when an endpoint cannot find the +// specified application +type DropletNotFoundError struct { +} + +func (e DropletNotFoundError) Error() string { + return "Droplet not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/feature_flag_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/feature_flag_not_found_error.go new file mode 100644 index 0000000..05fb7d1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/feature_flag_not_found_error.go @@ -0,0 +1,9 @@ +package ccerror + +// FeatureFlagNotFoundError is returned when the API endpoint is not found. +type FeatureFlagNotFoundError struct { +} + +func (e FeatureFlagNotFoundError) Error() string { + return "Feature flag not found." +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/forbidden_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/forbidden_error.go new file mode 100644 index 0000000..dd7f2c5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/forbidden_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ForbiddenError is returned when the client is forbidden from executing the +// request. +type ForbiddenError struct { + Message string +} + +func (e ForbiddenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instance_not_found_error.go new file mode 100644 index 0000000..0d91555 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instance_not_found_error.go @@ -0,0 +1,10 @@ +package ccerror + +// InstanceNotFoundError is returned when an endpoint cannot find the +// specified instance +type InstanceNotFoundError struct { +} + +func (e InstanceNotFoundError) Error() string { + return "Instance not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instances_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instances_error.go new file mode 100644 index 0000000..fcd8dea --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/instances_error.go @@ -0,0 +1,11 @@ +package ccerror + +// InstancesError is returned when requesting instance information encounters +// an error. +type InstancesError struct { + Message string +} + +func (e InstancesError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_auth_token_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_auth_token_error.go new file mode 100644 index 0000000..55d9420 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_auth_token_error.go @@ -0,0 +1,11 @@ +package ccerror + +// InvalidAuthTokenError is returned when the client has an invalid +// authorization header. +type InvalidAuthTokenError struct { + Message string +} + +func (e InvalidAuthTokenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_buildpack_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_buildpack_error.go new file mode 100644 index 0000000..cf243a2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_buildpack_error.go @@ -0,0 +1,8 @@ +package ccerror + +type InvalidBuildpackError struct { +} + +func (e InvalidBuildpackError) Error() string { + return "Buildpack must be an existing admin buildpack or a valid git URI" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_relation_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_relation_error.go new file mode 100644 index 0000000..c43964a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_relation_error.go @@ -0,0 +1,11 @@ +package ccerror + +// InvalidRelationError is returned when an association between two entities +// cannot be created. +type InvalidRelationError struct { + Message string +} + +func (e InvalidRelationError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_start_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_start_error.go new file mode 100644 index 0000000..9bcfefc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_start_error.go @@ -0,0 +1,8 @@ +package ccerror + +type InvalidStartError struct { +} + +func (e InvalidStartError) Error() string { + return "App cannot start without a package to stage or a droplet to run." +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_state_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_state_error.go new file mode 100644 index 0000000..9a79fb0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/invalid_state_error.go @@ -0,0 +1,8 @@ +package ccerror + +type InvalidStateError struct { +} + +func (e InvalidStateError) Error() string { + return "Cannot stage package unless its state is 'READY'." +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_failed_no_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_failed_no_error.go new file mode 100644 index 0000000..65e3a8e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_failed_no_error.go @@ -0,0 +1,15 @@ +package ccerror + +import ( + "fmt" +) + +// V3JobFailedError represents a failed Cloud Controller Job. It wraps the error +// returned back from the Cloud Controller. +type JobFailedNoErrorError struct { + JobGUID string +} + +func (e JobFailedNoErrorError) Error() string { + return fmt.Sprintf("Job (%s) failed with no error. This is unexpected, contact your operator for details.", e.JobGUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_timeout_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_timeout_error.go new file mode 100644 index 0000000..8414c6a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/job_timeout_error.go @@ -0,0 +1,17 @@ +package ccerror + +import ( + "fmt" + "time" +) + +// JobTimeoutError is returned from PollJob when the OverallPollingTimeout has +// been reached. +type JobTimeoutError struct { + JobGUID string + Timeout time.Duration +} + +func (e JobTimeoutError) Error() string { + return fmt.Sprintf("Job (%s) polling has reached the maximum timeout of %s seconds", e.JobGUID, e.Timeout) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/minimum_api_version_not_met_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/minimum_api_version_not_met_error.go new file mode 100644 index 0000000..1054c41 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/minimum_api_version_not_met_error.go @@ -0,0 +1,12 @@ +package ccerror + +import "fmt" + +type MinimumAPIVersionNotMetError struct { + CurrentVersion string + MinimumVersion string +} + +func (e MinimumAPIVersionNotMetError) Error() string { + return fmt.Sprintf("CF API version %s or higher is required. Your target is %s.", e.CurrentVersion, e.MinimumVersion) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/multi_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/multi_error.go new file mode 100644 index 0000000..123f5ae --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/multi_error.go @@ -0,0 +1,34 @@ +package ccerror + +import ( + "fmt" + "strings" +) + +type MultiError struct { + Errors []V3Error + ResponseCode int +} + +func (e MultiError) Details() []string { + var errorMsg []string + + for _, err := range e.Errors { + errorMsg = append(errorMsg, err.Detail) + } + + return errorMsg +} + +func (e MultiError) Error() string { + errorMsg := []string{ + "Multiple errors occurred:", + fmt.Sprintf("Response Code: %d", e.ResponseCode), + } + + for _, err := range e.Errors { + errorMsg = append(errorMsg, fmt.Sprintf("Code: %d, Title: %s, Detail: %s", err.Code, err.Title, err.Detail)) + } + + return strings.Join(errorMsg, "\n") +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_org_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_org_error.go new file mode 100644 index 0000000..8041d78 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_org_error.go @@ -0,0 +1,8 @@ +package ccerror + +type NameNotUniqueInOrgError struct { +} + +func (e NameNotUniqueInOrgError) Error() string { + return "name must be unique per organization" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_space_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_space_error.go new file mode 100644 index 0000000..caf2794 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/name_not_unique_in_space_error.go @@ -0,0 +1,5 @@ +package ccerror + +type NameNotUniqueInSpaceError struct { + UnprocessableEntityError +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/nil_object_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/nil_object_error.go new file mode 100644 index 0000000..8ed6c51 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/nil_object_error.go @@ -0,0 +1,12 @@ +package ccerror + +import "fmt" + +// NilObjectError gets returned when passed a nil object as a parameter. +type NilObjectError struct { + Object string +} + +func (e NilObjectError) Error() string { + return fmt.Sprintf("%s cannot be nil", e.Object) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/not_staged_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/not_staged_error.go new file mode 100644 index 0000000..7051fbd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/not_staged_error.go @@ -0,0 +1,11 @@ +package ccerror + +// NotStagedError is returned when requesting instance information from a +// not staged app. +type NotStagedError struct { + Message string +} + +func (e NotStagedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/org_quota_already_exists.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/org_quota_already_exists.go new file mode 100644 index 0000000..a16fa12 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/org_quota_already_exists.go @@ -0,0 +1,9 @@ +package ccerror + +type QuotaAlreadyExists struct { + Message string +} + +func (e QuotaAlreadyExists) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/organization_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/organization_name_taken_error.go new file mode 100644 index 0000000..051f348 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/organization_name_taken_error.go @@ -0,0 +1,7 @@ +package ccerror + +// OrganizationNameTakenError is returned when an organization with the +// requested name already exists in the Cloud Controller. +type OrganizationNameTakenError struct { + UnprocessableEntityError +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/pipe_seek_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/pipe_seek_error.go new file mode 100644 index 0000000..a890f9d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/pipe_seek_error.go @@ -0,0 +1,13 @@ +package ccerror + +import "fmt" + +// PipeSeekError is returned by Pipebomb when a Seek is called. +type PipeSeekError struct { + // Err is the error that caused the Seek to be called. + Err error +} + +func (e PipeSeekError) Error() string { + return fmt.Sprintf("error seeking a stream on retry: %s", e.Err) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/process_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/process_not_found_error.go new file mode 100644 index 0000000..484cf1f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/process_not_found_error.go @@ -0,0 +1,10 @@ +package ccerror + +// ProcessNotFoundError is returned when an endpoint cannot find the +// specified process +type ProcessNotFoundError struct { +} + +func (e ProcessNotFoundError) Error() string { + return "Process not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/raw_http_status_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/raw_http_status_error.go new file mode 100644 index 0000000..918cd8d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/raw_http_status_error.go @@ -0,0 +1,14 @@ +package ccerror + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + StatusCode int + RawResponse []byte + RequestIDs []string +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("Error Code: %d\nRaw Response: %s", r.StatusCode, r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/request_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/request_error.go new file mode 100644 index 0000000..26d5b30 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/request_error.go @@ -0,0 +1,11 @@ +package ccerror + +// RequestError represents a generic error encountered while performing the +// HTTP request. This generic error occurs before a HTTP response is obtained. +type RequestError struct { + Err error +} + +func (e RequestError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_alredy_exists_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_alredy_exists_error.go new file mode 100644 index 0000000..9969d16 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_alredy_exists_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ResourceAlreadyExistsError is returned when a resource cannot be created +// because an identical resource already exists in the Cloud Controller. +type ResourceAlreadyExistsError struct { + Message string +} + +func (e ResourceAlreadyExistsError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_not_found_error.go new file mode 100644 index 0000000..18b8c54 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/resource_not_found_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ResourceNotFoundError is returned when the client requests a resource that +// does not exist or does not have permissions to see. +type ResourceNotFoundError struct { + Message string +} + +func (e ResourceNotFoundError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/role_already_exists_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/role_already_exists_error.go new file mode 100644 index 0000000..135bc9d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/role_already_exists_error.go @@ -0,0 +1,7 @@ +package ccerror + +// RoleAlreadyExistsError is returned when a role with the same type, user, +// and org or space already exists in the Cloud Controller. +type RoleAlreadyExistsError struct { + UnprocessableEntityError +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/route_not_unique_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/route_not_unique_error.go new file mode 100644 index 0000000..8311076 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/route_not_unique_error.go @@ -0,0 +1,5 @@ +package ccerror + +type RouteNotUniqueError struct { + UnprocessableEntityError +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_already_exists.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_already_exists.go new file mode 100644 index 0000000..551f2ae --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_already_exists.go @@ -0,0 +1,9 @@ +package ccerror + +type SecurityGroupAlreadyExists struct { + Message string +} + +func (e SecurityGroupAlreadyExists) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_not_bound_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_not_bound_error.go new file mode 100644 index 0000000..92ea0e9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/security_group_not_bound_error.go @@ -0,0 +1,9 @@ +package ccerror + +type SecurityGroupNotBound struct { + Message string +} + +func (e SecurityGroupNotBound) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_binding_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_binding_taken_error.go new file mode 100644 index 0000000..0980fe7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_binding_taken_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceBindingTakenError is returned when creating a +// service binding that already exists +type ServiceBindingTakenError struct { + Message string +} + +func (e ServiceBindingTakenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_bad_response_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_bad_response_error.go new file mode 100644 index 0000000..465eb00 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_bad_response_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceBrokerBadResponseError is returned when CC returns an error +// of type CF-ServiceBrokerBadResponse. +type ServiceBrokerBadResponseError struct { + Message string +} + +func (e ServiceBrokerBadResponseError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_catalog_invalid_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_catalog_invalid_error.go new file mode 100644 index 0000000..38d2477 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_catalog_invalid_error.go @@ -0,0 +1,9 @@ +package ccerror + +type ServiceBrokerCatalogInvalidError struct { + Message string +} + +func (e ServiceBrokerCatalogInvalidError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_request_rejected_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_request_rejected_error.go new file mode 100644 index 0000000..c28448a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_broker_request_rejected_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceBrokerRequestRejectedError is returned when CC returns an error +// of type CF-ServiceBrokerRequestRejected. +type ServiceBrokerRequestRejectedError struct { + Message string +} + +func (e ServiceBrokerRequestRejectedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_name_taken_error.go new file mode 100644 index 0000000..027c06a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_name_taken_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceInstanceNameTakenError is returned when creating a +// service instance that already exists. +type ServiceInstanceNameTakenError struct { + Message string +} + +func (e ServiceInstanceNameTakenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_not_found_error.go new file mode 100644 index 0000000..c2fb76b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_not_found_error.go @@ -0,0 +1,13 @@ +package ccerror + +import "fmt" + +// ServiceInstanceNotFoundError is returned when an endpoint cannot find the +// specified service instance +type ServiceInstanceNotFoundError struct { + Name, SpaceGUID string +} + +func (e ServiceInstanceNotFoundError) Error() string { + return fmt.Sprintf("Service instance '%s' not found in space '%s'.", e.Name, e.SpaceGUID) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_operation_in_progress_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_operation_in_progress_error.go new file mode 100644 index 0000000..3f2373f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_operation_in_progress_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceInstanceOperationInProgressError is returned when an operation +// cannot proceed because an operation is already in progress +type ServiceInstanceOperationInProgressError struct { + Message string +} + +func (e ServiceInstanceOperationInProgressError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_parameters_fetch_not_supported_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_parameters_fetch_not_supported_error.go new file mode 100644 index 0000000..51ed9f5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_instance_parameters_fetch_not_supported_error.go @@ -0,0 +1,12 @@ +package ccerror + +// ServiceInstanceParametersFetchNotSupportedError is returned when +// the service instance is user-provided or +// service instance fetching is not supported for managed instances +type ServiceInstanceParametersFetchNotSupportedError struct { + Message string +} + +func (e ServiceInstanceParametersFetchNotSupportedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_key_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_key_taken_error.go new file mode 100644 index 0000000..09b313c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_key_taken_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServiceKeyTakenError is returned when creating a +// service key that already exists +type ServiceKeyTakenError struct { + Message string +} + +func (e ServiceKeyTakenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_name_ambiguity_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_name_ambiguity_error.go new file mode 100644 index 0000000..b613c9f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_name_ambiguity_error.go @@ -0,0 +1,21 @@ +package ccerror + +import ( + "fmt" + "strings" +) + +type ServiceOfferingNameAmbiguityError struct { + ServiceOfferingName string + ServiceBrokerNames []string +} + +func (e ServiceOfferingNameAmbiguityError) Error() string { + const msg = "Service '%s' is provided by multiple service brokers%s" + switch len(e.ServiceBrokerNames) { + case 0: + return fmt.Sprintf(msg, e.ServiceOfferingName, ".") + default: + return fmt.Sprintf(msg, e.ServiceOfferingName, ": "+strings.Join(e.ServiceBrokerNames, ", ")) + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_not_found_error.go new file mode 100644 index 0000000..59204da --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_offering_not_found_error.go @@ -0,0 +1,23 @@ +package ccerror + +import "fmt" + +type ServiceOfferingNotFoundError struct { + ServiceOfferingName, ServiceBrokerName string +} + +func (e ServiceOfferingNotFoundError) Error() string { + if e.ServiceOfferingName != "" && e.ServiceBrokerName != "" { + return fmt.Sprintf("Service offering '%s' for service broker '%s' not found.", e.ServiceOfferingName, e.ServiceBrokerName) + } + + if e.ServiceOfferingName != "" { + return fmt.Sprintf("Service offering '%s' not found.", e.ServiceOfferingName) + } + + if e.ServiceBrokerName != "" { + return fmt.Sprintf("No service offerings found for service broker '%s'.", e.ServiceBrokerName) + } + + return "No service offerings found." +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_not_found_error.go new file mode 100644 index 0000000..87c4859 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_not_found_error.go @@ -0,0 +1,7 @@ +package ccerror + +type ServicePlanNotFound struct{} + +func (ServicePlanNotFound) Error() string { + return "The service plan was not found" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_visibility_exists_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_visibility_exists_error.go new file mode 100644 index 0000000..4de9233 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_plan_visibility_exists_error.go @@ -0,0 +1,11 @@ +package ccerror + +// ServicePlanVisibilityExistsError is returned when creating a +// service plan visibility that already exists +type ServicePlanVisibilityExistsError struct { + Message string +} + +func (e ServicePlanVisibilityExistsError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_unavailable_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_unavailable_error.go new file mode 100644 index 0000000..8e43034 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/service_unavailable_error.go @@ -0,0 +1,10 @@ +package ccerror + +// ServiceUnavailableError wraps a http 503 error. +type ServiceUnavailableError struct { + Message string +} + +func (e ServiceUnavailableError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/space_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/space_name_taken_error.go new file mode 100644 index 0000000..9531b37 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/space_name_taken_error.go @@ -0,0 +1,11 @@ +package ccerror + +// SpaceNameTakenError is returned when creating a +// space that already exists. +type SpaceNameTakenError struct { + Message string +} + +func (e SpaceNameTakenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/ssl_validation_hostname_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/ssl_validation_hostname_error.go new file mode 100644 index 0000000..d8ede3d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/ssl_validation_hostname_error.go @@ -0,0 +1,13 @@ +package ccerror + +import "fmt" + +// SSLValidationHostnameError replaces x509.HostnameError when the server has +// SSL certificate that does not match the hostname. +type SSLValidationHostnameError struct { + Message string +} + +func (e SSLValidationHostnameError) Error() string { + return fmt.Sprintf("Hostname does not match SSL Certificate (%s)", e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/task_workers_unavailable_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/task_workers_unavailable_error.go new file mode 100644 index 0000000..3eabc8b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/task_workers_unavailable_error.go @@ -0,0 +1,11 @@ +package ccerror + +// TaskWorkersUnavailableError represents the case when no Diego workers are +// available. +type TaskWorkersUnavailableError struct { + Message string +} + +func (e TaskWorkersUnavailableError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unauthorized_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unauthorized_error.go new file mode 100644 index 0000000..f23dbc5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unauthorized_error.go @@ -0,0 +1,11 @@ +package ccerror + +// UnauthorizedError is returned when the client does not have the correct +// permissions to execute the request. +type UnauthorizedError struct { + Message string +} + +func (e UnauthorizedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_http_source_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_http_source_error.go new file mode 100644 index 0000000..ff326d4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_http_source_error.go @@ -0,0 +1,16 @@ +package ccerror + +import "fmt" + +// UnknownHTTPSourceError represents HTTP responses with status code >= 400 +// that we cannot unmarshal into a {V2,V3}ErrorResponse. +// Ex: In "cf api google.com", google will return a 404, but the body will not match +// an error from the Cloud Controller +type UnknownHTTPSourceError struct { + StatusCode int + RawResponse []byte +} + +func (r UnknownHTTPSourceError) Error() string { + return fmt.Sprintf("Error unmarshalling the following into a cloud controller error: %s", r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_object_in_list_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_object_in_list_error.go new file mode 100644 index 0000000..c19edd0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unknown_object_in_list_error.go @@ -0,0 +1,22 @@ +package ccerror + +import ( + "fmt" + "reflect" +) + +// UnknownObjectInListError is returned when iterating through a paginated +// list. Assuming tests are written for the paginated function, this should be +// impossible to get. +type UnknownObjectInListError struct { + Expected interface{} + Unexpected interface{} +} + +func (e UnknownObjectInListError) Error() string { + return fmt.Sprintf( + "Error while processing a paginated list. Expected %s but %s was returned", + reflect.TypeOf(e.Expected), + reflect.TypeOf(e.Unexpected), + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unprocessable_entity_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unprocessable_entity_error.go new file mode 100644 index 0000000..fd3f3bc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unprocessable_entity_error.go @@ -0,0 +1,11 @@ +package ccerror + +// UnprocessableEntityError is returned when the request cannot be processed by +// the cloud controller. +type UnprocessableEntityError struct { + Message string +} + +func (e UnprocessableEntityError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unverified_server_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unverified_server_error.go new file mode 100644 index 0000000..d04cd79 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/unverified_server_error.go @@ -0,0 +1,11 @@ +package ccerror + +// UnverifiedServerError replaces x509.UnknownAuthorityError when the server +// has SSL but the client is unable to verify it's certificate +type UnverifiedServerError struct { + URL string +} + +func (UnverifiedServerError) Error() string { + return "x509: certificate signed by unknown authority" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/user_not_found.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/user_not_found.go new file mode 100644 index 0000000..1ed3c3e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/user_not_found.go @@ -0,0 +1,21 @@ +package ccerror + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// UserNotFoundError is returned when a role does not exist. +type UserNotFoundError struct { + Username string + Origin string +} + +func (e UserNotFoundError) Error() string { + if e.Origin != "" && e.Origin != constant.DefaultOriginUaa { + return fmt.Sprintf("User '%s' with origin '%s' does not exist.", e.Username, e.Origin) + } + + return fmt.Sprintf("User '%s' does not exist.", e.Username) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_job_failed_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_job_failed_error.go new file mode 100644 index 0000000..73fcc3a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_job_failed_error.go @@ -0,0 +1,14 @@ +package ccerror + +import "fmt" + +// V2JobFailedError represents a failed Cloud Controller Job. It wraps the error +// returned back from the Cloud Controller. +type V2JobFailedError struct { + JobGUID string + Message string +} + +func (e V2JobFailedError) Error() string { + return fmt.Sprintf("Job (%s) failed: %s", e.JobGUID, e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_unexpected_response_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_unexpected_response_error.go new file mode 100644 index 0000000..37f15e6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v2_unexpected_response_error.go @@ -0,0 +1,27 @@ +package ccerror + +import "fmt" + +// V2ErrorResponse represents a generic Cloud Controller V2 error response. +type V2ErrorResponse struct { + Code int `json:"code"` + Description string `json:"description"` + ErrorCode string `json:"error_code"` +} + +// V2UnexpectedResponseError is returned when the client gets an error that has +// not been accounted for. +type V2UnexpectedResponseError struct { + V2ErrorResponse + + RequestIDs []string + ResponseCode int +} + +func (e V2UnexpectedResponseError) Error() string { + message := fmt.Sprintf("Unexpected Response\nResponse code: %d\nCC code: %d\nCC error code: %s", e.ResponseCode, e.Code, e.ErrorCode) + for _, id := range e.RequestIDs { + message = fmt.Sprintf("%s\nRequest ID: %s", message, id) + } + return fmt.Sprintf("%s\nDescription: %s", message, e.Description) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_error.go new file mode 100644 index 0000000..b19a055 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_error.go @@ -0,0 +1,8 @@ +package ccerror + +// V3Error represents a cloud controller error. +type V3Error struct { + Code int64 `json:"code"` + Detail string `json:"detail"` + Title string `json:"title"` +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_job_failed_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_job_failed_error.go new file mode 100644 index 0000000..aac4025 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_job_failed_error.go @@ -0,0 +1,24 @@ +package ccerror + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// V3JobFailedError represents a failed Cloud Controller Job. It wraps the error +// returned back from the Cloud Controller. +type V3JobFailedError struct { + JobGUID string + + // Code is a numeric code for this error. + Code constant.JobErrorCode `json:"code"` + // Detail is a verbose description of the error. + Detail string `json:"detail"` + // Title is a short description of the error. + Title string `json:"title"` +} + +func (e V3JobFailedError) Error() string { + return fmt.Sprintf("Job (%s) failed: %s", e.JobGUID, e.Detail) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_unexpected_response_error.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_unexpected_response_error.go new file mode 100644 index 0000000..7d60138 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccerror/v3_unexpected_response_error.go @@ -0,0 +1,37 @@ +package ccerror + +import ( + "fmt" + "strings" +) + +// V3ErrorResponse represents a generic Cloud Controller V3 error response. +type V3ErrorResponse struct { + Errors []V3Error `json:"errors"` +} + +// V3UnexpectedResponseError is returned when the client gets an error that has +// not been accounted for. +type V3UnexpectedResponseError struct { + V3ErrorResponse + + ResponseCode int + RequestIDs []string +} + +func (e V3UnexpectedResponseError) Error() string { + messages := []string{ + "Unexpected Response", + fmt.Sprintf("Response Code: %d", e.ResponseCode), + } + + for _, id := range e.RequestIDs { + messages = append(messages, fmt.Sprintf("Request ID: %s", id)) + } + + for _, ccError := range e.V3ErrorResponse.Errors { + messages = append(messages, fmt.Sprintf("Code: %d, Title: %s, Detail: %s", ccError.Code, ccError.Title, ccError.Detail)) + } + + return strings.Join(messages, "\n") +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application.go new file mode 100644 index 0000000..a060993 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application.go @@ -0,0 +1,106 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateApplication creates an application with the given settings. +func (client *Client) CreateApplication(app resources.Application) (resources.Application, Warnings, error) { + var responseBody resources.Application + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationRequest, + RequestBody: app, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, Warnings, error) { + apps, warnings, err := client.GetApplications( + Query{Key: NameFilter, Values: []string{appName}}, + Query{Key: SpaceGUIDFilter, Values: []string{spaceGUID}}, + ) + if err != nil { + return resources.Application{}, warnings, err + } + + if len(apps) == 0 { + return resources.Application{}, warnings, ccerror.ApplicationNotFoundError{Name: appName} + } + + return apps[0], warnings, nil +} + +// GetApplications lists applications with optional queries. +func (client *Client) GetApplications(query ...Query) ([]resources.Application, Warnings, error) { + var apps []resources.Application + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationsRequest, + Query: query, + ResponseBody: resources.Application{}, + AppendToList: func(item interface{}) error { + apps = append(apps, item.(resources.Application)) + return nil + }, + }) + + return apps, warnings, err +} + +// UpdateApplication updates an application with the given settings. +func (client *Client) UpdateApplication(app resources.Application) (resources.Application, Warnings, error) { + var responseBody resources.Application + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchApplicationRequest, + URIParams: internal.Params{"app_guid": app.GUID}, + RequestBody: app, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateApplicationRestart restarts the given application. +func (client *Client) UpdateApplicationRestart(appGUID string) (resources.Application, Warnings, error) { + var responseBody resources.Application + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationActionRestartRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateApplicationStart starts the given application. +func (client *Client) UpdateApplicationStart(appGUID string) (resources.Application, Warnings, error) { + var responseBody resources.Application + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationActionStartRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateApplicationStop stops the given application. +func (client *Client) UpdateApplicationStop(appGUID string) (resources.Application, Warnings, error) { + var responseBody resources.Application + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationActionStopRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application_feature.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application_feature.go new file mode 100644 index 0000000..ee07cc6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/application_feature.go @@ -0,0 +1,48 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +type SSHEnabled struct { + Enabled bool + Reason string +} + +func (client *Client) GetAppFeature(appGUID string, featureName string) (resources.ApplicationFeature, Warnings, error) { + var responseBody resources.ApplicationFeature + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetApplicationFeaturesRequest, + URIParams: internal.Params{"app_guid": appGUID, "name": featureName}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetSSHEnabled(appGUID string) (SSHEnabled, Warnings, error) { + var responseBody SSHEnabled + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetSSHEnabled, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateAppFeature enables/disables the ability to ssh for a given application. +func (client *Client) UpdateAppFeature(appGUID string, enabled bool, featureName string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchApplicationFeaturesRequest, + RequestBody: struct { + Enabled bool `json:"enabled"` + }{Enabled: enabled}, + URIParams: internal.Params{"app_guid": appGUID, "name": featureName}, + }) + + return warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/build.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/build.go new file mode 100644 index 0000000..2c67189 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/build.go @@ -0,0 +1,33 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateBuild creates the given build, requires Package GUID to be set on the +// build. +func (client *Client) CreateBuild(build resources.Build) (resources.Build, Warnings, error) { + var responseBody resources.Build + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostBuildRequest, + RequestBody: build, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetBuild gets the build with the given GUID. +func (client *Client) GetBuild(guid string) (resources.Build, Warnings, error) { + var responseBody resources.Build + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetBuildRequest, + URIParams: internal.Params{"build_guid": guid}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/buildpack.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/buildpack.go new file mode 100644 index 0000000..7846d58 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/buildpack.go @@ -0,0 +1,86 @@ +package ccv3 + +import ( + "io" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/api/cloudcontroller/uploads" + "code.cloudfoundry.org/cli/resources" +) + +// CreateBuildpack creates a buildpack with the given settings, Type and the +// ApplicationRelationship must be set. +func (client *Client) CreateBuildpack(bp resources.Buildpack) (resources.Buildpack, Warnings, error) { + var responseBody resources.Buildpack + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostBuildpackRequest, + RequestBody: bp, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// DeleteBuildpack deletes the buildpack with the provided guid. +func (client Client) DeleteBuildpack(buildpackGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteBuildpackRequest, + URIParams: internal.Params{"buildpack_guid": buildpackGUID}, + }) + + return jobURL, warnings, err +} + +// GetBuildpacks lists buildpacks with optional filters. +func (client *Client) GetBuildpacks(query ...Query) ([]resources.Buildpack, Warnings, error) { + var buildpacks []resources.Buildpack + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetBuildpacksRequest, + Query: query, + ResponseBody: resources.Buildpack{}, + AppendToList: func(item interface{}) error { + buildpacks = append(buildpacks, item.(resources.Buildpack)) + return nil + }, + }) + + return buildpacks, warnings, err +} + +func (client Client) UpdateBuildpack(buildpack resources.Buildpack) (resources.Buildpack, Warnings, error) { + var responseBody resources.Buildpack + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchBuildpackRequest, + URIParams: internal.Params{"buildpack_guid": buildpack.GUID}, + RequestBody: buildpack, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UploadBuildpack uploads the contents of a buildpack zip to the server. +func (client *Client) UploadBuildpack(buildpackGUID string, buildpackPath string, buildpack io.Reader, buildpackLength int64) (JobURL, Warnings, error) { + + contentLength, err := uploads.CalculateRequestSize(buildpackLength, buildpackPath, "bits") + if err != nil { + return "", nil, err + } + + contentType, body, writeErrors := uploads.CreateMultipartBodyAndHeader(buildpack, buildpackPath, "bits") + + responseLocation, warnings, err := client.MakeRequestUploadAsync( + internal.PostBuildpackBitsRequest, + internal.Params{"buildpack_guid": buildpackGUID}, + contentType, + body, + contentLength, + nil, + writeErrors, + ) + + return JobURL(responseLocation), warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/client.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/client.go new file mode 100644 index 0000000..5a998f3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/client.go @@ -0,0 +1,135 @@ +// Package ccv3 represents a Cloud Controller V3 client. +// +// These sets of packages are still under development/pre-pre-pre...alpha. Use +// at your own risk! Functionality and design may change without warning. +// +// It is currently designed to support Cloud Controller API 3.0.0. However, it +// may include features and endpoints of later API versions. +// +// For more information on the Cloud Controller API see +// https://apidocs.cloudfoundry.org/ +// +// Method Naming Conventions +// +// The client takes a '' +// approach to method names. If the and +// are similar, they do not need to be repeated. If a GUID is required for the +// , the pluralization is removed from said endpoint in the +// method name. +// +// Additionally, if the endpoint is an "action" endpoint, do not include the +// word "Action" in the method name. +// +// For Example: +// Method Name: GetApplication +// Endpoint: /v3/applications/:guid +// Action Name: Get +// Top Level Endpoint: applications +// Return Value: Application +// +// Method Name: GetServiceInstances +// Endpoint: /v3/service_instances +// Action Name: Get +// Top Level Endpoint: service_instances +// Return Value: []ServiceInstance +// +// Method Name: GetSpaceServiceInstances +// Endpoint: /v3/spaces/:guid/service_instances +// Action Name: Get +// Top Level Endpoint: spaces +// Return Value: []ServiceInstance +// +// Method Name: CreateApplicationTask +// Endpoint: /v3/apps/:application_guid/task +// Action Name: Post +// Top Level Endpoint: apps +// Return Value: Task +// +// Use the following table to determine which HTTP Command equates to which +// Action Name: +// HTTP Command -> Action Name +// POST -> Create OR Update* +// GET -> Get +// PUT -> Update +// DELETE -> Delete +// PATCH -> Update +// +// * - In some cases POSTs are updating resources, in these cases the method +// should be called Update, not Create. +// +// Method Locations +// +// Methods exist in the same file as their return type, regardless of which +// endpoint they use. +// +// Error Handling +// +// All error handling that requires parsing the error_code/code returned back +// from the Cloud Controller should be placed in the errorWrapper. Everything +// else can be handled in the individual operations. All parsed cloud +// controller errors should exist in errors.go, all generic HTTP errors should +// exist in the cloudcontroller's errors.go. Errors related to the individual +// operation should exist at the top of that operation's file. +package ccv3 + +import ( + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +// Warnings are a collection of warnings that the Cloud Controller can return +// back from an API request. +type Warnings []string + +// Client can be used to talk to a Cloud Controller's V3 Endpoints. +type Client struct { + Info + CloudControllerURL string + + Requester + + jobPollingInterval time.Duration + jobPollingTimeout time.Duration + + clock Clock +} + +// Config allows the Client to be configured +type Config struct { + // AppName is the name of the application/process using the client. + AppName string + + // AppVersion is the version of the application/process using the client. + AppVersion string + + // JobPollingTimeout is the maximum amount of time a job polls for. + JobPollingTimeout time.Duration + + // JobPollingInterval is the wait time between job polls. + JobPollingInterval time.Duration + + // Wrappers that apply to the client connection. + Wrappers []ConnectionWrapper +} + +// NewClient returns a new Client. +func NewClient(config Config) *Client { + return &Client{ + clock: new(internal.RealTime), + jobPollingInterval: config.JobPollingInterval, + jobPollingTimeout: config.JobPollingTimeout, + Requester: NewRequester(config), + } +} + +// TestClient returns a new client explicitly meant for internal testing. This +// should not be used for production code. +func TestClient(config Config, clock Clock, requester Requester) *Client { + return &Client{ + clock: clock, + jobPollingInterval: config.JobPollingInterval, + jobPollingTimeout: config.JobPollingTimeout, + Requester: requester, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/clock.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/clock.go new file mode 100644 index 0000000..b8f8c71 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/clock.go @@ -0,0 +1,9 @@ +package ccv3 + +import "time" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Clock + +type Clock interface { + Now() time.Time +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/connection_wrapper.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/connection_wrapper.go new file mode 100644 index 0000000..376891c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/connection_wrapper.go @@ -0,0 +1,17 @@ +package ccv3 + +import "code.cloudfoundry.org/cli/api/cloudcontroller" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ConnectionWrapper + +// ConnectionWrapper can wrap a given connection allowing the wrapper to modify +// all requests going in and out of the given connection. +type ConnectionWrapper interface { + cloudcontroller.Connection + Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection +} + +// WrapConnection wraps the current Client connection in the wrapper. +func (requester *RealRequester) WrapConnection(wrapper ConnectionWrapper) { + requester.connection = wrapper.Wrap(requester.connection) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/application.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/application.go new file mode 100644 index 0000000..b0acd64 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/application.go @@ -0,0 +1,35 @@ +package constant + +// AppLifecycleType informs the platform of how to build droplets and run apps. +type AppLifecycleType string + +const ( + // AppLifecycleTypeBuildpack will use a droplet and a rootfs to run the app. + AppLifecycleTypeBuildpack AppLifecycleType = "buildpack" + // AppLifecycleTypeDocker will pull a docker image from a registry to run an + // app. + AppLifecycleTypeDocker AppLifecycleType = "docker" +) + +// ApplicationAction represents the action being taken on an application +type ApplicationAction string + +const ( + // ApplicationStarting indicates that the app is being started + ApplicationStarting ApplicationAction = "Starting" + // ApplicationRestarting indicates that the app is being restarted + ApplicationRestarting ApplicationAction = "Restarting" + // ApplicationRollingBack indicates that the app is being rolled back to a + // prior revision + ApplicationRollingBack ApplicationAction = "Rolling Back" +) + +// ApplicationState represents the current desired state of the app. +type ApplicationState string + +const ( + // ApplicationStopped is a desired 'stopped' state. + ApplicationStopped ApplicationState = "STOPPED" + // ApplicationStarted is a desired 'started' state. + ApplicationStarted ApplicationState = "STARTED" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/build.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/build.go new file mode 100644 index 0000000..253defd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/build.go @@ -0,0 +1,13 @@ +package constant + +// BuildState represents the current state of the build. +type BuildState string + +const ( + // BuildFailed is when the build has failed/erred during staging. + BuildFailed BuildState = "FAILED" + // BuildStaged is when the build has successfully been staged. + BuildStaged BuildState = "STAGED" + // BuildStaging is when the build is in the process of being staged. + BuildStaging BuildState = "STAGING" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/buildpack.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/buildpack.go new file mode 100644 index 0000000..2353102 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/buildpack.go @@ -0,0 +1,17 @@ +package constant + +const ( + // AutodetectBuildpackValueDefault is used to unset the buildpack values on + // an application. + AutodetectBuildpackValueDefault = "default" + // AutodetectBuildpackValueNull is used to unset the buildpack values on an + // application. + AutodetectBuildpackValueNull = "null" +) + +const ( + // BuildpackAwaitingUpload represents the awaiting upload state of a buildpack. + BuildpackAwaitingUpload = "AWAITING_UPLOAD" + // BuildpackReady represents the ready state of a buildpack. + BuildpackReady = "READY" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment.go new file mode 100644 index 0000000..d324cb9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment.go @@ -0,0 +1,55 @@ +package constant + +// DeploymentState describes the states a zero down time deployment used to +// push new apps without restart can be in. +type DeploymentState string + +const ( + // DeploymentDeploying means the deployment is in state 'DEPLOYING' + DeploymentDeploying DeploymentState = "DEPLOYING" + + // DeploymentCanceled means the deployment is in state 'CANCELED' + DeploymentCanceled DeploymentState = "CANCELED" + + // DeploymentDeployed means the deployment is in state 'DEPLOYED' + DeploymentDeployed DeploymentState = "DEPLOYED" + + // DeploymentCanceled means the deployment is in state 'CANCELING' + DeploymentCanceling DeploymentState = "CANCELING" + + // DeploymentFailing means the deployment is in state 'FAILING' + DeploymentFailing DeploymentState = "FAILING" + + // DeploymentFailed means the deployment is in state 'FAILED' + DeploymentFailed DeploymentState = "FAILED" +) + +// DeploymentStatusReason describes the status reasons a deployment can have +type DeploymentStatusReason string + +const ( + // DeploymentStatusReasonDeployed means the deployment's status.value is + // 'DEPLOYED' + DeploymentStatusReasonDeployed DeploymentStatusReason = "DEPLOYED" + + // DeploymentStatusReasonCanceled means the deployment's status.value is + // 'CANCELED' + DeploymentStatusReasonCanceled DeploymentStatusReason = "CANCELED" + + // DeploymentStatusReasonSuperseded means the deployment's status.value is + // 'SUPERSEDED' + DeploymentStatusReasonSuperseded DeploymentStatusReason = "SUPERSEDED" +) + +// DeploymentStatusValue describes the status values a deployment can have +type DeploymentStatusValue string + +const ( + // DeploymentStatusValueActive means the deployment's status.value is + // 'ACTIVE' + DeploymentStatusValueActive DeploymentStatusValue = "ACTIVE" + + // DeploymentStatusValueFinalized means the deployment's status.value is + // 'FINALIZED' + DeploymentStatusValueFinalized DeploymentStatusValue = "FINALIZED" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment_strategy.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment_strategy.go new file mode 100644 index 0000000..2e607f6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/deployment_strategy.go @@ -0,0 +1,12 @@ +package constant + +// DeploymentStrategy is the strategy used to push an application. +type DeploymentStrategy string + +const ( + // Default means app will be stopped and started with new droplet. + DeploymentStrategyDefault DeploymentStrategy = "" + + // Rolling means a new web process will be created for the app and instances will roll from the old one to the new one. + DeploymentStrategyRolling DeploymentStrategy = "rolling" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/droplet.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/droplet.go new file mode 100644 index 0000000..579ce3d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/droplet.go @@ -0,0 +1,18 @@ +package constant + +// DropletState is the state of the droplet. +type DropletState string + +const ( + // DropletAwaitingUpload is a droplet that has been created without a package. + DropletAwaitingUpload DropletState = "AWAITING_UPLOAD" + // DropletStaged is a droplet that has been properly processed. + DropletStaged DropletState = "STAGED" + // DropletFailed is a droplet that had failed the staging process. + DropletFailed DropletState = "FAILED" + // DropletCopying is a droplet that's being copied from another droplet. + DropletCopying DropletState = "COPYING" + // DropletExpired is a droplet that has expired and is no longer in the + // system. + DropletExpired DropletState = "EXPIRED" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/environment_variable_group.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/environment_variable_group.go new file mode 100644 index 0000000..61adee6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/environment_variable_group.go @@ -0,0 +1,8 @@ +package constant + +type EnvironmentVariableGroupName string + +const ( + StagingEnvironmentVariableGroup EnvironmentVariableGroupName = "staging" + RunningEnvironmentVariableGroup EnvironmentVariableGroupName = "running" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/godoc.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/godoc.go new file mode 100644 index 0000000..f45e500 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/godoc.go @@ -0,0 +1,18 @@ +// Package constant contains types and constants used by the ccv3 package. +// +// Constant Naming Conventions: +// +// The standard naming for a constant is . The only +// exception is 'state' types, where the word 'state' is omitted. +// +// For Example: +// Constant Type: PackageType +// Enum Name: Bits +// Enum Value: "bits" +// const PackageTypeBits PackageType = "bits" +// +// Constant Type: PackageState +// Enum Name: Expired +// Enum Value: "EXPIRED" +// const PackageExpired PackageState = "EXPIRED" +package constant diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/health_check_type.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/health_check_type.go new file mode 100644 index 0000000..b95d667 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/health_check_type.go @@ -0,0 +1,13 @@ +package constant + +// HealthCheckType is the manner in which Cloud Foundry verifies the app's status. +type HealthCheckType string + +const ( + // HTTP means that CF will make a GET request to the configured HTTP endpoint on the app's default port. Useful if the app can provide an HTTP 200 response. + HTTP HealthCheckType = "http" + // Port means that CF will make a TCP connection to the port of ports configured. Useful if the app can receive TCP connections. + Port HealthCheckType = "port" + // Process means that Diego ensures that the process(es) stay running. Useful if the app cannot support TCP connections. + Process HealthCheckType = "process" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/included_users.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/included_users.go new file mode 100644 index 0000000..531a8b7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/included_users.go @@ -0,0 +1,9 @@ +package constant + +// IncludedType represents the additional resources queried from CloudController +// using the include parameter +type IncludedType string + +const ( + IncludedTypeUsers IncludedType = "users" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/job.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/job.go new file mode 100644 index 0000000..5cba85f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/job.go @@ -0,0 +1,26 @@ +package constant + +// JobState is the current state of a job. +type JobState string + +const ( + // JobComplete is when the job is no longer and it was successful. + JobComplete JobState = "COMPLETE" + // JobFailed is when the job is no longer running due to a failure. + JobFailed JobState = "FAILED" + // JobProcessing is when the job is waiting to be run. + JobProcessing JobState = "PROCESSING" + // JobPolling is when the job is waiting on an external resource to do the task + JobPolling JobState = "POLLING" +) + +// JobErrorCode is the numeric code for a particular error. +type JobErrorCode int64 + +const ( + JobErrorCodeBuildpackAlreadyExistsForStack JobErrorCode = 290000 + JobErrorCodeBuildpackInvalid JobErrorCode = 290003 + JobErrorCodeBuildpackStacksDontMatch JobErrorCode = 390011 + JobErrorCodeBuildpackStackDoesNotExist JobErrorCode = 390012 + JobErrorCodeBuildpackZipInvalid JobErrorCode = 390013 +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/origin.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/origin.go new file mode 100644 index 0000000..7afd1d8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/origin.go @@ -0,0 +1,5 @@ +package constant + +// DefaultOriginUaa is the default origin used for looking up users by username +// when no origin is given. +const DefaultOriginUaa = "uaa" diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/package.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/package.go new file mode 100644 index 0000000..3d9160b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/package.go @@ -0,0 +1,31 @@ +package constant + +// PackageState represents the state of a package. +type PackageState string + +const ( + // PackageProcessingUpload is a package that's being process by the CC. + PackageProcessingUpload PackageState = "PROCESSING_UPLOAD" + // PackageReady is a package that's ready to use. + PackageReady PackageState = "READY" + // PackageFailed is a package that has failed to be constructed. + PackageFailed PackageState = "FAILED" + // PackageAwaitingUpload is a package that does not have any bits or settings + // yet. + PackageAwaitingUpload PackageState = "AWAITING_UPLOAD" + // PackageCopying is a package that's being copied from another package. + PackageCopying PackageState = "COPYING" + // PackageExpired is a package that has expired and is no longer in the + // system. + PackageExpired PackageState = "EXPIRED" +) + +// PackageType represents the type of package. +type PackageType string + +const ( + // PackageTypeBits is used to upload source code for an app. + PackageTypeBits PackageType = "bits" + // PackageTypeDocker references a docker image from a registry. + PackageTypeDocker PackageType = "docker" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process.go new file mode 100644 index 0000000..833e349 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process.go @@ -0,0 +1,15 @@ +package constant + +// ProcessInstanceState is the state of a given process. +type ProcessInstanceState string + +const ( + // ProcessInstanceRunning is when the process is running normally. + ProcessInstanceRunning ProcessInstanceState = "RUNNING" + // ProcessInstanceCrashed is when the process has crashed. + ProcessInstanceCrashed ProcessInstanceState = "CRASHED" + // ProcessInstanceStarting is when the process is starting up. + ProcessInstanceStarting ProcessInstanceState = "STARTING" + // ProcessInstanceDown is when the process has gone down. + ProcessInstanceDown ProcessInstanceState = "DOWN" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_health_check_endpoint.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_health_check_endpoint.go new file mode 100644 index 0000000..c848290 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_health_check_endpoint.go @@ -0,0 +1,5 @@ +package constant + +// ProcessHealthCheckEndpointDefault is the default HTTP endpoint used for the +// HTTP health check in the runtime. +const ProcessHealthCheckEndpointDefault = "/" diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_type_web.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_type_web.go new file mode 100644 index 0000000..ca3e7a9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/process_type_web.go @@ -0,0 +1,4 @@ +package constant + +// ProcessTypeWeb represents the "web" process type. +const ProcessTypeWeb = "web" diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/relationships.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/relationships.go new file mode 100644 index 0000000..6a8b3c1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/relationships.go @@ -0,0 +1,24 @@ +package constant + +// RelationshipType represents the Cloud Controller To-One resource targeted by +// a relationship. +type RelationshipType string + +const ( + // RelationshipTypeApplication is a relationship with a Cloud Controller + // application. + RelationshipTypeApplication RelationshipType = "app" + + // RelationshipTypeSpace is a relationship with a Cloud Controller space. + RelationshipTypeSpace RelationshipType = "space" + + // RelationshipTypeOrganization is a relationship with a Cloud Controller + // organization. + RelationshipTypeOrganization RelationshipType = "organization" + + // RelationshipTypeUser is a relationship with a Cloud Controller user. + RelationshipTypeUser RelationshipType = "user" + + // RelationshipTypeQuota is a relationship with a Cloud Controller quota (org quota or space quota). + RelationshipTypeQuota RelationshipType = "quota" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/resource.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/resource.go new file mode 100644 index 0000000..717ba3c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/resource.go @@ -0,0 +1,4 @@ +package constant + +// MaxNumberOfResourcesForMatching is the maximum number of resources that can be sent to the /v3/resource_match endpoint. +const MaxNumberOfResourcesForMatching = 5000 diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/role_type.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/role_type.go new file mode 100644 index 0000000..70d3a59 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/role_type.go @@ -0,0 +1,15 @@ +package constant + +// RoleType is the type of a CCV3 role resource. +type RoleType string + +const ( + OrgUserRole RoleType = "organization_user" + OrgAuditorRole RoleType = "organization_auditor" + OrgManagerRole RoleType = "organization_manager" + OrgBillingManagerRole RoleType = "organization_billing_manager" + SpaceDeveloperRole RoleType = "space_developer" + SpaceAuditorRole RoleType = "space_auditor" + SpaceManagerRole RoleType = "space_manager" + SpaceSupporterRole RoleType = "space_supporter" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/security_group_lifecycle.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/security_group_lifecycle.go new file mode 100644 index 0000000..5f4cd24 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/security_group_lifecycle.go @@ -0,0 +1,13 @@ +package constant + +// SecurityGroupLifecycle represents the lifecycle phase of a security group +// binding. +type SecurityGroupLifecycle string + +const ( + // SecurityGroupLifecycleRunning indicates the lifecycle phase running. + SecurityGroupLifecycleRunning SecurityGroupLifecycle = "running" + + // SecurityGroupLifecycleStaging indicates the lifecycle phase staging. + SecurityGroupLifecycleStaging SecurityGroupLifecycle = "staging" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/task.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/task.go new file mode 100644 index 0000000..4c0f509 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant/task.go @@ -0,0 +1,17 @@ +package constant + +// TaskState represents the state of the task +type TaskState string + +const ( + // TaskPending is when the task is pending. + TaskPending TaskState = "PENDING" + // TaskRunning is when the task is running. + TaskRunning TaskState = "RUNNING" + // TaskSucceeded is when the task succeeded. + TaskSucceeded TaskState = "SUCCEEDED" + // TaskCanceling is when the task is canceling. + TaskCanceling TaskState = "CANCELING" + // TaskFailed is when the task Failed. + TaskFailed TaskState = "FAILED" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/deployment.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/deployment.go new file mode 100644 index 0000000..a4dc7da --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/deployment.go @@ -0,0 +1,78 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CancelDeployment(deploymentGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationDeploymentActionCancelRequest, + URIParams: internal.Params{"deployment_guid": deploymentGUID}, + }) + + return warnings, err +} + +func (client *Client) CreateApplicationDeployment(appGUID string, dropletGUID string) (string, Warnings, error) { + dep := resources.Deployment{ + DropletGUID: dropletGUID, + Relationships: resources.Relationships{constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}}, + } + + var responseBody resources.Deployment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationDeploymentRequest, + RequestBody: dep, + ResponseBody: &responseBody, + }) + + return responseBody.GUID, warnings, err +} + +func (client *Client) CreateApplicationDeploymentByRevision(appGUID string, revisionGUID string) (string, Warnings, error) { + dep := resources.Deployment{ + RevisionGUID: revisionGUID, + Relationships: resources.Relationships{constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}}, + } + + var responseBody resources.Deployment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationDeploymentRequest, + RequestBody: dep, + ResponseBody: &responseBody, + }) + + return responseBody.GUID, warnings, err +} + +func (client *Client) GetDeployment(deploymentGUID string) (resources.Deployment, Warnings, error) { + var responseBody resources.Deployment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetDeploymentRequest, + URIParams: internal.Params{"deployment_guid": deploymentGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetDeployments(query ...Query) ([]resources.Deployment, Warnings, error) { + var deployments []resources.Deployment + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetDeploymentsRequest, + Query: query, + ResponseBody: resources.Deployment{}, + AppendToList: func(item interface{}) error { + deployments = append(deployments, item.(resources.Deployment)) + return nil + }, + }) + + return deployments, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/domain.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/domain.go new file mode 100644 index 0000000..6b0aae2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/domain.go @@ -0,0 +1,175 @@ +package ccv3 + +import ( + "encoding/json" + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +type SharedOrgs struct { + GUIDs []string +} + +func (sharedOrgs SharedOrgs) MarshalJSON() ([]byte, error) { + type Org struct { + GUID string `json:"guid,omitempty"` + } + + type Data = []Org + + type sharedOrgsRelationship struct { + Data Data `json:"data"` + } + + var orgs []Org + for _, sharedOrgGUID := range sharedOrgs.GUIDs { + orgs = append(orgs, Org{GUID: sharedOrgGUID}) + } + + relationship := sharedOrgsRelationship{ + Data: orgs, + } + + return json.Marshal(relationship) +} + +func (sharedOrgs *SharedOrgs) UnmarshalJSON(data []byte) error { + var alias struct { + Data []struct { + GUID string `json:"guid,omitempty"` + } `json:"data,omitempty"` + } + + err := cloudcontroller.DecodeJSON(data, &alias) + if err != nil { + return err + } + + var guids []string + for _, org := range alias.Data { + guids = append(guids, org.GUID) + } + + sharedOrgs.GUIDs = guids + return nil +} + +// CheckRoute checks whether the route with the given domain GUID, hostname, +// and path exists in the foundation. +func (client Client) CheckRoute(domainGUID string, hostname string, path string, port int) (bool, Warnings, error) { + var query []Query + + if hostname != "" { + query = append(query, Query{Key: HostFilter, Values: []string{hostname}}) + } + + if path != "" { + query = append(query, Query{Key: PathFilter, Values: []string{path}}) + } + + if port != 0 { + query = append(query, Query{Key: PortFilter, Values: []string{fmt.Sprintf("%d", port)}}) + } + + var responseBody struct { + MatchingRoute bool `json:"matching_route"` + } + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetDomainRouteReservationsRequest, + URIParams: internal.Params{"domain_guid": domainGUID}, + Query: query, + ResponseBody: &responseBody, + }) + + return responseBody.MatchingRoute, warnings, err +} + +func (client Client) CreateDomain(domain resources.Domain) (resources.Domain, Warnings, error) { + var responseBody resources.Domain + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostDomainRequest, + RequestBody: domain, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) DeleteDomain(domainGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteDomainRequest, + URIParams: internal.Params{"domain_guid": domainGUID}, + }) + + return jobURL, warnings, err +} + +// GetDomain returns a domain with the given GUID. +func (client *Client) GetDomain(domainGUID string) (resources.Domain, Warnings, error) { + var responseBody resources.Domain + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetDomainRequest, + URIParams: internal.Params{"domain_guid": domainGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) GetDomains(query ...Query) ([]resources.Domain, Warnings, error) { + var domains []resources.Domain + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetDomainsRequest, + Query: query, + ResponseBody: resources.Domain{}, + AppendToList: func(item interface{}) error { + domains = append(domains, item.(resources.Domain)) + return nil + }, + }) + + return domains, warnings, err +} + +func (client Client) GetOrganizationDomains(orgGUID string, query ...Query) ([]resources.Domain, Warnings, error) { + var domains []resources.Domain + + _, warnings, err := client.MakeListRequest(RequestParams{ + URIParams: internal.Params{"organization_guid": orgGUID}, + RequestName: internal.GetOrganizationDomainsRequest, + Query: query, + ResponseBody: resources.Domain{}, + AppendToList: func(item interface{}) error { + domains = append(domains, item.(resources.Domain)) + return nil + }, + }) + + return domains, warnings, err +} + +func (client Client) SharePrivateDomainToOrgs(domainGuid string, sharedOrgs SharedOrgs) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.SharePrivateDomainRequest, + URIParams: internal.Params{"domain_guid": domainGuid}, + RequestBody: sharedOrgs, + }) + + return warnings, err +} + +func (client Client) UnsharePrivateDomainFromOrg(domainGuid string, orgGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSharedOrgFromDomainRequest, + URIParams: internal.Params{"domain_guid": domainGuid, "org_guid": orgGUID}, + }) + + return warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/droplet.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/droplet.go new file mode 100644 index 0000000..7d9bfe5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/droplet.go @@ -0,0 +1,128 @@ +package ccv3 + +import ( + "io" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/api/cloudcontroller/uploads" + "code.cloudfoundry.org/cli/resources" +) + +type DropletCreateRequest struct { + Relationships resources.Relationships `json:"relationships"` +} + +// CreateDroplet creates a new droplet without a package for the app with +// the given guid. +func (client *Client) CreateDroplet(appGUID string) (resources.Droplet, Warnings, error) { + requestBody := DropletCreateRequest{ + Relationships: resources.Relationships{ + constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}, + }, + } + + var responseBody resources.Droplet + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostDropletRequest, + RequestBody: requestBody, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetApplicationDropletCurrent returns the current droplet for a given +// application. +func (client *Client) GetApplicationDropletCurrent(appGUID string) (resources.Droplet, Warnings, error) { + var responseBody resources.Droplet + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetApplicationDropletCurrentRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetDroplet returns a droplet with the given GUID. +func (client *Client) GetDroplet(dropletGUID string) (resources.Droplet, Warnings, error) { + var responseBody resources.Droplet + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetDropletRequest, + URIParams: internal.Params{"droplet_guid": dropletGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetDroplets lists droplets with optional filters. +func (client *Client) GetDroplets(query ...Query) ([]resources.Droplet, Warnings, error) { + var droplets []resources.Droplet + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetDropletsRequest, + Query: query, + ResponseBody: resources.Droplet{}, + AppendToList: func(item interface{}) error { + droplets = append(droplets, item.(resources.Droplet)) + return nil + }, + }) + + return droplets, warnings, err +} + +// GetPackageDroplets returns the droplets that run the specified packages +func (client *Client) GetPackageDroplets(packageGUID string, query ...Query) ([]resources.Droplet, Warnings, error) { + var droplets []resources.Droplet + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetPackageDropletsRequest, + URIParams: internal.Params{"package_guid": packageGUID}, + Query: query, + ResponseBody: resources.Droplet{}, + AppendToList: func(item interface{}) error { + droplets = append(droplets, item.(resources.Droplet)) + return nil + }, + }) + + return droplets, warnings, err +} + +// UploadDropletBits asynchronously uploads bits from a .tgz file located at dropletPath to the +// droplet with guid dropletGUID. It returns a job URL pointing to the asynchronous upload job. +func (client *Client) UploadDropletBits(dropletGUID string, dropletPath string, droplet io.Reader, dropletLength int64) (JobURL, Warnings, error) { + contentLength, err := uploads.CalculateRequestSize(dropletLength, dropletPath, "bits") + if err != nil { + return "", nil, err + } + + contentType, body, writeErrors := uploads.CreateMultipartBodyAndHeader(droplet, dropletPath, "bits") + + responseLocation, warnings, err := client.MakeRequestUploadAsync( + internal.PostDropletBitsRequest, + internal.Params{"droplet_guid": dropletGUID}, + contentType, + body, + contentLength, + nil, + writeErrors, + ) + + return JobURL(responseLocation), warnings, err +} + +func (client *Client) DownloadDroplet(dropletGUID string) ([]byte, Warnings, error) { + bytes, warnings, err := client.MakeRequestReceiveRaw( + internal.GetDropletBitsRequest, + internal.Params{"droplet_guid": dropletGUID}, + "application/json", + ) + return bytes, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment.go new file mode 100644 index 0000000..45af18d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment.go @@ -0,0 +1,39 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +// Environment variables that will be provided to an app at runtime. It will +// include environment variables for Environment Variable Groups and Service +// Bindings. +type Environment struct { + // Application contains basic application settings set by the user and CF + // instance. + Application map[string]interface{} `json:"application_env_json"` + // EnvironmentVariables are user provided environment variables. + EnvironmentVariables map[string]interface{} `json:"environment_variables"` + //Running is the set of default environment variables available to running + //apps. + Running map[string]interface{} `json:"running_env_json"` + //Staging is the set of default environment variables available during + //staging. + Staging map[string]interface{} `json:"staging_env_json"` + // System contains information about bound services for the application. AKA + // VCAP_SERVICES. + System map[string]interface{} `json:"system_env_json"` +} + +// GetApplicationEnvironment fetches all the environment variables on +// an application by groups. +func (client *Client) GetApplicationEnvironment(appGUID string) (Environment, Warnings, error) { + var responseBody Environment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetApplicationEnvRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment_variables.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment_variables.go new file mode 100644 index 0000000..22c50d8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/environment_variables.go @@ -0,0 +1,52 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// EnvironmentVariables represents the environment variables that can be set on +// an application by the user. + +// GetEnvironmentVariableGroup gets the values of a particular environment variable group. +func (client *Client) GetEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName) (resources.EnvironmentVariables, Warnings, error) { + var responseBody resources.EnvironmentVariables + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetEnvironmentVariableGroupRequest, + URIParams: internal.Params{"group_name": string(group)}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateApplicationEnvironmentVariables adds/updates the user provided +// environment variables on an application. A restart is required for changes +// to take effect. +func (client *Client) UpdateApplicationEnvironmentVariables(appGUID string, envVars resources.EnvironmentVariables) (resources.EnvironmentVariables, Warnings, error) { + var responseBody resources.EnvironmentVariables + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchApplicationEnvironmentVariablesRequest, + URIParams: internal.Params{"app_guid": appGUID}, + RequestBody: envVars, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) UpdateEnvironmentVariableGroup(group constant.EnvironmentVariableGroupName, envVars resources.EnvironmentVariables) (resources.EnvironmentVariables, Warnings, error) { + var responseBody resources.EnvironmentVariables + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchEnvironmentVariableGroupRequest, + URIParams: internal.Params{"group_name": string(group)}, + RequestBody: envVars, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/errors.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/errors.go new file mode 100644 index 0000000..c89a60d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/errors.go @@ -0,0 +1,222 @@ +package ccv3 + +import ( + "encoding/json" + "net/http" + "regexp" + "strings" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" +) + +const ( + taskWorkersUnavailable = "CF-TaskWorkersUnavailable" + operationInProgress = "CF-AsyncServiceInstanceOperationInProgress" +) + +// errorWrapper is the wrapper that converts responses with 4xx and 5xx status +// codes to an error. +type errorWrapper struct { + connection cloudcontroller.Connection +} + +func newErrorWrapper() *errorWrapper { + return new(errorWrapper) +} + +// Make creates a connection in the wrapped connection and handles errors +// that it returns. +func (e *errorWrapper) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + err := e.connection.Make(request, passedResponse) + + if rawHTTPStatusErr, ok := err.(ccerror.RawHTTPStatusError); ok { + if rawHTTPStatusErr.StatusCode >= http.StatusInternalServerError { + return convert500(rawHTTPStatusErr) + } + return convert400(rawHTTPStatusErr, request) + } + return err +} + +// Wrap wraps a Cloud Controller connection in this error handling wrapper. +func (e *errorWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + e.connection = innerconnection + return e +} + +func convert400(rawHTTPStatusErr ccerror.RawHTTPStatusError, request *cloudcontroller.Request) error { + firstErr, errorResponse, err := unmarshalFirstV3Error(rawHTTPStatusErr) + if err != nil { + return err + } + + if len(errorResponse.Errors) > 1 { + return ccerror.MultiError{Errors: errorResponse.Errors, ResponseCode: rawHTTPStatusErr.StatusCode} + } + + switch rawHTTPStatusErr.StatusCode { + case http.StatusBadRequest: // 400 + return handleBadRequest(firstErr, request) + case http.StatusUnauthorized: // 401 + if firstErr.Title == "CF-InvalidAuthToken" { + return ccerror.InvalidAuthTokenError{Message: firstErr.Detail} + } + return ccerror.UnauthorizedError{Message: firstErr.Detail} + case http.StatusForbidden: // 403 + return ccerror.ForbiddenError{Message: firstErr.Detail} + case http.StatusNotFound: // 404 + return handleNotFound(firstErr, request) + case http.StatusUnprocessableEntity: // 422 + return handleUnprocessableEntity(firstErr) + case http.StatusServiceUnavailable: // 503 + if firstErr.Title == taskWorkersUnavailable { + return ccerror.TaskWorkersUnavailableError{Message: firstErr.Detail} + } + return ccerror.ServiceUnavailableError{Message: firstErr.Detail} + case http.StatusConflict: + if firstErr.Title == operationInProgress { + return ccerror.ServiceInstanceOperationInProgressError{Message: firstErr.Detail} + } + } + + return ccerror.V3UnexpectedResponseError{ + ResponseCode: rawHTTPStatusErr.StatusCode, + RequestIDs: rawHTTPStatusErr.RequestIDs, + V3ErrorResponse: errorResponse, + } +} + +func convert500(rawHTTPStatusErr ccerror.RawHTTPStatusError) error { + switch rawHTTPStatusErr.StatusCode { + case http.StatusServiceUnavailable: // 503 + firstErr, _, err := unmarshalFirstV3Error(rawHTTPStatusErr) + if err != nil { + return err + } + if firstErr.Title == taskWorkersUnavailable { + return ccerror.TaskWorkersUnavailableError{Message: firstErr.Detail} + } + return ccerror.ServiceUnavailableError{Message: firstErr.Detail} + default: + return ccerror.V3UnexpectedResponseError{ + ResponseCode: rawHTTPStatusErr.StatusCode, + RequestIDs: rawHTTPStatusErr.RequestIDs, + V3ErrorResponse: ccerror.V3ErrorResponse{ + Errors: []ccerror.V3Error{{ + Detail: string(rawHTTPStatusErr.RawResponse), + }}, + }, + } + } +} + +func handleBadRequest(errorResponse ccerror.V3Error, _ *cloudcontroller.Request) error { + switch errorResponse.Detail { + case "Bad request: Cannot stage package whose state is not ready.": + return ccerror.InvalidStateError{} + case "This service does not support fetching service instance parameters.": + return ccerror.ServiceInstanceParametersFetchNotSupportedError{Message: errorResponse.Detail} + default: + return ccerror.BadRequestError{Message: errorResponse.Detail} + } +} + +func handleNotFound(errorResponse ccerror.V3Error, request *cloudcontroller.Request) error { + switch errorResponse.Detail { + case "App not found": + return ccerror.ApplicationNotFoundError{} + case "Droplet not found": + return ccerror.DropletNotFoundError{} + case "Deployment not found": + return ccerror.DeploymentNotFoundError{} + case "Feature flag not found": + return ccerror.FeatureFlagNotFoundError{} + case "Instance not found": + return ccerror.InstanceNotFoundError{} + case "Process not found": + return ccerror.ProcessNotFoundError{} + case "User not found": + return ccerror.UserNotFoundError{} + case "Unknown request": + return ccerror.APINotFoundError{URL: request.URL.String()} + default: + return ccerror.ResourceNotFoundError{Message: errorResponse.Detail} + } +} + +func handleUnprocessableEntity(errorResponse ccerror.V3Error) error { + //idea to make route already exist error flexible for all relevant error cases + errorString := errorResponse.Detail + err := ccerror.UnprocessableEntityError{Message: errorResponse.Detail} + appNameTakenRegexp := regexp.MustCompile(`App with the name '.*' already exists\.`) + orgNameTakenRegexp := regexp.MustCompile(`Organization '.*' already exists\.`) + roleExistsRegexp := regexp.MustCompile(`User '.*' already has '.*' role.*`) + quotaExistsRegexp := regexp.MustCompile(`.* Quota '.*' already exists\.`) + securityGroupExistsRegexp := regexp.MustCompile(`Security group with name '.*' already exists\.`) + + // boolean switch case with partial/regex string matchers + switch { + case appNameTakenRegexp.MatchString(errorString) || strings.Contains(errorString, "name must be unique in space"): + return ccerror.NameNotUniqueInSpaceError{UnprocessableEntityError: err} + case strings.Contains(errorString, + "Name must be unique per organization"): + return ccerror.NameNotUniqueInOrgError{} + case strings.Contains(errorString, + "Route already exists"): + return ccerror.RouteNotUniqueError{UnprocessableEntityError: err} + case strings.Contains(errorString, + "Buildpack must be an existing admin buildpack or a valid git URI"): + return ccerror.InvalidBuildpackError{} + case strings.Contains(errorString, + "Assign a droplet before starting this app."): + return ccerror.InvalidStartError{} + case strings.Contains(errorString, + "The service instance name is taken"): + return ccerror.ServiceInstanceNameTakenError{Message: err.Message} + case orgNameTakenRegexp.MatchString(errorString): + return ccerror.OrganizationNameTakenError{UnprocessableEntityError: err} + case roleExistsRegexp.MatchString(errorString): + return ccerror.RoleAlreadyExistsError{UnprocessableEntityError: err} + case quotaExistsRegexp.MatchString(errorString): + return ccerror.QuotaAlreadyExists{Message: err.Message} + case securityGroupExistsRegexp.MatchString(errorString): + return ccerror.SecurityGroupAlreadyExists{Message: err.Message} + case strings.Contains(errorString, + "Ensure the space is bound to this security group."): + return ccerror.SecurityGroupNotBound{Message: err.Message} + case errorResponse.Title == "CF-ServiceInstanceAlreadyBoundToSameRoute": + return ccerror.ResourceAlreadyExistsError{Message: err.Message} + case strings.Contains(errorString, + "The app is already bound to the service instance"): + return ccerror.ResourceAlreadyExistsError{Message: err.Message} + case strings.Contains(errorString, + "Key binding names must be unique"): + return ccerror.ServiceKeyTakenError{Message: err.Message} + default: + return err + } +} + +func unmarshalFirstV3Error(rawHTTPStatusErr ccerror.RawHTTPStatusError) (ccerror.V3Error, ccerror.V3ErrorResponse, error) { + // Try to unmarshal the raw error into a CC error. If unmarshaling fails, + // return the raw error. + var errorResponse ccerror.V3ErrorResponse + err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) + if err != nil { + return ccerror.V3Error{}, errorResponse, ccerror.UnknownHTTPSourceError{ + StatusCode: rawHTTPStatusErr.StatusCode, + RawResponse: rawHTTPStatusErr.RawResponse, + } + } + + errors := errorResponse.Errors + if len(errors) == 0 { + return ccerror.V3Error{}, errorResponse, ccerror.V3UnexpectedResponseError{ + ResponseCode: rawHTTPStatusErr.StatusCode, + V3ErrorResponse: errorResponse, + } + } + + return errors[0], errorResponse, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/event.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/event.go new file mode 100644 index 0000000..bedc56f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/event.go @@ -0,0 +1,58 @@ +package ccv3 + +import ( + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +type Event struct { + GUID string + CreatedAt time.Time + Type string + ActorName string + Data map[string]interface{} +} + +func (e *Event) UnmarshalJSON(data []byte) error { + var ccEvent struct { + GUID string `json:"guid"` + CreatedAt time.Time `json:"created_at"` + Type string `json:"type"` + Actor struct { + Name string `json:"name"` + } `json:"actor"` + Data map[string]interface{} `json:"data"` + } + err := cloudcontroller.DecodeJSON(data, &ccEvent) + if err != nil { + return err + } + + e.GUID = ccEvent.GUID + e.CreatedAt = ccEvent.CreatedAt + e.Type = ccEvent.Type + e.ActorName = ccEvent.Actor.Name + e.Data = ccEvent.Data + + return nil +} + +// GetEvents uses the /v3/audit_events endpoint to retrieve a list of audit events. +// NOTE: This only returns the first page of results. We are intentionally not using the paginate helper to fetch all +// pages here because we only needed the first page for the `cf events` output. If we need to, we can refactor this +// later to fetch all pages and make `cf events` only filter down to the first page. +func (client *Client) GetEvents(query ...Query) ([]Event, Warnings, error) { + var responseBody struct { + Resources []Event `json:"resources"` + } + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetEventsRequest, + ResponseBody: &responseBody, + Query: query, + }) + + return responseBody.Resources, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/feature_flag.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/feature_flag.go new file mode 100644 index 0000000..80f775a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/feature_flag.go @@ -0,0 +1,47 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) GetFeatureFlag(flagName string) (resources.FeatureFlag, Warnings, error) { + var responseBody resources.FeatureFlag + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetFeatureFlagRequest, + URIParams: internal.Params{"name": flagName}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetFeatureFlags lists feature flags. +func (client *Client) GetFeatureFlags() ([]resources.FeatureFlag, Warnings, error) { + var featureFlags []resources.FeatureFlag + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetFeatureFlagsRequest, + ResponseBody: resources.FeatureFlag{}, + AppendToList: func(item interface{}) error { + featureFlags = append(featureFlags, item.(resources.FeatureFlag)) + return nil + }, + }) + + return featureFlags, warnings, err +} + +func (client *Client) UpdateFeatureFlag(flag resources.FeatureFlag) (resources.FeatureFlag, Warnings, error) { + var responseBody resources.FeatureFlag + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchFeatureFlagRequest, + URIParams: internal.Params{"name": flag.Name}, + RequestBody: flag, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/included_resources.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/included_resources.go new file mode 100644 index 0000000..0044707 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/included_resources.go @@ -0,0 +1,14 @@ +package ccv3 + +import "code.cloudfoundry.org/cli/resources" + +type IncludedResources struct { + Users []resources.User `json:"users,omitempty"` + Organizations []resources.Organization `json:"organizations,omitempty"` + Spaces []resources.Space `json:"spaces,omitempty"` + ServiceInstances []resources.ServiceInstance `json:"service_instances,omitempty"` + ServiceOfferings []resources.ServiceOffering `json:"service_offerings,omitempty"` + ServiceBrokers []resources.ServiceBroker `json:"service_brokers,omitempty"` + ServicePlans []resources.ServicePlan `json:"service_plans,omitempty"` + Apps []resources.Application `json:"apps,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/info.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/info.go new file mode 100644 index 0000000..8a2e694 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/info.go @@ -0,0 +1,148 @@ +package ccv3 + +import ( + "net/http" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/resources" +) + +type InfoLinks struct { + // AppSSH is the link for application ssh info. + AppSSH resources.APILink `json:"app_ssh"` + + // CCV3 is the link to the Cloud Controller V3 API. + CCV3 resources.APILink `json:"cloud_controller_v3"` + + // Logging is the link to the Logging API. + Logging resources.APILink `json:"logging"` + + // Logging is the link to the Logging API. + LogCache resources.APILink `json:"log_cache"` + + // NetworkPolicyV1 is the link to the Container to Container Networking + // API. + NetworkPolicyV1 resources.APILink `json:"network_policy_v1"` + + // Routing is the link to the routing API + Routing resources.APILink `json:"routing"` + + // UAA is the link to the UAA API. + UAA resources.APILink `json:"uaa"` + + // Login is the link to the Login API. + Login resources.APILink `json:"login"` +} + +// Info represents a GET response from the '/' endpoint of the cloud +// controller API. +type Info struct { + // Links is a list of top level Cloud Controller APIs. + Links InfoLinks `json:"links"` + CFOnK8s bool `json:"cf_on_k8s"` +} + +// AppSSHEndpoint returns the HREF for SSHing into an app container. +func (info Info) AppSSHEndpoint() string { + return info.Links.AppSSH.HREF +} + +// AppSSHHostKeyFingerprint returns the SSH key fingerprint of the SSH proxy +// that brokers connections to application instances. +func (info Info) AppSSHHostKeyFingerprint() string { + return info.Links.AppSSH.Meta.HostKeyFingerprint +} + +// CloudControllerAPIVersion returns the version of the CloudController. +func (info Info) CloudControllerAPIVersion() string { + return info.Links.CCV3.Meta.Version +} + +// LogCache returns the HREF of the Loggregator Traffic Controller. +func (info Info) LogCache() string { + return info.Links.LogCache.HREF +} + +// Logging returns the HREF of the Loggregator Traffic Controller. +func (info Info) Logging() string { + return info.Links.Logging.HREF +} + +// NetworkPolicyV1 returns the HREF of the Container Networking v1 Policy API +func (info Info) NetworkPolicyV1() string { + return info.Links.NetworkPolicyV1.HREF +} + +// OAuthClient returns the oauth client ID of the SSH proxy that brokers +// connections to application instances. +func (info Info) OAuthClient() string { + return info.Links.AppSSH.Meta.OAuthClient +} + +// Routing returns the HREF of the routing API. +func (info Info) Routing() string { + return info.Links.Routing.HREF +} + +// UAA returns the HREF of the UAA server. +func (info Info) UAA() string { + return info.Links.UAA.HREF +} + +// Login returns the HREF of the login server. +func (info Info) Login() string { + return info.Links.Login.HREF +} + +// ccv3Link returns the HREF of the CloudController v3 API. +func (info Info) ccV3Link() string { + return info.Links.CCV3.HREF +} + +// ResourceLinks represents the information returned back from /v3. +type ResourceLinks map[string]resources.APILink + +// UnmarshalJSON helps unmarshal a Cloud Controller /v3 response. +func (links ResourceLinks) UnmarshalJSON(data []byte) error { + var ccResourceLinks struct { + Links map[string]resources.APILink `json:"links"` + } + err := cloudcontroller.DecodeJSON(data, &ccResourceLinks) + if err != nil { + return err + } + + for key, val := range ccResourceLinks.Links { + links[key] = val + } + + return nil +} + +// GetInfo returns endpoint and API information from /v3. +func (client *Client) GetInfo() (Info, Warnings, error) { + rootResponse, warnings, err := client.RootResponse() + if err != nil { + return Info{}, warnings, err + } + + return rootResponse, warnings, err +} + +// rootResponse returns the CC API root document. +func (client *Client) RootResponse() (Info, Warnings, error) { + var responseBody Info + + _, warnings, err := client.MakeRequest(RequestParams{ + URL: client.CloudControllerURL, + ResponseBody: &responseBody, + }) + + unknownSourceErr, ok := err.(ccerror.UnknownHTTPSourceError) + if ok && unknownSourceErr.StatusCode == http.StatusNotFound { + return Info{}, nil, ccerror.APINotFoundError{URL: client.CloudControllerURL} + } + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/api_routes.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/api_routes.go new file mode 100644 index 0000000..8f22393 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/api_routes.go @@ -0,0 +1,346 @@ +package internal + +import "net/http" + +// Naming convention: +// +// HTTP method + non-parameter parts of the path + "Request" +// +// If the request returns a single entity by GUID, use the singular (for example +// /v3/organizations/:organization_guid is GetOrganization). +const ( + DeleteApplicationProcessInstanceRequest = "DeleteApplicationProcessInstance" + DeleteApplicationRequest = "DeleteApplication" + DeleteBuildpackRequest = "DeleteBuildpack" + DeleteDomainRequest = "DeleteDomainRequest" + DeleteIsolationSegmentRelationshipOrganizationRequest = "DeleteIsolationSegmentRelationshipOrganization" + DeleteIsolationSegmentRequest = "DeleteIsolationSegment" + DeleteOrganizationRequest = "DeleteOrganization" + DeleteOrganizationQuotaRequest = "DeleteOrganizationQuota" + DeleteOrphanedRoutesRequest = "DeleteOrphanedRoutes" + DeleteRoleRequest = "DeleteRoleRequest" + DeleteRouteRequest = "DeleteRouteRequest" + DeleteRouteBindingRequest = "DeleteRouteBinding" + DeleteSecurityGroupRequest = "DeleteSecurityGroup" + DeleteSecurityGroupStagingSpaceRequest = "DeleteSecurityGroupStagingSpace" + DeleteSecurityGroupRunningSpaceRequest = "DeleteSecurityGroupRunningSpace" + DeleteServiceCredentialBindingRequest = "DeleteServiceCredentialBinding" + DeleteServiceBrokerRequest = "DeleteServiceBrokerRequest" + DeleteServiceInstanceRelationshipsSharedSpaceRequest = "DeleteServiceInstanceRelationshipsSharedSpace" + DeleteServiceInstanceRequest = "DeleteServiceInstance" + DeleteServiceOfferingRequest = "DeleteServiceOffering" + DeleteServicePlanVisibilityRequest = "DeleteServicePlanVisibility" + DeleteSharedOrgFromDomainRequest = "DeleteSharedOrgFromDomain" + DeleteSpaceQuotaRequest = "DeleteSpaceQuota" + DeleteSpaceRequest = "DeleteSpace" + DeleteSpaceQuotaFromSpaceRequest = "DeleteSpaceQuotaFromSpace" + DeleteUserRequest = "DeleteUser" + GetApplicationDropletCurrentRequest = "GetApplicationDropletCurrent" + GetApplicationEnvRequest = "GetApplicationEnv" + GetApplicationFeaturesRequest = "GetApplicationFeatures" + GetApplicationManifestRequest = "GetApplicationManifest" + GetApplicationProcessRequest = "GetApplicationProcess" + GetApplicationProcessesRequest = "GetApplicationProcesses" + GetApplicationRevisionsRequest = "GetApplicationRevisions" + GetApplicationRevisionsDeployedRequest = "GetApplicationRevisionsDeployed" + GetApplicationRoutesRequest = "GetApplicationRoutes" + GetApplicationTasksRequest = "GetApplicationTasks" + GetApplicationsRequest = "GetApplications" + GetBuildRequest = "GetBuild" + GetBuildpacksRequest = "GetBuildpacks" + GetDefaultDomainRequest = "GetDefaultDomain" + GetDeploymentRequest = "GetDeployment" + GetDeploymentsRequest = "GetDeployments" + GetDomainRequest = "GetDomain" + GetDomainRouteReservationsRequest = "GetDomainRouteReservations" + GetDomainsRequest = "GetDomains" + GetDropletRequest = "GetDroplet" + GetDropletsRequest = "GetDroplets" + GetDropletBitsRequest = "GetDropletBits" + GetEnvironmentVariableGroupRequest = "GetEnvironmentVariableGroup" + GetEventsRequest = "GetEvents" + GetFeatureFlagRequest = "GetFeatureFlag" + GetFeatureFlagsRequest = "GetFeatureFlags" + GetIsolationSegmentOrganizationsRequest = "GetIsolationSegmentOrganizations" + GetIsolationSegmentRequest = "GetIsolationSegment" + GetIsolationSegmentsRequest = "GetIsolationSegments" + GetOrganizationDomainsRequest = "GetOrganizationDomains" + GetOrganizationQuotasRequest = "GetOrganizationQuotas" + GetOrganizationQuotaRequest = "GetOrganizationQuota" + GetOrganizationRelationshipDefaultIsolationSegmentRequest = "GetOrganizationRelationshipDefaultIsolationSegment" + GetOrganizationRequest = "GetOrganization" + GetOrganizationsRequest = "GetOrganizations" + GetPackageRequest = "GetPackage" + GetPackagesRequest = "GetPackages" + GetPackageDropletsRequest = "GetPackageDroplets" + GetProcessRequest = "GetProcess" + GetProcessesRequest = "GetProcesses" + GetProcessStatsRequest = "GetProcessStats" + GetProcessSidecarsRequest = "GetProcessSidecars" + GetRolesRequest = "GetRoles" + GetRouteBindingsRequest = "GetRouteBindings" + GetRouteDestinationsRequest = "GetRouteDestinations" + GetRoutesRequest = "GetRoutes" + GetSecurityGroupsRequest = "GetSecurityGroups" + GetServiceBrokersRequest = "GetServiceBrokers" + GetServiceCredentialBindingsRequest = "GetServiceCredentialBindings" + GetServiceCredentialBindingDetailsRequest = "GetServiceCredentialBindingDetails" + GetServiceInstanceParametersRequest = "GetServiceInstanceParameters" + GetServiceInstancesRequest = "GetServiceInstances" + GetServiceInstanceRelationshipsSharedSpacesRequest = "GetServiceInstanceRelationshipSharedSpacesRequest" + GetServiceInstanceSharedSpacesUsageSummaryRequest = "GetServiceInstanceSharedSpacesUsageSummaryRequest" + GetServiceOfferingRequest = "GetServiceOffering" + GetServiceOfferingsRequest = "GetServiceOfferings" + GetServicePlanRequest = "GetServicePlan" + GetServicePlansRequest = "GetServicePlans" + GetServicePlanVisibilityRequest = "GetServicePlanVisibility" + GetSpaceFeatureRequest = "GetSpaceFeatureRequest" + GetSpaceRelationshipIsolationSegmentRequest = "GetSpaceRelationshipIsolationSegment" + GetSpaceRunningSecurityGroupsRequest = "GetSpaceRunningSecurityGroups" + GetSpacesRequest = "GetSpaces" + GetSpaceQuotaRequest = "GetSpaceQuota" + GetSpaceQuotasRequest = "GetSpaceQuotas" + GetSpaceStagingSecurityGroupsRequest = "GetSpaceStagingSecurityGroups" + GetSSHEnabled = "GetSSHEnabled" + GetStacksRequest = "GetStacks" + GetUserRequest = "GetUser" + GetUsersRequest = "GetUsers" + MapRouteRequest = "MapRoute" + PatchApplicationCurrentDropletRequest = "PatchApplicationCurrentDroplet" + PatchApplicationEnvironmentVariablesRequest = "PatchApplicationEnvironmentVariables" + PatchApplicationRequest = "PatchApplication" + PatchApplicationFeaturesRequest = "PatchApplicationFeatures" + PatchEnvironmentVariableGroupRequest = "PatchEnvironmentVariableGroup" + PatchBuildpackRequest = "PatchBuildpack" + PatchDestinationRequest = "PatchDestination" + PatchDomainRequest = "PatchDomain" + PatchFeatureFlagRequest = "PatchFeatureFlag" + PatchOrganizationRelationshipDefaultIsolationSegmentRequest = "PatchOrganizationRelationshipDefaultIsolationSegment" + PatchOrganizationRequest = "PatchOrganization" + PatchOrganizationQuotaRequest = "PatchOrganizationQuota" + PatchProcessRequest = "PatchProcess" + PatchRouteRequest = "PatchRoute" + PatchSecurityGroupRequest = "PatchSecurityGroup" + PatchServiceBrokerRequest = "PatchServiceBrokerRequest" + PatchServiceInstanceRequest = "PatchServiceInstance" + PatchServiceOfferingRequest = "PatchServiceOfferingRequest" + PatchServicePlanRequest = "PatchServicePlanRequest" + PatchSpaceRelationshipIsolationSegmentRequest = "PatchSpaceRelationshipIsolationSegment" + PatchSpaceRequest = "PatchSpace" + PatchSpaceFeaturesRequest = "PatchSpaceFeatures" + PatchSpaceQuotaRequest = "PatchSpaceQuota" + PatchStackRequest = "PatchStack" + PostApplicationActionApplyManifest = "PostApplicationActionApplyM" + PostApplicationActionRestartRequest = "PostApplicationActionRestart" + PostApplicationActionStartRequest = "PostApplicationActionStart" + PostApplicationActionStopRequest = "PostApplicationActionStop" + PostApplicationDeploymentActionCancelRequest = "PostApplicationDeploymentActionCancel" + PostApplicationDeploymentRequest = "PostApplicationDeployment" + PostApplicationProcessActionScaleRequest = "PostApplicationProcessActionScale" + PostApplicationRequest = "PostApplication" + PostApplicationTasksRequest = "PostApplicationTasks" + PostBuildRequest = "PostBuild" + PostBuildpackBitsRequest = "PostBuildpackBits" + PostBuildpackRequest = "PostBuildpack" + PostDomainRequest = "PostDomain" + PostDropletBitsRequest = "PostDropletBits" + PostDropletRequest = "PostDroplet" + PostIsolationSegmentRelationshipOrganizationsRequest = "PostIsolationSegmentRelationshipOrganizations" + PostIsolationSegmentsRequest = "PostIsolationSegments" + PostOrganizationRequest = "PostOrganization" + PostOrganizationQuotaRequest = "PostOrganizationQuota" + PostOrganizationQuotaApplyRequest = "PostOrganizationQuotaApply" + PostPackageRequest = "PostPackage" + PostPackageBitsRequest = "PostPackageBits" + PostResourceMatchesRequest = "PostResourceMatches" + PostRoleRequest = "PostRole" + PostRouteRequest = "PostRoute" + PostRouteBindingRequest = "PostRouteBinding" + PostSecurityGroupRequest = "PostSecurityGroup" + PostSecurityGroupStagingSpaceRequest = "PostSecurityGroupStagingSpace" + PostSecurityGroupRunningSpaceRequest = "PostSecurityGroupRunningSpace" + PostServiceCredentialBindingRequest = "PostServiceCredentialBinding" + PostServiceBrokerRequest = "PostServiceBroker" + PostServiceInstanceRequest = "PostServiceInstance" + PostServiceInstanceRelationshipsSharedSpacesRequest = "PostServiceInstanceRelationshipsSharedSpaces" + PostServicePlanVisibilityRequest = "PostServicePlanVisibility" + PostSpaceActionApplyManifestRequest = "PostSpaceActionApplyManifest" + PostSpaceDiffManifestRequest = "PostSpaceDiffManifest" + PostSpaceRequest = "PostSpace" + PostSpaceQuotaRequest = "PostSpaceQuota" + PostSpaceQuotaRelationshipsRequest = "PostSpaceQuotaRelationships" + PostUserRequest = "PostUser" + PutTaskCancelRequest = "PutTaskCancel" + SharePrivateDomainRequest = "SharePrivateDomainRequest" + UnmapRouteRequest = "UnmapRoute" + WhoAmI = "WhoAmI" +) + +// APIRoutes is a list of routes used by the router to construct request URLs. +var APIRoutes = map[string]Route{ + GetApplicationsRequest: {Path: "/v3/apps", Method: http.MethodGet}, + PostApplicationRequest: {Path: "/v3/apps", Method: http.MethodPost}, + DeleteApplicationRequest: {Path: "/v3/apps/:app_guid", Method: http.MethodDelete}, + PatchApplicationRequest: {Path: "/v3/apps/:app_guid", Method: http.MethodPatch}, + PatchApplicationFeaturesRequest: {Path: "/v3/apps/:app_guid/features/:name", Method: http.MethodPatch}, + GetApplicationFeaturesRequest: {Path: "/v3/apps/:app_guid/features/:name", Method: http.MethodGet}, + PostApplicationActionApplyManifest: {Path: "/v3/apps/:app_guid/actions/apply_manifest", Method: http.MethodPost}, + PostApplicationActionRestartRequest: {Path: "/v3/apps/:app_guid/actions/restart", Method: http.MethodPost}, + PostApplicationActionStartRequest: {Path: "/v3/apps/:app_guid/actions/start", Method: http.MethodPost}, + PostApplicationActionStopRequest: {Path: "/v3/apps/:app_guid/actions/stop", Method: http.MethodPost}, + GetApplicationDropletCurrentRequest: {Path: "/v3/apps/:app_guid/droplets/current", Method: http.MethodGet}, + GetApplicationEnvRequest: {Path: "/v3/apps/:app_guid/env", Method: http.MethodGet}, + PatchApplicationEnvironmentVariablesRequest: {Path: "/v3/apps/:app_guid/environment_variables", Method: http.MethodPatch}, + GetApplicationManifestRequest: {Path: "/v3/apps/:app_guid/manifest", Method: http.MethodGet}, + GetApplicationProcessesRequest: {Path: "/v3/apps/:app_guid/processes", Method: http.MethodGet}, + GetApplicationProcessRequest: {Path: "/v3/apps/:app_guid/processes/:type", Method: http.MethodGet}, + PostApplicationProcessActionScaleRequest: {Path: "/v3/apps/:app_guid/processes/:type/actions/scale", Method: http.MethodPost}, + DeleteApplicationProcessInstanceRequest: {Path: "/v3/apps/:app_guid/processes/:type/instances/:index", Method: http.MethodDelete}, + PatchApplicationCurrentDropletRequest: {Path: "/v3/apps/:app_guid/relationships/current_droplet", Method: http.MethodPatch}, + GetApplicationRevisionsRequest: {Path: "/v3/apps/:app_guid/revisions", Method: http.MethodGet}, + GetApplicationRevisionsDeployedRequest: {Path: "/v3/apps/:app_guid/revisions/deployed", Method: http.MethodGet}, + GetApplicationRoutesRequest: {Path: "/v3/apps/:app_guid/routes", Method: http.MethodGet}, + GetSSHEnabled: {Path: "/v3/apps/:app_guid/ssh_enabled", Method: http.MethodGet}, + GetApplicationTasksRequest: {Path: "/v3/apps/:app_guid/tasks", Method: http.MethodGet}, + PostApplicationTasksRequest: {Path: "/v3/apps/:app_guid/tasks", Method: http.MethodPost}, + GetBuildpacksRequest: {Path: "/v3/buildpacks", Method: http.MethodGet}, + PostBuildpackRequest: {Path: "/v3/buildpacks/", Method: http.MethodPost}, + DeleteBuildpackRequest: {Path: "/v3/buildpacks/:buildpack_guid", Method: http.MethodDelete}, + PatchBuildpackRequest: {Path: "/v3/buildpacks/:buildpack_guid", Method: http.MethodPatch}, + PostBuildpackBitsRequest: {Path: "/v3/buildpacks/:buildpack_guid/upload", Method: http.MethodPost}, + PostBuildRequest: {Path: "/v3/builds", Method: http.MethodPost}, + GetBuildRequest: {Path: "/v3/builds/:build_guid", Method: http.MethodGet}, + GetDeploymentsRequest: {Path: "/v3/deployments", Method: http.MethodGet}, + PostApplicationDeploymentRequest: {Path: "/v3/deployments", Method: http.MethodPost}, + GetDeploymentRequest: {Path: "/v3/deployments/:deployment_guid", Method: http.MethodGet}, + PostApplicationDeploymentActionCancelRequest: {Path: "/v3/deployments/:deployment_guid/actions/cancel", Method: http.MethodPost}, + GetDomainsRequest: {Path: "/v3/domains", Method: http.MethodGet}, + PostDomainRequest: {Path: "/v3/domains", Method: http.MethodPost}, + DeleteDomainRequest: {Path: "/v3/domains/:domain_guid", Method: http.MethodDelete}, + GetDomainRequest: {Path: "/v3/domains/:domain_guid", Method: http.MethodGet}, + PatchDomainRequest: {Path: "/v3/domains/:domain_guid", Method: http.MethodPatch}, + SharePrivateDomainRequest: {Path: "/v3/domains/:domain_guid/relationships/shared_organizations", Method: http.MethodPost}, + DeleteSharedOrgFromDomainRequest: {Path: "/v3/domains/:domain_guid/relationships/shared_organizations/:org_guid", Method: http.MethodDelete}, + GetDomainRouteReservationsRequest: {Path: "/v3/domains/:domain_guid/route_reservations", Method: http.MethodGet}, + GetDropletsRequest: {Path: "/v3/droplets", Method: http.MethodGet}, + PostDropletRequest: {Path: "/v3/droplets", Method: http.MethodPost}, + GetDropletRequest: {Path: "/v3/droplets/:droplet_guid", Method: http.MethodGet}, + PostDropletBitsRequest: {Path: "/v3/droplets/:droplet_guid/upload", Method: http.MethodPost}, + GetDropletBitsRequest: {Path: "/v3/droplets/:droplet_guid/download", Method: http.MethodGet}, + GetEnvironmentVariableGroupRequest: {Path: "/v3/environment_variable_groups/:group_name", Method: http.MethodGet}, + PatchEnvironmentVariableGroupRequest: {Path: "/v3/environment_variable_groups/:group_name", Method: http.MethodPatch}, + GetEventsRequest: {Path: "/v3/audit_events", Method: http.MethodGet}, + GetFeatureFlagsRequest: {Path: "/v3/feature_flags", Method: http.MethodGet}, + GetFeatureFlagRequest: {Path: "/v3/feature_flags/:name", Method: http.MethodGet}, + PatchFeatureFlagRequest: {Path: "/v3/feature_flags/:name", Method: http.MethodPatch}, + GetIsolationSegmentsRequest: {Path: "/v3/isolation_segments", Method: http.MethodGet}, + PostIsolationSegmentsRequest: {Path: "/v3/isolation_segments", Method: http.MethodPost}, + DeleteIsolationSegmentRequest: {Path: "/v3/isolation_segments/:isolation_segment_guid", Method: http.MethodDelete}, + GetIsolationSegmentRequest: {Path: "/v3/isolation_segments/:isolation_segment_guid", Method: http.MethodGet}, + GetIsolationSegmentOrganizationsRequest: {Path: "/v3/isolation_segments/:isolation_segment_guid/organizations", Method: http.MethodGet}, + PostIsolationSegmentRelationshipOrganizationsRequest: {Path: "/v3/isolation_segments/:isolation_segment_guid/relationships/organizations", Method: http.MethodPost}, + DeleteIsolationSegmentRelationshipOrganizationRequest: {Path: "/v3/isolation_segments/:isolation_segment_guid/relationships/organizations/:organization_guid", Method: http.MethodDelete}, + GetOrganizationsRequest: {Path: "/v3/organizations", Method: http.MethodGet}, + PostOrganizationRequest: {Path: "/v3/organizations", Method: http.MethodPost}, + GetOrganizationRequest: {Path: "/v3/organizations/:organization_guid", Method: http.MethodGet}, + DeleteOrganizationRequest: {Path: "/v3/organizations/:organization_guid/", Method: http.MethodDelete}, + PatchOrganizationRequest: {Path: "/v3/organizations/:organization_guid/", Method: http.MethodPatch}, + GetOrganizationDomainsRequest: {Path: "/v3/organizations/:organization_guid/domains", Method: http.MethodGet}, + GetDefaultDomainRequest: {Path: "/v3/organizations/:organization_guid/domains/default", Method: http.MethodGet}, + GetOrganizationRelationshipDefaultIsolationSegmentRequest: {Path: "/v3/organizations/:organization_guid/relationships/default_isolation_segment", Method: http.MethodGet}, + PatchOrganizationRelationshipDefaultIsolationSegmentRequest: {Path: "/v3/organizations/:organization_guid/relationships/default_isolation_segment", Method: http.MethodPatch}, + PatchOrganizationQuotaRequest: {Path: "/v3/organization_quotas/:quota_guid", Method: http.MethodPatch}, + PostOrganizationQuotaRequest: {Path: "/v3/organization_quotas", Method: http.MethodPost}, + PostOrganizationQuotaApplyRequest: {Path: "/v3/organization_quotas/:quota_guid/relationships/organizations", Method: http.MethodPost}, + GetOrganizationQuotaRequest: {Path: "/v3/organization_quotas/:quota_guid", Method: http.MethodGet}, + GetOrganizationQuotasRequest: {Path: "/v3/organization_quotas", Method: http.MethodGet}, + DeleteOrganizationQuotaRequest: {Path: "/v3/organization_quotas/:quota_guid", Method: http.MethodDelete}, + GetPackagesRequest: {Path: "/v3/packages", Method: http.MethodGet}, + PostPackageRequest: {Path: "/v3/packages", Method: http.MethodPost}, + GetPackageRequest: {Path: "/v3/packages/:package_guid", Method: http.MethodGet}, + PostPackageBitsRequest: {Path: "/v3/packages/:package_guid/upload", Method: http.MethodPost}, + GetPackageDropletsRequest: {Path: "/v3/packages/:package_guid/droplets", Method: http.MethodGet}, + GetProcessRequest: {Path: "/v3/processes/:process_guid", Method: http.MethodGet}, + GetProcessesRequest: {Path: "/v3/processes", Method: http.MethodGet}, + PatchProcessRequest: {Path: "/v3/processes/:process_guid", Method: http.MethodPatch}, + GetProcessStatsRequest: {Path: "/v3/processes/:process_guid/stats", Method: http.MethodGet}, + GetProcessSidecarsRequest: {Path: "/v3/processes/:process_guid/sidecars", Method: http.MethodGet}, + PostResourceMatchesRequest: {Path: "/v3/resource_matches", Method: http.MethodPost}, + GetRolesRequest: {Path: "/v3/roles", Method: http.MethodGet}, + PostRoleRequest: {Path: "/v3/roles", Method: http.MethodPost}, + DeleteRoleRequest: {Path: "/v3/roles/:role_guid", Method: http.MethodDelete}, + GetRoutesRequest: {Path: "/v3/routes", Method: http.MethodGet}, + PostRouteRequest: {Path: "/v3/routes", Method: http.MethodPost}, + DeleteRouteRequest: {Path: "/v3/routes/:route_guid", Method: http.MethodDelete}, + PatchRouteRequest: {Path: "/v3/routes/:route_guid", Method: http.MethodPatch}, + GetRouteDestinationsRequest: {Path: "/v3/routes/:route_guid/destinations", Method: http.MethodGet}, + MapRouteRequest: {Path: "/v3/routes/:route_guid/destinations", Method: http.MethodPost}, + UnmapRouteRequest: {Path: "/v3/routes/:route_guid/destinations/:destination_guid", Method: http.MethodDelete}, + PatchDestinationRequest: {Path: "/v3/routes/:route_guid/destinations/:destination_guid", Method: http.MethodPatch}, + GetSecurityGroupsRequest: {Path: "/v3/security_groups", Method: http.MethodGet}, + PostSecurityGroupRequest: {Path: "/v3/security_groups", Method: http.MethodPost}, + DeleteSecurityGroupRequest: {Path: "/v3/security_groups/:security_group_guid", Method: http.MethodDelete}, + PostSecurityGroupStagingSpaceRequest: {Path: "/v3/security_groups/:security_group_guid/relationships/staging_spaces", Method: http.MethodPost}, + PostSecurityGroupRunningSpaceRequest: {Path: "/v3/security_groups/:security_group_guid/relationships/running_spaces", Method: http.MethodPost}, + DeleteSecurityGroupStagingSpaceRequest: {Path: "/v3/security_groups/:security_group_guid/relationships/staging_spaces/:space_guid", Method: http.MethodDelete}, + DeleteSecurityGroupRunningSpaceRequest: {Path: "/v3/security_groups/:security_group_guid/relationships/running_spaces/:space_guid", Method: http.MethodDelete}, + PatchSecurityGroupRequest: {Path: "/v3/security_groups/:security_group_guid", Method: http.MethodPatch}, + GetServiceBrokersRequest: {Path: "/v3/service_brokers", Method: http.MethodGet}, + PostServiceBrokerRequest: {Path: "/v3/service_brokers", Method: http.MethodPost}, + DeleteServiceBrokerRequest: {Path: "/v3/service_brokers/:service_broker_guid", Method: http.MethodDelete}, + PatchServiceBrokerRequest: {Path: "/v3/service_brokers/:service_broker_guid", Method: http.MethodPatch}, + PostServiceCredentialBindingRequest: {Path: "/v3/service_credential_bindings", Method: http.MethodPost}, + GetServiceCredentialBindingsRequest: {Path: "/v3/service_credential_bindings", Method: http.MethodGet}, + DeleteServiceCredentialBindingRequest: {Path: "/v3/service_credential_bindings/:service_credential_binding_guid", Method: http.MethodDelete}, + GetServiceCredentialBindingDetailsRequest: {Path: "/v3/service_credential_bindings/:service_credential_binding_guid/details", Method: http.MethodGet}, + GetServiceInstancesRequest: {Path: "/v3/service_instances", Method: http.MethodGet}, + PostServiceInstanceRequest: {Path: "/v3/service_instances", Method: http.MethodPost}, + GetServiceInstanceParametersRequest: {Path: "/v3/service_instances/:service_instance_guid/parameters", Method: http.MethodGet}, + PatchServiceInstanceRequest: {Path: "/v3/service_instances/:service_instance_guid", Method: http.MethodPatch}, + DeleteServiceInstanceRequest: {Path: "/v3/service_instances/:service_instance_guid", Method: http.MethodDelete}, + GetServiceInstanceSharedSpacesUsageSummaryRequest: {Path: "/v3/service_instances/:service_instance_guid/relationships/shared_spaces/usage_summary", Method: http.MethodGet}, + GetServiceInstanceRelationshipsSharedSpacesRequest: {Path: "/v3/service_instances/:service_instance_guid/relationships/shared_spaces", Method: http.MethodGet}, + PostServiceInstanceRelationshipsSharedSpacesRequest: {Path: "/v3/service_instances/:service_instance_guid/relationships/shared_spaces", Method: http.MethodPost}, + DeleteServiceInstanceRelationshipsSharedSpaceRequest: {Path: "/v3/service_instances/:service_instance_guid/relationships/shared_spaces/:space_guid", Method: http.MethodDelete}, + GetServiceOfferingRequest: {Path: "/v3/service_offerings/:service_offering_guid", Method: http.MethodGet}, + GetServiceOfferingsRequest: {Path: "/v3/service_offerings", Method: http.MethodGet}, + PatchServiceOfferingRequest: {Path: "/v3/service_offerings/:service_offering_guid", Method: http.MethodPatch}, + DeleteServiceOfferingRequest: {Path: "/v3/service_offerings/:service_offering_guid", Method: http.MethodDelete}, + GetServicePlanRequest: {Path: "/v3/service_plans/:service_plan_guid", Method: http.MethodGet}, + GetServicePlansRequest: {Path: "/v3/service_plans", Method: http.MethodGet}, + PatchServicePlanRequest: {Path: "/v3/service_plans/:service_plan_guid", Method: http.MethodPatch}, + GetServicePlanVisibilityRequest: {Path: "/v3/service_plans/:service_plan_guid/visibility", Method: http.MethodGet}, + PostServicePlanVisibilityRequest: {Path: "/v3/service_plans/:service_plan_guid/visibility", Method: http.MethodPost}, + DeleteServicePlanVisibilityRequest: {Path: "/v3/service_plans/:service_plan_guid/visibility/:organization_guid", Method: http.MethodDelete}, + PostRouteBindingRequest: {Path: "/v3/service_route_bindings", Method: http.MethodPost}, + GetRouteBindingsRequest: {Path: "/v3/service_route_bindings", Method: http.MethodGet}, + DeleteRouteBindingRequest: {Path: "/v3/service_route_bindings/:route_binding_guid", Method: http.MethodDelete}, + GetSpacesRequest: {Path: "/v3/spaces", Method: http.MethodGet}, + PostSpaceRequest: {Path: "/v3/spaces", Method: http.MethodPost}, + DeleteSpaceRequest: {Path: "/v3/spaces/:space_guid", Method: http.MethodDelete}, + PatchSpaceRequest: {Path: "/v3/spaces/:space_guid", Method: http.MethodPatch}, + PostSpaceActionApplyManifestRequest: {Path: "/v3/spaces/:space_guid/actions/apply_manifest", Method: http.MethodPost}, + PostSpaceDiffManifestRequest: {Path: "/v3/spaces/:space_guid/manifest_diff", Method: http.MethodPost}, + GetSpaceRelationshipIsolationSegmentRequest: {Path: "/v3/spaces/:space_guid/relationships/isolation_segment", Method: http.MethodGet}, + PatchSpaceRelationshipIsolationSegmentRequest: {Path: "/v3/spaces/:space_guid/relationships/isolation_segment", Method: http.MethodPatch}, + DeleteOrphanedRoutesRequest: {Path: "/v3/spaces/:space_guid/routes", Method: http.MethodDelete}, + GetSpaceRunningSecurityGroupsRequest: {Path: "/v3/spaces/:space_guid/running_security_groups", Method: http.MethodGet}, + GetSpaceStagingSecurityGroupsRequest: {Path: "/v3/spaces/:space_guid/staging_security_groups", Method: http.MethodGet}, + PatchSpaceFeaturesRequest: {Path: "/v3/spaces/:space_guid/features/:feature", Method: http.MethodPatch}, + GetSpaceFeatureRequest: {Path: "/v3/spaces/:space_guid/features/:feature", Method: http.MethodGet}, + PostSpaceQuotaRequest: {Path: "/v3/space_quotas", Method: http.MethodPost}, + GetSpaceQuotaRequest: {Path: "/v3/space_quotas/:quota_guid", Method: http.MethodGet}, + DeleteSpaceQuotaRequest: {Path: "/v3/space_quotas/:quota_guid", Method: http.MethodDelete}, + PostSpaceQuotaRelationshipsRequest: {Path: "/v3/space_quotas/:quota_guid/relationships/spaces", Method: http.MethodPost}, + GetSpaceQuotasRequest: {Path: "/v3/space_quotas", Method: http.MethodGet}, + PatchSpaceQuotaRequest: {Path: "/v3/space_quotas/:quota_guid", Method: http.MethodPatch}, + DeleteSpaceQuotaFromSpaceRequest: {Path: "/v3/space_quotas/:quota_guid/relationships/spaces/:space_guid", Method: http.MethodDelete}, + GetStacksRequest: {Path: "/v3/stacks", Method: http.MethodGet}, + PatchStackRequest: {Path: "/v3/stacks/:stack_guid", Method: http.MethodPatch}, + PutTaskCancelRequest: {Path: "/v3/tasks/:task_guid/cancel", Method: http.MethodPut}, + GetUsersRequest: {Path: "/v3/users", Method: http.MethodGet}, + GetUserRequest: {Path: "/v3/users/:user_guid", Method: http.MethodGet}, + PostUserRequest: {Path: "/v3/users", Method: http.MethodPost}, + DeleteUserRequest: {Path: "/v3/users/:user_guid", Method: http.MethodDelete}, + WhoAmI: {Path: "/whoami", Method: http.MethodGet}, +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/real_time.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/real_time.go new file mode 100644 index 0000000..e759d1f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/real_time.go @@ -0,0 +1,9 @@ +package internal + +import "time" + +type RealTime struct{} + +func (RealTime) Now() time.Time { + return time.Now() +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/routing.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/routing.go new file mode 100644 index 0000000..4b818cf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal/routing.go @@ -0,0 +1,132 @@ +package internal + +import ( + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" +) + +// Params map path keys to values. For example, if your route has the path +// pattern: +// /person/:person_id/pets/:pet_type +// Then a correct Params map would lool like: +// router.Params{ +// "person_id": "123", +// "pet_type": "cats", +// } +type Params map[string]string + +// Route defines the property of a Cloud Controller V3 endpoint. +// +// Method can be one of the following: +// GET HEAD POST PUT PATCH DELETE CONNECT OPTIONS TRACE +// +// Path conforms to Pat-style pattern matching. The following docs are taken +// from http://godoc.org/github.com/bmizerany/pat#PatternServeMux +// +// Path Patterns may contain literals or captures. Capture names start with a +// colon and consist of letters A-Z, a-z, _, and 0-9. The rest of the pattern +// matches literally. The portion of the URL matching each name ends with an +// occurrence of the character in the pattern immediately following the name, +// or a /, whichever comes first. It is possible for a name to match the empty +// string. +// +// Example pattern with one capture: +// /hello/:name +// Will match: +// /hello/blake +// /hello/keith +// Will not match: +// /hello/blake/ +// /hello/blake/foo +// /foo +// /foo/bar +// +// Example 2: +// /hello/:name/ +// Will match: +// /hello/blake/ +// /hello/keith/foo +// /hello/blake +// /hello/keith +// Will not match: +// /foo +// /foo/bar +type Route struct { + // Method is any valid HTTP method + Method string + // Path contains a path pattern + Path string +} + +// CreatePath combines the route's path pattern with a Params map +// to produce a valid path. +func (r Route) CreatePath(params Params) (string, error) { + components := strings.Split(r.Path, "/") + for i, c := range components { + if len(c) == 0 { + continue + } + if c[0] == ':' { + val, ok := params[c[1:]] + if !ok { + return "", fmt.Errorf("missing param %s", c) + } + components[i] = val + } + } + + u, err := url.Parse(strings.Join(components, "/")) + if err != nil { + return "", err + } + return u.String(), nil +} + +// Router combines route and resource information in order to generate HTTP +// requests. +type Router struct { + routes map[string]Route + baseURL string +} + +// NewRouter returns a pointer to a new Router. +func NewRouter(routes map[string]Route, baseURL string) *Router { + return &Router{ + routes: routes, + baseURL: baseURL, + } +} + +// CreateRequest returns a request key'd off of the name given. The params are +// merged into the URL and body is set as the request body. +func (router Router) CreateRequest(name string, params Params, body io.Reader) (*http.Request, error) { + route, ok := router.routes[name] + if !ok { + return &http.Request{}, fmt.Errorf("no route exists with the name %s", name) + } + + uri, err := route.CreatePath(params) + if err != nil { + return &http.Request{}, err + } + + url, err := router.urlFrom(router.baseURL, uri) + if err != nil { + return &http.Request{}, err + } + + return http.NewRequest(route.Method, url, body) +} + +func (Router) urlFrom(resource string, uri string) (string, error) { + u, err := url.Parse(resource) + if err != nil { + return "", err + } + u.Path = path.Join(u.Path, uri) + return u.String(), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/isolation_segment.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/isolation_segment.go new file mode 100644 index 0000000..16dbd4e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/isolation_segment.go @@ -0,0 +1,64 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateIsolationSegment will create an Isolation Segment on the Cloud +// Controller. Note: This will not validate that the placement tag exists in +// the diego cluster. +func (client *Client) CreateIsolationSegment(isolationSegment resources.IsolationSegment) (resources.IsolationSegment, Warnings, error) { + var responseBody resources.IsolationSegment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostIsolationSegmentsRequest, + RequestBody: isolationSegment, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// DeleteIsolationSegment removes an isolation segment from the cloud +// controller. Note: This will only remove it from the cloud controller +// database. It will not remove it from diego. +func (client *Client) DeleteIsolationSegment(guid string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteIsolationSegmentRequest, + URIParams: internal.Params{"isolation_segment_guid": guid}, + }) + + return warnings, err +} + +// GetIsolationSegment returns back the requested isolation segment that +// matches the GUID. +func (client *Client) GetIsolationSegment(guid string) (resources.IsolationSegment, Warnings, error) { + var responseBody resources.IsolationSegment + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetIsolationSegmentRequest, + URIParams: internal.Params{"isolation_segment_guid": guid}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetIsolationSegments lists isolation segments with optional filters. +func (client *Client) GetIsolationSegments(query ...Query) ([]resources.IsolationSegment, Warnings, error) { + var isolationSegments []resources.IsolationSegment + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetIsolationSegmentsRequest, + Query: query, + ResponseBody: resources.IsolationSegment{}, + AppendToList: func(item interface{}) error { + isolationSegments = append(isolationSegments, item.(resources.IsolationSegment)) + return nil + }, + }) + + return isolationSegments, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job.go new file mode 100644 index 0000000..a0704a8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job.go @@ -0,0 +1,199 @@ +package ccv3 + +import ( + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Job represents a Cloud Controller Job. +type Job struct { + // RawErrors is a list of errors that occurred while processing the job. + RawErrors []JobErrorDetails `json:"errors"` + // GUID is a unique identifier for the job. + GUID string `json:"guid"` + // State is the state of the job. + State constant.JobState `json:"state"` + // Warnings are the warnings emitted by the job during its processing. + Warnings []jobWarning `json:"warnings"` +} + +// Errors returns back a list of +func (job Job) Errors() []error { + var errs []error + for _, errDetails := range job.RawErrors { + switch errDetails.Code { + case constant.JobErrorCodeBuildpackAlreadyExistsForStack: + errs = append(errs, ccerror.BuildpackAlreadyExistsForStackError{Message: errDetails.Detail}) + case constant.JobErrorCodeBuildpackInvalid: + errs = append(errs, ccerror.BuildpackInvalidError{Message: errDetails.Detail}) + case constant.JobErrorCodeBuildpackStacksDontMatch: + errs = append(errs, ccerror.BuildpackStacksDontMatchError{Message: errDetails.Detail}) + case constant.JobErrorCodeBuildpackStackDoesNotExist: + errs = append(errs, ccerror.BuildpackStackDoesNotExistError{Message: errDetails.Detail}) + case constant.JobErrorCodeBuildpackZipInvalid: + errs = append(errs, ccerror.BuildpackZipInvalidError{Message: errDetails.Detail}) + default: + errs = append(errs, ccerror.V3JobFailedError{ + JobGUID: job.GUID, + Code: errDetails.Code, + Detail: errDetails.Detail, + Title: errDetails.Title, + }) + } + } + return errs +} + +// HasFailed returns true when the job has completed with an error/failure. +func (job Job) HasFailed() bool { + return job.State == constant.JobFailed +} + +// IsComplete returns true when the job has completed successfully. +func (job Job) IsComplete() bool { + return job.State == constant.JobComplete +} + +// IsAt returns true when the job has reached the desired state. +func (job Job) IsAt(state constant.JobState) bool { + return job.State == state +} + +type jobWarning struct { + Detail string `json:"detail"` +} + +// JobErrorDetails provides information regarding a job's error. +type JobErrorDetails struct { + // Code is a numeric code for this error. + Code constant.JobErrorCode `json:"code"` + // Detail is a verbose description of the error. + Detail string `json:"detail"` + // Title is a short description of the error. + Title string `json:"title"` +} + +// GetJob returns a job for the provided GUID. +func (client *Client) GetJob(jobURL JobURL) (Job, Warnings, error) { + var responseBody Job + + _, warnings, err := client.MakeRequest(RequestParams{ + URL: string(jobURL), + ResponseBody: &responseBody, + }) + + for _, jobWarning := range responseBody.Warnings { + warnings = append(warnings, jobWarning.Detail) + } + + return responseBody, warnings, err +} + +// PollJob will keep polling the given job until the job has terminated, an +// error is encountered, or config.OverallPollingTimeout is reached. In the +// last case, a JobTimeoutError is returned. +func (client *Client) PollJob(jobURL JobURL) (Warnings, error) { + return client.PollJobForState(jobURL, constant.JobComplete) +} + +func (client *Client) PollJobForState(jobURL JobURL, state constant.JobState) (Warnings, error) { + if jobURL == "" { + return nil, nil + } + + var ( + err error + warnings Warnings + allWarnings Warnings + job Job + ) + + startTime := client.clock.Now() + for client.clock.Now().Sub(startTime) < client.jobPollingTimeout { + job, warnings, err = client.GetJob(jobURL) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + if job.HasFailed() { + if len(job.Errors()) > 0 { + firstError := job.Errors()[0] + return allWarnings, firstError + } else { + return allWarnings, ccerror.JobFailedNoErrorError{ + JobGUID: job.GUID, + } + } + } + + if job.IsComplete() { + return allWarnings, nil + } + + if job.IsAt(state) { + return allWarnings, nil + } + + time.Sleep(client.jobPollingInterval) + } + + return allWarnings, ccerror.JobTimeoutError{ + JobGUID: job.GUID, + Timeout: client.jobPollingTimeout, + } +} + +type PollJobEvent struct { + State constant.JobState + Err error + Warnings Warnings +} + +func (client *Client) PollJobToEventStream(jobURL JobURL) chan PollJobEvent { + stream := make(chan PollJobEvent) + + if jobURL == "" { + close(stream) + return stream + } + + go func() { + var end bool + + startTime := client.clock.Now() + for !end { + job, warnings, err := client.GetJob(jobURL) + event := PollJobEvent{ + State: job.State, + Err: err, + Warnings: warnings, + } + + switch { + case event.Err != nil: + end = true + case job.IsComplete(): + end = true + case job.HasFailed(): + event.Err = job.Errors()[0] + end = true + case client.clock.Now().Sub(startTime) > client.jobPollingTimeout: + event.Err = ccerror.JobTimeoutError{ + JobGUID: job.GUID, + Timeout: client.jobPollingTimeout, + } + end = true + } + + stream <- event + time.Sleep(client.jobPollingInterval) + } + + close(stream) + }() + + return stream +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job_url.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job_url.go new file mode 100644 index 0000000..f49a965 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/job_url.go @@ -0,0 +1,55 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +// JobURL is the URL to a given Job. +type JobURL string + +// DeleteApplication deletes the app with the given app GUID. Returns back a +// resulting job URL to poll. +func (client *Client) DeleteApplication(appGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteApplicationRequest, + URIParams: internal.Params{"app_guid": appGUID}, + }) + + return jobURL, warnings, err +} + +// UpdateApplicationApplyManifest applies the manifest to the given +// application. Returns back a resulting job URL to poll. +func (client *Client) UpdateApplicationApplyManifest(appGUID string, rawManifest []byte) (JobURL, Warnings, error) { + responseLocation, warnings, err := client.MakeRequestSendRaw( + internal.PostApplicationActionApplyManifest, + internal.Params{"app_guid": appGUID}, + rawManifest, + "application/x-yaml", + nil, + ) + + return JobURL(responseLocation), warnings, err +} + +// UpdateSpaceApplyManifest - Is there a better name for this, since ... +// -- The Space resource is not actually updated. +// -- Instead what this ApplyManifest may do is to Create or Update Applications instead. + +// Applies the manifest to the given space. Returns back a resulting job URL to poll. + +// For each app specified in the manifest, the server-side handles: +// (1) Finding or creating this app. +// (2) Applying manifest properties to this app. + +func (client *Client) UpdateSpaceApplyManifest(spaceGUID string, rawManifest []byte) (JobURL, Warnings, error) { + responseLocation, warnings, err := client.MakeRequestSendRaw( + internal.PostSpaceActionApplyManifestRequest, + internal.Params{"space_guid": spaceGUID}, + rawManifest, + "application/x-yaml", + nil, + ) + + return JobURL(responseLocation), warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/manifest.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/manifest.go new file mode 100644 index 0000000..fba84e1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/manifest.go @@ -0,0 +1,32 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// GetApplicationManifest returns a (YAML) manifest for an application and its +// underlying processes. +func (client *Client) GetApplicationManifest(appGUID string) ([]byte, Warnings, error) { + bytes, warnings, err := client.MakeRequestReceiveRaw( + internal.GetApplicationManifestRequest, + internal.Params{"app_guid": appGUID}, + "application/x-yaml", + ) + + return bytes, warnings, err +} + +func (client *Client) GetSpaceManifestDiff(spaceGUID string, rawManifest []byte) (resources.ManifestDiff, Warnings, error) { + var responseBody resources.ManifestDiff + + _, warnings, err := client.MakeRequestSendRaw( + internal.PostSpaceDiffManifestRequest, + internal.Params{"space_guid": spaceGUID}, + rawManifest, + "application/x-yaml", + &responseBody, + ) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/metadata.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/metadata.go new file mode 100644 index 0000000..a909e49 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/metadata.go @@ -0,0 +1,86 @@ +package ccv3 + +import ( + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) UpdateResourceMetadata(resource string, resourceGUID string, metadata resources.Metadata) (JobURL, Warnings, error) { + var params RequestParams + requestMetadata := resources.ResourceMetadata{Metadata: &metadata} + + switch resource { + case "app": + params = RequestParams{ + RequestName: internal.PatchApplicationRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"app_guid": resourceGUID}, + } + case "buildpack": + params = RequestParams{ + RequestName: internal.PatchBuildpackRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"buildpack_guid": resourceGUID}, + } + case "domain": + params = RequestParams{ + RequestName: internal.PatchDomainRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"domain_guid": resourceGUID}, + } + case "org": + params = RequestParams{ + RequestName: internal.PatchOrganizationRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"organization_guid": resourceGUID}, + } + case "route": + params = RequestParams{ + RequestName: internal.PatchRouteRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"route_guid": resourceGUID}, + } + case "service-broker": + params = RequestParams{ + RequestName: internal.PatchServiceBrokerRequest, + URIParams: internal.Params{"service_broker_guid": resourceGUID}, + RequestBody: resources.ResourceMetadata{Metadata: &metadata}, + } + case "service-instance": + params = RequestParams{ + RequestName: internal.PatchServiceInstanceRequest, + URIParams: internal.Params{"service_instance_guid": resourceGUID}, + RequestBody: resources.ResourceMetadata{Metadata: &metadata}, + } + case "service-offering": + params = RequestParams{ + RequestName: internal.PatchServiceOfferingRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"service_offering_guid": resourceGUID}, + } + case "service-plan": + params = RequestParams{ + RequestName: internal.PatchServicePlanRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"service_plan_guid": resourceGUID}, + } + case "space": + params = RequestParams{ + RequestName: internal.PatchSpaceRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"space_guid": resourceGUID}, + } + case "stack": + params = RequestParams{ + RequestName: internal.PatchStackRequest, + RequestBody: requestMetadata, + URIParams: internal.Params{"stack_guid": resourceGUID}, + } + default: + return "", nil, fmt.Errorf("unknown resource type (%s) requested", resource) + } + + return client.MakeRequest(params) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization.go new file mode 100644 index 0000000..b75cad5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization.go @@ -0,0 +1,107 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CreateOrganization(orgName string) (resources.Organization, Warnings, error) { + org := resources.Organization{Name: orgName} + var responseBody resources.Organization + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostOrganizationRequest, + RequestBody: org, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// DeleteOrganization deletes the organization with the given GUID. +func (client *Client) DeleteOrganization(orgGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteOrganizationRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + }) + + return jobURL, warnings, err +} + +// GetDefaultDomain gets the default domain for the organization with the given GUID. +func (client *Client) GetDefaultDomain(orgGUID string) (resources.Domain, Warnings, error) { + var responseBody resources.Domain + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetDefaultDomainRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetIsolationSegmentOrganizations lists organizations +// entitled to an isolation segment. +func (client *Client) GetIsolationSegmentOrganizations(isolationSegmentGUID string) ([]resources.Organization, Warnings, error) { + var organizations []resources.Organization + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetIsolationSegmentOrganizationsRequest, + URIParams: internal.Params{"isolation_segment_guid": isolationSegmentGUID}, + ResponseBody: resources.Organization{}, + AppendToList: func(item interface{}) error { + organizations = append(organizations, item.(resources.Organization)) + return nil + }, + }) + + return organizations, warnings, err +} + +// GetOrganization gets an organization by the given guid. +func (client *Client) GetOrganization(orgGUID string) (resources.Organization, Warnings, error) { + var responseBody resources.Organization + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetOrganizationRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetOrganizations lists organizations with optional filters. +func (client *Client) GetOrganizations(query ...Query) ([]resources.Organization, Warnings, error) { + var organizations []resources.Organization + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetOrganizationsRequest, + Query: query, + ResponseBody: resources.Organization{}, + AppendToList: func(item interface{}) error { + organizations = append(organizations, item.(resources.Organization)) + return nil + }, + }) + + return organizations, warnings, err +} + +// UpdateOrganization updates an organization with the given properties. +func (client *Client) UpdateOrganization(org resources.Organization) (resources.Organization, Warnings, error) { + orgGUID := org.GUID + org.GUID = "" + + var responseBody resources.Organization + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchOrganizationRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + RequestBody: org, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization_quota.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization_quota.go new file mode 100644 index 0000000..8812493 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/organization_quota.go @@ -0,0 +1,84 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) ApplyOrganizationQuota(quotaGuid, orgGuid string) (resources.RelationshipList, Warnings, error) { + var responseBody resources.RelationshipList + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostOrganizationQuotaApplyRequest, + URIParams: internal.Params{"quota_guid": quotaGuid}, + RequestBody: resources.RelationshipList{GUIDs: []string{orgGuid}}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) CreateOrganizationQuota(orgQuota resources.OrganizationQuota) (resources.OrganizationQuota, Warnings, error) { + var responseOrgQuota resources.OrganizationQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostOrganizationQuotaRequest, + RequestBody: orgQuota, + ResponseBody: &responseOrgQuota, + }) + + return responseOrgQuota, warnings, err +} + +func (client *Client) DeleteOrganizationQuota(quotaGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteOrganizationQuotaRequest, + URIParams: internal.Params{"quota_guid": quotaGUID}, + }) + + return jobURL, warnings, err +} + +func (client *Client) GetOrganizationQuota(quotaGUID string) (resources.OrganizationQuota, Warnings, error) { + var responseBody resources.OrganizationQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetOrganizationQuotaRequest, + URIParams: internal.Params{"quota_guid": quotaGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetOrganizationQuotas(query ...Query) ([]resources.OrganizationQuota, Warnings, error) { + var organizationQuotas []resources.OrganizationQuota + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetOrganizationQuotasRequest, + Query: query, + ResponseBody: resources.OrganizationQuota{}, + AppendToList: func(item interface{}) error { + organizationQuotas = append(organizationQuotas, item.(resources.OrganizationQuota)) + return nil + }, + }) + + return organizationQuotas, warnings, err +} + +func (client *Client) UpdateOrganizationQuota(orgQuota resources.OrganizationQuota) (resources.OrganizationQuota, Warnings, error) { + orgQuotaGUID := orgQuota.GUID + orgQuota.GUID = "" + + var responseBody resources.OrganizationQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchOrganizationQuotaRequest, + URIParams: internal.Params{"quota_guid": orgQuotaGUID}, + RequestBody: orgQuota, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/package.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/package.go new file mode 100644 index 0000000..0dcdfca --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/package.go @@ -0,0 +1,266 @@ +package ccv3 + +import ( + "bytes" + "encoding/json" + "io" + "mime/multipart" + "os" + "path/filepath" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 io.Reader + +// CreatePackage creates a package with the given settings, Type and the +// ApplicationRelationship must be set. +func (client *Client) CreatePackage(pkg resources.Package) (resources.Package, Warnings, error) { + var responseBody resources.Package + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostPackageRequest, + RequestBody: pkg, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetPackage returns the package with the given GUID. +func (client *Client) GetPackage(packageGUID string) (resources.Package, Warnings, error) { + var responseBody resources.Package + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetPackageRequest, + URIParams: internal.Params{"package_guid": packageGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetPackages returns the list of packages. +func (client *Client) GetPackages(query ...Query) ([]resources.Package, Warnings, error) { + var packages []resources.Package + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetPackagesRequest, + Query: query, + ResponseBody: resources.Package{}, + AppendToList: func(item interface{}) error { + packages = append(packages, item.(resources.Package)) + return nil + }, + }) + + return packages, warnings, err +} + +// UploadBitsPackage uploads the newResources and a list of existing resources +// to the cloud controller. An updated package is returned. The function will +// act differently given the following Readers: +// - io.ReadSeeker: Will function properly on retry. +// - io.Reader: Will return a ccerror.PipeSeekError on retry. +// - nil: Will not add the "application" section to the request. The newResourcesLength is ignored in this case. +// +// Note: In order to determine if package creation is successful, poll the +// Package's state field for more information. +func (client *Client) UploadBitsPackage(pkg resources.Package, matchedResources []Resource, newResources io.Reader, newResourcesLength int64) (resources.Package, Warnings, error) { + if matchedResources == nil { + return resources.Package{}, nil, ccerror.NilObjectError{Object: "matchedResources"} + } + + if newResources == nil { + return client.uploadExistingResourcesOnly(pkg.GUID, matchedResources) + } + + return client.uploadNewAndExistingResources(pkg.GUID, matchedResources, newResources, newResourcesLength) +} + +// UploadPackage uploads a file to a given package's Upload resource. Note: +// fileToUpload is read entirely into memory prior to sending data to CC. +func (client *Client) UploadPackage(pkg resources.Package, fileToUpload string) (resources.Package, Warnings, error) { + body, contentType, err := client.createUploadBuffer(fileToUpload, "bits") + if err != nil { + return resources.Package{}, nil, err + } + + responsePackage := resources.Package{} + _, warnings, err := client.MakeRequestSendRaw( + internal.PostPackageBitsRequest, + internal.Params{"package_guid": pkg.GUID}, + body.Bytes(), + contentType, + &responsePackage, + ) + + return responsePackage, warnings, err +} + +// CopyPackage copies a package from a source package to a destination package +// Note: source app guid is in URL; dest app guid is in body +func (client *Client) CopyPackage(sourcePkgGUID string, targetAppGUID string) (resources.Package, Warnings, error) { + var targetPackage resources.Package + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostPackageRequest, + Query: []Query{{Key: SourceGUID, Values: []string{sourcePkgGUID}}}, + RequestBody: map[string]resources.Relationships{ + "relationships": { + constant.RelationshipTypeApplication: resources.Relationship{GUID: targetAppGUID}, + }, + }, + ResponseBody: &targetPackage, + }) + + return targetPackage, warnings, err +} + +func (client *Client) calculateAppBitsRequestSize(matchedResources []Resource, newResourcesLength int64) (int64, error) { + body := &bytes.Buffer{} + form := multipart.NewWriter(body) + + jsonResources, err := json.Marshal(matchedResources) + if err != nil { + return 0, err + } + err = form.WriteField("resources", string(jsonResources)) + if err != nil { + return 0, err + } + _, err = form.CreateFormFile("bits", "package.zip") + if err != nil { + return 0, err + } + err = form.Close() + if err != nil { + return 0, err + } + + return int64(body.Len()) + newResourcesLength, nil +} + +func (client *Client) createMultipartBodyAndHeaderForAppBits(matchedResources []Resource, newResources io.Reader, newResourcesLength int64) (string, io.ReadSeeker, <-chan error) { + writerOutput, writerInput := cloudcontroller.NewPipeBomb() + form := multipart.NewWriter(writerInput) + + writeErrors := make(chan error) + + go func() { + defer close(writeErrors) + defer writerInput.Close() + + jsonResources, err := json.Marshal(matchedResources) + if err != nil { + writeErrors <- err + return + } + + err = form.WriteField("resources", string(jsonResources)) + if err != nil { + writeErrors <- err + return + } + + writer, err := form.CreateFormFile("bits", "package.zip") + if err != nil { + writeErrors <- err + return + } + + if newResourcesLength != 0 { + _, err = io.Copy(writer, newResources) + if err != nil { + writeErrors <- err + return + } + } + + err = form.Close() + if err != nil { + writeErrors <- err + } + }() + + return form.FormDataContentType(), writerOutput, writeErrors +} + +func (*Client) createUploadBuffer(path string, paramName string) (bytes.Buffer, string, error) { + file, err := os.Open(path) + if err != nil { + return bytes.Buffer{}, "", err + } + defer file.Close() + + body := bytes.Buffer{} + writer := multipart.NewWriter(&body) + part, err := writer.CreateFormFile(paramName, filepath.Base(path)) + if err != nil { + return bytes.Buffer{}, "", err + } + _, err = io.Copy(part, file) + if err != nil { + return bytes.Buffer{}, "", err + } + + err = writer.Close() + + return body, writer.FormDataContentType(), err +} + +func (client *Client) uploadExistingResourcesOnly(packageGUID string, matchedResources []Resource) (resources.Package, Warnings, error) { + jsonResources, err := json.Marshal(matchedResources) + if err != nil { + return resources.Package{}, nil, err + } + + body := bytes.NewBuffer(nil) + form := multipart.NewWriter(body) + err = form.WriteField("resources", string(jsonResources)) + if err != nil { + return resources.Package{}, nil, err + } + + err = form.Close() + if err != nil { + return resources.Package{}, nil, err + } + + responsePackage := resources.Package{} + + _, warnings, err := client.MakeRequestSendRaw( + internal.PostPackageBitsRequest, + internal.Params{"package_guid": packageGUID}, + body.Bytes(), + form.FormDataContentType(), + &responsePackage, + ) + + return responsePackage, warnings, err +} + +func (client *Client) uploadNewAndExistingResources(packageGUID string, matchedResources []Resource, newResources io.Reader, newResourcesLength int64) (resources.Package, Warnings, error) { + contentLength, err := client.calculateAppBitsRequestSize(matchedResources, newResourcesLength) + if err != nil { + return resources.Package{}, nil, err + } + + contentType, body, writeErrors := client.createMultipartBodyAndHeaderForAppBits(matchedResources, newResources, newResourcesLength) + + responseBody := resources.Package{} + _, warnings, err := client.MakeRequestUploadAsync( + internal.PostPackageBitsRequest, + internal.Params{"package_guid": packageGUID}, + contentType, + body, + contentLength, + &responseBody, + writeErrors, + ) + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginate.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginate.go new file mode 100644 index 0000000..2fcf46a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginate.go @@ -0,0 +1,71 @@ +package ccv3 + +import ( + "net/http" + + "code.cloudfoundry.org/cli/api/cloudcontroller" +) + +func (requester RealRequester) paginate(request *cloudcontroller.Request, obj interface{}, appendToExternalList func(interface{}) error) (IncludedResources, Warnings, error) { + fullWarningsList := Warnings{} + var includes IncludedResources + + for { + wrapper, warnings, err := requester.wrapFirstPage(request, obj, appendToExternalList) + fullWarningsList = append(fullWarningsList, warnings...) + if err != nil { + return IncludedResources{}, fullWarningsList, err + } + + includes.Apps = append(includes.Apps, wrapper.IncludedResources.Apps...) + includes.Users = append(includes.Users, wrapper.IncludedResources.Users...) + includes.Organizations = append(includes.Organizations, wrapper.IncludedResources.Organizations...) + includes.Spaces = append(includes.Spaces, wrapper.IncludedResources.Spaces...) + includes.ServiceBrokers = append(includes.ServiceBrokers, wrapper.IncludedResources.ServiceBrokers...) + includes.ServiceInstances = append(includes.ServiceInstances, wrapper.IncludedResources.ServiceInstances...) + includes.ServiceOfferings = append(includes.ServiceOfferings, wrapper.IncludedResources.ServiceOfferings...) + includes.ServicePlans = append(includes.ServicePlans, wrapper.IncludedResources.ServicePlans...) + + if wrapper.NextPage() == "" { + break + } + + request, err = requester.newHTTPRequest(requestOptions{ + URL: wrapper.NextPage(), + Method: http.MethodGet, + }) + if err != nil { + return IncludedResources{}, fullWarningsList, err + } + } + + return includes, fullWarningsList, nil +} + +func (requester RealRequester) wrapFirstPage(request *cloudcontroller.Request, obj interface{}, appendToExternalList func(interface{}) error) (*PaginatedResources, Warnings, error) { + warnings := Warnings{} + wrapper := NewPaginatedResources(obj) + response := cloudcontroller.Response{ + DecodeJSONResponseInto: &wrapper, + } + + err := requester.connection.Make(request, &response) + warnings = append(warnings, response.Warnings...) + if err != nil { + return nil, warnings, err + } + + list, err := wrapper.Resources() + if err != nil { + return nil, warnings, err + } + + for _, item := range list { + err = appendToExternalList(item) + if err != nil { + return nil, warnings, err + } + } + + return wrapper, warnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginated_resources.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginated_resources.go new file mode 100644 index 0000000..33e28ec --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/paginated_resources.go @@ -0,0 +1,50 @@ +package ccv3 + +import ( + "encoding/json" + "reflect" +) + +// NewPaginatedResources returns a new PaginatedResources struct with the +// given resource type. +func NewPaginatedResources(exampleResource interface{}) *PaginatedResources { + return &PaginatedResources{ + resourceType: reflect.TypeOf(exampleResource), + } +} + +// PaginatedResources represents a page of resources returned by the Cloud +// Controller. +type PaginatedResources struct { + // Pagination represents information about the paginated resource. + Pagination struct { + // Next represents a link to the next page. + Next struct { + // HREF is the HREF of the next page. + HREF string `json:"href"` + } `json:"next"` + } `json:"pagination"` + // ResourceBytes is the list of resources for the current page. + ResourcesBytes json.RawMessage `json:"resources"` + resourceType reflect.Type + IncludedResources IncludedResources `json:"included"` +} + +// NextPage returns the HREF of the next page of results. +func (pr PaginatedResources) NextPage() string { + return pr.Pagination.Next.HREF +} + +// Resources unmarshals JSON representing a page of resources and returns a +// slice of the given resource type. +func (pr PaginatedResources) Resources() ([]interface{}, error) { + slicePtr := reflect.New(reflect.SliceOf(pr.resourceType)) + err := json.Unmarshal([]byte(pr.ResourcesBytes), slicePtr.Interface()) + slice := reflect.Indirect(slicePtr) + + contents := make([]interface{}, 0, slice.Len()) + for i := 0; i < slice.Len(); i++ { + contents = append(contents, slice.Index(i).Interface()) + } + return contents, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process.go new file mode 100644 index 0000000..d03f288 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process.go @@ -0,0 +1,142 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateApplicationProcessScale updates process instances count, memory or disk +func (client *Client) CreateApplicationProcessScale(appGUID string, process resources.Process) (resources.Process, Warnings, error) { + var responseBody resources.Process + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationProcessActionScaleRequest, + URIParams: internal.Params{"app_guid": appGUID, "type": process.Type}, + RequestBody: process, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetApplicationProcessByType returns application process of specified type +func (client *Client) GetApplicationProcessByType(appGUID string, processType string) (resources.Process, Warnings, error) { + var responseBody resources.Process + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetApplicationProcessRequest, + URIParams: internal.Params{"app_guid": appGUID, "type": processType}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetApplicationProcesses lists processes for a given application. **Note**: +// Due to security, the API obfuscates certain values such as `command`. +func (client *Client) GetApplicationProcesses(appGUID string) ([]resources.Process, Warnings, error) { + var processes []resources.Process + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationProcessesRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: resources.Process{}, + AppendToList: func(item interface{}) error { + processes = append(processes, item.(resources.Process)) + return nil + }, + }) + + return processes, warnings, err +} + +// GetNewApplicationProcesses gets processes for an application in the middle of a deployment. +// The app's processes will include a web process that will be removed when the deployment completes, +// so exclude that soon-to-be-removed process from the result. +func (client *Client) GetNewApplicationProcesses(appGUID string, deploymentGUID string) ([]resources.Process, Warnings, error) { + var allWarnings Warnings + + deployment, warnings, err := client.GetDeployment(deploymentGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + allProcesses, warnings, err := client.GetApplicationProcesses(appGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + var newWebProcessGUID string + for _, process := range deployment.NewProcesses { + if process.Type == constant.ProcessTypeWeb { + newWebProcessGUID = process.GUID + } + } + + var processesList []resources.Process + for _, process := range allProcesses { + if process.Type == constant.ProcessTypeWeb { + if process.GUID == newWebProcessGUID { + processesList = append(processesList, process) + } + } else { + processesList = append(processesList, process) + } + } + + return processesList, allWarnings, nil +} + +// GetProcess returns a process with the given guid +func (client *Client) GetProcess(processGUID string) (resources.Process, Warnings, error) { + var responseBody resources.Process + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetProcessRequest, + URIParams: internal.Params{"process_guid": processGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) GetProcesses(query ...Query) ([]resources.Process, Warnings, error) { + var processes []resources.Process + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetProcessesRequest, + Query: query, + ResponseBody: resources.Process{}, + AppendToList: func(item interface{}) error { + processes = append(processes, item.(resources.Process)) + return nil + }, + }) + + return processes, warnings, err +} + +// UpdateProcess updates the process's command or health check settings. GUID +// is always required; HealthCheckType is only required when updating health +// check settings. +func (client *Client) UpdateProcess(process resources.Process) (resources.Process, Warnings, error) { + var responseBody resources.Process + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchProcessRequest, + URIParams: internal.Params{"process_guid": process.GUID}, + RequestBody: resources.Process{ + Command: process.Command, + HealthCheckType: process.HealthCheckType, + HealthCheckEndpoint: process.HealthCheckEndpoint, + HealthCheckTimeout: process.HealthCheckTimeout, + HealthCheckInvocationTimeout: process.HealthCheckInvocationTimeout, + }, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process_instance.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process_instance.go new file mode 100644 index 0000000..572ce04 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/process_instance.go @@ -0,0 +1,113 @@ +package ccv3 + +import ( + "fmt" + "strconv" + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +// ProcessInstance represents a single process instance for a particular +// application. +type ProcessInstance struct { + // CPU is the current CPU usage of the instance. + CPU float64 + // Details is information about errors placing the instance. + Details string + // DiskQuota is the maximum disk the instance is allowed to use. + DiskQuota uint64 + // DiskUsage is the current disk usage of the instance. + DiskUsage uint64 + // Index is the index of the instance. + Index int64 + // Isolation segment is the current isolation segment that the instance is + // running on. The value is empty when the instance is not placed on a + // particular isolation segment. + IsolationSegment string + // MemoryQuota is the maximum memory the instance is allowed to use. + MemoryQuota uint64 + // DiskUsage is the current memory usage of the instance. + MemoryUsage uint64 + // State is the state of the instance. + State constant.ProcessInstanceState + // Type is the process type for the instance. + Type string + // Uptime is the duration that the instance has been running. + Uptime time.Duration +} + +// UnmarshalJSON helps unmarshal a V3 Cloud Controller Instance response. +func (instance *ProcessInstance) UnmarshalJSON(data []byte) error { + var inputInstance struct { + Details string `json:"details"` + DiskQuota uint64 `json:"disk_quota"` + Index int64 `json:"index"` + IsolationSegment string `json:"isolation_segment"` + MemQuota uint64 `json:"mem_quota"` + State string `json:"state"` + Type string `json:"type"` + Uptime int64 `json:"uptime"` + Usage struct { + CPU float64 `json:"cpu"` + Mem uint64 `json:"mem"` + Disk uint64 `json:"disk"` + } `json:"usage"` + } + + err := cloudcontroller.DecodeJSON(data, &inputInstance) + if err != nil { + return err + } + + instance.CPU = inputInstance.Usage.CPU + instance.Details = inputInstance.Details + instance.DiskQuota = inputInstance.DiskQuota + instance.DiskUsage = inputInstance.Usage.Disk + instance.Index = inputInstance.Index + instance.IsolationSegment = inputInstance.IsolationSegment + instance.MemoryQuota = inputInstance.MemQuota + instance.MemoryUsage = inputInstance.Usage.Mem + instance.State = constant.ProcessInstanceState(inputInstance.State) + instance.Type = inputInstance.Type + instance.Uptime, err = time.ParseDuration(fmt.Sprintf("%ds", inputInstance.Uptime)) + if err != nil { + return err + } + + return nil +} + +// DeleteApplicationProcessInstance deletes/stops a particular application's +// process instance. +func (client *Client) DeleteApplicationProcessInstance(appGUID string, processType string, instanceIndex int) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteApplicationProcessInstanceRequest, + URIParams: internal.Params{ + "app_guid": appGUID, + "type": processType, + "index": strconv.Itoa(instanceIndex), + }, + }) + + return warnings, err +} + +// GetProcessInstances lists instance stats for a given process. +func (client *Client) GetProcessInstances(processGUID string) ([]ProcessInstance, Warnings, error) { + var resources []ProcessInstance + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetProcessStatsRequest, + URIParams: internal.Params{"process_guid": processGUID}, + ResponseBody: ProcessInstance{}, + AppendToList: func(item interface{}) error { + resources = append(resources, item.(ProcessInstance)) + return nil + }, + }) + + return resources, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/query.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/query.go new file mode 100644 index 0000000..6761676 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/query.go @@ -0,0 +1,155 @@ +package ccv3 + +import ( + "net/url" + "strings" +) + +// QueryKey is the type of query that is being selected on. +type QueryKey string + +const ( + // AppGUIDFilter is a query parameter for listing objects by app GUID. + AppGUIDFilter QueryKey = "app_guids" + // AvailableFilter is a query parameter for listing available resources + AvailableFilter QueryKey = "available" + // GUIDFilter is a query parameter for listing objects by GUID. + GUIDFilter QueryKey = "guids" + // LabelSelectorFilter is a query parameter for listing objects by label + LabelSelectorFilter QueryKey = "label_selector" + // NameFilter is a query parameter for listing objects by name. + NameFilter QueryKey = "names" + // NoRouteFilter is a query parameter for skipping route creation and unmapping existing routes. + NoRouteFilter QueryKey = "no_route" + // OrganizationGUIDFilter is a query parameter for listing objects by Organization GUID. + OrganizationGUIDFilter QueryKey = "organization_guids" + // SequenceIDFilter is a query parameter for listing objects by sequence ID. + SequenceIDFilter QueryKey = "sequence_ids" + // RouteGUIDFilter is a query parameter for listing objects by Route GUID. + RouteGUIDFilter QueryKey = "route_guids" + // ServiceInstanceGUIDFilter is a query parameter for listing objects by Service Instance GUID. + ServiceInstanceGUIDFilter QueryKey = "service_instance_guids" + // SpaceGUIDFilter is a query parameter for listing objects by Space GUID. + SpaceGUIDFilter QueryKey = "space_guids" + // StatusValueFilter is a query parameter for listing deployments by status.value + StatusValueFilter QueryKey = "status_values" + // DomainGUIDFilter is a query param for listing events by target_guid + TargetGUIDFilter QueryKey = "target_guids" + // DomainGUIDFilter is a query param for listing objects by domain_guid + DomainGUIDFilter QueryKey = "domain_guids" + // HostsFilter is a query param for listing objects by hostname + HostsFilter QueryKey = "hosts" + // HostFilter is a query param for getting an object with the given host + HostFilter QueryKey = "host" + // Origins filter is a query parameter when getting a user by origin (Note: CAPI will return an error if usernames filter is not also provided) + OriginsFilter QueryKey = "origins" + // PathsFilter is a query param for listing objects by path + PathsFilter QueryKey = "paths" + // PathFilter is a query param for getting an object with the given host + PathFilter QueryKey = "path" + // PortFilter is a query param for getting an object with the given port (TCP routes) + PortFilter QueryKey = "port" + // PortsFilter is a query param for getting an object with the given ports (TCP routes) + PortsFilter QueryKey = "ports" + // RoleTypesFilter is a query param for getting a role by type + RoleTypesFilter QueryKey = "types" + // StackFilter is a query parameter for listing objects by stack name + StackFilter QueryKey = "stacks" + // TypeFiler is a query parameter for selecting binding type + TypeFilter QueryKey = "type" + // UnmappedFilter is a query parameter specifying unmapped routes + UnmappedFilter QueryKey = "unmapped" + // UserGUIDFilter is a query parameter when getting a user by GUID + UserGUIDFilter QueryKey = "user_guids" + // UsernamesFilter is a query parameter when getting a user by username + UsernamesFilter QueryKey = "usernames" + // StatesFilter is a query parameter when getting a package's droplets by state + VersionsFilter QueryKey = "versions" + // VersionsFilter is a query parameter when getting an apps revisions by version + StatesFilter QueryKey = "states" + // ServiceBrokerNamesFilter is a query parameter when getting plans or offerings according to the Service Brokers that it relates to + ServiceBrokerNamesFilter QueryKey = "service_broker_names" + // ServiceBrokerGUIDsFilter is a query parameter for getting resources according to the service broker GUID + ServiceBrokerGUIDsFilter QueryKey = "service_broker_guids" + // ServiceOfferingNamesFilter is a query parameter when getting a plan according to the Service Offerings that it relates to + ServiceOfferingNamesFilter QueryKey = "service_offering_names" + // ServiceOfferingGUIDsFilter is a query parameter when getting resources according to service offering GUIDs + ServiceOfferingGUIDsFilter QueryKey = "service_offering_guids" + // FieldsServiceOfferingServiceBroker is a query parameter to include specific fields from a service broker in a plan response + FieldsServiceOfferingServiceBroker QueryKey = "fields[service_offering.service_broker]" + // FieldsServiceBroker is a query parameter to include specific fields from a service broker in an offering response + FieldsServiceBroker QueryKey = "fields[service_broker]" + // FieldsServicePlan is a query parameter to include specific fields from a service plan + FieldsServicePlan QueryKey = "fields[service_plan]" + // FieldsServicePlanServiceOffering is a query parameter to include specific fields from a service offering + FieldsServicePlanServiceOffering QueryKey = "fields[service_plan.service_offering]" + // FieldsServicePlanServiceOfferingServiceBroker is a query parameter to include specific fields from a service broker + FieldsServicePlanServiceOfferingServiceBroker QueryKey = "fields[service_plan.service_offering.service_broker]" + // FieldsSpace is a query parameter to include specific fields from a space + FieldsSpace QueryKey = "fields[space]" + // FieldsSpaceOrganization is a query parameter to include specific fields from a organization + FieldsSpaceOrganization QueryKey = "fields[space.organization]" + + // OrderBy is a query parameter to specify how to order objects. + OrderBy QueryKey = "order_by" + // PerPage is a query parameter for specifying the number of results per page. + PerPage QueryKey = "per_page" + // Include is a query parameter for specifying other resources associated with the + // resource returned by the endpoint + Include QueryKey = "include" + + // GloballyEnabledStaging is the query parameter for getting only security groups that are globally enabled for staging + GloballyEnabledStaging QueryKey = "globally_enabled_staging" + + // GloballyEnabledRunning is the query parameter for getting only security groups that are globally enabled for running + GloballyEnabledRunning QueryKey = "globally_enabled_running" + + // NameOrder is a query value for ordering by name. This value is used in + // conjunction with the OrderBy QueryKey. + NameOrder = "name" + + // PositionOrder is a query value for ordering by position. This value is + // used in conjunction with the OrderBy QueryKey. + PositionOrder = "position" + + // CreatedAtDescendingOrder is a query value for ordering by created_at timestamp, + // in descending order. + CreatedAtDescendingOrder = "-created_at" + + // SourceGUID is the query parameter for getting an object. Currently it's used as a package GUID + // to retrieve a package to later copy it to an app (CopyPackage()) + SourceGUID = "source_guid" + + // Purge is a query parameter used on a Delete request to indicate that dependent resources should also be deleted + Purge = "purge" + + // MaxPerPage is the largest value of "per_page" that should be used + MaxPerPage = "5000" +) + +// Query is additional settings that can be passed to some requests that can +// filter, sort, etc. the results. +type Query struct { + Key QueryKey + Values []string +} + +// FormatQueryParameters converts a Query object into a collection that +// cloudcontroller.Request can accept. +func FormatQueryParameters(queries []Query) url.Values { + params := url.Values{} + for _, query := range queries { + if query.Key == NameFilter { + encodedParamValues := []string{} + for _, valString := range query.Values { + commaEncoded := strings.ReplaceAll(valString, ",", "%2C") + encodedParamValues = append(encodedParamValues, commaEncoded) + } + query.Values = encodedParamValues + } + + params.Add(string(query.Key), strings.Join(query.Values, ",")) + } + + return params +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship.go new file mode 100644 index 0000000..e4ed3b8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship.go @@ -0,0 +1,90 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// DeleteIsolationSegmentOrganization will delete the relationship between +// the isolation segment and the organization provided. +func (client *Client) DeleteIsolationSegmentOrganization(isolationSegmentGUID string, orgGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteIsolationSegmentRelationshipOrganizationRequest, + URIParams: internal.Params{"isolation_segment_guid": isolationSegmentGUID, "organization_guid": orgGUID}, + }) + + return warnings, err +} + +// GetOrganizationDefaultIsolationSegment returns the relationship between an +// organization and it's default isolation segment. +func (client *Client) GetOrganizationDefaultIsolationSegment(orgGUID string) (resources.Relationship, Warnings, error) { + var responseBody resources.Relationship + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetOrganizationRelationshipDefaultIsolationSegmentRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetSpaceIsolationSegment returns the relationship between a space and it's +// isolation segment. +func (client *Client) GetSpaceIsolationSegment(spaceGUID string) (resources.Relationship, Warnings, error) { + var responseBody resources.Relationship + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetSpaceRelationshipIsolationSegmentRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// SetApplicationDroplet sets the specified droplet on the given application. +func (client *Client) SetApplicationDroplet(appGUID string, dropletGUID string) (resources.Relationship, Warnings, error) { + var responseBody resources.Relationship + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchApplicationCurrentDropletRequest, + URIParams: internal.Params{"app_guid": appGUID}, + RequestBody: resources.Relationship{GUID: dropletGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateOrganizationDefaultIsolationSegmentRelationship sets the default isolation segment +// for an organization on the controller. +// If isoSegGuid is empty it will reset the default isolation segment. +func (client *Client) UpdateOrganizationDefaultIsolationSegmentRelationship(orgGUID string, isoSegGUID string) (resources.Relationship, Warnings, error) { + var responseBody resources.Relationship + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchOrganizationRelationshipDefaultIsolationSegmentRequest, + URIParams: internal.Params{"organization_guid": orgGUID}, + RequestBody: resources.Relationship{GUID: isoSegGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UpdateSpaceIsolationSegmentRelationship assigns an isolation segment to a space and +// returns the relationship. +func (client *Client) UpdateSpaceIsolationSegmentRelationship(spaceGUID string, isolationSegmentGUID string) (resources.Relationship, Warnings, error) { + var responseBody resources.Relationship + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchSpaceRelationshipIsolationSegmentRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + RequestBody: resources.Relationship{GUID: isolationSegmentGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship_list.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship_list.go new file mode 100644 index 0000000..a60adef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/relationship_list.go @@ -0,0 +1,21 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// EntitleIsolationSegmentToOrganizations will create a link between the +// isolation segment and the list of organizations provided. +func (client *Client) EntitleIsolationSegmentToOrganizations(isolationSegmentGUID string, organizationGUIDs []string) (resources.RelationshipList, Warnings, error) { + var responseBody resources.RelationshipList + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostIsolationSegmentRelationshipOrganizationsRequest, + URIParams: internal.Params{"isolation_segment_guid": isolationSegmentGUID}, + RequestBody: resources.RelationshipList{GUIDs: organizationGUIDs}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/request.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/request.go new file mode 100644 index 0000000..dc799fc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/request.go @@ -0,0 +1,77 @@ +package ccv3 + +import ( + "io" + "net/http" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +// requestOptions contains all the options to create an HTTP request. +type requestOptions struct { + // URIParams are the list URI route parameters + URIParams internal.Params + + // Query is a list of HTTP query parameters. Query will overwrite any + // existing query string in the URI. If you want to preserve the query + // string in URI make sure Query is nil. + Query []Query + + // RequestName is the name of the request (see routes) + RequestName string + // Header contains custom headers to pass to the request. + Header http.Header + // Method is the HTTP method. + Method string + // URL is the request path. + URL string + // Body is the content of the request. + Body io.ReadSeeker +} + +// newHTTPRequest returns a constructed HTTP.Request with some defaults. +// Defaults are applied when Request options are not filled in. +func (requester *RealRequester) newHTTPRequest(passedRequest requestOptions) (*cloudcontroller.Request, error) { + var request *http.Request + var err error + if passedRequest.URL != "" { + request, err = http.NewRequest( + passedRequest.Method, + passedRequest.URL, + passedRequest.Body, + ) + } else { + request, err = requester.router.CreateRequest( + passedRequest.RequestName, + map[string]string(passedRequest.URIParams), + passedRequest.Body, + ) + } + if err != nil { + return nil, err + } + + if passedRequest.Query != nil { + request.URL.RawQuery = FormatQueryParameters(passedRequest.Query).Encode() + } + + request.Header = http.Header{} + if passedRequest.Header != nil { + request.Header = passedRequest.Header + } + + if request.Header.Get("User-Agent") == "" { + request.Header.Set("User-Agent", requester.userAgent) + } + + if request.Header.Get("Accept") == "" { + request.Header.Set("Accept", "application/json") + } + + if request.Header.Get("Content-Type") == "" { + request.Header.Set("Content-Type", "application/json") + } + + return cloudcontroller.NewRequest(request, passedRequest.Body), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/requester.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/requester.go new file mode 100644 index 0000000..f811a00 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/requester.go @@ -0,0 +1,304 @@ +package ccv3 + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "runtime" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Requester + +type RequestParams struct { + RequestName string + URIParams internal.Params + Query []Query + RequestBody interface{} + ResponseBody interface{} + URL string + AppendToList func(item interface{}) error +} + +type Requester interface { + InitializeConnection(settings TargetSettings) + + InitializeRouter(baseURL string) + + MakeListRequest(requestParams RequestParams) (IncludedResources, Warnings, error) + + MakeRequest(requestParams RequestParams) (JobURL, Warnings, error) + + MakeRequestReceiveRaw( + requestName string, + uriParams internal.Params, + responseBodyMimeType string, + ) ([]byte, Warnings, error) + + MakeRequestSendRaw( + requestName string, + uriParams internal.Params, + requestBody []byte, + requestBodyMimeType string, + responseBody interface{}, + ) (string, Warnings, error) + + MakeRequestSendReceiveRaw( + Method string, + URL string, + headers http.Header, + requestBody []byte, + ) ([]byte, *http.Response, error) + + MakeRequestUploadAsync( + requestName string, + uriParams internal.Params, + requestBodyMimeType string, + requestBody io.ReadSeeker, + dataLength int64, + responseBody interface{}, + writeErrors <-chan error, + ) (string, Warnings, error) + + WrapConnection(wrapper ConnectionWrapper) +} + +type RealRequester struct { + connection cloudcontroller.Connection + router *internal.Router + userAgent string + wrappers []ConnectionWrapper +} + +func (requester *RealRequester) InitializeConnection(settings TargetSettings) { + requester.connection = cloudcontroller.NewConnection(cloudcontroller.Config{ + DialTimeout: settings.DialTimeout, + SkipSSLValidation: settings.SkipSSLValidation, + }) + + for _, wrapper := range requester.wrappers { + requester.connection = wrapper.Wrap(requester.connection) + } +} + +func (requester *RealRequester) InitializeRouter(baseURL string) { + requester.router = internal.NewRouter(internal.APIRoutes, baseURL) +} + +func (requester *RealRequester) MakeListRequest(requestParams RequestParams) (IncludedResources, Warnings, error) { + request, err := requester.buildRequest(requestParams) + if err != nil { + return IncludedResources{}, nil, err + } + + return requester.paginate(request, requestParams.ResponseBody, requestParams.AppendToList) +} + +func (requester *RealRequester) MakeRequest(requestParams RequestParams) (JobURL, Warnings, error) { + request, err := requester.buildRequest(requestParams) + if err != nil { + return "", nil, err + } + + response := cloudcontroller.Response{} + if requestParams.ResponseBody != nil { + response.DecodeJSONResponseInto = requestParams.ResponseBody + } + + err = requester.connection.Make(request, &response) + + return JobURL(response.ResourceLocationURL), response.Warnings, err +} + +func (requester *RealRequester) MakeRequestReceiveRaw( + requestName string, + uriParams internal.Params, + responseBodyMimeType string, +) ([]byte, Warnings, error) { + request, err := requester.newHTTPRequest(requestOptions{ + RequestName: requestName, + URIParams: uriParams, + }) + if err != nil { + return nil, nil, err + } + + response := cloudcontroller.Response{} + + request.Header.Set("Accept", responseBodyMimeType) + + err = requester.connection.Make(request, &response) + + return response.RawResponse, response.Warnings, err +} + +func (requester *RealRequester) MakeRequestSendReceiveRaw( + Method string, + URL string, + headers http.Header, + requestBody []byte, +) ([]byte, *http.Response, error) { + request, err := requester.newHTTPRequest(requestOptions{ + URL: URL, + Method: Method, + Body: bytes.NewReader(requestBody), + Header: headers, + }) + if err != nil { + return nil, nil, err + } + + response := cloudcontroller.Response{} + + err = requester.connection.Make(request, &response) + + return response.RawResponse, response.HTTPResponse, err +} + +func (requester *RealRequester) MakeRequestSendRaw( + requestName string, + uriParams internal.Params, + requestBody []byte, + requestBodyMimeType string, + responseBody interface{}, +) (string, Warnings, error) { + request, err := requester.newHTTPRequest(requestOptions{ + RequestName: requestName, + URIParams: uriParams, + Body: bytes.NewReader(requestBody), + }) + if err != nil { + return "", nil, err + } + + request.Header.Set("Content-type", requestBodyMimeType) + + response := cloudcontroller.Response{ + DecodeJSONResponseInto: responseBody, + } + + err = requester.connection.Make(request, &response) + + return response.ResourceLocationURL, response.Warnings, err +} + +func (requester *RealRequester) MakeRequestUploadAsync( + requestName string, + uriParams internal.Params, + requestBodyMimeType string, + requestBody io.ReadSeeker, + dataLength int64, + responseBody interface{}, + writeErrors <-chan error, +) (string, Warnings, error) { + request, err := requester.newHTTPRequest(requestOptions{ + RequestName: requestName, + URIParams: uriParams, + Body: requestBody, + }) + if err != nil { + return "", nil, err + } + + request.Header.Set("Content-Type", requestBodyMimeType) + request.ContentLength = dataLength + + return requester.uploadAsynchronously(request, responseBody, writeErrors) +} + +func NewRequester(config Config) *RealRequester { + userAgent := fmt.Sprintf( + "%s/%s (%s; %s %s)", + config.AppName, + config.AppVersion, + runtime.Version(), + runtime.GOARCH, + runtime.GOOS, + ) + + return &RealRequester{ + userAgent: userAgent, + wrappers: append([]ConnectionWrapper{newErrorWrapper()}, config.Wrappers...), + } +} + +func (requester *RealRequester) buildRequest(requestParams RequestParams) (*cloudcontroller.Request, error) { + options := requestOptions{ + RequestName: requestParams.RequestName, + URIParams: requestParams.URIParams, + Query: requestParams.Query, + URL: requestParams.URL, + } + + if requestParams.RequestBody != nil { + body, err := json.Marshal(requestParams.RequestBody) + if err != nil { + return nil, err + } + + options.Body = bytes.NewReader(body) + } + + request, err := requester.newHTTPRequest(options) + if err != nil { + return nil, err + } + + return request, err +} + +func (requester *RealRequester) uploadAsynchronously(request *cloudcontroller.Request, responseBody interface{}, writeErrors <-chan error) (string, Warnings, error) { + response := cloudcontroller.Response{ + DecodeJSONResponseInto: responseBody, + } + + httpErrors := make(chan error) + + go func() { + defer close(httpErrors) + + err := requester.connection.Make(request, &response) + if err != nil { + httpErrors <- err + } + }() + + // The following section makes the following assumptions: + // 1) If an error occurs during file reading, an EOF is sent to the request + // object. Thus ending the request transfer. + // 2) If an error occurs during request transfer, an EOF is sent to the pipe. + // Thus ending the writing routine. + var firstError error + var writeClosed, httpClosed bool + + for { + select { + case writeErr, ok := <-writeErrors: + if !ok { + writeClosed = true + break // for select + } + if firstError == nil { + firstError = writeErr + } + case httpErr, ok := <-httpErrors: + if !ok { + httpClosed = true + break // for select + } + if firstError == nil { + firstError = httpErr + } + } + + if writeClosed && httpClosed { + break // for for + } + } + + return response.ResourceLocationURL, response.Warnings, firstError +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/resource.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/resource.go new file mode 100644 index 0000000..cb8d778 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/resource.go @@ -0,0 +1,92 @@ +package ccv3 + +import ( + "encoding/json" + "os" + "strconv" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" +) + +type Checksum struct { + Value string `json:"value"` +} + +type Resource struct { + // FilePath is the path of the resource. + FilePath string `json:"path"` + + // Mode is the operating system file mode (aka file permissions) of the + // resource. + Mode os.FileMode `json:"mode"` + + // SHA1 represents the SHA-1 hash of the resource. + Checksum Checksum `json:"checksum"` + + // Size represents the file size of the resource. + SizeInBytes int64 `json:"size_in_bytes"` +} + +// MarshalJSON converts a resource into a Cloud Controller Resource. +func (r Resource) MarshalJSON() ([]byte, error) { + var ccResource struct { + FilePath string `json:"path,omitempty"` + Mode string `json:"mode,omitempty"` + Checksum Checksum `json:"checksum"` + SizeInBytes int64 `json:"size_in_bytes"` + } + + ccResource.FilePath = r.FilePath + ccResource.SizeInBytes = r.SizeInBytes + ccResource.Checksum = r.Checksum + ccResource.Mode = strconv.FormatUint(uint64(r.Mode), 8) + return json.Marshal(ccResource) +} + +func (r Resource) ToV2FormattedResource() V2FormattedResource { + return V2FormattedResource{ + Filename: r.FilePath, + Mode: r.Mode, + SHA1: r.Checksum.Value, + Size: r.SizeInBytes, + } +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Resource response. +func (r *Resource) UnmarshalJSON(data []byte) error { + var ccResource struct { + FilePath string `json:"path,omitempty"` + Mode string `json:"mode,omitempty"` + Checksum Checksum `json:"checksum"` + SizeInBytes int64 `json:"size_in_bytes"` + } + + err := cloudcontroller.DecodeJSON(data, &ccResource) + if err != nil { + return err + } + + r.FilePath = ccResource.FilePath + r.SizeInBytes = ccResource.SizeInBytes + r.Checksum = ccResource.Checksum + mode, err := strconv.ParseUint(ccResource.Mode, 8, 32) + if err != nil { + return err + } + + r.Mode = os.FileMode(mode) + return nil +} + +func (client Client) ResourceMatch(resources []Resource) ([]Resource, Warnings, error) { + var responseBody map[string][]Resource + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostResourceMatchesRequest, + RequestBody: map[string][]Resource{"resources": resources}, + ResponseBody: &responseBody, + }) + + return responseBody["resources"], warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/revisions.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/revisions.go new file mode 100644 index 0000000..67b14a0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/revisions.go @@ -0,0 +1,37 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) GetApplicationRevisions(appGUID string, query ...Query) ([]resources.Revision, Warnings, error) { + var revisions []resources.Revision + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationRevisionsRequest, + Query: query, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: resources.Revision{}, + AppendToList: func(item interface{}) error { + revisions = append(revisions, item.(resources.Revision)) + return nil + }, + }) + return revisions, warnings, err +} + +func (client *Client) GetApplicationRevisionsDeployed(appGUID string) ([]resources.Revision, Warnings, error) { + var revisions []resources.Revision + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationRevisionsDeployedRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: resources.Revision{}, + AppendToList: func(item interface{}) error { + revisions = append(revisions, item.(resources.Revision)) + return nil + }, + }) + return revisions, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/role.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/role.go new file mode 100644 index 0000000..7e12f96 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/role.go @@ -0,0 +1,44 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CreateRole(roleSpec resources.Role) (resources.Role, Warnings, error) { + var responseBody resources.Role + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostRoleRequest, + RequestBody: roleSpec, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) DeleteRole(roleGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteRoleRequest, + URIParams: internal.Params{"role_guid": roleGUID}, + }) + + return jobURL, warnings, err +} + +// GetRoles lists roles with optional filters & includes. +func (client *Client) GetRoles(query ...Query) ([]resources.Role, IncludedResources, Warnings, error) { + var roles []resources.Role + + includedResources, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetRolesRequest, + Query: query, + ResponseBody: resources.Role{}, + AppendToList: func(item interface{}) error { + roles = append(roles, item.(resources.Role)) + return nil + }, + }) + + return roles, includedResources, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route.go new file mode 100644 index 0000000..b40aed9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route.go @@ -0,0 +1,150 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client Client) CreateRoute(route resources.Route) (resources.Route, Warnings, error) { + var responseBody resources.Route + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostRouteRequest, + RequestBody: route, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) DeleteOrphanedRoutes(spaceGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteOrphanedRoutesRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + Query: []Query{{Key: UnmappedFilter, Values: []string{"true"}}}, + }) + + return jobURL, warnings, err +} + +func (client Client) DeleteRoute(routeGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteRouteRequest, + URIParams: internal.Params{"route_guid": routeGUID}, + }) + + return jobURL, warnings, err +} + +func (client Client) GetApplicationRoutes(appGUID string) ([]resources.Route, Warnings, error) { + var routes []resources.Route + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationRoutesRequest, + URIParams: internal.Params{"app_guid": appGUID}, + ResponseBody: resources.Route{}, + AppendToList: func(item interface{}) error { + routes = append(routes, item.(resources.Route)) + return nil + }, + }) + + return routes, warnings, err +} + +func (client Client) GetRouteDestinations(routeGUID string) ([]resources.RouteDestination, Warnings, error) { + var responseBody struct { + Destinations []resources.RouteDestination `json:"destinations"` + } + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetRouteDestinationsRequest, + URIParams: internal.Params{"route_guid": routeGUID}, + ResponseBody: &responseBody, + }) + + return responseBody.Destinations, warnings, err +} + +func (client Client) GetRoutes(query ...Query) ([]resources.Route, Warnings, error) { + var routes []resources.Route + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetRoutesRequest, + Query: query, + ResponseBody: resources.Route{}, + AppendToList: func(item interface{}) error { + routes = append(routes, item.(resources.Route)) + return nil + }, + }) + + return routes, warnings, err +} + +func (client Client) MapRoute(routeGUID string, appGUID string, destinationProtocol string) (Warnings, error) { + type destinationProcess struct { + ProcessType string `json:"process_type"` + } + + type destinationApp struct { + GUID string `json:"guid"` + Process *destinationProcess `json:"process,omitempty"` + } + type destination struct { + App destinationApp `json:"app"` + Protocol string `json:"protocol,omitempty"` + } + + type body struct { + Destinations []destination `json:"destinations"` + } + + requestBody := body{ + Destinations: []destination{ + { + App: destinationApp{GUID: appGUID}, + }, + }, + } + if destinationProtocol != "" { + requestBody.Destinations[0].Protocol = destinationProtocol + } + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.MapRouteRequest, + URIParams: internal.Params{"route_guid": routeGUID}, + RequestBody: &requestBody, + }) + + return warnings, err +} + +func (client Client) UnmapRoute(routeGUID string, destinationGUID string) (Warnings, error) { + var responseBody resources.Build + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.UnmapRouteRequest, + URIParams: internal.Params{"route_guid": routeGUID, "destination_guid": destinationGUID}, + ResponseBody: &responseBody, + }) + + return warnings, err +} + +func (client Client) UpdateDestination(routeGUID string, destinationGUID string, protocol string) (Warnings, error) { + type body struct { + Protocol string `json:"protocol"` + } + requestBody := body{ + Protocol: protocol, + } + var responseBody resources.Build + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchDestinationRequest, + URIParams: internal.Params{"route_guid": routeGUID, "destination_guid": destinationGUID}, + RequestBody: &requestBody, + ResponseBody: &responseBody, + }) + return warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route_binding.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route_binding.go new file mode 100644 index 0000000..643479d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/route_binding.go @@ -0,0 +1,36 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CreateRouteBinding(binding resources.RouteBinding) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.PostRouteBindingRequest, + RequestBody: binding, + }) +} + +func (client *Client) GetRouteBindings(query ...Query) ([]resources.RouteBinding, IncludedResources, Warnings, error) { + var result []resources.RouteBinding + + included, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetRouteBindingsRequest, + Query: query, + ResponseBody: resources.RouteBinding{}, + AppendToList: func(item interface{}) error { + result = append(result, item.(resources.RouteBinding)) + return nil + }, + }) + + return result, included, warnings, err +} + +func (client *Client) DeleteRouteBinding(guid string) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.DeleteRouteBindingRequest, + URIParams: internal.Params{"route_binding_guid": guid}, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/security_group.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/security_group.go new file mode 100644 index 0000000..1880769 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/security_group.go @@ -0,0 +1,142 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CreateSecurityGroup(securityGroup resources.SecurityGroup) (resources.SecurityGroup, Warnings, error) { + var responseBody resources.SecurityGroup + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSecurityGroupRequest, + RequestBody: securityGroup, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetSecurityGroups(queries ...Query) ([]resources.SecurityGroup, Warnings, error) { + var securityGroups []resources.SecurityGroup + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetSecurityGroupsRequest, + Query: queries, + ResponseBody: resources.SecurityGroup{}, + AppendToList: func(item interface{}) error { + securityGroups = append(securityGroups, item.(resources.SecurityGroup)) + return nil + }, + }) + + return securityGroups, warnings, err +} + +func (client *Client) GetRunningSecurityGroups(spaceGUID string, queries ...Query) ([]resources.SecurityGroup, Warnings, error) { + var securityGroups []resources.SecurityGroup + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetSpaceRunningSecurityGroupsRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + Query: queries, + ResponseBody: resources.SecurityGroup{}, + AppendToList: func(item interface{}) error { + securityGroups = append(securityGroups, item.(resources.SecurityGroup)) + return nil + }, + }) + + return securityGroups, warnings, err +} + +func (client *Client) GetStagingSecurityGroups(spaceGUID string, queries ...Query) ([]resources.SecurityGroup, Warnings, error) { + var securityGroups []resources.SecurityGroup + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetSpaceStagingSecurityGroupsRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + Query: queries, + ResponseBody: resources.SecurityGroup{}, + AppendToList: func(item interface{}) error { + securityGroups = append(securityGroups, item.(resources.SecurityGroup)) + return nil + }, + }) + + return securityGroups, warnings, err +} + +func (client *Client) UnbindSecurityGroupRunningSpace(securityGroupGUID string, spaceGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSecurityGroupRunningSpaceRequest, + URIParams: internal.Params{ + "security_group_guid": securityGroupGUID, + "space_guid": spaceGUID, + }, + }) + + return warnings, err +} + +func (client *Client) UnbindSecurityGroupStagingSpace(securityGroupGUID string, spaceGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSecurityGroupStagingSpaceRequest, + URIParams: internal.Params{ + "security_group_guid": securityGroupGUID, + "space_guid": spaceGUID, + }, + }) + + return warnings, err +} + +func (client *Client) UpdateSecurityGroupRunningSpace(securityGroupGUID string, spaceGUIDs []string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSecurityGroupRunningSpaceRequest, + URIParams: internal.Params{"security_group_guid": securityGroupGUID}, + RequestBody: resources.RelationshipList{ + GUIDs: spaceGUIDs, + }, + }) + + return warnings, err +} + +func (client *Client) UpdateSecurityGroupStagingSpace(securityGroupGUID string, spaceGUIDs []string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSecurityGroupStagingSpaceRequest, + URIParams: internal.Params{"security_group_guid": securityGroupGUID}, + RequestBody: resources.RelationshipList{ + GUIDs: spaceGUIDs, + }, + }) + + return warnings, err +} + +func (client *Client) UpdateSecurityGroup(securityGroup resources.SecurityGroup) (resources.SecurityGroup, Warnings, error) { + var responseBody resources.SecurityGroup + + securityGroupGUID := securityGroup.GUID + securityGroup.GUID = "" + securityGroup.Name = "" + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchSecurityGroupRequest, + URIParams: internal.Params{"security_group_guid": securityGroupGUID}, + RequestBody: securityGroup, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) DeleteSecurityGroup(securityGroupGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSecurityGroupRequest, + URIParams: internal.Params{"security_group_guid": securityGroupGUID}, + }) + + return jobURL, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_broker.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_broker.go new file mode 100644 index 0000000..c61b0d9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_broker.go @@ -0,0 +1,66 @@ +package ccv3 + +import ( + "errors" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateServiceBroker registers a new service broker. +func (client *Client) CreateServiceBroker(serviceBroker resources.ServiceBroker) (JobURL, Warnings, error) { + serviceBroker.CredentialsType = resources.ServiceBrokerBasicCredentials + + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostServiceBrokerRequest, + RequestBody: serviceBroker, + }) + + return jobURL, warnings, err +} + +// DeleteServiceBroker deletes a named service broker +func (client *Client) DeleteServiceBroker(serviceBrokerGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServiceBrokerRequest, + URIParams: internal.Params{"service_broker_guid": serviceBrokerGUID}, + }) + + return jobURL, warnings, err +} + +// GetServiceBrokers lists service brokers. +func (client *Client) GetServiceBrokers(query ...Query) ([]resources.ServiceBroker, Warnings, error) { + var result []resources.ServiceBroker + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetServiceBrokersRequest, + Query: query, + ResponseBody: resources.ServiceBroker{}, + AppendToList: func(item interface{}) error { + result = append(result, item.(resources.ServiceBroker)) + return nil + }, + }) + + return result, warnings, err +} + +// UpdateServiceBroker updates an existing service broker. +func (client *Client) UpdateServiceBroker(serviceBrokerGUID string, serviceBroker resources.ServiceBroker) (JobURL, Warnings, error) { + if (serviceBroker.Username == "" && serviceBroker.Password != "") || (serviceBroker.Username != "" && serviceBroker.Password == "") { + return "", nil, errors.New("Incorrect usage: both username and password must be defined in order to do an update") + } + + if serviceBroker.Username != "" && serviceBroker.Password != "" { + serviceBroker.CredentialsType = resources.ServiceBrokerBasicCredentials + } + + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchServiceBrokerRequest, + URIParams: internal.Params{"service_broker_guid": serviceBrokerGUID}, + RequestBody: serviceBroker, + }) + + return jobURL, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_credential_binding.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_credential_binding.go new file mode 100644 index 0000000..8d39102 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_credential_binding.go @@ -0,0 +1,60 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/lookuptable" +) + +func (client *Client) CreateServiceCredentialBinding(binding resources.ServiceCredentialBinding) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.PostServiceCredentialBindingRequest, + RequestBody: binding, + }) +} + +// GetServiceCredentialBindings queries the CC API with the specified query +// and returns a slice of ServiceCredentialBindings. Additionally if Apps are +// included in the API response (by having `include=app` in the query) then the +// App names will be added into each ServiceCredentialBinding for app bindings +func (client *Client) GetServiceCredentialBindings(query ...Query) ([]resources.ServiceCredentialBinding, Warnings, error) { + var result []resources.ServiceCredentialBinding + + included, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetServiceCredentialBindingsRequest, + Query: query, + ResponseBody: resources.ServiceCredentialBinding{}, + AppendToList: func(item interface{}) error { + result = append(result, item.(resources.ServiceCredentialBinding)) + return nil + }, + }) + + if len(included.Apps) > 0 { + appLookup := lookuptable.AppFromGUID(included.Apps) + + for i := range result { + result[i].AppName = appLookup[result[i].AppGUID].Name + result[i].AppSpaceGUID = appLookup[result[i].AppGUID].SpaceGUID + } + } + + return result, warnings, err +} + +func (client *Client) DeleteServiceCredentialBinding(guid string) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServiceCredentialBindingRequest, + URIParams: internal.Params{"service_credential_binding_guid": guid}, + }) +} + +func (client *Client) GetServiceCredentialBindingDetails(guid string) (details resources.ServiceCredentialBindingDetails, warnings Warnings, err error) { + _, warnings, err = client.MakeRequest(RequestParams{ + RequestName: internal.GetServiceCredentialBindingDetailsRequest, + URIParams: internal.Params{"service_credential_binding_guid": guid}, + ResponseBody: &details, + }) + + return +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_instance.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_instance.go new file mode 100644 index 0000000..5a0b590 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_instance.go @@ -0,0 +1,171 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/cli/util/lookuptable" +) + +type SpaceWithOrganization struct { + SpaceGUID string + SpaceName string + OrganizationName string +} + +// GetServiceInstances lists service instances with optional filters. +func (client *Client) GetServiceInstances(query ...Query) ([]resources.ServiceInstance, IncludedResources, Warnings, error) { + var result []resources.ServiceInstance + + included, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetServiceInstancesRequest, + Query: query, + ResponseBody: resources.ServiceInstance{}, + AppendToList: func(item interface{}) error { + result = append(result, item.(resources.ServiceInstance)) + return nil + }, + }) + + return result, included, warnings, err +} + +func (client *Client) GetServiceInstanceByNameAndSpace(name, spaceGUID string, query ...Query) (resources.ServiceInstance, IncludedResources, Warnings, error) { + query = append(query, + Query{ + Key: NameFilter, + Values: []string{name}, + }, + Query{ + Key: SpaceGUIDFilter, + Values: []string{spaceGUID}, + }, + ) + + instances, included, warnings, err := client.GetServiceInstances(query...) + + if err != nil { + return resources.ServiceInstance{}, IncludedResources{}, warnings, err + } + + if len(instances) == 0 { + return resources.ServiceInstance{}, + IncludedResources{}, + warnings, + ccerror.ServiceInstanceNotFoundError{ + Name: name, + SpaceGUID: spaceGUID, + } + } + + return instances[0], included, warnings, nil +} + +func (client *Client) GetServiceInstanceParameters(serviceInstanceGUID string) (parameters types.JSONObject, warnings Warnings, err error) { + _, warnings, err = client.MakeRequest(RequestParams{ + RequestName: internal.GetServiceInstanceParametersRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + ResponseBody: ¶meters, + }) + + return +} + +func (client *Client) CreateServiceInstance(serviceInstance resources.ServiceInstance) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.PostServiceInstanceRequest, + RequestBody: serviceInstance, + }) +} + +func (client *Client) UpdateServiceInstance(serviceInstanceGUID string, serviceInstanceUpdates resources.ServiceInstance) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.PatchServiceInstanceRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + RequestBody: serviceInstanceUpdates, + }) +} + +func (client *Client) DeleteServiceInstance(serviceInstanceGUID string, query ...Query) (JobURL, Warnings, error) { + return client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServiceInstanceRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + Query: query, + }) +} + +// ShareServiceInstanceToSpaces will create a sharing relationship between +// the service instance and the shared-to space for each space provided. +func (client *Client) ShareServiceInstanceToSpaces(serviceInstanceGUID string, spaceGUIDs []string) (resources.RelationshipList, Warnings, error) { + var responseBody resources.RelationshipList + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostServiceInstanceRelationshipsSharedSpacesRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + RequestBody: resources.RelationshipList{GUIDs: spaceGUIDs}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// UnshareServiceInstanceFromSpace will delete the sharing relationship +// between the service instance and the shared-to space provided. +func (client *Client) UnshareServiceInstanceFromSpace(serviceInstanceGUID string, spaceGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServiceInstanceRelationshipsSharedSpaceRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID, "space_guid": spaceGUID}, + }) + + return warnings, err +} + +// GetServiceInstanceSharedSpaces will fetch relationships between +// a service instance and the shared-to spaces for that service. +func (client *Client) GetServiceInstanceSharedSpaces(serviceInstanceGUID string) ([]SpaceWithOrganization, Warnings, error) { + var responseBody resources.SharedToSpacesListWrapper + query := []Query{ + { + Key: FieldsSpace, + Values: []string{"guid", "name", "relationships.organization"}, + }, + { + Key: FieldsSpaceOrganization, + Values: []string{"guid", "name"}, + }, + } + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetServiceInstanceRelationshipsSharedSpacesRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + Query: query, + ResponseBody: &responseBody, + }) + return mapRelationshipsToSpaces(responseBody), warnings, err +} + +func (client *Client) GetServiceInstanceUsageSummary(serviceInstanceGUID string) ([]resources.ServiceInstanceUsageSummary, Warnings, error) { + var result resources.ServiceInstanceUsageSummaryList + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetServiceInstanceSharedSpacesUsageSummaryRequest, + URIParams: internal.Params{"service_instance_guid": serviceInstanceGUID}, + ResponseBody: &result, + }) + return result.UsageSummary, warnings, err +} + +func mapRelationshipsToSpaces(sharedToSpaces resources.SharedToSpacesListWrapper) []SpaceWithOrganization { + var spacesToReturn []SpaceWithOrganization + + guidToOrgNameLookup := lookuptable.NameFromGUID(sharedToSpaces.Organizations) + + for _, s := range sharedToSpaces.Spaces { + org := s.Relationships[constant.RelationshipTypeOrganization] + space := SpaceWithOrganization{SpaceGUID: s.GUID, SpaceName: s.Name, OrganizationName: guidToOrgNameLookup[org.GUID]} + spacesToReturn = append(spacesToReturn, space) + } + + return spacesToReturn +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_offering.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_offering.go new file mode 100644 index 0000000..86567c5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_offering.go @@ -0,0 +1,92 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/lookuptable" +) + +// GetServiceOffering lists service offering with optional filters. +func (client *Client) GetServiceOfferings(query ...Query) ([]resources.ServiceOffering, Warnings, error) { + var result []resources.ServiceOffering + + query = append(query, Query{Key: FieldsServiceBroker, Values: []string{"name", "guid"}}) + + included, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetServiceOfferingsRequest, + Query: query, + ResponseBody: resources.ServiceOffering{}, + AppendToList: func(item interface{}) error { + result = append(result, item.(resources.ServiceOffering)) + return nil + }, + }) + + brokerNameLookup := lookuptable.NameFromGUID(included.ServiceBrokers) + + for i, _ := range result { + result[i].ServiceBrokerName = brokerNameLookup[result[i].ServiceBrokerGUID] + } + + return result, warnings, err +} + +func (client *Client) GetServiceOfferingByGUID(guid string) (resources.ServiceOffering, Warnings, error) { + if guid == "" { + return resources.ServiceOffering{}, nil, ccerror.ServiceOfferingNotFoundError{} + } + + var result resources.ServiceOffering + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetServiceOfferingRequest, + URIParams: internal.Params{"service_offering_guid": guid}, + ResponseBody: &result, + }) + + return result, warnings, err +} + +func (client *Client) GetServiceOfferingByNameAndBroker(serviceOfferingName, serviceBrokerName string) (resources.ServiceOffering, Warnings, error) { + query := []Query{{Key: NameFilter, Values: []string{serviceOfferingName}}} + if serviceBrokerName != "" { + query = append(query, Query{Key: ServiceBrokerNamesFilter, Values: []string{serviceBrokerName}}) + } + + offerings, warnings, err := client.GetServiceOfferings(query...) + if err != nil { + return resources.ServiceOffering{}, warnings, err + } + + switch len(offerings) { + case 0: + return resources.ServiceOffering{}, warnings, ccerror.ServiceOfferingNotFoundError{ + ServiceOfferingName: serviceOfferingName, + ServiceBrokerName: serviceBrokerName, + } + case 1: + return offerings[0], warnings, nil + default: + return resources.ServiceOffering{}, warnings, ccerror.ServiceOfferingNameAmbiguityError{ + ServiceOfferingName: serviceOfferingName, + ServiceBrokerNames: extractServiceBrokerNames(offerings), + } + } +} + +func (client *Client) PurgeServiceOffering(serviceOfferingGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServiceOfferingRequest, + URIParams: internal.Params{"service_offering_guid": serviceOfferingGUID}, + Query: []Query{{Key: Purge, Values: []string{"true"}}}, + }) + return warnings, err +} + +func extractServiceBrokerNames(offerings []resources.ServiceOffering) (result []string) { + for _, o := range offerings { + result = append(result, o.ServiceBrokerName) + } + return +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan.go new file mode 100644 index 0000000..e61a462 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan.go @@ -0,0 +1,174 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" + "code.cloudfoundry.org/cli/util/lookuptable" +) + +func (client *Client) GetServicePlanByGUID(guid string) (resources.ServicePlan, Warnings, error) { + if guid == "" { + return resources.ServicePlan{}, nil, ccerror.ServicePlanNotFound{} + } + + var result resources.ServicePlan + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetServicePlanRequest, + URIParams: internal.Params{"service_plan_guid": guid}, + ResponseBody: &result, + }) + + return result, warnings, err +} + +// GetServicePlans lists service plan with optional filters. +func (client *Client) GetServicePlans(query ...Query) ([]resources.ServicePlan, Warnings, error) { + plans, _, warnings, err := client.getServicePlans(query...) + return plans, warnings, err +} + +func (client *Client) getServicePlans(query ...Query) ([]resources.ServicePlan, IncludedResources, Warnings, error) { + var plans []resources.ServicePlan + + included, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetServicePlansRequest, + Query: query, + ResponseBody: resources.ServicePlan{}, + AppendToList: func(item interface{}) error { + plans = append(plans, item.(resources.ServicePlan)) + return nil + }, + }) + + return plans, included, warnings, err +} + +type ServicePlanWithSpaceAndOrganization struct { + // GUID is a unique service plan identifier. + GUID string + // Name is the name of the service plan. + Name string + // VisibilityType can be "public", "admin", "organization" or "space" + VisibilityType resources.ServicePlanVisibilityType + // ServicePlanGUID is the GUID of the service offering + ServiceOfferingGUID string + + SpaceGUID string + + SpaceName string + + OrganizationName string +} + +type planSpaceDetails struct{ spaceName, orgName string } + +func (client *Client) GetServicePlansWithSpaceAndOrganization(query ...Query) ([]ServicePlanWithSpaceAndOrganization, Warnings, error) { + query = append(query, Query{ + Key: Include, + Values: []string{"space.organization"}, + }) + + plans, included, warnings, err := client.getServicePlans(query...) + + spaceDetailsFromGUID := computeSpaceDetailsTable(included) + + var enrichedPlans []ServicePlanWithSpaceAndOrganization + for _, plan := range plans { + sd := spaceDetailsFromGUID[plan.SpaceGUID] + + enrichedPlans = append(enrichedPlans, ServicePlanWithSpaceAndOrganization{ + GUID: plan.GUID, + Name: plan.Name, + VisibilityType: plan.VisibilityType, + ServiceOfferingGUID: plan.ServiceOfferingGUID, + SpaceGUID: plan.SpaceGUID, + SpaceName: sd.spaceName, + OrganizationName: sd.orgName, + }) + } + + return enrichedPlans, warnings, err +} + +type ServiceOfferingWithPlans struct { + // GUID is a unique service offering identifier. + GUID string + // Name is the name of the service offering. + Name string + // Description of the service offering + Description string + // ServiceBrokerName is the name of the service broker + ServiceBrokerName string + + // List of service plans that this service offering provides + Plans []resources.ServicePlan +} + +func (client *Client) GetServicePlansWithOfferings(query ...Query) ([]ServiceOfferingWithPlans, Warnings, error) { + query = append(query, + Query{ + Key: Include, + Values: []string{"service_offering"}, + }, + Query{ + Key: FieldsServiceOfferingServiceBroker, + Values: []string{"name,guid"}, + }, + ) + + plans, included, warnings, err := client.getServicePlans(query...) + if err != nil { + return nil, warnings, err + } + + var offeringsWithPlans []ServiceOfferingWithPlans + offeringGUIDLookup := make(map[string]int) + + indexOfOffering := func(serviceOfferingGUID string) int { + if i, ok := offeringGUIDLookup[serviceOfferingGUID]; ok { + return i + } + + i := len(offeringsWithPlans) + offeringGUIDLookup[serviceOfferingGUID] = i + offeringsWithPlans = append(offeringsWithPlans, ServiceOfferingWithPlans{GUID: serviceOfferingGUID}) + + return i + } + + brokerNameLookup := lookuptable.NameFromGUID(included.ServiceBrokers) + + for _, p := range plans { + i := indexOfOffering(p.ServiceOfferingGUID) + offeringsWithPlans[i].Plans = append(offeringsWithPlans[i].Plans, p) + } + + for _, o := range included.ServiceOfferings { + i := indexOfOffering(o.GUID) + offeringsWithPlans[i].Name = o.Name + offeringsWithPlans[i].Description = o.Description + offeringsWithPlans[i].ServiceBrokerName = brokerNameLookup[o.ServiceBrokerGUID] + } + + return offeringsWithPlans, warnings, nil +} + +func computeSpaceDetailsTable(included IncludedResources) map[string]planSpaceDetails { + orgNameFromGUID := lookuptable.NameFromGUID(included.Organizations) + + spaceDetailsFromGUID := make(map[string]planSpaceDetails) + for _, space := range included.Spaces { + details := planSpaceDetails{spaceName: space.Name} + + if orgRelationship, ok := space.Relationships[constant.RelationshipTypeOrganization]; ok { + details.orgName = orgNameFromGUID[orgRelationship.GUID] + } + + spaceDetailsFromGUID[space.GUID] = details + } + + return spaceDetailsFromGUID +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan_visibility.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan_visibility.go new file mode 100644 index 0000000..89fb79b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/service_plan_visibility.go @@ -0,0 +1,41 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) GetServicePlanVisibility(servicePlanGUID string) (resources.ServicePlanVisibility, Warnings, error) { + var result resources.ServicePlanVisibility + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetServicePlanVisibilityRequest, + URIParams: internal.Params{"service_plan_guid": servicePlanGUID}, + ResponseBody: &result, + }) + + return result, warnings, err +} + +func (client *Client) UpdateServicePlanVisibility(servicePlanGUID string, planVisibility resources.ServicePlanVisibility) (resources.ServicePlanVisibility, Warnings, error) { + var result resources.ServicePlanVisibility + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostServicePlanVisibilityRequest, + URIParams: internal.Params{"service_plan_guid": servicePlanGUID}, + RequestBody: planVisibility, + ResponseBody: &result, + }) + + return result, warnings, err +} + +func (client *Client) DeleteServicePlanVisibility(servicePlanGUID, organizationGUID string) (Warnings, error) { + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteServicePlanVisibilityRequest, + URIParams: internal.Params{"service_plan_guid": servicePlanGUID, "organization_guid": organizationGUID}, + }) + + return warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/sidecar.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/sidecar.go new file mode 100644 index 0000000..f9e59c9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/sidecar.go @@ -0,0 +1,22 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) GetProcessSidecars(processGuid string) ([]resources.Sidecar, Warnings, error) { + var sidecars []resources.Sidecar + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetProcessSidecarsRequest, + URIParams: internal.Params{"process_guid": processGuid}, + ResponseBody: resources.Sidecar{}, + AppendToList: func(item interface{}) error { + sidecars = append(sidecars, item.(resources.Sidecar)) + return nil + }, + }) + + return sidecars, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space.go new file mode 100644 index 0000000..cad3173 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space.go @@ -0,0 +1,61 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) CreateSpace(space resources.Space) (resources.Space, Warnings, error) { + var responseBody resources.Space + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSpaceRequest, + RequestBody: space, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) DeleteSpace(spaceGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSpaceRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + }) + + return jobURL, warnings, err +} + +// GetSpaces lists spaces with optional filters. +func (client *Client) GetSpaces(query ...Query) ([]resources.Space, IncludedResources, Warnings, error) { + var returnedResources []resources.Space + + includedResources, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetSpacesRequest, + Query: query, + ResponseBody: resources.Space{}, + AppendToList: func(item interface{}) error { + returnedResources = append(returnedResources, item.(resources.Space)) + return nil + }, + }) + + return returnedResources, includedResources, warnings, err +} + +func (client *Client) UpdateSpace(space resources.Space) (resources.Space, Warnings, error) { + spaceGUID := space.GUID + space.GUID = "" + space.Relationships = nil + + var responseBody resources.Space + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchSpaceRequest, + URIParams: internal.Params{"space_guid": spaceGUID}, + RequestBody: space, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_feature.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_feature.go new file mode 100644 index 0000000..462295b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_feature.go @@ -0,0 +1,30 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client *Client) GetSpaceFeature(spaceGUID string, featureName string) (bool, Warnings, error) { + var responseBody resources.SpaceFeature + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetSpaceFeatureRequest, + URIParams: internal.Params{"space_guid": spaceGUID, "feature": featureName}, + ResponseBody: &responseBody, + }) + + return responseBody.Enabled, warnings, err +} + +func (client *Client) UpdateSpaceFeature(spaceGUID string, enabled bool, featureName string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchSpaceFeaturesRequest, + URIParams: internal.Params{"space_guid": spaceGUID, "feature": featureName}, + RequestBody: struct { + Enabled bool `json:"enabled"` + }{Enabled: enabled}, + }) + + return warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_quota.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_quota.go new file mode 100644 index 0000000..b8fb01a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/space_quota.go @@ -0,0 +1,93 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +func (client Client) ApplySpaceQuota(quotaGUID string, spaceGUID string) (resources.RelationshipList, Warnings, error) { + var responseBody resources.RelationshipList + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSpaceQuotaRelationshipsRequest, + URIParams: internal.Params{"quota_guid": quotaGUID}, + RequestBody: resources.RelationshipList{GUIDs: []string{spaceGUID}}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) CreateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, Warnings, error) { + var responseBody resources.SpaceQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostSpaceQuotaRequest, + RequestBody: spaceQuota, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client Client) DeleteSpaceQuota(spaceQuotaGUID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSpaceQuotaRequest, + URIParams: internal.Params{"quota_guid": spaceQuotaGUID}, + }) + + return jobURL, warnings, err +} + +func (client Client) GetSpaceQuota(spaceQuotaGUID string) (resources.SpaceQuota, Warnings, error) { + var responseBody resources.SpaceQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetSpaceQuotaRequest, + URIParams: internal.Params{"quota_guid": spaceQuotaGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetSpaceQuotas(query ...Query) ([]resources.SpaceQuota, Warnings, error) { + var spaceQuotas []resources.SpaceQuota + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetSpaceQuotasRequest, + Query: query, + ResponseBody: resources.SpaceQuota{}, + AppendToList: func(item interface{}) error { + spaceQuotas = append(spaceQuotas, item.(resources.SpaceQuota)) + return nil + }, + }) + + return spaceQuotas, warnings, err +} + +func (client *Client) UnsetSpaceQuota(spaceQuotaGUID, spaceGUID string) (Warnings, error) { + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteSpaceQuotaFromSpaceRequest, + URIParams: internal.Params{"quota_guid": spaceQuotaGUID, "space_guid": spaceGUID}, + }) + + return warnings, err +} + +func (client *Client) UpdateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, Warnings, error) { + spaceQuotaGUID := spaceQuota.GUID + spaceQuota.GUID = "" + + var responseBody resources.SpaceQuota + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PatchSpaceQuotaRequest, + URIParams: internal.Params{"quota_guid": spaceQuotaGUID}, + RequestBody: spaceQuota, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/stack.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/stack.go new file mode 100644 index 0000000..e1704a3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/stack.go @@ -0,0 +1,23 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// GetStacks lists stacks with optional filters. +func (client *Client) GetStacks(query ...Query) ([]resources.Stack, Warnings, error) { + var stacks []resources.Stack + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetStacksRequest, + Query: query, + ResponseBody: resources.Stack{}, + AppendToList: func(item interface{}) error { + stacks = append(stacks, item.(resources.Stack)) + return nil + }, + }) + + return stacks, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/target.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/target.go new file mode 100644 index 0000000..9d83183 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/target.go @@ -0,0 +1,33 @@ +package ccv3 + +import ( + "time" +) + +// TargetSettings represents configuration for establishing a connection to the +// Cloud Controller server. +type TargetSettings struct { + // DialTimeout is the DNS timeout used to make all requests to the Cloud + // Controller. + DialTimeout time.Duration + + // SkipSSLValidation controls whether a client verifies the server's + // certificate chain and host name. If SkipSSLValidation is true, TLS accepts + // any certificate presented by the server and any host name in that + // certificate for *all* client requests going forward. + // + // In this mode, TLS is susceptible to man-in-the-middle attacks. This should + // be used only for testing. + SkipSSLValidation bool + + // URL is a fully qualified URL to the Cloud Controller API. + URL string +} + +// TargetCF sets the client to use the Cloud Controller specified in the +// configuration. Any other configuration is also applied to the client. +func (client *Client) TargetCF(settings TargetSettings) { + client.CloudControllerURL = settings.URL + client.InitializeConnection(settings) + client.InitializeRouter(settings.URL) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/task.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/task.go new file mode 100644 index 0000000..2b67040 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/task.go @@ -0,0 +1,55 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateApplication resources.Task runs a command in the Application environment +// associated with the provided Application GUID. +func (client *Client) CreateApplicationTask(appGUID string, task resources.Task) (resources.Task, Warnings, error) { + var responseBody resources.Task + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostApplicationTasksRequest, + URIParams: internal.Params{"app_guid": appGUID}, + RequestBody: task, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetApplicationTasks returns a list of tasks associated with the provided +// application GUID. Results can be filtered by providing URL queries. +func (client *Client) GetApplicationTasks(appGUID string, query ...Query) ([]resources.Task, Warnings, error) { + var tasks []resources.Task + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetApplicationTasksRequest, + URIParams: internal.Params{"app_guid": appGUID}, + Query: query, + ResponseBody: resources.Task{}, + AppendToList: func(item interface{}) error { + tasks = append(tasks, item.(resources.Task)) + return nil + }, + }) + + return tasks, warnings, err +} + +// UpdateTaskCancel cancels a task. +func (client *Client) UpdateTaskCancel(taskGUID string) (resources.Task, Warnings, error) { + var responseBody resources.Task + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PutTaskCancelRequest, + URIParams: internal.Params{ + "task_guid": taskGUID, + }, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/user.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/user.go new file mode 100644 index 0000000..7b2aa8e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/user.go @@ -0,0 +1,73 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/resources" +) + +// CreateUser creates a new Cloud Controller User from the provided UAA user +// ID. +func (client *Client) CreateUser(uaaUserID string) (resources.User, Warnings, error) { + type userRequestBody struct { + GUID string `json:"guid"` + } + + user := userRequestBody{GUID: uaaUserID} + var responseBody resources.User + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostUserRequest, + RequestBody: user, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) DeleteUser(uaaUserID string) (JobURL, Warnings, error) { + jobURL, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteUserRequest, + URIParams: internal.Params{"user_guid": uaaUserID}, + }) + + return jobURL, warnings, err +} + +func (client *Client) GetUser(userGUID string) (resources.User, Warnings, error) { + var responseBody resources.User + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetUserRequest, + URIParams: internal.Params{"user_guid": userGUID}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +func (client *Client) GetUsers(query ...Query) ([]resources.User, Warnings, error) { + var users []resources.User + + _, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetUsersRequest, + Query: query, + ResponseBody: resources.User{}, + AppendToList: func(item interface{}) error { + users = append(users, item.(resources.User)) + return nil + }, + }) + + return users, warnings, err +} + +func (client *Client) WhoAmI() (resources.K8sUser, Warnings, error) { + var user resources.K8sUser + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.WhoAmI, + ResponseBody: &user, + }) + + return user, warnings, err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/v2_formatted_resource.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/v2_formatted_resource.go new file mode 100644 index 0000000..2107a90 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/v2_formatted_resource.go @@ -0,0 +1,73 @@ +package ccv3 + +import ( + "encoding/json" + "os" + "strconv" + + "code.cloudfoundry.org/cli/api/cloudcontroller" +) + +// V2FormattedResource represents a Cloud Controller Resource that still has the same shape as the V2 Resource. +// The v3 package upload endpoint understands both the V2 shape and the new V3 shape. +// The v3 resource matching endpoint only understands the new V3 shape. +// +// Deprecated: Use Resource going forward. We anticipate that this struct will only be used +// by the v6 cli's v3-push command, which is experimental. +type V2FormattedResource struct { + + // Filename is the name of the resource. + Filename string `json:"fn"` + + // Mode is the operating system file mode (aka file permissions) of the + // resource. + Mode os.FileMode `json:"mode"` + + // SHA1 represents the SHA-1 hash of the resource. + SHA1 string `json:"sha1"` + + // Size represents the file size of the resource. + Size int64 `json:"size"` +} + +// MarshalJSON converts a resource into a Cloud Controller V2FormattedResource. +func (r V2FormattedResource) MarshalJSON() ([]byte, error) { + var ccResource struct { + Filename string `json:"fn,omitempty"` + Mode string `json:"mode,omitempty"` + SHA1 string `json:"sha1"` + Size int64 `json:"size"` + } + + ccResource.Filename = r.Filename + ccResource.Size = r.Size + ccResource.SHA1 = r.SHA1 + ccResource.Mode = strconv.FormatUint(uint64(r.Mode), 8) + return json.Marshal(ccResource) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller V2FormattedResource response. +func (r *V2FormattedResource) UnmarshalJSON(data []byte) error { + var ccResource struct { + Filename string `json:"fn,omitempty"` + Mode string `json:"mode,omitempty"` + SHA1 string `json:"sha1"` + Size int64 `json:"size"` + } + + err := cloudcontroller.DecodeJSON(data, &ccResource) + if err != nil { + return err + } + + r.Filename = ccResource.Filename + r.Size = ccResource.Size + r.SHA1 = ccResource.SHA1 + mode, err := strconv.ParseUint(ccResource.Mode, 8, 32) + if err != nil { + return err + } + + r.Mode = os.FileMode(mode) + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/maximum_version.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/maximum_version.go new file mode 100644 index 0000000..8be3114 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/maximum_version.go @@ -0,0 +1,5 @@ +package ccversion + +const ( + MaxVersionServiceProviderV2 = "2.46.0" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/minimum_version.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/minimum_version.go new file mode 100644 index 0000000..524f740 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/ccversion/minimum_version.go @@ -0,0 +1,16 @@ +package ccversion + +const ( + MinSupportedV2ClientVersion = "2.128.0" + MinSupportedClientVersionV8 = "3.99.0" + + MinVersionUpdateServiceNameWhenPlanNotVisibleV2 = "2.131.0" + MinVersionUpdateServiceInstanceMaintenanceInfoV2 = "2.135.0" + MinVersionMaintenanceInfoInSummaryV2 = "2.138.0" + + MinVersionCreateServiceBrokerV3 = "3.72.0" + MinVersionCreateSpaceScopedServiceBrokerV3 = "3.75.0" + + MinVersionHTTP2RoutingV3 = "3.104.0" + MinVersionSpaceSupporterV3 = "3.104.0" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/cloud_controller_connection.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/cloud_controller_connection.go new file mode 100644 index 0000000..da37547 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/cloud_controller_connection.go @@ -0,0 +1,151 @@ +package cloudcontroller + +import ( + "crypto/x509" + "io/ioutil" + "net" + "net/http" + "net/url" + "strings" + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/util" +) + +// Config is for configuring a CloudControllerConnection. +type Config struct { + DialTimeout time.Duration + SkipSSLValidation bool +} + +// CloudControllerConnection represents a connection to the Cloud Controller +// server. +type CloudControllerConnection struct { + HTTPClient *http.Client + UserAgent string +} + +// NewConnection returns a new CloudControllerConnection with provided +// configuration. +func NewConnection(config Config) *CloudControllerConnection { + tr := &http.Transport{ + TLSClientConfig: util.NewTLSConfig(nil, config.SkipSSLValidation), + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + KeepAlive: 30 * time.Second, + Timeout: config.DialTimeout, + }).DialContext, + } + + return &CloudControllerConnection{ + HTTPClient: &http.Client{Transport: tr}, + } +} + +// Make performs the request and parses the response. +func (connection *CloudControllerConnection) Make(request *Request, passedResponse *Response) error { + // In case this function is called from a retry, passedResponse may already + // be populated with a previous response. We reset in case there's an HTTP + // error and we don't repopulate it in populateResponse. + passedResponse.reset() + + response, err := connection.HTTPClient.Do(request.Request) + if err != nil { + return connection.processRequestErrors(request.Request, err) + } + + return connection.populateResponse(response, passedResponse) +} + +func (*CloudControllerConnection) handleStatusCodes(response *http.Response, passedResponse *Response) error { + if response.StatusCode == http.StatusNoContent { + passedResponse.RawResponse = []byte("{}") + } else { + rawBytes, err := ioutil.ReadAll(response.Body) + defer response.Body.Close() + if err != nil { + return err + } + + passedResponse.RawResponse = rawBytes + } + + if response.StatusCode >= 400 { + return ccerror.RawHTTPStatusError{ + StatusCode: response.StatusCode, + RawResponse: passedResponse.RawResponse, + RequestIDs: response.Header["X-Vcap-Request-Id"], + } + } + + return nil +} + +// handleWarnings looks for the "X-Cf-Warnings" header in the cloud controller +// response and URI decodes them. The value can contain multiple warnings that +// are comma separated. +func (*CloudControllerConnection) handleWarnings(response *http.Response) ([]string, error) { + rawWarnings := response.Header["X-Cf-Warnings"] + + var warnings []string + for _, rawWarningsCommaSeparated := range rawWarnings { + for _, rawWarning := range strings.Split(rawWarningsCommaSeparated, ",") { + warning, err := url.QueryUnescape(rawWarning) + if err != nil { + return nil, err + } + warnings = append(warnings, strings.Trim(warning, " ")) + } + } + + return warnings, nil +} + +func (connection *CloudControllerConnection) populateResponse(response *http.Response, passedResponse *Response) error { + passedResponse.HTTPResponse = response + + warnings, err := connection.handleWarnings(response) + if err != nil { + return err + } + passedResponse.Warnings = warnings + + if resourceLocationURL := response.Header.Get("Location"); resourceLocationURL != "" { + passedResponse.ResourceLocationURL = resourceLocationURL + } + + err = connection.handleStatusCodes(response, passedResponse) + if err != nil { + return err + } + + if passedResponse.DecodeJSONResponseInto != nil { + err = DecodeJSON(passedResponse.RawResponse, passedResponse.DecodeJSONResponseInto) + if err != nil { + return err + } + } + + return nil +} + +func (*CloudControllerConnection) processRequestErrors(request *http.Request, err error) error { + switch e := err.(type) { + case *url.Error: + switch urlErr := e.Err.(type) { + case x509.UnknownAuthorityError: + return ccerror.UnverifiedServerError{ + URL: request.URL.String(), + } + case x509.HostnameError: + return ccerror.SSLValidationHostnameError{ + Message: urlErr.Error(), + } + default: + return ccerror.RequestError{Err: e} + } + default: + return err + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/connection.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/connection.go new file mode 100644 index 0000000..65ab216 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/connection.go @@ -0,0 +1,18 @@ +// Package cloudcontroller contains shared utilies between the V2 and V3 +// clients. +// +// These sets of packages are still under development/pre-pre-pre...alpha. Use +// at your own risk! Functionality and design may change without warning. +// +// Where are the clients? +// +// These clients live in ccv2 and ccv3 packages. Each of them only works with +// the V2 and V3 api respectively. +package cloudcontroller + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Connection + +// Connection creates and executes http requests +type Connection interface { + Make(request *Request, passedResponse *Response) error +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/decode_json.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/decode_json.go new file mode 100644 index 0000000..4402dac --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/decode_json.go @@ -0,0 +1,14 @@ +package cloudcontroller + +import ( + "bytes" + "encoding/json" +) + +// DecodeJSON unmarshals JSON into the given object with the appropriate +// settings. +func DecodeJSON(raw []byte, v interface{}) error { + decoder := json.NewDecoder(bytes.NewBuffer(raw)) + decoder.UseNumber() + return decoder.Decode(v) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/pipebomb.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/pipebomb.go new file mode 100644 index 0000000..29ac6b0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/pipebomb.go @@ -0,0 +1,27 @@ +package cloudcontroller + +import ( + "io" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" +) + +// Pipebomb is a wrapper around an io.Pipe's io.ReadCloser that turns it into a +// ReadSeeker that errors on Seek calls. This is designed to prevent the caller +// from rereading the body multiple times. +type Pipebomb struct { + io.ReadCloser +} + +// Seek returns a PipeSeekError; allowing the top level calling function to +// handle the retry instead of seeking back to the beginning of the Reader. +func (*Pipebomb) Seek(offset int64, whence int) (int64, error) { + return 0, ccerror.PipeSeekError{} +} + +// NewPipeBomb returns an io.WriteCloser that can be used to stream data to a +// the Pipebomb. +func NewPipeBomb() (*Pipebomb, io.WriteCloser) { + writerOutput, writerInput := io.Pipe() + return &Pipebomb{ReadCloser: writerOutput}, writerInput +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/request.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/request.go new file mode 100644 index 0000000..04ed550 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/request.go @@ -0,0 +1,29 @@ +package cloudcontroller + +import ( + "io" + "net/http" +) + +// Request represents the request of the cloud controller. +type Request struct { + *http.Request + + body io.ReadSeeker +} + +func (r *Request) ResetBody() error { + if r.body == nil { + return nil + } + + _, err := r.body.Seek(0, 0) + return err +} + +func NewRequest(request *http.Request, body io.ReadSeeker) *Request { + return &Request{ + Request: request, + body: body, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/response.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/response.go new file mode 100644 index 0000000..0653dfa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/response.go @@ -0,0 +1,29 @@ +package cloudcontroller + +import "net/http" + +// Response represents a Cloud Controller response object. +type Response struct { + // DecodeJSONResponseInto represents the resource entity type that is + // expected in the response JSON. + DecodeJSONResponseInto interface{} + + // RawResponse represents the response body. + RawResponse []byte + + // Warnings represents warnings parsed from the custom warnings headers of a + // Cloud Controller response. + Warnings []string + + // HTTPResponse represents the HTTP response object. + HTTPResponse *http.Response + + // ResourceLocationURL represents the Location header value + ResourceLocationURL string +} + +func (r *Response) reset() { + r.RawResponse = []byte{} + r.Warnings = []string{} + r.HTTPResponse = nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/uploads/upload.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/uploads/upload.go new file mode 100644 index 0000000..fa69b97 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/uploads/upload.go @@ -0,0 +1,62 @@ +package uploads + +import ( + "bytes" + "io" + "mime/multipart" + "path/filepath" + + "code.cloudfoundry.org/cli/api/cloudcontroller" +) + +func CalculateRequestSize(fileSize int64, path string, fieldName string) (int64, error) { + body := &bytes.Buffer{} + form := multipart.NewWriter(body) + + bpFileName := filepath.Base(path) + + _, err := form.CreateFormFile(fieldName, bpFileName) + if err != nil { + return 0, err + } + + err = form.Close() + if err != nil { + return 0, err + } + + return int64(body.Len()) + fileSize, nil +} + +func CreateMultipartBodyAndHeader(file io.Reader, path string, fieldName string) (string, io.ReadSeeker, <-chan error) { + writerOutput, writerInput := cloudcontroller.NewPipeBomb() + + form := multipart.NewWriter(writerInput) + + writeErrors := make(chan error) + + go func() { + defer close(writeErrors) + defer writerInput.Close() + + bpFileName := filepath.Base(path) + writer, err := form.CreateFormFile(fieldName, bpFileName) + if err != nil { + writeErrors <- err + return + } + + _, err = io.Copy(writer, file) + if err != nil { + writeErrors <- err + return + } + + err = form.Close() + if err != nil { + writeErrors <- err + } + }() + + return form.FormDataContentType(), writerOutput, writeErrors +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/custom_wrapper.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/custom_wrapper.go new file mode 100644 index 0000000..dc6b38a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/custom_wrapper.go @@ -0,0 +1,19 @@ +package wrapper + +import "code.cloudfoundry.org/cli/api/cloudcontroller" + +// CustomWrapper is a wrapper that can execute arbitrary code via the +// CustomMake function on every request that passes through Make. +type CustomWrapper struct { + connection cloudcontroller.Connection + CustomMake func(connection cloudcontroller.Connection, request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error +} + +func (e *CustomWrapper) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + return e.CustomMake(e.connection, request, passedResponse) +} + +func (e *CustomWrapper) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + e.connection = innerconnection + return e +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/kubernetes_authentication.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/kubernetes_authentication.go new file mode 100644 index 0000000..622bd58 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/kubernetes_authentication.go @@ -0,0 +1,67 @@ +package wrapper + +import ( + "net/http" + + "code.cloudfoundry.org/cli/actor/v7action" + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/shared" + "code.cloudfoundry.org/cli/command" +) + +type KubernetesAuthentication struct { + connection cloudcontroller.Connection + config command.Config + k8sConfigGetter v7action.KubernetesConfigGetter +} + +func NewKubernetesAuthentication( + config command.Config, + k8sConfigGetter v7action.KubernetesConfigGetter, +) *KubernetesAuthentication { + + return &KubernetesAuthentication{ + config: config, + k8sConfigGetter: k8sConfigGetter, + } +} + +func (a *KubernetesAuthentication) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + roundTripper, err := shared.WrapForCFOnK8sAuth(a.config, a.k8sConfigGetter, connectionRoundTripper{ + connection: a.connection, + ccRequest: request, + ccResponse: passedResponse, + }) + if err != nil { + return err + } + + _, err = roundTripper.RoundTrip(request.Request) + + return err +} + +func (a *KubernetesAuthentication) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + a.connection = innerconnection + + return a +} + +type connectionRoundTripper struct { + connection cloudcontroller.Connection + ccRequest *cloudcontroller.Request + ccResponse *cloudcontroller.Response +} + +func (rt connectionRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + // The passed `*req` is a shallow clone of the original `*req` with the auth header added. + // So we need to reset it on the `ccRequest`. + rt.ccRequest.Request = req + + err := rt.connection.Make(rt.ccRequest, rt.ccResponse) + if err != nil { + return nil, err + } + + return rt.ccResponse.HTTPResponse, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/request_logger.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/request_logger.go new file mode 100644 index 0000000..e354cad --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/request_logger.go @@ -0,0 +1,174 @@ +package wrapper + +import ( + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RequestLoggerOutput + +// RequestLoggerOutput is the interface for displaying logs +type RequestLoggerOutput interface { + DisplayHeader(name string, value string) error + DisplayHost(name string) error + DisplayJSONBody(body []byte) error + DisplayMessage(msg string) error + DisplayRequestHeader(method string, uri string, httpProtocol string) error + DisplayResponseHeader(httpProtocol string, status string) error + DisplayType(name string, requestDate time.Time) error + HandleInternalError(err error) + Start() error + Stop() error +} + +// RequestLogger is the wrapper that logs requests to and responses from the +// Cloud Controller server +type RequestLogger struct { + connection cloudcontroller.Connection + output RequestLoggerOutput +} + +// NewRequestLogger returns a pointer to a RequestLogger wrapper +func NewRequestLogger(output RequestLoggerOutput) *RequestLogger { + return &RequestLogger{ + output: output, + } +} + +// Make records the request and the response to UI +func (logger *RequestLogger) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + err := logger.displayRequest(request) + if err != nil { + logger.output.HandleInternalError(err) + } + + err = logger.connection.Make(request, passedResponse) + + if passedResponse.HTTPResponse != nil { + displayErr := logger.displayResponse(passedResponse) + if displayErr != nil { + logger.output.HandleInternalError(displayErr) + } + } + + return err +} + +// Wrap sets the connection on the RequestLogger and returns itself +func (logger *RequestLogger) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + logger.connection = innerconnection + return logger +} + +func (logger *RequestLogger) displayRequest(request *cloudcontroller.Request) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("REQUEST", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayRequestHeader(request.Method, request.URL.RequestURI(), request.Proto) + if err != nil { + return err + } + err = logger.output.DisplayHost(request.URL.Host) + if err != nil { + return err + } + err = logger.displaySortedHeaders(request.Header) + if err != nil { + return err + } + + contentType := request.Header.Get("Content-Type") + if request.Body != nil { + if strings.Contains(contentType, "json") { + rawRequestBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return err + } + + defer request.ResetBody() + + return logger.output.DisplayJSONBody(rawRequestBody) + } else if strings.Contains(contentType, "x-www-form-urlencoded") { + rawRequestBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return err + } + + defer request.ResetBody() + + return logger.output.DisplayMessage(fmt.Sprintf("[application/x-www-form-urlencoded %s]", rawRequestBody)) + } + } + if contentType != "" { + return logger.output.DisplayMessage(fmt.Sprintf("[%s Content Hidden]", strings.Split(contentType, ";")[0])) + } + return nil +} + +func (logger *RequestLogger) displayResponse(passedResponse *cloudcontroller.Response) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("RESPONSE", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayResponseHeader(passedResponse.HTTPResponse.Proto, passedResponse.HTTPResponse.Status) + if err != nil { + return err + } + err = logger.displaySortedHeaders(passedResponse.HTTPResponse.Header) + if err != nil { + return err + } + contentType := passedResponse.HTTPResponse.Header["Content-Type"] + if len(contentType) > 0 && strings.Contains(contentType[0], "application/x-yaml") { + return logger.output.DisplayMessage("[application/x-yaml Content Hidden]") + } + return logger.output.DisplayJSONBody(passedResponse.RawResponse) +} + +func (logger *RequestLogger) displaySortedHeaders(headers http.Header) error { + keys := []string{} + for key := range headers { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + for _, value := range headers[key] { + err := logger.output.DisplayHeader(key, redactHeaders(key, value)) + if err != nil { + return err + } + } + } + return nil +} + +func redactHeaders(key string, value string) string { + redactedKeys := []string{"Authorization", "Set-Cookie"} + for _, redactedKey := range redactedKeys { + if key == redactedKey { + return "[PRIVATE DATA HIDDEN]" + } + } + + return value +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/retry_request.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/retry_request.go new file mode 100644 index 0000000..cf9e7f6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/retry_request.go @@ -0,0 +1,65 @@ +package wrapper + +import ( + "net/http" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" +) + +// RetryRequest is a wrapper that retries failed requests if they contain a 5XX +// status code. +type RetryRequest struct { + maxRetries int + connection cloudcontroller.Connection +} + +// NewRetryRequest returns a pointer to a RetryRequest wrapper. +func NewRetryRequest(maxRetries int) *RetryRequest { + return &RetryRequest{ + maxRetries: maxRetries, + } +} + +// Make retries the request if it comes back with a 5XX status code. +func (retry *RetryRequest) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + var err error + + for i := 0; i < retry.maxRetries+1; i++ { + err = retry.connection.Make(request, passedResponse) + if err == nil { + return nil + } + + if retry.skipRetry(request.Method, passedResponse.HTTPResponse) { + break + } + + // Reset the request body prior to the next retry + resetErr := request.ResetBody() + if resetErr != nil { + if _, ok := resetErr.(ccerror.PipeSeekError); ok { + return ccerror.PipeSeekError{Err: err} + } + return resetErr + } + } + return err +} + +// Wrap sets the connection in the RetryRequest and returns itself. +func (retry *RetryRequest) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + retry.connection = innerconnection + return retry +} + +// skipRetry will skip retry if the request method is POST or contains a status +// code that is not one of following http status codes: 500, 502, 503, 504. +func (*RetryRequest) skipRetry(httpMethod string, response *http.Response) bool { + return httpMethod == http.MethodPost || + response != nil && + response.StatusCode != http.StatusInternalServerError && + response.StatusCode != http.StatusBadGateway && + response.StatusCode != http.StatusServiceUnavailable && + response.StatusCode != http.StatusGatewayTimeout +} diff --git a/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/uaa_authentication.go b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/uaa_authentication.go new file mode 100644 index 0000000..d11ae16 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/cloudcontroller/wrapper/uaa_authentication.go @@ -0,0 +1,102 @@ +package wrapper + +import ( + "strings" + "time" + + "github.com/SermoDigital/jose/jws" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/uaa" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UAAClient + +const accessTokenExpirationMargin = time.Minute + +// UAAClient is the interface for getting a valid access token +type UAAClient interface { + RefreshAccessToken(refreshToken string) (uaa.RefreshedTokens, error) +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . TokenCache + +// TokenCache is where the UAA token information is stored. +type TokenCache interface { + AccessToken() string + RefreshToken() string + SetAccessToken(token string) + SetRefreshToken(token string) +} + +// UAAAuthentication wraps connections and adds authentication headers to all +// requests +type UAAAuthentication struct { + connection cloudcontroller.Connection + client UAAClient + cache TokenCache +} + +// NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with +// the client and a token cache. +func NewUAAAuthentication(client UAAClient, cache TokenCache) *UAAAuthentication { + return &UAAAuthentication{ + client: client, + cache: cache, + } +} + +// Make adds authentication headers to the passed in request and then calls the +// wrapped connection's Make. If the client is not set on the wrapper, it will +// not add any header or handle any authentication errors. +func (t *UAAAuthentication) Make(request *cloudcontroller.Request, passedResponse *cloudcontroller.Response) error { + if request.Header.Get("Authorization") == "" && (t.cache.AccessToken() != "" || t.cache.RefreshToken() != "") { + // assert a valid access token for authenticated requests + err := t.refreshTokenIfNecessary(t.cache.AccessToken()) + if nil != err { + return err + } + + request.Header.Set("Authorization", t.cache.AccessToken()) + } + + err := t.connection.Make(request, passedResponse) + return err +} + +// SetClient sets the UAA client that the wrapper will use. +func (t *UAAAuthentication) SetClient(client UAAClient) { + t.client = client +} + +// Wrap sets the connection on the UAAAuthentication and returns itself +func (t *UAAAuthentication) Wrap(innerconnection cloudcontroller.Connection) cloudcontroller.Connection { + t.connection = innerconnection + return t +} + +// refreshToken refreshes the JWT access token if it is expired or about to expire. +// If the access token is not yet expired, no action is performed. +func (t *UAAAuthentication) refreshTokenIfNecessary(accessToken string) error { + var expiresIn time.Duration + + tokenStr := strings.TrimPrefix(accessToken, "bearer ") + token, err := jws.ParseJWT([]byte(tokenStr)) + + if err == nil { + expiration, ok := token.Claims().Expiration() + if ok { + expiresIn = time.Until(expiration) + } + } + + if err != nil || expiresIn < accessTokenExpirationMargin { + tokens, err := t.client.RefreshAccessToken(t.cache.RefreshToken()) + if err != nil { + return err + } + t.cache.SetAccessToken(tokens.AuthorizationToken()) + t.cache.SetRefreshToken(tokens.RefreshToken) + } + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/raw_http_status_error.go b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/raw_http_status_error.go new file mode 100644 index 0000000..9c10da5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/raw_http_status_error.go @@ -0,0 +1,13 @@ +package pluginerror + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + Status string + RawResponse []byte +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("HTTP Response: %s\nHTTP Response Body: %s", r.Status, r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/request_error.go b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/request_error.go new file mode 100644 index 0000000..937b72a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/request_error.go @@ -0,0 +1,11 @@ +package pluginerror + +// RequestError represents a generic error encountered while performing the +// HTTP request. This generic error occurs before a HTTP response is obtained. +type RequestError struct { + Err error +} + +func (e RequestError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/ssl_validation_hostname_error.go b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/ssl_validation_hostname_error.go new file mode 100644 index 0000000..332a48c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/ssl_validation_hostname_error.go @@ -0,0 +1,13 @@ +package pluginerror + +import "fmt" + +// SSLValidationHostnameError replaces x509.HostnameError when the server has +// SSL certificate that does not match the hostname. +type SSLValidationHostnameError struct { + Message string +} + +func (e SSLValidationHostnameError) Error() string { + return fmt.Sprintf("Hostname does not match SSL Certificate (%s)", e.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/unverified_server_error.go b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/unverified_server_error.go new file mode 100644 index 0000000..f65e2e1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/plugin/pluginerror/unverified_server_error.go @@ -0,0 +1,11 @@ +package pluginerror + +// UnverifiedServerError replaces x509.UnknownAuthorityError when the server +// has SSL but the client is unable to verify it's certificate +type UnverifiedServerError struct { + URL string +} + +func (UnverifiedServerError) Error() string { + return "x509: certificate signed by unknown authority" +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/client.go b/vendor/code.cloudfoundry.org/cli/api/router/client.go new file mode 100644 index 0000000..b6ceeef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/client.go @@ -0,0 +1,60 @@ +// Package router is a GoLang library that interacts with CloudFoundry Go Router +package router + +import ( + "fmt" + "runtime" + + "code.cloudfoundry.org/cli/api/router/internal" + + "github.com/tedsuo/rata" +) + +// Client is a client that can be used to talk to a Cloud Controller's V2 +// Endpoints. +type Client struct { + connection Connection + router *rata.RequestGenerator + userAgent string +} + +// Config allows the Client to be configured +type Config struct { + // AppName is the name of the application/process using the client. + AppName string + + // AppVersion is the version of the application/process using the client. + AppVersion string + + // ConnectionConfig is the configuration for the client connection. + ConnectionConfig + + // RoutingEndpoint is the url of the router API. + RoutingEndpoint string + + // Wrappers that apply to the client connection. + Wrappers []ConnectionWrapper +} + +// NewClient returns a new Router Client. +func NewClient(config Config) *Client { + userAgent := fmt.Sprintf("%s/%s (%s; %s %s)", + config.AppName, + config.AppVersion, + runtime.Version(), + runtime.GOARCH, + runtime.GOOS, + ) + + client := Client{ + userAgent: userAgent, + router: rata.NewRequestGenerator(config.RoutingEndpoint, internal.APIRoutes), + connection: NewConnection(config.ConnectionConfig), + } + + for _, wrapper := range config.Wrappers { + client.connection = wrapper.Wrap(client.connection) + } + + return &client +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/connection.go b/vendor/code.cloudfoundry.org/cli/api/router/connection.go new file mode 100644 index 0000000..9570fab --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/connection.go @@ -0,0 +1,9 @@ +// Package router contains utilities to make call to the router API +package router + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Connection + +// Connection creates and executes http requests +type Connection interface { + Make(request *Request, passedResponse *Response) error +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/connection_wrapper.go b/vendor/code.cloudfoundry.org/cli/api/router/connection_wrapper.go new file mode 100644 index 0000000..61ade20 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/connection_wrapper.go @@ -0,0 +1,15 @@ +package router + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ConnectionWrapper + +// ConnectionWrapper can wrap a given connection allowing the wrapper to modify +// all requests going in and out of the given connection. +type ConnectionWrapper interface { + Connection + Wrap(innerconnection Connection) Connection +} + +// WrapConnection wraps the current Client connection in the wrapper. +func (client *Client) WrapConnection(wrapper ConnectionWrapper) { + client.connection = wrapper.Wrap(client.connection) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/internal/api_routes.go b/vendor/code.cloudfoundry.org/cli/api/router/internal/api_routes.go new file mode 100644 index 0000000..ad7a8dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/internal/api_routes.go @@ -0,0 +1,25 @@ +package internal + +import ( + "net/http" + + "github.com/tedsuo/rata" +) + +// Naming convention: +// +// Method + non-parameter parts of the path +// +// If the request returns a single entity by GUID, use the singular (for example +// /v2/organizations/:organization_guid is GetOrganization). +// +// The const name should always be the const value + Request. +const ( + GetRouterGroups = "GetRouterGroups" +) + +// APIRoutes is a list of routes used by the rata library to construct request +// URLs. +var APIRoutes = rata.Routes{ + {Path: "/v1/router_groups", Method: http.MethodGet, Name: GetRouterGroups}, +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/request.go b/vendor/code.cloudfoundry.org/cli/api/router/request.go new file mode 100644 index 0000000..a269bd3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/request.go @@ -0,0 +1,90 @@ +package router + +import ( + "io" + "net/http" + "net/url" + + "github.com/tedsuo/rata" +) + +// Request represents the request of the router +type Request struct { + *http.Request + + body io.ReadSeeker +} + +func (r *Request) ResetBody() error { + if r.body == nil { + return nil + } + + _, err := r.body.Seek(0, 0) + return err +} + +// Params represents URI parameters for a request. +type Params map[string]string + +// requestOptions contains all the options to create an HTTP request. +type requestOptions struct { + // Header is the set of request headers + Header http.Header + + // Body is the request body + Body io.ReadSeeker + + // Method is the HTTP method of the request. + Method string + + // Query is a list of HTTP query parameters + Query url.Values + + // RequestName is the name of the request (see routes) + RequestName string + + // URI is the URI of the request. + URI string + + // URIParams are the list URI route parameters + URIParams Params +} + +// newHTTPRequest returns a constructed HTTP.Request with some defaults. +// Defaults are applied when Request fields are not filled in. +func (client Client) newHTTPRequest(passedRequest requestOptions) (*Request, error) { + request, err := client.router.CreateRequest( + passedRequest.RequestName, + rata.Params(passedRequest.URIParams), + passedRequest.Body, + ) + + if err != nil { + return nil, err + } + + if passedRequest.Query != nil { + request.URL.RawQuery = passedRequest.Query.Encode() + } + + if passedRequest.Header != nil { + request.Header = passedRequest.Header + } else { + request.Header = http.Header{} + } + + request.Header.Set("Accept", "application/json") + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Connection", "close") + request.Header.Set("User-Agent", client.userAgent) + + return &Request{Request: request, body: passedRequest.Body}, nil +} + +func NewRequest(request *http.Request, body io.ReadSeeker) *Request { + return &Request{ + Request: request, + body: body, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/response.go b/vendor/code.cloudfoundry.org/cli/api/router/response.go new file mode 100644 index 0000000..ab6ddb5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/response.go @@ -0,0 +1,21 @@ +package router + +import "net/http" + +// Response represents a Router response object. +type Response struct { + // Result represents the resource entity type that is expected in the + // response JSON. + Result interface{} + + // RawResponse represents the response body. + RawResponse []byte + + // HTTPResponse represents the HTTP response object. + HTTPResponse *http.Response +} + +func (r *Response) reset() { + r.RawResponse = []byte{} + r.HTTPResponse = nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/router_connection.go b/vendor/code.cloudfoundry.org/cli/api/router/router_connection.go new file mode 100644 index 0000000..999ec88 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/router_connection.go @@ -0,0 +1,116 @@ +package router + +import ( + "bytes" + "crypto/x509" + "encoding/json" + "io/ioutil" + "net" + "net/http" + "net/url" + "time" + + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/router/routererror" + "code.cloudfoundry.org/cli/util" +) + +// ConnectionConfig is for configuring the RouterConnection +type ConnectionConfig struct { + DialTimeout time.Duration + SkipSSLValidation bool +} + +// RouterConnection represents the connection to Router +type RouterConnection struct { + HTTPClient *http.Client +} + +// NewConnection returns a pointer to a new RouterConnection with the provided configuration +func NewConnection(config ConnectionConfig) *RouterConnection { + tr := &http.Transport{ + TLSClientConfig: util.NewTLSConfig(nil, config.SkipSSLValidation), + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + KeepAlive: 30 * time.Second, + Timeout: config.DialTimeout, + }).DialContext, + } + + return &RouterConnection{ + HTTPClient: &http.Client{Transport: tr}, + } +} + +// Make performs the request and parses the response. +func (connection *RouterConnection) Make(request *Request, responseToPopulate *Response) error { + // In case this function is called from a retry, passedResponse may already + // be populated with a previous response. We reset in case there's an HTTP + // error and we don't repopulate it in populateResponse. + responseToPopulate.reset() + + httpResponse, err := connection.HTTPClient.Do(request.Request) + if err != nil { + // request could not be made, e.g., ssl handshake or tcp dial timeout + return connection.processRequestErrors(request.Request, err) + } + + return connection.populateResponse(httpResponse, responseToPopulate) +} + +func (*RouterConnection) handleStatusCodes(httpResponse *http.Response, responseToPopulate *Response) error { + if httpResponse.StatusCode >= 400 { + return routererror.RawHTTPStatusError{ + StatusCode: httpResponse.StatusCode, + RawResponse: responseToPopulate.RawResponse, + } + } + return nil +} + +func (connection *RouterConnection) populateResponse(httpResponse *http.Response, responseToPopulate *Response) error { + responseToPopulate.HTTPResponse = httpResponse + + rawBytes, err := ioutil.ReadAll(httpResponse.Body) + defer httpResponse.Body.Close() + if err != nil { + return err + } + responseToPopulate.RawResponse = rawBytes + + err = connection.handleStatusCodes(httpResponse, responseToPopulate) + if err != nil { + return err + } + + if responseToPopulate.Result != nil { + decoder := json.NewDecoder(bytes.NewBuffer(responseToPopulate.RawResponse)) + decoder.UseNumber() + err = decoder.Decode(responseToPopulate.Result) + if err != nil { + return err + } + } + + return nil +} + +func (*RouterConnection) processRequestErrors(request *http.Request, err error) error { + switch e := err.(type) { + case *url.Error: + switch urlErr := e.Err.(type) { + case x509.UnknownAuthorityError: + return ccerror.UnverifiedServerError{ + URL: request.URL.String(), + } + case x509.HostnameError: + return ccerror.SSLValidationHostnameError{ + Message: urlErr.Error(), + } + default: + return ccerror.RequestError{Err: e} + } + default: + return err + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/router_group.go b/vendor/code.cloudfoundry.org/cli/api/router/router_group.go new file mode 100644 index 0000000..de67d5c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/router_group.go @@ -0,0 +1,68 @@ +package router + +import ( + "net/url" + + "code.cloudfoundry.org/cli/api/router/internal" + "code.cloudfoundry.org/cli/api/router/routererror" +) + +// RouterGroup represents a router group. +type RouterGroup struct { + GUID string `json:"guid"` + Name string `json:"name"` + ReservablePorts string `json:"reservable_ports"` + Type string `json:"type"` +} + +func (client *Client) GetRouterGroups() ([]RouterGroup, error) { + request, err := client.newHTTPRequest(requestOptions{ + RequestName: internal.GetRouterGroups, + }) + + if err != nil { + return nil, err + } + var routerGroups []RouterGroup + + var response = Response{ + Result: &routerGroups, + } + + err = client.connection.Make(request, &response) + if err != nil { + return nil, err + } + + return routerGroups, nil +} + +// GetRouterGroupByName returns a list of RouterGroups. +func (client *Client) GetRouterGroupByName(name string) (RouterGroup, error) { + request, err := client.newHTTPRequest(requestOptions{ + RequestName: internal.GetRouterGroups, + Query: url.Values{"name": []string{name}}, + }) + + if err != nil { + return RouterGroup{}, err + } + var routerGroups []RouterGroup + + var response = Response{ + Result: &routerGroups, + } + + err = client.connection.Make(request, &response) + if err != nil { + return RouterGroup{}, err + } + + for _, routerGroup := range routerGroups { + if routerGroup.Name == name { + return routerGroup, nil + } + } + + return RouterGroup{}, routererror.ResourceNotFoundError{} +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/routererror/error_response.go b/vendor/code.cloudfoundry.org/cli/api/router/routererror/error_response.go new file mode 100644 index 0000000..2b0c797 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/routererror/error_response.go @@ -0,0 +1,13 @@ +package routererror + +import "fmt" + +type ErrorResponse struct { + Name string `json:"name"` + Message string `json:"message"` + StatusCode int +} + +func (err ErrorResponse) Error() string { + return fmt.Sprintf("Server error, status code: %d, error code: %s, message: %s", err.StatusCode, err.Name, err.Message) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/routererror/invalid_auth_token_error.go b/vendor/code.cloudfoundry.org/cli/api/router/routererror/invalid_auth_token_error.go new file mode 100644 index 0000000..de464c3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/routererror/invalid_auth_token_error.go @@ -0,0 +1,11 @@ +package routererror + +// InvalidAuthTokenError is returned when the client has an invalid +// authorization header. +type InvalidAuthTokenError struct { + Message string +} + +func (e InvalidAuthTokenError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/routererror/raw_http_status_error.go b/vendor/code.cloudfoundry.org/cli/api/router/routererror/raw_http_status_error.go new file mode 100644 index 0000000..30220f8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/routererror/raw_http_status_error.go @@ -0,0 +1,14 @@ +package routererror + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + StatusCode int + RawResponse []byte + RequestIDs []string +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("Error Code: %d\nRaw Response: %s", r.StatusCode, r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/routererror/resource_not_found_error.go b/vendor/code.cloudfoundry.org/cli/api/router/routererror/resource_not_found_error.go new file mode 100644 index 0000000..750d130 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/routererror/resource_not_found_error.go @@ -0,0 +1,9 @@ +package routererror + +type ResourceNotFoundError struct { + Message string +} + +func (e ResourceNotFoundError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/routererror/unauthorized_error.go b/vendor/code.cloudfoundry.org/cli/api/router/routererror/unauthorized_error.go new file mode 100644 index 0000000..dd4e74e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/routererror/unauthorized_error.go @@ -0,0 +1,11 @@ +package routererror + +// UnauthorizedError is returned when the client does not have the correct +// permissions to execute the request. +type UnauthorizedError struct { + Message string +} + +func (e UnauthorizedError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/wrapper/error_wrapper.go b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/error_wrapper.go new file mode 100644 index 0000000..07579b9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/error_wrapper.go @@ -0,0 +1,55 @@ +package wrapper + +import ( + "encoding/json" + "net/http" + + "code.cloudfoundry.org/cli/api/router" + "code.cloudfoundry.org/cli/api/router/routererror" +) + +const expiredTokenMessage = "Token is expired" +const unauthorizedMessage = "You are not authorized to perform the requested action" + +// ErrorWrapper is the wrapper that converts responses with 4xx and 5xx status +// codes to an error. +type ErrorWrapper struct { + connection router.Connection +} + +func NewErrorWrapper() *ErrorWrapper { + return new(ErrorWrapper) +} + +func (e *ErrorWrapper) Make(request *router.Request, passedResponse *router.Response) error { + err := e.connection.Make(request, passedResponse) + + if rawHTTPStatusErr, ok := err.(routererror.RawHTTPStatusError); ok { + if rawHTTPStatusErr.StatusCode == http.StatusNotFound { + var resourceNotFoundError routererror.ResourceNotFoundError + _ = json.Unmarshal(rawHTTPStatusErr.RawResponse, &resourceNotFoundError) + return resourceNotFoundError + } + + if rawHTTPStatusErr.StatusCode == http.StatusUnauthorized { + var routingAPIErrorBody routererror.ErrorResponse + + _ = json.Unmarshal(rawHTTPStatusErr.RawResponse, &routingAPIErrorBody) + + if routingAPIErrorBody.Message == expiredTokenMessage { + return routererror.InvalidAuthTokenError{Message: "Token is expired"} + } + + if routingAPIErrorBody.Message == unauthorizedMessage { + return routererror.UnauthorizedError{Message: routingAPIErrorBody.Message} + } + } + } + + return err +} + +func (e *ErrorWrapper) Wrap(connection router.Connection) router.Connection { + e.connection = connection + return e +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/wrapper/request_logger.go b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/request_logger.go new file mode 100644 index 0000000..e843d15 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/request_logger.go @@ -0,0 +1,170 @@ +package wrapper + +import ( + "fmt" + "io/ioutil" + "net/http" + "sort" + "strings" + "time" + + "code.cloudfoundry.org/cli/api/router" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RequestLoggerOutput + +// RequestLoggerOutput is the interface for displaying logs +type RequestLoggerOutput interface { + DisplayHeader(name string, value string) error + DisplayHost(name string) error + DisplayJSONBody(body []byte) error + DisplayMessage(msg string) error + DisplayRequestHeader(method string, uri string, httpProtocol string) error + DisplayResponseHeader(httpProtocol string, status string) error + DisplayType(name string, requestDate time.Time) error + HandleInternalError(err error) + Start() error + Stop() error +} + +// RequestLogger is the wrapper that logs requests to and responses from the +// Cloud Controller server +type RequestLogger struct { + connection router.Connection + output RequestLoggerOutput +} + +// NewRequestLogger returns a pointer to a RequestLogger wrapper +func NewRequestLogger(output RequestLoggerOutput) *RequestLogger { + return &RequestLogger{ + output: output, + } +} + +// Make records the request and the response to UI +func (logger *RequestLogger) Make(request *router.Request, passedResponse *router.Response) error { + err := logger.displayRequest(request) + if err != nil { + logger.output.HandleInternalError(err) + } + + err = logger.connection.Make(request, passedResponse) + + if passedResponse.HTTPResponse != nil { + displayErr := logger.displayResponse(passedResponse) + if displayErr != nil { + logger.output.HandleInternalError(displayErr) + } + } + + return err +} + +// Wrap sets the connection on the RequestLogger and returns itself +func (logger *RequestLogger) Wrap(innerconnection router.Connection) router.Connection { + logger.connection = innerconnection + return logger +} + +func (logger *RequestLogger) displayRequest(request *router.Request) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("REQUEST", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayRequestHeader(request.Method, request.URL.RequestURI(), request.Proto) + if err != nil { + return err + } + err = logger.output.DisplayHost(request.URL.Host) + if err != nil { + return err + } + err = logger.displaySortedHeaders(request.Header) + if err != nil { + return err + } + + contentType := request.Header.Get("Content-Type") + if request.Body != nil { + if strings.Contains(contentType, "json") { + rawRequestBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return err + } + + defer request.ResetBody() + + return logger.output.DisplayJSONBody(rawRequestBody) + } else if strings.Contains(contentType, "x-www-form-urlencoded") { + rawRequestBody, err := ioutil.ReadAll(request.Body) + if err != nil { + return err + } + + defer request.ResetBody() + + return logger.output.DisplayMessage(fmt.Sprintf("[application/x-www-form-urlencoded %s]", rawRequestBody)) + } + } + if contentType != "" { + return logger.output.DisplayMessage(fmt.Sprintf("[%s Content Hidden]", strings.Split(contentType, ";")[0])) + } + return nil +} + +func (logger *RequestLogger) displayResponse(passedResponse *router.Response) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("RESPONSE", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayResponseHeader(passedResponse.HTTPResponse.Proto, passedResponse.HTTPResponse.Status) + if err != nil { + return err + } + err = logger.displaySortedHeaders(passedResponse.HTTPResponse.Header) + if err != nil { + return err + } + return logger.output.DisplayJSONBody(passedResponse.RawResponse) +} + +func (logger *RequestLogger) displaySortedHeaders(headers http.Header) error { + keys := []string{} + for key := range headers { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + for _, value := range headers[key] { + err := logger.output.DisplayHeader(key, redactHeaders(key, value)) + if err != nil { + return err + } + } + } + return nil +} + +func redactHeaders(key string, value string) string { + redactedKeys := []string{"Authorization", "Set-Cookie"} + for _, redactedKey := range redactedKeys { + if key == redactedKey { + return "[PRIVATE DATA HIDDEN]" + } + } + + return value +} diff --git a/vendor/code.cloudfoundry.org/cli/api/router/wrapper/uaa_authentication.go b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/uaa_authentication.go new file mode 100644 index 0000000..6fca8a0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/router/wrapper/uaa_authentication.go @@ -0,0 +1,85 @@ +package wrapper + +import ( + "code.cloudfoundry.org/cli/api/router" + "code.cloudfoundry.org/cli/api/router/routererror" + "code.cloudfoundry.org/cli/api/uaa" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UAAClient + +// UAAClient is the interface for getting a valid access token +type UAAClient interface { + RefreshAccessToken(refreshToken string) (uaa.RefreshedTokens, error) +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . TokenCache + +// TokenCache is where the UAA token information is stored. +type TokenCache interface { + AccessToken() string + RefreshToken() string + SetAccessToken(token string) + SetRefreshToken(token string) +} + +// UAAAuthentication wraps connections and adds authentication headers to all +// requests +type UAAAuthentication struct { + connection router.Connection + client UAAClient + cache TokenCache +} + +// NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with +// the client and a token cache. +func NewUAAAuthentication(client UAAClient, cache TokenCache) *UAAAuthentication { + return &UAAAuthentication{ + client: client, + cache: cache, + } +} + +// Make adds authentication headers to the passed in request and then calls the +// wrapped connection's Make. If the client is not set on the wrapper, it will +// not add any header or handle any authentication errors. +func (t *UAAAuthentication) Make(request *router.Request, passedResponse *router.Response) error { + if t.client == nil { + return t.connection.Make(request, passedResponse) + } + + request.Header.Set("Authorization", t.cache.AccessToken()) + + requestErr := t.connection.Make(request, passedResponse) + if _, ok := requestErr.(routererror.InvalidAuthTokenError); ok { + tokens, err := t.client.RefreshAccessToken(t.cache.RefreshToken()) + if err != nil { + return err + } + + t.cache.SetAccessToken(tokens.AuthorizationToken()) + t.cache.SetRefreshToken(tokens.RefreshToken) + + if request.Body != nil { + err = request.ResetBody() + if err != nil { + return err + } + } + request.Header.Set("Authorization", t.cache.AccessToken()) + requestErr = t.connection.Make(request, passedResponse) + } + + return requestErr +} + +// SetClient sets the UAA client that the wrapper will use. +func (t *UAAAuthentication) SetClient(client UAAClient) { + t.client = client +} + +// Wrap sets the connection on the UAAAuthentication and returns itself +func (t *UAAAuthentication) Wrap(innerconnection router.Connection) router.Connection { + t.connection = innerconnection + return t +} diff --git a/vendor/code.cloudfoundry.org/cli/api/shared/wrap_for_cf_on_k8s.go b/vendor/code.cloudfoundry.org/cli/api/shared/wrap_for_cf_on_k8s.go new file mode 100644 index 0000000..d5734d6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/shared/wrap_for_cf_on_k8s.go @@ -0,0 +1,124 @@ +package shared + +import ( + "bytes" + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "errors" + "fmt" + "net/http" + + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" + "k8s.io/client-go/transport" + + "code.cloudfoundry.org/cli/actor/v7action" + "code.cloudfoundry.org/cli/command" + + // imported for the side effects + _ "k8s.io/client-go/plugin/pkg/client/auth/azure" + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 net/http.RoundTripper + +func WrapForCFOnK8sAuth(config command.Config, k8sConfigGetter v7action.KubernetesConfigGetter, roundTripper http.RoundTripper) (http.RoundTripper, error) { + username, err := config.CurrentUserName() + if err != nil { + return nil, err + } + if username == "" { + return nil, errors.New("current user not set") + } + + k8sConfig, err := k8sConfigGetter.Get() + if err != nil { + return nil, err + } + + restConfig, err := clientcmd.NewDefaultClientConfig( + *k8sConfig, + &clientcmd.ConfigOverrides{ + Context: api.Context{AuthInfo: username}, + }, + ).ClientConfig() + if err != nil { + return nil, err + } + + // Special case for certs, since we don't want mtls + cert, err := getCert(restConfig) + if err != nil { + return nil, err + } + + transportConfig, err := restConfig.TransportConfig() + if err != nil { + return nil, fmt.Errorf("failed to get transport config: %w", err) + } + + if cert != nil { + return certRoundTripper{ + cert: cert, + roundTripper: roundTripper, + }, nil + } + + if transportConfig.WrapTransport == nil { + // i.e. not auth-provider or exec plugin + return transport.HTTPWrappersForConfig(transportConfig, roundTripper) + } + + // using auth provider to generate token + return transportConfig.WrapTransport(roundTripper), nil +} + +func getCert(restConfig *rest.Config) (*tls.Certificate, error) { + tlsConfig, err := rest.TLSConfigFor(restConfig) + if err != nil { + return nil, fmt.Errorf("failed to get tls config: %w", err) + } + + if tlsConfig != nil && tlsConfig.GetClientCertificate != nil { + cert, err := tlsConfig.GetClientCertificate(nil) + if err != nil { + return nil, fmt.Errorf("failed to get client certificate: %w", err) + } + + if len(cert.Certificate) > 0 && cert.PrivateKey != nil { + return cert, nil + } + } + return nil, nil +} + +type certRoundTripper struct { + cert *tls.Certificate + roundTripper http.RoundTripper +} + +func (rt certRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + var buf bytes.Buffer + + if err := pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: rt.cert.Certificate[0]}); err != nil { + return nil, fmt.Errorf("could not convert certificate to PEM format: %w", err) + } + + key, err := x509.MarshalPKCS8PrivateKey(rt.cert.PrivateKey) + if err != nil { + return nil, fmt.Errorf("could not marshal private key: %w", err) + } + + if err := pem.Encode(&buf, &pem.Block{Type: "PRIVATE KEY", Bytes: key}); err != nil { + return nil, fmt.Errorf("could not convert key to PEM format: %w", err) + } + + auth := "ClientCert " + base64.StdEncoding.EncodeToString(buf.Bytes()) + req.Header.Set("Authorization", auth) + + return rt.roundTripper.RoundTrip(req) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/auth.go b/vendor/code.cloudfoundry.org/cli/api/uaa/auth.go new file mode 100644 index 0000000..fa20861 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/auth.go @@ -0,0 +1,120 @@ +package uaa + +import ( + "encoding/base64" + "encoding/json" + "errors" + "net/http" + "net/url" + "strings" + + "code.cloudfoundry.org/cli/api/uaa/constant" + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// AuthResponse contains the access token and refresh token which are granted +// after UAA has authorized a user. +type AuthResponse struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` +} + +// Authenticate sends a username and password to UAA then returns an access +// token and a refresh token. +func (client Client) Authenticate(creds map[string]string, origin string, grantType constant.GrantType) (string, string, error) { + requestBody := url.Values{ + "grant_type": {string(grantType)}, + } + + for k, v := range creds { + requestBody.Set(k, v) + } + + type loginHint struct { + Origin string `json:"origin"` + } + + originStruct := loginHint{origin} + originParam, err := json.Marshal(originStruct) + if err != nil { + return "", "", err + } + + var query url.Values + if origin != "" { + query = url.Values{ + "login_hint": {string(originParam)}, + } + } + + request, err := client.newRequest(requestOptions{ + RequestName: internal.PostOAuthTokenRequest, + Header: http.Header{ + "Content-Type": {"application/x-www-form-urlencoded"}, + }, + Body: strings.NewReader(requestBody.Encode()), + Query: query, + }) + + if err != nil { + return "", "", err + } + + if grantType == constant.GrantTypePassword { + request.SetBasicAuth(client.config.UAAOAuthClient(), client.config.UAAOAuthClientSecret()) + } + + responseBody := AuthResponse{} + response := Response{ + Result: &responseBody, + } + + err = client.connection.Make(request, &response) + return responseBody.AccessToken, responseBody.RefreshToken, err +} + +func (client Client) Revoke(token string) error { + jti, err := client.getJtiFromToken(token) + if err != nil { + return err + } + + revokeRequest, err := client.newRequest(requestOptions{ + RequestName: internal.DeleteTokenRequest, + URIParams: map[string]string{ + "token_id": jti, + }, + }) + revokeRequest.Header.Set("Authorization", "Bearer "+token) + + if err != nil { + return err + } + + err = client.connection.Make(revokeRequest, &Response{}) + return err +} + +func (client Client) getJtiFromToken(token string) (string, error) { + segments := strings.Split(token, ".") + + if len(segments) < 2 { + return "", errors.New("access token missing segments") + } + + jsonPayload, err := base64.RawURLEncoding.DecodeString(segments[1]) + + if err != nil { + return "", errors.New("could not base64 decode token payload") + } + + payload := make(map[string]interface{}) + json.Unmarshal(jsonPayload, &payload) + jti, ok := payload["jti"].(string) + + if !ok { + return "", errors.New("could not parse jti from payload") + } + + return jti, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/client.go b/vendor/code.cloudfoundry.org/cli/api/uaa/client.go new file mode 100644 index 0000000..a8ccd54 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/client.go @@ -0,0 +1,45 @@ +// Package uaa is a GoLang library that interacts with CloudFoundry User +// Account and Authentication (UAA) Server. +// +// It is currently designed to support UAA API X.X.X. However, it may include +// features and endpoints of later API versions. +package uaa + +import ( + "fmt" + "runtime" + + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// Client is the UAA client +type Client struct { + Info + + config Config + + connection Connection + router *internal.Router + userAgent string +} + +// NewClient returns a new UAA Client with the provided configuration +func NewClient(config Config) *Client { + userAgent := fmt.Sprintf("%s/%s (%s; %s %s)", + config.BinaryName(), + config.BinaryVersion(), + runtime.Version(), + runtime.GOARCH, + runtime.GOOS, + ) + + client := Client{ + config: config, + + connection: NewConnection(config.SkipSSLValidation(), config.UAADisableKeepAlives(), config.DialTimeout()), + userAgent: userAgent, + } + client.WrapConnection(NewErrorWrapper()) + + return &client +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/config.go b/vendor/code.cloudfoundry.org/cli/api/uaa/config.go new file mode 100644 index 0000000..729d3fa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/config.go @@ -0,0 +1,46 @@ +package uaa + +import "time" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Config + +// Config allows the Client to be configured +type Config interface { + // BinaryName is the name of the application/process using the client. + BinaryName() string + + // BinaryVersion is the version of the application/process using the client. + BinaryVersion() string + + // DialTimeout is the DNS lookup timeout for the client. If not set, it is + // infinite. + DialTimeout() time.Duration + + // SetUAAEndpoint sets the UAA endpoint that is obtained from hitting + // /login. + SetUAAEndpoint(uaaEndpoint string) + + // SkipSSLValidation controls whether a client verifies the server's + // certificate chain and host name. If SkipSSLValidation is true, TLS accepts + // any certificate presented by the server and any host name in that + // certificate for *all* client requests going forward. + // + // In this mode, TLS is susceptible to man-in-the-middle attacks. This should + // be used only for testing. + SkipSSLValidation() bool + + // UAADisableKeepAlives controls whether the UAA client will reuse TCP connections + // for multiple requests. If true, the client will always use a new TCP request + // and set Connection: close in the request header. If false, the client + // will reuse the TCP connection. + UAADisableKeepAlives() bool + + // UAAGrantType returns the grant type of the supplied UAA credentials. + UAAGrantType() string + + // UAAOAuthClient is the UAA client ID the client will use. + UAAOAuthClient() string + + // UAAOAuthClientSecret is the UAA client secret the client will use. + UAAOAuthClientSecret() string +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/connection.go b/vendor/code.cloudfoundry.org/cli/api/uaa/connection.go new file mode 100644 index 0000000..2192413 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/connection.go @@ -0,0 +1,10 @@ +package uaa + +import "net/http" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Connection + +// Connection creates and executes http requests +type Connection interface { + Make(request *http.Request, passedResponse *Response) error +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/connection_wrapper.go b/vendor/code.cloudfoundry.org/cli/api/uaa/connection_wrapper.go new file mode 100644 index 0000000..18ede34 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/connection_wrapper.go @@ -0,0 +1,15 @@ +package uaa + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ConnectionWrapper + +// ConnectionWrapper can wrap a given connection allowing the wrapper to modify +// all requests going in and out of the given connection. +type ConnectionWrapper interface { + Connection + Wrap(innerconnection Connection) Connection +} + +// WrapConnection wraps the current Client connection in the wrapper. +func (client *Client) WrapConnection(wrapper ConnectionWrapper) { + client.connection = wrapper.Wrap(client.connection) +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/constant/grant_type.go b/vendor/code.cloudfoundry.org/cli/api/uaa/constant/grant_type.go new file mode 100644 index 0000000..e302d2f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/constant/grant_type.go @@ -0,0 +1,13 @@ +package constant + +// GrantType is the type of authentication being used to obtain the token. +type GrantType string + +const ( + // GrantTypeClientCredentials is used for a preconfigured client ID/secret + // authentication. + GrantTypeClientCredentials GrantType = "client_credentials" + // GrantTypePassword is used for user's username/password authentication. + GrantTypePassword GrantType = "password" + GrantTypeRefreshToken GrantType = "refresh_token" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/constant/package.go b/vendor/code.cloudfoundry.org/cli/api/uaa/constant/package.go new file mode 100644 index 0000000..fd06481 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/constant/package.go @@ -0,0 +1,18 @@ +// Package constant contains types and constants used by the uaa package. +// +// Constant Naming Conventions: +// +// The standard naming for a constant is . The only +// exception is 'state' types, where the word 'state' is omitted. +// +// For Example: +// Constant Type: PackageType +// Enum Name: Bits +// Enum Value: "bits" +// const PackageTypeBits PackageType = "bits" +// +// Constant Type: PackageState +// Enum Name: Expired +// Enum Value: "EXPIRED" +// const PackageExpired PackageState = "EXPIRED" +package constant diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/error_converter.go b/vendor/code.cloudfoundry.org/cli/api/uaa/error_converter.go new file mode 100644 index 0000000..ebbe950 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/error_converter.go @@ -0,0 +1,78 @@ +package uaa + +import ( + "encoding/json" + "net/http" +) + +// errorWrapper is the wrapper that converts responses with 4xx and 5xx status +// codes to an error. +type errorWrapper struct { + connection Connection +} + +// NewErrorWrapper returns a new error wrapper. +func NewErrorWrapper() *errorWrapper { + return new(errorWrapper) +} + +// Make converts RawHTTPStatusError, which represents responses with 4xx and +// 5xx status codes, to specific errors. +func (e *errorWrapper) Make(request *http.Request, passedResponse *Response) error { + err := e.connection.Make(request, passedResponse) + + if rawHTTPStatusErr, ok := err.(RawHTTPStatusError); ok { + return convert(rawHTTPStatusErr) + } + + return err +} + +// Wrap wraps a UAA connection in this error handling wrapper. +func (e *errorWrapper) Wrap(innerconnection Connection) Connection { + e.connection = innerconnection + return e +} + +func convert(rawHTTPStatusErr RawHTTPStatusError) error { + // Try to unmarshal the raw http status error into a UAA error. If + // unmarshaling fails, return the raw error. + var uaaErrorResponse UAAErrorResponse + err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &uaaErrorResponse) + if err != nil { + return rawHTTPStatusErr + } + + switch rawHTTPStatusErr.StatusCode { + case http.StatusBadRequest: // 400 + if uaaErrorResponse.Type == "invalid_scim_resource" { + return InvalidSCIMResourceError{Message: uaaErrorResponse.Description} + } + return rawHTTPStatusErr + case http.StatusUnauthorized: // 401 + if uaaErrorResponse.Type == "invalid_token" { + return InvalidAuthTokenError{Message: uaaErrorResponse.Description} + } + if uaaErrorResponse.Type == "unauthorized" { + if uaaErrorResponse.Description == "Your account has been locked because of too many failed attempts to login." { + return AccountLockedError{Message: "Your account has been locked because of too many failed attempts to login."} + } + return UnauthorizedError{Message: uaaErrorResponse.Description} + } + return rawHTTPStatusErr + case http.StatusForbidden: // 403 + if uaaErrorResponse.Type == "insufficient_scope" { + return InsufficientScopeError{Message: uaaErrorResponse.Description} + } + return rawHTTPStatusErr + case http.StatusConflict: // 409 + return ConflictError{Message: uaaErrorResponse.Description} + case http.StatusUnprocessableEntity: // 422 + if uaaErrorResponse.Type == "invalid_password" { + return InvalidPasswordError{Message: uaaErrorResponse.Description} + } + return rawHTTPStatusErr + default: + return rawHTTPStatusErr + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/errors.go b/vendor/code.cloudfoundry.org/cli/api/uaa/errors.go new file mode 100644 index 0000000..0fdd428 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/errors.go @@ -0,0 +1,106 @@ +package uaa + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + StatusCode int + RawResponse []byte +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("Error Code: %d\nRaw Response: %s", r.StatusCode, r.RawResponse) +} + +// UAAErrorResponse represents a generic UAA error response. +type UAAErrorResponse struct { + Type string `json:"error"` + Description string `json:"error_description"` +} + +func (e UAAErrorResponse) Error() string { + return fmt.Sprintf("Error Type: %s\nDescription: %s", e.Type, e.Description) +} + +// ConflictError is returned when the response status code is 409. It +// represents when there is a conflict in the state of the requested resource. +type ConflictError struct { + Message string +} + +func (e ConflictError) Error() string { + return e.Message +} + +// UnverifiedServerError replaces x509.UnknownAuthorityError when the server +// has SSL but the client is unable to verify it's certificate +type UnverifiedServerError struct { + URL string +} + +func (e UnverifiedServerError) Error() string { + return "x509: certificate signed by unknown authority" +} + +// RequestError represents a generic error encountered while performing the +// HTTP request. This generic error occurs before a HTTP response is obtained. +type RequestError struct { + Err error +} + +func (e RequestError) Error() string { + return e.Err.Error() +} + +// UnauthorizedError is returned when the authentication informatin is invalid. +type UnauthorizedError struct { + Message string +} + +func (e UnauthorizedError) Error() string { + return e.Message +} + +// InvalidAuthTokenError is returned when the client has an invalid +// authorization header. +type InvalidAuthTokenError struct { + Message string +} + +func (e InvalidAuthTokenError) Error() string { + return e.Message +} + +// InsufficientScopeError is returned when the client has insufficient scope +type InsufficientScopeError struct { + Message string +} + +func (e InsufficientScopeError) Error() string { + return e.Message +} + +// InvalidSCIMResourceError is returned usually when the client tries to create an inproperly formatted username +type InvalidSCIMResourceError struct { + Message string +} + +func (e InvalidSCIMResourceError) Error() string { + return e.Message +} + +type AccountLockedError struct { + Message string +} + +func (e AccountLockedError) Error() string { + return "" +} + +type InvalidPasswordError struct { + Message string +} + +func (e InvalidPasswordError) Error() string { + return e.Message +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/info.go b/vendor/code.cloudfoundry.org/cli/api/uaa/info.go new file mode 100644 index 0000000..dc24ae8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/info.go @@ -0,0 +1,27 @@ +package uaa + +// Info represents a GET response from a login server +type Info struct { + Links struct { + UAA string `json:"uaa"` + Login string `json:"login"` + } `json:"links"` +} + +// LoginLink is the URL to the login server. +func (info Info) LoginLink() string { + return info.Links.Login +} + +// UAALink is the URL to the UAA server. +func (info Info) UAALink() string { + return info.Links.UAA +} + +// NewInfo returns back a new +func NewInfo(uaaURL string, loginURL string) Info { + var info Info + info.Links.Login = loginURL + info.Links.UAA = uaaURL + return info +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/internal/resources.go b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/resources.go new file mode 100644 index 0000000..fc86c09 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/resources.go @@ -0,0 +1,6 @@ +package internal + +const ( + AuthorizationResource = "authorization_endpoint" + UAAResource = "uaa" +) diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routes.go b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routes.go new file mode 100644 index 0000000..f132faa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routes.go @@ -0,0 +1,28 @@ +package internal + +import ( + "net/http" +) + +const ( + GetClientUser = "GetClientUser" + GetSSHPasscodeRequest = "GetSSHPasscode" + PostOAuthTokenRequest = "PostOAuthToken" + PostUserRequest = "PostUser" + ListUsersRequest = "ListUsers" + DeleteUserRequest = "DeleteUser" + UpdatePasswordRequest = "UpdatePassword" + DeleteTokenRequest = "DeleteToken" +) + +// APIRoutes is a list of routes used by the router to construct request URLs. +var APIRoutes = []Route{ + {Path: "/Users", Method: http.MethodPost, Name: PostUserRequest, Resource: UAAResource}, + {Path: "/Users", Method: http.MethodGet, Name: ListUsersRequest, Resource: UAAResource}, + {Path: "/Users/:user_guid", Method: http.MethodDelete, Name: DeleteUserRequest, Resource: UAAResource}, + {Path: "/Users/:user_guid/password", Method: http.MethodPut, Name: UpdatePasswordRequest, Resource: UAAResource}, + {Path: "/oauth/authorize", Method: http.MethodGet, Name: GetSSHPasscodeRequest, Resource: UAAResource}, + {Path: "/oauth/clients/:client_id", Method: http.MethodGet, Name: GetClientUser, Resource: UAAResource}, + {Path: "/oauth/token", Method: http.MethodPost, Name: PostOAuthTokenRequest, Resource: AuthorizationResource}, + {Path: "/oauth/token/revoke/:token_id", Method: http.MethodDelete, Name: DeleteTokenRequest, Resource: AuthorizationResource}, +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routing.go b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routing.go new file mode 100644 index 0000000..7c1fcad --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/internal/routing.go @@ -0,0 +1,147 @@ +package internal + +import ( + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" +) + +// Params map path keys to values. For example, if your route has the path +// pattern: +// /person/:person_id/pets/:pet_type +// Then a correct Params map would lool like: +// router.Params{ +// "person_id": "123", +// "pet_type": "cats", +// } +type Params map[string]string + +// Route defines the property of a Cloud Controller V3 endpoint. +// +// Method can be one of the following: +// GET HEAD POST PUT PATCH DELETE CONNECT OPTIONS TRACE +// +// Path conforms to Pat-style pattern matching. The following docs are taken +// from http://godoc.org/github.com/bmizerany/pat#PatternServeMux +// +// Path Patterns may contain literals or captures. Capture names start with a +// colon and consist of letters A-Z, a-z, _, and 0-9. The rest of the pattern +// matches literally. The portion of the URL matching each name ends with an +// occurrence of the character in the pattern immediately following the name, +// or a /, whichever comes first. It is possible for a name to match the empty +// string. +// +// Example pattern with one capture: +// /hello/:name +// Will match: +// /hello/blake +// /hello/keith +// Will not match: +// /hello/blake/ +// /hello/blake/foo +// /foo +// /foo/bar +// +// Example 2: +// /hello/:name/ +// Will match: +// /hello/blake/ +// /hello/keith/foo +// /hello/blake +// /hello/keith +// Will not match: +// /foo +// /foo/bar +type Route struct { + // Name is a key specifying which HTTP route the router should associate with + // the endpoint at runtime. + Name string + // Method is any valid HTTP method + Method string + // Path contains a path pattern + Path string + // Resource is a key specifying which resource root the router should + // associate with the endpoint at runtime. + Resource string +} + +// CreatePath combines the route's path pattern with a Params map +// to produce a valid path. +func (r Route) CreatePath(params Params) (string, error) { + components := strings.Split(r.Path, "/") + for i, c := range components { + if len(c) == 0 { + continue + } + if c[0] == ':' { + val, ok := params[c[1:]] + if !ok { + return "", fmt.Errorf("missing param %s", c) + } + components[i] = val + } + } + + u, err := url.Parse(strings.Join(components, "/")) + if err != nil { + return "", err + } + return u.String(), nil +} + +// Router combines route and resource information in order to generate HTTP +// requests. +type Router struct { + routes map[string]Route + resources map[string]string +} + +// NewRouter returns a pointer to a new Router. +func NewRouter(routes []Route, resources map[string]string) *Router { + mappedRoutes := map[string]Route{} + for _, route := range routes { + mappedRoutes[route.Name] = route + } + return &Router{ + routes: mappedRoutes, + resources: resources, + } +} + +// CreateRequest returns a request key'd off of the name given. The params are +// merged into the URL and body is set as the request body. +func (router Router) CreateRequest(name string, params Params, body io.Reader) (*http.Request, error) { + route, ok := router.routes[name] + if !ok { + return &http.Request{}, fmt.Errorf("No route exists with the name %s", name) + } + + uri, err := route.CreatePath(params) + if err != nil { + return &http.Request{}, err + } + + resource, ok := router.resources[route.Resource] + if !ok { + return &http.Request{}, fmt.Errorf("No resource exists with the name %s", route.Resource) + } + + url, err := router.urlFrom(resource, uri) + if err != nil { + return &http.Request{}, err + } + + return http.NewRequest(route.Method, url, body) +} + +func (Router) urlFrom(resource string, uri string) (string, error) { + u, err := url.Parse(resource) + if err != nil { + return "", err + } + u.Path = path.Join(u.Path, uri) + return u.String(), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/prompts.go b/vendor/code.cloudfoundry.org/cli/api/uaa/prompts.go new file mode 100644 index 0000000..f65d379 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/prompts.go @@ -0,0 +1,32 @@ +package uaa + +import ( + "fmt" + "net/http" +) + +func (client *Client) GetLoginPrompts() (map[string][]string, error) { + type loginResponse struct { + Prompts map[string][]string `json:"prompts"` + } + + request, err := client.newRequest(requestOptions{ + Method: http.MethodGet, + URL: fmt.Sprintf("%s/login", client.LoginLink()), + }) + if err != nil { + return nil, err + } + + info := loginResponse{} + response := Response{ + Result: &info, + } + + err = client.connection.Make(request, &response) + if err != nil { + return nil, err + } + + return info.Prompts, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/refresh_token.go b/vendor/code.cloudfoundry.org/cli/api/uaa/refresh_token.go new file mode 100644 index 0000000..fba19e2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/refresh_token.go @@ -0,0 +1,77 @@ +package uaa + +import ( + "fmt" + "net/http" + "net/url" + "strings" + + "code.cloudfoundry.org/cli/api/uaa/constant" + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// RefreshedTokens represents the UAA refresh token response. +type RefreshedTokens struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + Type string `json:"token_type"` +} + +// AuthorizationToken returns formatted authorization header. +func (refreshTokenResponse RefreshedTokens) AuthorizationToken() string { + return fmt.Sprintf("%s %s", refreshTokenResponse.Type, refreshTokenResponse.AccessToken) +} + +// RefreshAccessToken refreshes the current access token. +func (client *Client) RefreshAccessToken(refreshToken string) (RefreshedTokens, error) { + var values url.Values + + switch client.config.UAAGrantType() { + case string(constant.GrantTypeClientCredentials): + values = client.clientCredentialRefreshBody() + case "", string(constant.GrantTypePassword): // CLI used to write empty string for grant type in the case of password; preserve compatibility with old config.json files + values = client.refreshTokenBody(refreshToken) + } + + body := strings.NewReader(values.Encode()) + + request, err := client.newRequest(requestOptions{ + RequestName: internal.PostOAuthTokenRequest, + Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded"}}, + Body: body, + }) + if err != nil { + return RefreshedTokens{}, err + } + + if client.config.UAAGrantType() != string(constant.GrantTypeClientCredentials) { + request.SetBasicAuth(client.config.UAAOAuthClient(), client.config.UAAOAuthClientSecret()) + } + + var refreshResponse RefreshedTokens + response := Response{ + Result: &refreshResponse, + } + + err = client.connection.Make(request, &response) + if err != nil { + return RefreshedTokens{}, err + } + + return refreshResponse, nil +} + +func (client *Client) clientCredentialRefreshBody() url.Values { + return url.Values{ + "client_id": {client.config.UAAOAuthClient()}, + "client_secret": {client.config.UAAOAuthClientSecret()}, + "grant_type": {string(constant.GrantTypeClientCredentials)}, + } +} + +func (client *Client) refreshTokenBody(refreshToken string) url.Values { + return url.Values{ + "refresh_token": {refreshToken}, + "grant_type": {string(constant.GrantTypeRefreshToken)}, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/request.go b/vendor/code.cloudfoundry.org/cli/api/uaa/request.go new file mode 100644 index 0000000..a49df59 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/request.go @@ -0,0 +1,71 @@ +package uaa + +import ( + "io" + "net/http" + "net/url" + + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// RequestOptions contains all the options to create an HTTP Request. +type requestOptions struct { + // Header is the set of request headers + Header http.Header + + // URIParams are the list URI route parameters + URIParams internal.Params + + // Query is a list of HTTP query parameters + Query url.Values + + // RequestName is the name of the request (see routes) + RequestName string + + // Method is the HTTP method. + Method string + // URL is the request path. + URL string + // Body is the request body + Body io.Reader +} + +// newRequest returns a constructed http.Request with some defaults. The +// request will terminate the connection after it is sent (via a 'Connection: +// close' header). +func (client *Client) newRequest(passedRequest requestOptions) (*http.Request, error) { + var request *http.Request + var err error + + if passedRequest.URL != "" { + request, err = http.NewRequest( + passedRequest.Method, + passedRequest.URL, + passedRequest.Body, + ) + } else { + request, err = client.router.CreateRequest( + passedRequest.RequestName, + passedRequest.URIParams, + passedRequest.Body, + ) + } + if err != nil { + return nil, err + } + + if passedRequest.Query != nil { + request.URL.RawQuery = passedRequest.Query.Encode() + } + + if passedRequest.Header != nil { + request.Header = passedRequest.Header + } else { + request.Header = http.Header{} + } + request.Header.Set("Accept", "application/json") + request.Header.Set("Connection", "close") + request.Header.Set("User-Agent", client.userAgent) + + return request, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/resources.go b/vendor/code.cloudfoundry.org/cli/api/uaa/resources.go new file mode 100644 index 0000000..5a674db --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/resources.go @@ -0,0 +1,22 @@ +package uaa + +import ( + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// SetupResources configures the client to use the specified settings and diescopers the UAA and Authentication resources +func (client *Client) SetupResources(uaaURL string, loginURL string) error { + info := NewInfo(uaaURL, loginURL) + + resources := map[string]string{ + "uaa": uaaURL, + "authorization_endpoint": loginURL, + } + + client.router = internal.NewRouter(internal.APIRoutes, resources) + client.Info = info + + client.config.SetUAAEndpoint(uaaURL) + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/response.go b/vendor/code.cloudfoundry.org/cli/api/uaa/response.go new file mode 100644 index 0000000..714a9eb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/response.go @@ -0,0 +1,21 @@ +package uaa + +import "net/http" + +// Response represents an UAA response object. +type Response struct { + // Result represents the resource entity type that is expected in the + // response JSON. + Result interface{} + + // RawResponse represents the response body. + RawResponse []byte + + // HTTPResponse represents the HTTP response object. + HTTPResponse *http.Response +} + +func (r *Response) reset() { + r.RawResponse = []byte{} + r.HTTPResponse = nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/ssh.go b/vendor/code.cloudfoundry.org/cli/api/uaa/ssh.go new file mode 100644 index 0000000..01cff5e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/ssh.go @@ -0,0 +1,34 @@ +package uaa + +import ( + "net/url" + + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +func (client *Client) GetSSHPasscode(accessToken string, sshOAuthClient string) (string, error) { + queryValues := url.Values{} + queryValues.Add("response_type", "code") + queryValues.Add("client_id", sshOAuthClient) + + request, err := client.newRequest(requestOptions{ + RequestName: internal.GetSSHPasscodeRequest, + Query: queryValues, + }) + if err != nil { + return "", err + } + + response := Response{} + err = client.connection.Make(request, &response) + if err != nil { + return "", err + } + + locationURL, err := response.HTTPResponse.Location() + if err != nil { + return "", err + } + + return locationURL.Query().Get("code"), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/uaa_connection.go b/vendor/code.cloudfoundry.org/cli/api/uaa/uaa_connection.go new file mode 100644 index 0000000..6e6cd80 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/uaa_connection.go @@ -0,0 +1,112 @@ +package uaa + +import ( + "bytes" + "crypto/x509" + "encoding/json" + "io/ioutil" + "net" + "net/http" + "net/url" + "time" + + "code.cloudfoundry.org/cli/util" +) + +// UAAConnection represents the connection to UAA +type UAAConnection struct { + HTTPClient *http.Client +} + +// NewConnection returns a pointer to a new UAA Connection +func NewConnection(skipSSLValidation bool, disableKeepAlives bool, dialTimeout time.Duration) *UAAConnection { + tr := &http.Transport{ + DialContext: (&net.Dialer{ + KeepAlive: 30 * time.Second, + Timeout: dialTimeout, + }).DialContext, + DisableKeepAlives: disableKeepAlives, + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: util.NewTLSConfig(nil, skipSSLValidation), + } + + return &UAAConnection{ + HTTPClient: &http.Client{ + Transport: tr, + CheckRedirect: func(_ *http.Request, _ []*http.Request) error { + // This prevents redirects. When making a request to /oauth/authorize, + // the client should not follow redirects in order to obtain the ssh + // passcode. + return http.ErrUseLastResponse + }, + }, + } +} + +// Make takes a passedRequest, converts it into an HTTP request and then +// executes it. The response is then injected into passedResponse. +func (connection *UAAConnection) Make(request *http.Request, passedResponse *Response) error { + // In case this function is called from a retry, passedResponse may already + // be populated with a previous response. We reset in case there's an HTTP + // error and we don't repopulate it in populateResponse. + passedResponse.reset() + + response, err := connection.HTTPClient.Do(request) + if err != nil { + return connection.processRequestErrors(request, err) + } + + return connection.populateResponse(response, passedResponse) +} + +func (*UAAConnection) handleStatusCodes(response *http.Response, passedResponse *Response) error { + if response.StatusCode >= 400 { + return RawHTTPStatusError{ + StatusCode: response.StatusCode, + RawResponse: passedResponse.RawResponse, + } + } + + return nil +} + +func (connection *UAAConnection) populateResponse(response *http.Response, passedResponse *Response) error { + passedResponse.HTTPResponse = response + + rawBytes, err := ioutil.ReadAll(response.Body) + defer response.Body.Close() + if err != nil { + return err + } + passedResponse.RawResponse = rawBytes + + err = connection.handleStatusCodes(response, passedResponse) + if err != nil { + return err + } + + if passedResponse.Result != nil { + decoder := json.NewDecoder(bytes.NewBuffer(passedResponse.RawResponse)) + decoder.UseNumber() + err = decoder.Decode(passedResponse.Result) + if err != nil { + return err + } + } + + return nil +} + +func (connection *UAAConnection) processRequestErrors(request *http.Request, err error) error { + switch e := err.(type) { + case *url.Error: + if _, ok := e.Err.(x509.UnknownAuthorityError); ok { + return UnverifiedServerError{ + URL: request.URL.String(), + } + } + return RequestError{Err: e} + default: + return err + } +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/user.go b/vendor/code.cloudfoundry.org/cli/api/uaa/user.go new file mode 100644 index 0000000..0ca5fa9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/user.go @@ -0,0 +1,212 @@ +package uaa + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/uaa/internal" +) + +// User represents an UAA user account. +type User struct { + ID string + Origin string +} + +// newUserRequestBody represents the body of the request. +type newUserRequestBody struct { + Username string `json:"userName"` + Password string `json:"password"` + Origin string `json:"origin"` + Name userName `json:"name"` + Emails []email `json:"emails"` +} + +type userName struct { + FamilyName string `json:"familyName"` + GivenName string `json:"givenName"` +} + +type email struct { + Value string `json:"value"` + Primary bool `json:"primary"` +} + +// newUserResponse represents the HTTP JSON response. +type newUserResponse struct { + ID string `json:"id"` + Origin string `json:"origin"` +} + +type paginatedUsersResponse struct { + Resources []newUserResponse `json:"resources"` +} + +// CreateUser creates a new UAA user account with the provided password. +func (client *Client) CreateUser(user string, password string, origin string) (User, error) { + userRequest := newUserRequestBody{ + Username: user, + Password: password, + Origin: origin, + Name: userName{ + FamilyName: user, + GivenName: user, + }, + Emails: []email{ + { + Value: user, + Primary: true, + }, + }, + } + + bodyBytes, err := json.Marshal(userRequest) + if err != nil { + return User{}, err + } + + request, err := client.newRequest(requestOptions{ + RequestName: internal.PostUserRequest, + Header: http.Header{ + "Content-Type": {"application/json"}, + }, + Body: bytes.NewBuffer(bodyBytes), + }) + if err != nil { + return User{}, err + } + + var userResponse newUserResponse + response := Response{ + Result: &userResponse, + } + + err = client.connection.Make(request, &response) + if err != nil { + return User{}, err + } + + return User(userResponse), nil +} + +func (client *Client) DeleteUser(userGuid string) (User, error) { + deleteRequest, err := client.newRequest(requestOptions{ + RequestName: internal.DeleteUserRequest, + Header: http.Header{ + "Content-Type": {"application/json"}, + }, + URIParams: map[string]string{"user_guid": userGuid}, + }) + + if err != nil { + return User{}, err + } + + var deleteUserResponse newUserResponse + deleteResponse := Response{ + Result: &deleteUserResponse, + } + + err = client.connection.Make(deleteRequest, &deleteResponse) + if err != nil { + return User{}, err + } + + return User(deleteUserResponse), nil +} + +// ListUsers gets a list of users from UAA with the given username and (if provided) origin. +// NOTE: that this is a paginated response and we are only currently returning the first page +// of users. This will mean, if no origin is passed and there are more than 100 users with +// the given username, only the first 100 will be returned. For our current purposes, this is +// more than enough, but it would be a problem if we ever need to get all users with a username. +func (client Client) ListUsers(userName, origin string) ([]User, error) { + filter := fmt.Sprintf(`userName eq "%s"`, userName) + + if origin != "" { + filter = fmt.Sprintf(`%s and origin eq "%s"`, filter, origin) + } + + request, err := client.newRequest(requestOptions{ + RequestName: internal.ListUsersRequest, + Header: http.Header{ + "Content-Type": {"application/json"}, + }, + Query: url.Values{ + "filter": {filter}, + }, + }) + if err != nil { + return nil, err + } + + var usersResponse paginatedUsersResponse + response := Response{ + Result: &usersResponse, + } + + err = client.connection.Make(request, &response) + if err != nil { + return nil, err + } + + var users []User + for _, user := range usersResponse.Resources { + users = append(users, User(user)) + } + + return users, nil +} + +func (client *Client) UpdatePassword(userGUID string, oldPassword string, newPassword string) error { + requestBody := map[string]interface{}{ + "oldPassword": oldPassword, + "password": newPassword, + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return err + } + + request, err := client.newRequest(requestOptions{ + RequestName: internal.UpdatePasswordRequest, + Header: http.Header{"Content-Type": {"application/json"}}, + URIParams: map[string]string{"user_guid": userGUID}, + Body: bytes.NewBuffer(bodyBytes), + }) + if err != nil { + return err + } + + return client.connection.Make(request, &Response{}) +} + +func (client Client) ValidateClientUser(clientID string) error { + request, err := client.newRequest(requestOptions{ + RequestName: internal.GetClientUser, + Header: http.Header{ + "Content-Type": {"application/json"}, + }, + URIParams: map[string]string{"client_id": clientID}, + }) + if err != nil { + return err + } + err = client.connection.Make(request, &Response{}) + + if errType, ok := err.(RawHTTPStatusError); ok { + switch errType.StatusCode { + case http.StatusNotFound: + return actionerror.UserNotFoundError{Username: clientID} + case http.StatusForbidden: + return InsufficientScopeError{} + } + } + + return err +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/version.go b/vendor/code.cloudfoundry.org/cli/api/uaa/version.go new file mode 100644 index 0000000..9e3a63c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/version.go @@ -0,0 +1,35 @@ +package uaa + +import ( + "fmt" + "net/http" +) + +func (client *Client) GetAPIVersion() (string, error) { + type loginResponse struct { + App struct { + Version string `json:"version"` + } `json:"app"` + } + + request, err := client.newRequest(requestOptions{ + Method: http.MethodGet, + URL: fmt.Sprintf("%s/login", client.LoginLink()), + }) + + if err != nil { + return "", err + } + + info := loginResponse{} + response := Response{ + Result: &info, + } + + err = client.connection.Make(request, &response) + if err != nil { + return "", err + } + + return info.App.Version, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/request_logger.go b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/request_logger.go new file mode 100644 index 0000000..e68a8ad --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/request_logger.go @@ -0,0 +1,169 @@ +package wrapper + +import ( + "bytes" + "io/ioutil" + "net/http" + "regexp" + "sort" + "time" + + "code.cloudfoundry.org/cli/api/uaa" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RequestLoggerOutput + +// RequestLoggerOutput is the interface for displaying logs +type RequestLoggerOutput interface { + DisplayBody(body []byte) error + DisplayJSONBody(body []byte) error + DisplayHeader(name string, value string) error + DisplayHost(name string) error + DisplayRequestHeader(method string, uri string, httpProtocol string) error + DisplayResponseHeader(httpProtocol string, status string) error + DisplayType(name string, requestDate time.Time) error + HandleInternalError(err error) + Start() error + Stop() error +} + +// RequestLogger is the wrapper that logs requests to and responses from the +// UAA server +type RequestLogger struct { + connection uaa.Connection + output RequestLoggerOutput +} + +// NewRequestLogger returns a pointer to a RequestLogger wrapper +func NewRequestLogger(output RequestLoggerOutput) *RequestLogger { + return &RequestLogger{ + output: output, + } +} + +// Make records the request and the response to UI +func (logger *RequestLogger) Make(request *http.Request, passedResponse *uaa.Response) error { + err := logger.displayRequest(request) + if err != nil { + logger.output.HandleInternalError(err) + } + + err = logger.connection.Make(request, passedResponse) + + if passedResponse.HTTPResponse != nil { + displayErr := logger.displayResponse(passedResponse) + if displayErr != nil { + logger.output.HandleInternalError(displayErr) + } + } + + return err +} + +// Wrap sets the connection on the RequestLogger and returns itself +func (logger *RequestLogger) Wrap(innerconnection uaa.Connection) uaa.Connection { + logger.connection = innerconnection + return logger +} + +func (logger *RequestLogger) displayRequest(request *http.Request) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("REQUEST", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayRequestHeader(request.Method, request.URL.RequestURI(), request.Proto) + if err != nil { + return err + } + err = logger.output.DisplayHost(request.URL.Host) + if err != nil { + return err + } + err = logger.displaySortedHeaders(request.Header) + if err != nil { + return err + } + + if request.Body != nil { + rawRequestBody, err := ioutil.ReadAll(request.Body) + defer request.Body.Close() + if err != nil { + return err + } + + request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) + if request.Header.Get("Content-Type") == "application/json" { + err = logger.output.DisplayJSONBody(rawRequestBody) + } else { + err = logger.output.DisplayBody(rawRequestBody) + } + if err != nil { + return err + } + } + + return nil +} + +func (logger *RequestLogger) displayResponse(passedResponse *uaa.Response) error { + err := logger.output.Start() + if err != nil { + return err + } + defer logger.output.Stop() + + err = logger.output.DisplayType("RESPONSE", time.Now()) + if err != nil { + return err + } + err = logger.output.DisplayResponseHeader(passedResponse.HTTPResponse.Proto, passedResponse.HTTPResponse.Status) + if err != nil { + return err + } + err = logger.displaySortedHeaders(passedResponse.HTTPResponse.Header) + if err != nil { + return err + } + return logger.output.DisplayJSONBody(passedResponse.RawResponse) +} + +func (logger *RequestLogger) displaySortedHeaders(headers http.Header) error { + keys := []string{} + for key := range headers { + keys = append(keys, key) + } + sort.Strings(keys) + + for _, key := range keys { + for _, value := range headers[key] { + err := logger.output.DisplayHeader(key, redactHeaders(key, value)) + if err != nil { + return err + } + } + } + return nil +} + +func redactHeaders(key string, value string) string { + redactedValue := "[PRIVATE DATA HIDDEN]" + redactedKeys := []string{"Authorization", "Set-Cookie"} + for _, redactedKey := range redactedKeys { + if key == redactedKey { + return redactedValue + } + } + + re := regexp.MustCompile(`([&?]code)=[A-Za-z0-9\-._~!$'()*+,;=:@/?]*`) + if key == "Location" { + value = re.ReplaceAllString(value, "$1="+redactedValue) + } + + return value +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/retry_request.go b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/retry_request.go new file mode 100644 index 0000000..538752f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/retry_request.go @@ -0,0 +1,69 @@ +package wrapper + +import ( + "bytes" + "io/ioutil" + "net/http" + + "code.cloudfoundry.org/cli/api/uaa" +) + +// RetryRequest is a wrapper that retries failed requests if they contain a 5XX +// status code. +type RetryRequest struct { + maxRetries int + connection uaa.Connection +} + +// NewRetryRequest returns a pointer to a RetryRequest wrapper. +func NewRetryRequest(maxRetries int) *RetryRequest { + return &RetryRequest{ + maxRetries: maxRetries, + } +} + +// Make retries the request if it comes back with a 5XX status code. +func (retry *RetryRequest) Make(request *http.Request, passedResponse *uaa.Response) error { + var err error + var rawRequestBody []byte + + if request.Body != nil { + rawRequestBody, err = ioutil.ReadAll(request.Body) + defer request.Body.Close() + if err != nil { + return err + } + } + + for i := 0; i < retry.maxRetries+1; i++ { + if rawRequestBody != nil { + request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) + } + err = retry.connection.Make(request, passedResponse) + if err == nil { + return nil + } + + if retry.skipRetry(request.Method, passedResponse.HTTPResponse) { + break + } + } + return err +} + +// Wrap sets the connection in the RetryRequest and returns itself. +func (retry *RetryRequest) Wrap(innerconnection uaa.Connection) uaa.Connection { + retry.connection = innerconnection + return retry +} + +// skipRetry will skip retry if the request method is POST or contains a status +// code that is not one of following http status codes: 500, 502, 503, 504. +func (*RetryRequest) skipRetry(httpMethod string, response *http.Response) bool { + return httpMethod == http.MethodPost || + response != nil && + response.StatusCode != http.StatusInternalServerError && + response.StatusCode != http.StatusBadGateway && + response.StatusCode != http.StatusServiceUnavailable && + response.StatusCode != http.StatusGatewayTimeout +} diff --git a/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/uaa_authentication.go b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/uaa_authentication.go new file mode 100644 index 0000000..10b1268 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/api/uaa/wrapper/uaa_authentication.go @@ -0,0 +1,113 @@ +package wrapper + +import ( + "bytes" + "io/ioutil" + "net/http" + "strings" + + "code.cloudfoundry.org/cli/api/uaa" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UAAClient + +// UAAClient is the interface for getting a valid access token +type UAAClient interface { + RefreshAccessToken(refreshToken string) (uaa.RefreshedTokens, error) +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . TokenCache + +// TokenCache is where the UAA token information is stored. +type TokenCache interface { + AccessToken() string + RefreshToken() string + SetAccessToken(token string) + SetRefreshToken(token string) +} + +// UAAAuthentication wraps connections and adds authentication headers to all +// requests +type UAAAuthentication struct { + connection uaa.Connection + client UAAClient + cache TokenCache +} + +// NewUAAAuthentication returns a pointer to a UAAAuthentication wrapper with +// the client and token cache. +func NewUAAAuthentication(client UAAClient, cache TokenCache) *UAAAuthentication { + return &UAAAuthentication{ + client: client, + cache: cache, + } +} + +// Make adds authentication headers to the passed in request and then calls the +// wrapped connection's Make +func (t *UAAAuthentication) Make(request *http.Request, passedResponse *uaa.Response) error { + if t.client == nil { + return t.connection.Make(request, passedResponse) + } + + var err error + var rawRequestBody []byte + + if request.Body != nil { + rawRequestBody, err = ioutil.ReadAll(request.Body) + defer request.Body.Close() + if err != nil { + return err + } + + request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) + + if skipAuthenticationHeader(request, rawRequestBody) { + return t.connection.Make(request, passedResponse) + } + } + + request.Header.Set("Authorization", t.cache.AccessToken()) + + err = t.connection.Make(request, passedResponse) + if _, ok := err.(uaa.InvalidAuthTokenError); ok { + tokens, refreshErr := t.client.RefreshAccessToken(t.cache.RefreshToken()) + if refreshErr != nil { + return refreshErr + } + + t.cache.SetAccessToken(tokens.AuthorizationToken()) + t.cache.SetRefreshToken(tokens.RefreshToken) + + if rawRequestBody != nil { + request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody)) + } + request.Header.Set("Authorization", t.cache.AccessToken()) + return t.connection.Make(request, passedResponse) + } + + return err +} + +// SetClient sets the UAA client that the wrapper will use. +func (t *UAAAuthentication) SetClient(client UAAClient) { + t.client = client +} + +// Wrap sets the connection on the UAAAuthentication and returns itself +func (t *UAAAuthentication) Wrap(innerconnection uaa.Connection) uaa.Connection { + t.connection = innerconnection + return t +} + +// The authentication header is not added to token refresh requests or login +// requests. +func skipAuthenticationHeader(request *http.Request, body []byte) bool { + stringBody := string(body) + + return strings.Contains(request.URL.String(), "/oauth/token") && + request.Method == http.MethodPost && + (strings.Contains(stringBody, "grant_type=refresh_token") || + strings.Contains(stringBody, "grant_type=password") || + strings.Contains(stringBody, "grant_type=client_credentials")) +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor.go new file mode 100644 index 0000000..53ae6af --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor.go @@ -0,0 +1,90 @@ +package configuration + +import ( + "io/ioutil" + "os" +) + +const ( + filePermissions = 0600 + dirPermissions = 0700 +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Persistor + +type Persistor interface { + Delete() + Exists() bool + Load(DataInterface) error + Save(DataInterface) error +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . DataInterface + +type DataInterface interface { + JSONMarshalV3() ([]byte, error) + JSONUnmarshalV3([]byte) error +} + +type DiskPersistor struct { + filePath string +} + +func NewDiskPersistor(path string) DiskPersistor { + return DiskPersistor{ + filePath: path, + } +} + +func (dp DiskPersistor) Exists() bool { + _, err := os.Stat(dp.filePath) + if err != nil && !os.IsExist(err) { + return false + } + return true +} + +func (dp DiskPersistor) Delete() { + _ = os.Remove(dp.filePath) +} + +func (dp DiskPersistor) Load(data DataInterface) error { + err := dp.read(data) + if os.IsPermission(err) { + return err + } + + if err != nil { + err = dp.write(data) + } + return err +} + +func (dp DiskPersistor) Save(data DataInterface) error { + return dp.write(data) +} + +func (dp DiskPersistor) read(data DataInterface) error { + err := dp.makeDirectory() + if err != nil { + return err + } + + jsonBytes, err := ioutil.ReadFile(dp.filePath) + if err != nil { + return err + } + + err = data.JSONUnmarshalV3(jsonBytes) + return err +} + +func (dp DiskPersistor) write(data DataInterface) error { + bytes, err := data.JSONMarshalV3() + if err != nil { + return err + } + + err = ioutil.WriteFile(dp.filePath, bytes, filePermissions) + return err +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_unix.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_unix.go new file mode 100644 index 0000000..bdbfb3d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_unix.go @@ -0,0 +1,13 @@ +//go:build !windows +// +build !windows + +package configuration + +import ( + "os" + "path/filepath" +) + +func (dp DiskPersistor) makeDirectory() error { + return os.MkdirAll(filepath.Dir(dp.filePath), dirPermissions) +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_win.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_win.go new file mode 100644 index 0000000..663a768 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/config_disk_persistor_win.go @@ -0,0 +1,31 @@ +//go:build windows +// +build windows + +package configuration + +import ( + "os" + "path/filepath" + "syscall" +) + +func (dp DiskPersistor) makeDirectory() error { + dir := filepath.Dir(dp.filePath) + + err := os.MkdirAll(dir, dirPermissions) + if err != nil { + return err + } + + p, err := syscall.UTF16PtrFromString(dir) + if err != nil { + return err + } + + attrs, err := syscall.GetFileAttributes(p) + if err != nil { + return err + } + + return syscall.SetFileAttributes(p, attrs|syscall.FILE_ATTRIBUTE_HIDDEN) +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/access_token.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/access_token.go new file mode 100644 index 0000000..0ee7171 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/access_token.go @@ -0,0 +1,61 @@ +package coreconfig + +import ( + "encoding/base64" + "encoding/json" + "strings" +) + +type TokenInfo struct { + Username string `json:"user_name"` + ClientID string `json:"client_id"` + Email string `json:"email"` + UserGUID string `json:"user_id"` +} + +func NewTokenInfo(accessToken string) (info TokenInfo) { + tokenJSON, err := DecodeAccessToken(accessToken) + if err != nil { + return TokenInfo{} + } + + info = TokenInfo{} + err = json.Unmarshal(tokenJSON, &info) + if err != nil { + return TokenInfo{} + } + + return info +} + +func DecodeAccessToken(accessToken string) (tokenJSON []byte, err error) { + tokenParts := strings.Split(accessToken, " ") + + if len(tokenParts) < 2 { + return + } + + token := tokenParts[1] + encodedParts := strings.Split(token, ".") + + if len(encodedParts) < 3 { + return + } + + encodedTokenJSON := encodedParts[1] + return base64Decode(encodedTokenJSON) +} + +func base64Decode(encodedData string) ([]byte, error) { + return base64.StdEncoding.DecodeString(restorePadding(encodedData)) +} + +func restorePadding(seg string) string { + switch len(seg) % 4 { + case 2: + seg = seg + "==" + case 3: + seg = seg + "=" + } + return seg +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/api_config_refresher.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/api_config_refresher.go new file mode 100644 index 0000000..3e933ce --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/api_config_refresher.go @@ -0,0 +1,55 @@ +package coreconfig + +import ( + "strings" + + . "code.cloudfoundry.org/cli/cf/i18n" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . EndpointRepository + +type EndpointRepository interface { + GetCCInfo(string) (*CCInfo, string, error) +} + +type APIConfigRefresher struct { + EndpointRepo EndpointRepository + Config ReadWriter + Endpoint string +} + +func (a APIConfigRefresher) Refresh() (Warning, error) { + ccInfo, endpoint, err := a.EndpointRepo.GetCCInfo(a.Endpoint) + if err != nil { + return nil, err + } + + if endpoint != a.Config.APIEndpoint() { + a.Config.ClearSession() + } + + a.Config.SetAPIEndpoint(endpoint) + a.Config.SetAPIVersion(ccInfo.APIVersion) + a.Config.SetAuthenticationEndpoint(ccInfo.AuthorizationEndpoint) + a.Config.SetSSHOAuthClient(ccInfo.SSHOAuthClient) + a.Config.SetMinCLIVersion(ccInfo.MinCLIVersion) + a.Config.SetMinRecommendedCLIVersion(ccInfo.MinRecommendedCLIVersion) + + a.Config.SetDopplerEndpoint(ccInfo.DopplerEndpoint) + a.Config.SetRoutingAPIEndpoint(ccInfo.RoutingAPIEndpoint) + + if !strings.HasPrefix(endpoint, "https://") { + return new(insecureWarning), nil + } + return nil, nil +} + +type Warning interface { + Warn() string +} + +type insecureWarning struct{} + +func (w insecureWarning) Warn() string { + return T("Warning: Insecure http API endpoint detected: secure https API endpoints are recommended\n") +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_data.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_data.go new file mode 100644 index 0000000..a5314a1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_data.go @@ -0,0 +1,77 @@ +package coreconfig + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/cf/models" + "code.cloudfoundry.org/cli/util/configv3" +) + +type AuthPromptType string + +const ( + AuthPromptTypeText AuthPromptType = "TEXT" + AuthPromptTypePassword AuthPromptType = "PASSWORD" + AuthPromptTypeMenu AuthPromptType = "MENU" +) + +type AuthPrompt struct { + Type AuthPromptType + DisplayName string + Entries []string +} + +type Data struct { + AccessToken string + APIVersion string + AsyncTimeout uint + AuthorizationEndpoint string + ColorEnabled string + ConfigVersion int + DopplerEndPoint string + Locale string + LogCacheEndPoint string + MinCLIVersion string + MinRecommendedCLIVersion string + OrganizationFields models.OrganizationFields + PluginRepos []models.PluginRepo + RefreshToken string + RoutingAPIEndpoint string + SpaceFields models.SpaceFields + SSHOAuthClient string + SSLDisabled bool + Target string + Trace string + UaaEndpoint string + UAAGrantType string + UAAOAuthClient string + UAAOAuthClientSecret string +} + +func NewData() *Data { + data := new(Data) + + data.UAAOAuthClient = "cf" + data.UAAOAuthClientSecret = "" + + return data +} + +func (d *Data) JSONMarshalV3() ([]byte, error) { + d.ConfigVersion = configv3.CurrentConfigVersion + return json.MarshalIndent(d, "", " ") +} + +func (d *Data) JSONUnmarshalV3(input []byte) error { + err := json.Unmarshal(input, d) + if err != nil { + return err + } + + if d.ConfigVersion != configv3.CurrentConfigVersion { + *d = Data{} + return nil + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_repository.go b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_repository.go new file mode 100644 index 0000000..d3a6006 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/configuration/coreconfig/config_repository.go @@ -0,0 +1,607 @@ +package coreconfig + +import ( + "strings" + "sync" + + "code.cloudfoundry.org/cli/cf/configuration" + "code.cloudfoundry.org/cli/cf/models" + "code.cloudfoundry.org/cli/version" + "github.com/blang/semver" +) + +type ConfigRepository struct { + CFCLIVersion string + data *Data + mutex *sync.RWMutex + initOnce *sync.Once + persistor configuration.Persistor + onError func(error) +} + +type CCInfo struct { + APIVersion string `json:"api_version"` + AuthorizationEndpoint string `json:"authorization_endpoint"` + DopplerEndpoint string `json:"doppler_logging_endpoint"` + LogCacheEndpoint string `json:"log_cache_endpoint"` + MinCLIVersion string `json:"min_cli_version"` + MinRecommendedCLIVersion string `json:"min_recommended_cli_version"` + SSHOAuthClient string `json:"app_ssh_oauth_client"` + RoutingAPIEndpoint string `json:"routing_endpoint"` +} + +func NewRepositoryFromFilepath(filepath string, errorHandler func(error)) Repository { + if errorHandler == nil { + return nil + } + return NewRepositoryFromPersistor(configuration.NewDiskPersistor(filepath), errorHandler) +} + +func NewRepositoryFromPersistor(persistor configuration.Persistor, errorHandler func(error)) Repository { + data := NewData() + if !persistor.Exists() { + //set default plugin repo + data.PluginRepos = append(data.PluginRepos, models.PluginRepo{ + Name: "CF-Community", + URL: "https://plugins.cloudfoundry.org", + }) + } + + return &ConfigRepository{ + data: data, + mutex: new(sync.RWMutex), + initOnce: new(sync.Once), + persistor: persistor, + onError: errorHandler, + } +} + +type Reader interface { + APIEndpoint() string + APIVersion() string + HasAPIEndpoint() bool + + AuthenticationEndpoint() string + DopplerEndpoint() string + LogCacheEndpoint() string + UaaEndpoint() string + RoutingAPIEndpoint() string + AccessToken() string + UAAOAuthClient() string + UAAOAuthClientSecret() string + SSHOAuthClient() string + RefreshToken() string + + OrganizationFields() models.OrganizationFields + HasOrganization() bool + + SpaceFields() models.SpaceFields + HasSpace() bool + + Username() string + UserGUID() string + UserEmail() string + IsLoggedIn() bool + IsSSLDisabled() bool + IsMinAPIVersion(semver.Version) bool + IsMinCLIVersion(string) bool + MinCLIVersion() string + MinRecommendedCLIVersion() string + CLIVersion() string + + AsyncTimeout() uint + Trace() string + + ColorEnabled() string + + Locale() string + + PluginRepos() []models.PluginRepo +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ReadWriter + +type ReadWriter interface { + Reader + ClearSession() + SetAccessToken(string) + SetAPIEndpoint(string) + SetAPIVersion(string) + SetAsyncTimeout(uint) + SetAuthenticationEndpoint(string) + SetCLIVersion(string) + SetColorEnabled(string) + SetDopplerEndpoint(string) + SetLogCacheEndpoint(string) + SetLocale(string) + SetMinCLIVersion(string) + SetMinRecommendedCLIVersion(string) + SetOrganizationFields(models.OrganizationFields) + SetPluginRepo(models.PluginRepo) + SetRefreshToken(string) + SetRoutingAPIEndpoint(string) + SetSpaceFields(models.SpaceFields) + SetSSHOAuthClient(string) + SetSSLDisabled(bool) + SetTrace(string) + SetUaaEndpoint(string) + SetUAAGrantType(string) + SetUAAOAuthClient(string) + SetUAAOAuthClientSecret(string) + UAAGrantType() string + UnSetPluginRepo(int) +} + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Repository + +type Repository interface { + ReadWriter + Close() +} + +// ACCESS CONTROL + +func (c *ConfigRepository) init() { + c.initOnce.Do(func() { + err := c.persistor.Load(c.data) + if err != nil { + c.onError(err) + } + }) +} + +func (c *ConfigRepository) read(cb func()) { + c.mutex.RLock() + defer c.mutex.RUnlock() + c.init() + + cb() +} + +func (c *ConfigRepository) write(cb func()) { + c.mutex.Lock() + defer c.mutex.Unlock() + c.init() + + cb() + + err := c.persistor.Save(c.data) + if err != nil { + c.onError(err) + } +} + +// CLOSERS + +func (c *ConfigRepository) Close() { + c.read(func() { + // perform a read to ensure write lock has been cleared + }) +} + +// GETTERS + +func (c *ConfigRepository) APIVersion() (apiVersion string) { + c.read(func() { + apiVersion = c.data.APIVersion + }) + return +} + +func (c *ConfigRepository) AuthenticationEndpoint() (authEndpoint string) { + c.read(func() { + authEndpoint = c.data.AuthorizationEndpoint + }) + return +} + +func (c *ConfigRepository) DopplerEndpoint() (dopplerEndpoint string) { + c.read(func() { + dopplerEndpoint = c.data.DopplerEndPoint + }) + + return +} + +func (c *ConfigRepository) LogCacheEndpoint() (logCacheEndpoint string) { + c.read(func() { + logCacheEndpoint = c.data.LogCacheEndPoint + }) + + return +} + +func (c *ConfigRepository) UaaEndpoint() (uaaEndpoint string) { + c.read(func() { + uaaEndpoint = c.data.UaaEndpoint + }) + return +} + +func (c *ConfigRepository) RoutingAPIEndpoint() (routingAPIEndpoint string) { + c.read(func() { + routingAPIEndpoint = c.data.RoutingAPIEndpoint + }) + return +} + +func (c *ConfigRepository) APIEndpoint() string { + var apiEndpoint string + c.read(func() { + apiEndpoint = c.data.Target + }) + apiEndpoint = strings.TrimRight(apiEndpoint, "/") + + return apiEndpoint +} + +func (c *ConfigRepository) HasAPIEndpoint() (hasEndpoint bool) { + c.read(func() { + hasEndpoint = c.data.APIVersion != "" && c.data.Target != "" + }) + return +} + +func (c *ConfigRepository) AccessToken() (accessToken string) { + c.read(func() { + accessToken = c.data.AccessToken + }) + return +} + +func (c *ConfigRepository) UAAOAuthClient() (clientID string) { + c.read(func() { + clientID = c.data.UAAOAuthClient + }) + return +} + +func (c *ConfigRepository) UAAOAuthClientSecret() (clientID string) { + c.read(func() { + clientID = c.data.UAAOAuthClientSecret + }) + return +} + +func (c *ConfigRepository) SSHOAuthClient() (clientID string) { + c.read(func() { + clientID = c.data.SSHOAuthClient + }) + return +} + +func (c *ConfigRepository) RefreshToken() (refreshToken string) { + c.read(func() { + refreshToken = c.data.RefreshToken + }) + return +} + +func (c *ConfigRepository) OrganizationFields() (org models.OrganizationFields) { + c.read(func() { + org = c.data.OrganizationFields + }) + return +} + +func (c *ConfigRepository) SpaceFields() (space models.SpaceFields) { + c.read(func() { + space = c.data.SpaceFields + }) + return +} + +func (c *ConfigRepository) UserEmail() (email string) { + c.read(func() { + email = NewTokenInfo(c.data.AccessToken).Email + }) + return +} + +func (c *ConfigRepository) UserGUID() (guid string) { + c.read(func() { + guid = NewTokenInfo(c.data.AccessToken).UserGUID + }) + return +} + +func (c *ConfigRepository) Username() (name string) { + c.read(func() { + t := NewTokenInfo(c.data.AccessToken) + if t.Username != "" { + name = t.Username + } else { + name = t.ClientID + } + }) + return +} + +func (c *ConfigRepository) IsLoggedIn() (loggedIn bool) { + c.read(func() { + loggedIn = c.data.AccessToken != "" + }) + return +} + +func (c *ConfigRepository) HasOrganization() (hasOrg bool) { + c.read(func() { + hasOrg = c.data.OrganizationFields.GUID != "" && c.data.OrganizationFields.Name != "" + }) + return +} + +func (c *ConfigRepository) HasSpace() (hasSpace bool) { + c.read(func() { + hasSpace = c.data.SpaceFields.GUID != "" && c.data.SpaceFields.Name != "" + }) + return +} + +func (c *ConfigRepository) IsSSLDisabled() (isSSLDisabled bool) { + c.read(func() { + isSSLDisabled = c.data.SSLDisabled + }) + return +} + +// SetCLIVersion should only be used in testing +func (c *ConfigRepository) SetCLIVersion(v string) { + c.CFCLIVersion = v +} + +func (c *ConfigRepository) CLIVersion() string { + if c.CFCLIVersion == "" { + return version.VersionString() + } else { + return c.CFCLIVersion + } +} + +func (c *ConfigRepository) IsMinAPIVersion(requiredVersion semver.Version) bool { + var apiVersion string + c.read(func() { + apiVersion = c.data.APIVersion + }) + + actualVersion, err := semver.Make(apiVersion) + if err != nil { + return false + } + return actualVersion.GTE(requiredVersion) +} + +func (c *ConfigRepository) IsMinCLIVersion(checkVersion string) bool { + if checkVersion == version.DefaultVersion { + return true + } + var minCLIVersion string + c.read(func() { + minCLIVersion = c.data.MinCLIVersion + }) + if minCLIVersion == "" { + return true + } + + actualVersion, err := semver.Make(checkVersion) + if err != nil { + return false + } + requiredVersion, err := semver.Make(minCLIVersion) + if err != nil { + return false + } + return actualVersion.GTE(requiredVersion) +} + +func (c *ConfigRepository) MinCLIVersion() (minCLIVersion string) { + c.read(func() { + minCLIVersion = c.data.MinCLIVersion + }) + return +} + +func (c *ConfigRepository) MinRecommendedCLIVersion() (minRecommendedCLIVersion string) { + c.read(func() { + minRecommendedCLIVersion = c.data.MinRecommendedCLIVersion + }) + return +} + +func (c *ConfigRepository) AsyncTimeout() (timeout uint) { + c.read(func() { + timeout = c.data.AsyncTimeout + }) + return +} + +func (c *ConfigRepository) Trace() (trace string) { + c.read(func() { + trace = c.data.Trace + }) + return +} + +func (c *ConfigRepository) ColorEnabled() (enabled string) { + c.read(func() { + enabled = c.data.ColorEnabled + }) + return +} + +func (c *ConfigRepository) Locale() (locale string) { + c.read(func() { + locale = c.data.Locale + }) + return +} + +func (c *ConfigRepository) PluginRepos() (repos []models.PluginRepo) { + c.read(func() { + repos = c.data.PluginRepos + }) + return +} + +// SETTERS + +func (c *ConfigRepository) ClearSession() { + c.write(func() { + c.data.AccessToken = "" + c.data.RefreshToken = "" + c.data.OrganizationFields = models.OrganizationFields{} + c.data.SpaceFields = models.SpaceFields{} + }) +} + +func (c *ConfigRepository) SetAPIEndpoint(endpoint string) { + c.write(func() { + c.data.Target = endpoint + }) +} + +func (c *ConfigRepository) SetAPIVersion(version string) { + c.write(func() { + c.data.APIVersion = version + }) +} + +func (c *ConfigRepository) SetMinCLIVersion(version string) { + c.write(func() { + c.data.MinCLIVersion = version + }) +} + +func (c *ConfigRepository) SetMinRecommendedCLIVersion(version string) { + c.write(func() { + c.data.MinRecommendedCLIVersion = version + }) +} + +func (c *ConfigRepository) SetAuthenticationEndpoint(endpoint string) { + c.write(func() { + c.data.AuthorizationEndpoint = endpoint + }) +} + +func (c *ConfigRepository) SetDopplerEndpoint(endpoint string) { + c.write(func() { + c.data.DopplerEndPoint = endpoint + }) +} + +func (c *ConfigRepository) SetLogCacheEndpoint(endpoint string) { + c.write(func() { + c.data.LogCacheEndPoint = endpoint + }) +} + +func (c *ConfigRepository) SetUaaEndpoint(uaaEndpoint string) { + c.write(func() { + c.data.UaaEndpoint = uaaEndpoint + }) +} + +func (c *ConfigRepository) SetRoutingAPIEndpoint(routingAPIEndpoint string) { + c.write(func() { + c.data.RoutingAPIEndpoint = routingAPIEndpoint + }) +} + +func (c *ConfigRepository) SetAccessToken(token string) { + c.write(func() { + c.data.AccessToken = token + }) +} + +func (c *ConfigRepository) SetUAAOAuthClient(clientID string) { + c.write(func() { + c.data.UAAOAuthClient = clientID + }) +} + +func (c *ConfigRepository) SetUAAOAuthClientSecret(clientID string) { + c.write(func() { + c.data.UAAOAuthClientSecret = clientID + }) +} + +func (c *ConfigRepository) SetSSHOAuthClient(clientID string) { + c.write(func() { + c.data.SSHOAuthClient = clientID + }) +} + +func (c *ConfigRepository) SetRefreshToken(token string) { + c.write(func() { + c.data.RefreshToken = token + }) +} + +func (c *ConfigRepository) SetOrganizationFields(org models.OrganizationFields) { + c.write(func() { + c.data.OrganizationFields = org + }) +} + +func (c *ConfigRepository) SetSpaceFields(space models.SpaceFields) { + c.write(func() { + c.data.SpaceFields = space + }) +} + +func (c *ConfigRepository) SetSSLDisabled(disabled bool) { + c.write(func() { + c.data.SSLDisabled = disabled + }) +} + +func (c *ConfigRepository) SetAsyncTimeout(timeout uint) { + c.write(func() { + c.data.AsyncTimeout = timeout + }) +} + +func (c *ConfigRepository) SetTrace(value string) { + c.write(func() { + c.data.Trace = value + }) +} + +func (c *ConfigRepository) SetColorEnabled(enabled string) { + c.write(func() { + c.data.ColorEnabled = enabled + }) +} + +func (c *ConfigRepository) SetLocale(locale string) { + c.write(func() { + c.data.Locale = locale + }) +} + +func (c *ConfigRepository) SetPluginRepo(repo models.PluginRepo) { + c.write(func() { + c.data.PluginRepos = append(c.data.PluginRepos, repo) + }) +} + +func (c *ConfigRepository) UnSetPluginRepo(index int) { + c.write(func() { + c.data.PluginRepos = append(c.data.PluginRepos[:index], c.data.PluginRepos[index+1:]...) + }) +} + +func (c *ConfigRepository) UAAGrantType() string { + grantType := "" + c.read(func() { + grantType = c.data.UAAGrantType + }) + return grantType +} + +func (c *ConfigRepository) SetUAAGrantType(grantType string) { + c.write(func() { + c.data.UAAGrantType = grantType + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/formatters/bools.go b/vendor/code.cloudfoundry.org/cli/cf/formatters/bools.go new file mode 100644 index 0000000..4ce3d0c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/formatters/bools.go @@ -0,0 +1,12 @@ +package formatters + +import ( + . "code.cloudfoundry.org/cli/cf/i18n" +) + +func Allowed(allowed bool) string { + if allowed { + return T("allowed") + } + return T("disallowed") +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/formatters/bytes.go b/vendor/code.cloudfoundry.org/cli/cf/formatters/bytes.go new file mode 100644 index 0000000..bdd76a6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/formatters/bytes.go @@ -0,0 +1,82 @@ +package formatters + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "strings" + + . "code.cloudfoundry.org/cli/cf/i18n" +) + +const ( + BYTE = 1.0 + KILOBYTE = 1024 * BYTE + MEGABYTE = 1024 * KILOBYTE + GIGABYTE = 1024 * MEGABYTE + TERABYTE = 1024 * GIGABYTE +) + +func ByteSize(bytes int64) string { + unit := "" + value := float32(bytes) + + switch { + case bytes >= TERABYTE: + unit = "T" + value = value / TERABYTE + case bytes >= GIGABYTE: + unit = "G" + value = value / GIGABYTE + case bytes >= MEGABYTE: + unit = "M" + value = value / MEGABYTE + case bytes >= KILOBYTE: + unit = "K" + value = value / KILOBYTE + case bytes == 0: + return "0" + case bytes < KILOBYTE: + unit = "B" + } + + stringValue := fmt.Sprintf("%.1f", value) + stringValue = strings.TrimSuffix(stringValue, ".0") + return fmt.Sprintf("%s%s", stringValue, unit) +} + +func ToMegabytes(s string) (int64, error) { + parts := bytesPattern.FindStringSubmatch(strings.TrimSpace(s)) + if len(parts) < 3 { + return 0, invalidByteQuantityError() + } + + value, err := strconv.ParseInt(parts[1], 10, 0) + if err != nil { + return 0, invalidByteQuantityError() + } + + var bytes int64 + unit := strings.ToUpper(parts[2]) + switch unit { + case "T": + bytes = value * TERABYTE + case "G": + bytes = value * GIGABYTE + case "M": + bytes = value * MEGABYTE + case "K": + bytes = value * KILOBYTE + } + + return bytes / MEGABYTE, nil +} + +var ( + bytesPattern = regexp.MustCompile(`(?i)^(-?\d+)([KMGT])B?$`) +) + +func invalidByteQuantityError() error { + return errors.New(T("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB")) +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/formatters/memoryLimit.go b/vendor/code.cloudfoundry.org/cli/cf/formatters/memoryLimit.go new file mode 100644 index 0000000..8017ea8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/formatters/memoryLimit.go @@ -0,0 +1,11 @@ +package formatters + +import "strconv" + +func InstanceMemoryLimit(limit int64) string { + if limit == -1 { + return "unlimited" + } + + return strconv.FormatInt(limit, 10) + "M" +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/formatters/string.go b/vendor/code.cloudfoundry.org/cli/cf/formatters/string.go new file mode 100644 index 0000000..fc09732 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/formatters/string.go @@ -0,0 +1,16 @@ +package formatters + +import ( + "fmt" + "reflect" +) + +func MapStr(args interface{}) []string { + r := reflect.ValueOf(args) + rval := make([]string, r.Len()) + for i := 0; i < r.Len(); i++ { + rval[i] = r.Index(i).Interface().(fmt.Stringer).String() + } + return rval + +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/i18n/README-i18n.md b/vendor/code.cloudfoundry.org/cli/cf/i18n/README-i18n.md new file mode 100644 index 0000000..6b4e1d5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/i18n/README-i18n.md @@ -0,0 +1,48 @@ +# CLI i18n Support + +The CLI currently supports a variety of languages. These translations can be accessed by setting either LC_ALL or LANG in your environment, or by setting your locale within the cli via `cf config --locale your_LOCALE # (e.g. fr_FR)`. + +Translations only affect messages generated by the CLI. Responses from server side components (Cloud Controller, etc.) will be internationalized separately and are likely to be English. + +If you are interested in submitting translations for a currently unsupported language/locale, please communicate with us via the [cf-dev](https://lists.cloudfoundry.org/archives/list/cf-dev@lists.cloudfoundry.org/) mailing list. + +## How can you contribute? + +If you see typos, errors in grammar, ambiguous strings or English after setting your locale, please find the appropriate entry in the corresponding `i18n/resources/_.all.json` file and submit a [pull request](https://help.github.com/articles/creating-a-pull-request/) with the fix(es). It is much better to submit small pull requests as you complete translations, rather than submitting a large one. This makes it much easier to rapidly merge your changes in. You can also report translations needing fixes as an issue in Github. + +Pull requests should only contain changes to "translation" values; the "id" value should not change as it is the key which is used to find the translations, and will always be English. For example: + +Given a missing translation for "Create an org": +``` +[ + { + "id":"Create an org", + "translation":"" + }, + ... +] +``` + +Adding the translation would look like: +``` +[ + { + "id":"Create an org", + "translation":"Créez un org" + }, + ... +] +``` + +Finally, it is also important not to translate the argument names in templated strings. Templated strings are the ones which contain arguments, e.g., `{{.Name}}` or `{{.Username}}` and so on. The arguments can move to a different location on the translated string, however, the arguments cannot change, should not be translated, and should not be removed or new ones added. So for instance, the following string is translated in French as follows: + +``` +[ + ..., + { + "id": "Creating quota {{.QuotaName}} as {{.Username}}...", + "translation": "Créez quota {{.QuotaName}} étant {{.Username}}..." + }, + ... +] +``` diff --git a/vendor/code.cloudfoundry.org/cli/cf/i18n/excluded.json b/vendor/code.cloudfoundry.org/cli/cf/i18n/excluded.json new file mode 100644 index 0000000..ede5b16 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/i18n/excluded.json @@ -0,0 +1,41 @@ +{ + "excludedStrings" : [ + "", + " ", + "\n", + "\t", + "\n\t", + "extract_strings", + "excluded.json", + "i18n4go", + ".en.json", + ".extracted.json", + "recursive:", + ".json", + ".po", + ", column: ", + ", line: ", + ", offset: ", + "msgid ", + "msgstr ", + "# filename: ", + ".", + "\\", + "help", + ".go", + "", + "/", + "false", + "true", + + "allow-paid-service-plans" + ], + "excludedRegexps" : [ + "^\\d+$", + "^[-%]?\\w$", + "^\\w$", + "^json:", + "^\\w*[-]?quota[-]?\\w*$", + "^\\w+-paid-service-plans$" + ] +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/i18n/i18n.go b/vendor/code.cloudfoundry.org/cli/cf/i18n/i18n.go new file mode 100644 index 0000000..4084738 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/i18n/i18n.go @@ -0,0 +1,14 @@ +package i18n + +import "code.cloudfoundry.org/cli/util/ui" + +var T ui.TranslateFunc + +type LocaleReader interface { + Locale() string +} + +func Init(config LocaleReader) ui.TranslateFunc { + t, _ := ui.GetTranslationFunc(config) + return t +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/i18n/locale.go b/vendor/code.cloudfoundry.org/cli/cf/i18n/locale.go new file mode 100644 index 0000000..3857d1e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/i18n/locale.go @@ -0,0 +1,61 @@ +package i18n + +import ( + "path" + "strings" + + "code.cloudfoundry.org/cli/i18n/resources" + "code.cloudfoundry.org/cli/util/ui" +) + +const resourceSuffix = ".all.json" + +func SupportedLocales() []string { + languages := supportedLanguages() + localeNames := make([]string, len(languages)) + + for i, l := range languages { + localeParts := strings.Split(l, "-") + lang := localeParts[0] + regionOrScript := localeParts[1] + + switch len(regionOrScript) { + case 2: // Region + localeNames[i] = lang + "-" + strings.ToUpper(regionOrScript) + case 4: // Script + localeNames[i] = lang + "-" + strings.Title(regionOrScript) + default: + localeNames[i] = l + } + } + + return localeNames +} + +func IsSupportedLocale(locale string) bool { + sanitizedLocale, err := ui.ParseLocale(locale) + if err != nil { + return false + } + + for _, supportedLanguage := range supportedLanguages() { + if supportedLanguage == sanitizedLocale { + return true + } + } + + return false +} + +func supportedLanguages() []string { + assetNames := resources.AssetNames() + + var languages []string + for _, assetName := range assetNames { + assetLocale := strings.TrimSuffix(path.Base(assetName), resourceSuffix) + locale, _ := ui.ParseLocale(assetLocale) + languages = append(languages, locale) + } + + return languages +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/app_event.go b/vendor/code.cloudfoundry.org/cli/cf/models/app_event.go new file mode 100644 index 0000000..2292fea --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/app_event.go @@ -0,0 +1,12 @@ +package models + +import "time" + +type EventFields struct { + GUID string + Name string + Timestamp time.Time + Description string + Actor string + ActorName string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/app_file.go b/vendor/code.cloudfoundry.org/cli/cf/models/app_file.go new file mode 100644 index 0000000..33f23d3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/app_file.go @@ -0,0 +1,8 @@ +package models + +type AppFileFields struct { + Path string + Sha1 string + Size int64 + Mode string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/app_instance.go b/vendor/code.cloudfoundry.org/cli/cf/models/app_instance.go new file mode 100644 index 0000000..3be7f8e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/app_instance.go @@ -0,0 +1,24 @@ +package models + +import "time" + +type InstanceState string + +const ( + InstanceStarting InstanceState = "starting" + InstanceRunning InstanceState = "running" + InstanceFlapping InstanceState = "flapping" + InstanceDown InstanceState = "down" + InstanceCrashed InstanceState = "crashed" +) + +type AppInstanceFields struct { + State InstanceState + Details string + Since time.Time + CPUUsage float64 // percentage + DiskQuota int64 // in bytes + DiskUsage int64 + MemQuota int64 + MemUsage int64 +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/application.go b/vendor/code.cloudfoundry.org/cli/cf/models/application.go new file mode 100644 index 0000000..53fd219 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/application.go @@ -0,0 +1,222 @@ +package models + +import ( + "os" + "reflect" + "strings" + "time" +) + +type Application struct { + ApplicationFields + Stack *Stack + Routes []RouteSummary + Services []ServicePlanSummary +} + +func (model Application) HasRoute(route Route) bool { + for _, boundRoute := range model.Routes { + if boundRoute.GUID == route.GUID { + return true + } + } + return false +} + +func (model Application) ToParams() AppParams { + state := strings.ToUpper(model.State) + params := AppParams{ + GUID: &model.GUID, + Name: &model.Name, + BuildpackURL: &model.BuildpackURL, + Command: &model.Command, + DiskQuota: &model.DiskQuota, + InstanceCount: &model.InstanceCount, + HealthCheckType: &model.HealthCheckType, + HealthCheckHTTPEndpoint: &model.HealthCheckHTTPEndpoint, + Memory: &model.Memory, + State: &state, + SpaceGUID: &model.SpaceGUID, + EnvironmentVars: &model.EnvironmentVars, + DockerImage: &model.DockerImage, + } + + if model.Stack != nil { + params.StackGUID = &model.Stack.GUID + } + + return params +} + +type ApplicationFields struct { + GUID string + Name string + BuildpackURL string + Command string + Diego bool + DetectedStartCommand string + DiskQuota int64 // in Megabytes + EnvironmentVars map[string]interface{} + InstanceCount int + Memory int64 // in Megabytes + RunningInstances int + HealthCheckType string + HealthCheckHTTPEndpoint string + HealthCheckTimeout int + State string + SpaceGUID string + StackGUID string + PackageUpdatedAt *time.Time + PackageState string + StagingFailedReason string + Buildpack string + DetectedBuildpack string + DockerImage string + EnableSSH bool +} + +const ( + ApplicationStateStopped = "stopped" + ApplicationStateStarted = "started" + ApplicationStateRunning = "running" + ApplicationStateCrashed = "crashed" + ApplicationStateFlapping = "flapping" + ApplicationStateDown = "down" + ApplicationStateStarting = "starting" +) + +type AppParams struct { + BuildpackURL *string + Buildpacks []string + Command *string + DiskQuota *int64 + Domains []string + EnvironmentVars *map[string]interface{} + GUID *string + HealthCheckType *string + HealthCheckHTTPEndpoint *string + HealthCheckTimeout *int + DockerImage *string + DockerUsername *string + DockerPassword *string + EnableSSH *bool + Hosts []string + RoutePath *string + InstanceCount *int + Memory *int64 + Name *string + NoHostname *bool + NoRoute bool + UseRandomRoute bool + UseRandomPort bool + Path *string + ServicesToBind []string + SpaceGUID *string + StackGUID *string + StackName *string + State *string + PackageUpdatedAt *time.Time + Routes []ManifestRoute +} + +func (app *AppParams) Merge(flagContext *AppParams) { + if flagContext.BuildpackURL != nil { + app.BuildpackURL = flagContext.BuildpackURL + } + if flagContext.Command != nil { + app.Command = flagContext.Command + } + if flagContext.DiskQuota != nil { + app.DiskQuota = flagContext.DiskQuota + } + if flagContext.DockerImage != nil { + app.DockerImage = flagContext.DockerImage + } + + switch { + case flagContext.DockerUsername != nil: + app.DockerUsername = flagContext.DockerUsername + // the password is always non-nil after we parse the flag context + app.DockerPassword = flagContext.DockerPassword + case app.DockerUsername != nil: + password := os.Getenv("CF_DOCKER_PASSWORD") + // if the password is empty, we will get a CC error + app.DockerPassword = &password + } + + if flagContext.Domains != nil { + app.Domains = flagContext.Domains + } + if flagContext.EnableSSH != nil { + app.EnableSSH = flagContext.EnableSSH + } + if flagContext.EnvironmentVars != nil { + app.EnvironmentVars = flagContext.EnvironmentVars + } + if flagContext.GUID != nil { + app.GUID = flagContext.GUID + } + if flagContext.HealthCheckType != nil { + app.HealthCheckType = flagContext.HealthCheckType + } + if flagContext.HealthCheckHTTPEndpoint != nil { + app.HealthCheckHTTPEndpoint = flagContext.HealthCheckHTTPEndpoint + } + if flagContext.HealthCheckTimeout != nil { + app.HealthCheckTimeout = flagContext.HealthCheckTimeout + } + if flagContext.Hosts != nil { + app.Hosts = flagContext.Hosts + } + if flagContext.InstanceCount != nil { + app.InstanceCount = flagContext.InstanceCount + } + if flagContext.Memory != nil { + app.Memory = flagContext.Memory + } + if flagContext.Name != nil { + app.Name = flagContext.Name + } + if flagContext.Path != nil { + app.Path = flagContext.Path + } + if flagContext.RoutePath != nil { + app.RoutePath = flagContext.RoutePath + } + if flagContext.ServicesToBind != nil { + app.ServicesToBind = flagContext.ServicesToBind + } + if flagContext.SpaceGUID != nil { + app.SpaceGUID = flagContext.SpaceGUID + } + if flagContext.StackGUID != nil { + app.StackGUID = flagContext.StackGUID + } + if flagContext.StackName != nil { + app.StackName = flagContext.StackName + } + if flagContext.State != nil { + app.State = flagContext.State + } + + app.NoRoute = app.NoRoute || flagContext.NoRoute + noHostBool := app.IsNoHostnameTrue() || flagContext.IsNoHostnameTrue() + app.NoHostname = &noHostBool + app.UseRandomRoute = app.UseRandomRoute || flagContext.UseRandomRoute +} + +func (app *AppParams) IsEmpty() bool { + noHostBool := false + return reflect.DeepEqual(*app, AppParams{NoHostname: &noHostBool}) +} + +func (app *AppParams) IsHostEmpty() bool { + return app.Hosts == nil || len(app.Hosts) == 0 +} + +func (app *AppParams) IsNoHostnameTrue() bool { + if app.NoHostname == nil { + return false + } + return *app.NoHostname +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/buildpack.go b/vendor/code.cloudfoundry.org/cli/cf/models/buildpack.go new file mode 100644 index 0000000..a13df73 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/buildpack.go @@ -0,0 +1,12 @@ +package models + +type Buildpack struct { + GUID string + Name string + Stack string + Position *int + Enabled *bool + Key string + Filename string + Locked *bool +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/docker.go b/vendor/code.cloudfoundry.org/cli/cf/models/docker.go new file mode 100644 index 0000000..ab3eaff --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/docker.go @@ -0,0 +1,6 @@ +package models + +type ManifestDocker struct { + Image string + Username string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/domain.go b/vendor/code.cloudfoundry.org/cli/cf/models/domain.go new file mode 100644 index 0000000..5f25e4f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/domain.go @@ -0,0 +1,19 @@ +package models + +type DomainFields struct { + GUID string + Name string + OwningOrganizationGUID string + RouterGroupGUID string + RouterGroupType string + Shared bool +} + +func (model DomainFields) URLForHostAndPath(host, path string, port int) string { + return (&RoutePresenter{ + Host: host, + Domain: model.Name, + Path: path, + Port: port, + }).URL() +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/environment.go b/vendor/code.cloudfoundry.org/cli/cf/models/environment.go new file mode 100644 index 0000000..48a6fe7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/environment.go @@ -0,0 +1,19 @@ +package models + +func NewEnvironment() *Environment { + return &Environment{ + System: make(map[string]interface{}), + Application: make(map[string]interface{}), + Environment: make(map[string]interface{}), + Running: make(map[string]interface{}), + Staging: make(map[string]interface{}), + } +} + +type Environment struct { + System map[string]interface{} `json:"system_env_json,omitempty"` + Environment map[string]interface{} `json:"environment_json,omitempty"` + Running map[string]interface{} `json:"running_env_json,omitempty"` + Staging map[string]interface{} `json:"staging_env_json,omitempty"` + Application map[string]interface{} `json:"application_env_json,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/environment_variable.go b/vendor/code.cloudfoundry.org/cli/cf/models/environment_variable.go new file mode 100644 index 0000000..09872bc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/environment_variable.go @@ -0,0 +1,22 @@ +package models + +import "strings" + +type EnvironmentVariable struct { + Name string + Value string +} + +type EnvironmentVariableList []EnvironmentVariable + +func (evl EnvironmentVariableList) Len() int { + return len(evl) +} + +func (evl EnvironmentVariableList) Swap(i, j int) { + evl[i], evl[j] = evl[j], evl[i] +} + +func (evl EnvironmentVariableList) Less(i, j int) bool { + return strings.Compare(strings.ToLower(evl[i].Name), strings.ToLower(evl[j].Name)) == -1 +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/feature_flag.go b/vendor/code.cloudfoundry.org/cli/cf/models/feature_flag.go new file mode 100644 index 0000000..f50389c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/feature_flag.go @@ -0,0 +1,7 @@ +package models + +type FeatureFlag struct { + Name string `json:"name"` + Enabled bool `json:"enabled"` + ErrorMessage string `json:"error_message"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/organization.go b/vendor/code.cloudfoundry.org/cli/cf/models/organization.go new file mode 100644 index 0000000..12ed3fa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/organization.go @@ -0,0 +1,14 @@ +package models + +type OrganizationFields struct { + GUID string + Name string + QuotaDefinition QuotaFields +} + +type Organization struct { + OrganizationFields + Spaces []SpaceFields + Domains []DomainFields + SpaceQuotas []SpaceQuota +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/plugin_repo.go b/vendor/code.cloudfoundry.org/cli/cf/models/plugin_repo.go new file mode 100644 index 0000000..6e0398d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/plugin_repo.go @@ -0,0 +1,6 @@ +package models + +type PluginRepo struct { + Name string + URL string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/quota.go b/vendor/code.cloudfoundry.org/cli/cf/models/quota.go new file mode 100644 index 0000000..77712d9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/quota.go @@ -0,0 +1,27 @@ +package models + +import "encoding/json" + +type QuotaFields struct { + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + MemoryLimit int64 `json:"memory_limit"` // in Megabytes + InstanceMemoryLimit int64 `json:"instance_memory_limit"` // in Megabytes + RoutesLimit int `json:"total_routes"` + ServicesLimit int `json:"total_services"` + NonBasicServicesAllowed bool `json:"non_basic_services_allowed"` + AppInstanceLimit int `json:"app_instance_limit"` + ReservedRoutePorts json.Number `json:"total_reserved_route_ports,omitempty"` +} + +type QuotaResponse struct { + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + MemoryLimit int64 `json:"memory_limit"` // in Megabytes + InstanceMemoryLimit int64 `json:"instance_memory_limit"` // in Megabytes + RoutesLimit int `json:"total_routes"` + ServicesLimit int `json:"total_services"` + NonBasicServicesAllowed bool `json:"non_basic_services_allowed"` + AppInstanceLimit json.Number `json:"app_instance_limit"` + ReservedRoutePorts json.Number `json:"total_reserved_route_ports"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/role.go b/vendor/code.cloudfoundry.org/cli/cf/models/role.go new file mode 100644 index 0000000..3670e07 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/role.go @@ -0,0 +1,67 @@ +package models + +import ( + "errors" + "strings" +) + +type Role int + +const ( + RoleUnknown Role = iota - 1 + RoleOrgUser + RoleOrgManager + RoleBillingManager + RoleOrgAuditor + RoleSpaceManager + RoleSpaceDeveloper + RoleSpaceAuditor +) + +var ErrUnknownRole = errors.New("Unknown Role") + +func RoleFromString(roleString string) (Role, error) { + switch strings.ToLower(roleString) { + case "orgmanager": + return RoleOrgManager, nil + case "billingmanager": + return RoleBillingManager, nil + case "orgauditor": + return RoleOrgAuditor, nil + case "spacemanager": + return RoleSpaceManager, nil + case "spacedeveloper": + return RoleSpaceDeveloper, nil + case "spaceauditor": + return RoleSpaceAuditor, nil + default: + return RoleUnknown, ErrUnknownRole + } +} + +func (r Role) ToString() string { + switch r { + case RoleUnknown: + return "RoleUnknown" + case RoleOrgUser: + return "RoleOrgUser" + case RoleOrgManager: + return "RoleOrgManager" + case RoleBillingManager: + return "RoleBillingManager" + case RoleOrgAuditor: + return "RoleOrgAuditor" + case RoleSpaceManager: + return "RoleSpaceManager" + case RoleSpaceDeveloper: + return "RoleSpaceDeveloper" + case RoleSpaceAuditor: + return "RoleSpaceAuditor" + default: + return "" + } +} + +func (r Role) Display() string { + return strings.TrimPrefix(r.ToString(), "Role") +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/route.go b/vendor/code.cloudfoundry.org/cli/cf/models/route.go new file mode 100644 index 0000000..f1dcb1a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/route.go @@ -0,0 +1,59 @@ +package models + +import ( + "fmt" + "net/url" + "strings" +) + +type Route struct { + GUID string + Host string + Domain DomainFields + Path string + Port int + + Space SpaceFields + Apps []ApplicationFields + ServiceInstance ServiceInstanceFields +} + +func (r Route) URL() string { + return (&RoutePresenter{ + Host: r.Host, + Domain: r.Domain.Name, + Path: r.Path, + Port: r.Port, + }).URL() +} + +type RoutePresenter struct { + Host string + Domain string + Path string + Port int +} + +func (r *RoutePresenter) URL() string { + var host string + if r.Host != "" { + host = r.Host + "." + r.Domain + } else { + host = r.Domain + } + + if r.Port != 0 { + host = fmt.Sprintf("%s:%d", host, r.Port) + } + + u := url.URL{ + Host: host, + Path: r.Path, + } + + return strings.TrimPrefix(u.String(), "//") // remove the empty scheme +} + +type ManifestRoute struct { + Route string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/route_summary.go b/vendor/code.cloudfoundry.org/cli/cf/models/route_summary.go new file mode 100644 index 0000000..20e7b9d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/route_summary.go @@ -0,0 +1,18 @@ +package models + +type RouteSummary struct { + GUID string + Host string + Domain DomainFields + Path string + Port int +} + +func (r RouteSummary) URL() string { + return (&RoutePresenter{ + Host: r.Host, + Domain: r.Domain.Name, + Path: r.Path, + Port: r.Port, + }).URL() +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/router_group.go b/vendor/code.cloudfoundry.org/cli/cf/models/router_group.go new file mode 100644 index 0000000..38414d7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/router_group.go @@ -0,0 +1,9 @@ +package models + +type RouterGroups []RouterGroup + +type RouterGroup struct { + GUID string `json:"guid"` + Name string `json:"name"` + Type string `json:"type"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/security_group.go b/vendor/code.cloudfoundry.org/cli/cf/models/security_group.go new file mode 100644 index 0000000..ca23693 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/security_group.go @@ -0,0 +1,22 @@ +package models + +// represents just the attributes for an security group +type SecurityGroupFields struct { + Name string + GUID string + SpaceURL string `json:"spaces_url,omitempty"` + Rules []map[string]interface{} +} + +// represents the JSON that we send up to CC when the user creates / updates a record +type SecurityGroupParams struct { + Name string `json:"name,omitempty"` + GUID string `json:"guid,omitempty"` + Rules []map[string]interface{} `json:"rules"` +} + +// represents a fully instantiated model returned by the CC (e.g.: with its attributes and the fields for its child objects) +type SecurityGroup struct { + SecurityGroupFields + Spaces []Space +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_auth_token.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_auth_token.go new file mode 100644 index 0000000..9b2b097 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_auth_token.go @@ -0,0 +1,8 @@ +package models + +type ServiceAuthTokenFields struct { + GUID string + Label string + Provider string + Token string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_binding.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_binding.go new file mode 100644 index 0000000..248d8c6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_binding.go @@ -0,0 +1,13 @@ +package models + +type ServiceBindingRequest struct { + AppGUID string `json:"app_guid"` + ServiceInstanceGUID string `json:"service_instance_guid"` + Params map[string]interface{} `json:"parameters,omitempty"` +} + +type ServiceBindingFields struct { + GUID string + URL string + AppGUID string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_broker.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_broker.go new file mode 100644 index 0000000..23ea66b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_broker.go @@ -0,0 +1,10 @@ +package models + +type ServiceBroker struct { + GUID string + Name string + Username string + Password string + URL string + Services []ServiceOffering +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_instance.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_instance.go new file mode 100644 index 0000000..e3e55ec --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_instance.go @@ -0,0 +1,48 @@ +package models + +type LastOperationFields struct { + Type string + State string + Description string + CreatedAt string + UpdatedAt string +} + +type ServiceInstanceCreateRequest struct { + Name string `json:"name"` + SpaceGUID string `json:"space_guid"` + PlanGUID string `json:"service_plan_guid,omitempty"` + Params map[string]interface{} `json:"parameters,omitempty"` + Tags []string `json:"tags,omitempty"` +} + +type ServiceInstanceUpdateRequest struct { + PlanGUID string `json:"service_plan_guid,omitempty"` + Params map[string]interface{} `json:"parameters,omitempty"` + Tags *[]string `json:"tags,omitempty"` +} + +type ServiceInstanceFields struct { + GUID string + Name string + LastOperation LastOperationFields + SysLogDrainURL string + RouteServiceURL string + ApplicationNames []string + Params map[string]interface{} + DashboardURL string + Type string + Tags []string +} + +type ServiceInstance struct { + ServiceInstanceFields + ServiceBindings []ServiceBindingFields + ServiceKeys []ServiceKeyFields + ServicePlan ServicePlanFields + ServiceOffering ServiceOfferingFields +} + +func (inst ServiceInstance) IsUserProvided() bool { + return inst.Type == "user_provided_service_instance" +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_key.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_key.go new file mode 100644 index 0000000..ba48599 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_key.go @@ -0,0 +1,20 @@ +package models + +type ServiceKeyFields struct { + Name string + GUID string + URL string + ServiceInstanceGUID string + ServiceInstanceURL string +} + +type ServiceKeyRequest struct { + Name string `json:"name"` + ServiceInstanceGUID string `json:"service_instance_guid"` + Params map[string]interface{} `json:"parameters,omitempty"` +} + +type ServiceKey struct { + Fields ServiceKeyFields + Credentials map[string]interface{} +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_offering.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_offering.go new file mode 100644 index 0000000..efd8766 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_offering.go @@ -0,0 +1,31 @@ +package models + +type ServiceOfferingFields struct { + GUID string + BrokerGUID string + Label string + Provider string + Version string + Description string + DocumentationURL string + Requires []string +} + +type ServiceOffering struct { + ServiceOfferingFields + Plans []ServicePlanFields +} + +type ServiceOfferings []ServiceOffering + +func (s ServiceOfferings) Len() int { + return len(s) +} + +func (s ServiceOfferings) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s ServiceOfferings) Less(i, j int) bool { + return s[i].Label < s[j].Label +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_plan.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_plan.go new file mode 100644 index 0000000..4c7e65d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_plan.go @@ -0,0 +1,34 @@ +package models + +type ServicePlanFields struct { + GUID string + Name string + Free bool + Public bool + Description string + Active bool + ServiceOfferingGUID string + OrgNames []string +} + +type ServicePlan struct { + ServicePlanFields + ServiceOffering ServiceOfferingFields +} + +type ServicePlanSummary struct { + GUID string + Name string +} + +func (servicePlanFields ServicePlanFields) OrgHasVisibility(orgName string) bool { + if servicePlanFields.Public { + return true + } + for _, org := range servicePlanFields.OrgNames { + if org == orgName { + return true + } + } + return false +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/service_plan_visibility.go b/vendor/code.cloudfoundry.org/cli/cf/models/service_plan_visibility.go new file mode 100644 index 0000000..b50bb41 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/service_plan_visibility.go @@ -0,0 +1,7 @@ +package models + +type ServicePlanVisibilityFields struct { + GUID string `json:"guid"` + ServicePlanGUID string `json:"service_plan_guid"` + OrganizationGUID string `json:"organization_guid"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/space.go b/vendor/code.cloudfoundry.org/cli/cf/models/space.go new file mode 100644 index 0000000..43e492a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/space.go @@ -0,0 +1,17 @@ +package models + +type SpaceFields struct { + GUID string + Name string + AllowSSH bool +} + +type Space struct { + SpaceFields + Organization OrganizationFields + Applications []ApplicationFields + ServiceInstances []ServiceInstanceFields + Domains []DomainFields + SecurityGroups []SecurityGroupFields + SpaceQuotaGUID string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/space_quota.go b/vendor/code.cloudfoundry.org/cli/cf/models/space_quota.go new file mode 100644 index 0000000..4edf299 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/space_quota.go @@ -0,0 +1,75 @@ +package models + +import ( + "encoding/json" + "strconv" + + "code.cloudfoundry.org/cli/cf/formatters" + . "code.cloudfoundry.org/cli/cf/i18n" +) + +type SpaceQuota struct { + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + MemoryLimit int64 `json:"memory_limit"` // in Megabytes + InstanceMemoryLimit int64 `json:"instance_memory_limit"` // in Megabytes + RoutesLimit int `json:"total_routes"` + ServicesLimit int `json:"total_services"` + NonBasicServicesAllowed bool `json:"non_basic_services_allowed"` + OrgGUID string `json:"organization_guid"` + AppInstanceLimit int `json:"app_instance_limit"` + ReservedRoutePortsLimit json.Number `json:"total_reserved_route_ports,omitempty"` +} + +const UnlimitedDisplay = "unlimited" + +func (q SpaceQuota) FormattedMemoryLimit() string { + return formatters.ByteSize(q.MemoryLimit * formatters.MEGABYTE) +} + +func (q SpaceQuota) FormattedInstanceMemoryLimit() string { + if q.InstanceMemoryLimit == -1 { + return T(UnlimitedDisplay) + } + return formatters.ByteSize(q.InstanceMemoryLimit * formatters.MEGABYTE) +} + +func (q SpaceQuota) FormattedAppInstanceLimit() string { + appInstanceLimit := T(UnlimitedDisplay) + if q.AppInstanceLimit != -1 { //TODO - figure out how to use resources.UnlimitedAppInstances + appInstanceLimit = strconv.Itoa(q.AppInstanceLimit) + } + + return appInstanceLimit +} + +func (q SpaceQuota) FormattedServicesLimit() string { + servicesLimit := T(UnlimitedDisplay) + if q.ServicesLimit != -1 { + servicesLimit = strconv.Itoa(q.ServicesLimit) + } + + return servicesLimit +} + +func (q SpaceQuota) FormattedRoutePortsLimit() string { + reservedRoutePortsLimit := T(UnlimitedDisplay) + if q.ReservedRoutePortsLimit != "-1" { + reservedRoutePortsLimit = string(q.ReservedRoutePortsLimit) + } + + return reservedRoutePortsLimit +} + +type SpaceQuotaResponse struct { + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + MemoryLimit int64 `json:"memory_limit"` // in Megabytes + InstanceMemoryLimit int64 `json:"instance_memory_limit"` // in Megabytes + RoutesLimit int `json:"total_routes"` + ServicesLimit int `json:"total_services"` + NonBasicServicesAllowed bool `json:"non_basic_services_allowed"` + OrgGUID string `json:"organization_guid"` + AppInstanceLimit json.Number `json:"app_instance_limit"` + ReservedRoutePortsLimit json.Number `json:"total_reserved_route_ports"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/stack.go b/vendor/code.cloudfoundry.org/cli/cf/models/stack.go new file mode 100644 index 0000000..9e30f66 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/stack.go @@ -0,0 +1,7 @@ +package models + +type Stack struct { + GUID string + Name string + Description string +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/user.go b/vendor/code.cloudfoundry.org/cli/cf/models/user.go new file mode 100644 index 0000000..afccd1f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/user.go @@ -0,0 +1,8 @@ +package models + +type UserFields struct { + GUID string + Username string + Password string + IsAdmin bool +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/models/user_provided_service.go b/vendor/code.cloudfoundry.org/cli/cf/models/user_provided_service.go new file mode 100644 index 0000000..ec83a78 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/models/user_provided_service.go @@ -0,0 +1,19 @@ +package models + +type UserProvidedServiceSummary struct { + Total int `json:"total_results"` + Resources []UserProvidedServiceEntity `json:"resources"` +} + +type UserProvidedService struct { + Name string `json:"name,omitempty"` + Credentials map[string]interface{} `json:"credentials"` + SpaceGUID string `json:"space_guid,omitempty"` + SysLogDrainURL string `json:"syslog_drain_url"` + RouteServiceURL string `json:"route_service_url"` + Tags []string `json:"tags,omitempty"` +} + +type UserProvidedServiceEntity struct { + UserProvidedService `json:"entity"` +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch.go b/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch.go new file mode 100644 index 0000000..6eab1ee --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch.go @@ -0,0 +1,10 @@ +//go:build !windows +// +build !windows + +package sigwinch + +import "syscall" + +func SIGWINCH() syscall.Signal { + return syscall.SIGWINCH +} diff --git a/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch_win.go b/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch_win.go new file mode 100644 index 0000000..045da2d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/cf/ssh/sigwinch/sigwinch_win.go @@ -0,0 +1,10 @@ +//go:build windows +// +build windows + +package sigwinch + +import "syscall" + +func SIGWINCH() syscall.Signal { + panic("Not supported on windows") +} diff --git a/vendor/code.cloudfoundry.org/cli/command/api_version_warning.go b/vendor/code.cloudfoundry.org/cli/command/api_version_warning.go new file mode 100644 index 0000000..db206ed --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/api_version_warning.go @@ -0,0 +1,75 @@ +package command + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/version" + "github.com/blang/semver" +) + +type APIVersionTooHighError struct{} + +func (a APIVersionTooHighError) Error() string { + return "" +} + +func WarnIfCLIVersionBelowAPIDefinedMinimum(config Config, apiVersion string, ui UI) error { + minVer := config.MinCLIVersion() + currentVer := config.BinaryVersion() + + isOutdated, err := CheckVersionOutdated(currentVer, minVer) + if err != nil { + return err + } + + if isOutdated { + ui.DisplayWarning("Cloud Foundry API version {{.APIVersion}} requires CLI version {{.MinCLIVersion}}. You are currently on version {{.BinaryVersion}}. To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads", + map[string]interface{}{ + "APIVersion": apiVersion, + "MinCLIVersion": minVer, + "BinaryVersion": currentVer, + }) + } + + return nil +} + +func WarnIfAPIVersionBelowSupportedMinimum(apiVersion string, ui UI) error { + isOutdated, err := CheckVersionOutdated(apiVersion, ccversion.MinSupportedV2ClientVersion) + if err != nil { + return err + } + + if isOutdated { + ui.DisplayWarning("Your CF API version ({{.APIVersion}}) is no longer supported. "+ + "Upgrade to a newer version of the API (minimum version {{.MinSupportedVersion}}). Please refer to "+ + "https://github.com/cloudfoundry/cli/wiki/Versioning-Policy#cf-cli-minimum-supported-version", + map[string]interface{}{ + "APIVersion": apiVersion, + "MinSupportedVersion": ccversion.MinSupportedV2ClientVersion, + }) + } + + return nil +} + +func CheckVersionOutdated(current string, minimum string) (bool, error) { + if current == version.DefaultVersion || minimum == "" { + return false, nil + } + + currentSemver, err := semver.Make(current) + if err != nil { + return false, err + } + + minimumSemver, err := semver.Make(minimum) + if err != nil { + return false, err + } + + if currentSemver.Compare(minimumSemver) == -1 { + return true, nil + } + + return false, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/command/config.go b/vendor/code.cloudfoundry.org/cli/command/config.go new file mode 100644 index 0000000..44b30e5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/config.go @@ -0,0 +1,85 @@ +package command + +import ( + "time" + + "code.cloudfoundry.org/cli/util/configv3" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Config + +// Config a way of getting basic CF configuration +type Config interface { + AccessToken() string + AddPlugin(configv3.Plugin) + AddPluginRepository(name string, url string) + AuthorizationEndpoint() string + APIVersion() string + BinaryName() string + BinaryVersion() string + CFPassword() string + CFUsername() string + ColorEnabled() configv3.ColorSetting + CurrentUser() (configv3.User, error) + CurrentUserName() (string, error) + DialTimeout() time.Duration + DockerPassword() string + Experimental() bool + GetPlugin(pluginName string) (configv3.Plugin, bool) + GetPluginCaseInsensitive(pluginName string) (configv3.Plugin, bool) + HasTargetedOrganization() bool + HasTargetedSpace() bool + IsTTY() bool + Locale() string + LogCacheEndpoint() string + MinCLIVersion() string + NOAARequestRetryCount() int + NetworkPolicyV1Endpoint() string + OverallPollingTimeout() time.Duration + PluginHome() string + PluginRepositories() []configv3.PluginRepository + Plugins() []configv3.Plugin + PollingInterval() time.Duration + RefreshToken() string + RemovePlugin(string) + RequestRetryCount() int + RoutingEndpoint() string + SetAsyncTimeout(timeout int) + SetAccessToken(token string) + SetColorEnabled(enabled string) + SetLocale(locale string) + SetMinCLIVersion(version string) + SetOrganizationInformation(guid string, name string) + SetRefreshToken(token string) + SetSpaceInformation(guid string, name string, allowSSH bool) + V7SetSpaceInformation(guid string, name string) + SetTargetInformation(args configv3.TargetInformationArgs) + SetTokenInformation(accessToken string, refreshToken string, sshOAuthClient string) + SetTrace(trace string) + SetUAAClientCredentials(client string, clientSecret string) + SetUAAEndpoint(uaaEndpoint string) + SetUAAGrantType(uaaGrantType string) + SkipSSLValidation() bool + SSHOAuthClient() string + StagingTimeout() time.Duration + StartupTimeout() time.Duration + // TODO: Rename to APITarget() + Target() string + TargetedOrganization() configv3.Organization + TargetedOrganizationName() string + TargetedSpace() configv3.Space + TerminalWidth() int + UAADisableKeepAlives() bool + UAAEndpoint() string + UAAGrantType() string + UAAOAuthClient() string + UAAOAuthClientSecret() string + UnsetOrganizationAndSpaceInformation() + UnsetSpaceInformation() + UnsetUserInformation() + Verbose() (bool, []string) + WritePluginConfig() error + WriteConfig() error + IsCFOnK8s() bool + SetKubernetesAuthInfo(authInfo string) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/display_not_logged_in.go b/vendor/code.cloudfoundry.org/cli/command/display_not_logged_in.go new file mode 100644 index 0000000..085d90d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/display_not_logged_in.go @@ -0,0 +1,11 @@ +package command + +import "fmt" + +func DisplayNotLoggedInText(binaryName string, ui UI) { + ui.DisplayText("Not logged in. Use '{{.CFLoginCommand}}' or '{{.CFLoginCommandSSO}}' to log in.", + map[string]interface{}{ + "CFLoginCommand": fmt.Sprintf("%s login", binaryName), + "CFLoginCommandSSO": fmt.Sprintf("%s login --sso", binaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/experimental_warning.go b/vendor/code.cloudfoundry.org/cli/command/experimental_warning.go new file mode 100644 index 0000000..c3c630e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/experimental_warning.go @@ -0,0 +1,3 @@ +package command + +const ExperimentalWarning = "This command is in EXPERIMENTAL stage and may change without notice" diff --git a/vendor/code.cloudfoundry.org/cli/command/extended_commander.go b/vendor/code.cloudfoundry.org/cli/command/extended_commander.go new file mode 100644 index 0000000..d380403 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/extended_commander.go @@ -0,0 +1,11 @@ +package command + +import "github.com/jessevdk/go-flags" + +// ExtendedCommander extends the go-flags Command interface by forcing a Setup +// function on all commands. This setup function should setup all command +// dependencies. +type ExtendedCommander interface { + flags.Commander + Setup(Config, UI) error +} diff --git a/vendor/code.cloudfoundry.org/cli/command/godoc.go b/vendor/code.cloudfoundry.org/cli/command/godoc.go new file mode 100644 index 0000000..af10252 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/godoc.go @@ -0,0 +1,3 @@ +// Package command should not be imported by external consumers. It was not +// designed for external use. +package command diff --git a/vendor/code.cloudfoundry.org/cli/command/minimum_version_check.go b/vendor/code.cloudfoundry.org/cli/command/minimum_version_check.go new file mode 100644 index 0000000..9fa7aeb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/minimum_version_check.go @@ -0,0 +1,53 @@ +package command + +import ( + "code.cloudfoundry.org/cli/command/translatableerror" + log "github.com/sirupsen/logrus" +) + +func MinimumCCAPIVersionCheck(current string, minimum string, customCommand ...string) error { + log.WithFields(log.Fields{"current": current, "minimum": minimum}).Debug("minimum api version") + var command string + if len(customCommand) > 0 { + command = customCommand[0] + } + + isOutdated, err := CheckVersionOutdated(current, minimum) + if err != nil { + return err + } + + if isOutdated { + log.WithFields(log.Fields{"current": current, "minimum": minimum}).Error("minimum not met") + return translatableerror.MinimumCFAPIVersionNotMetError{ + Command: command, + CurrentVersion: current, + MinimumVersion: minimum, + } + } + + return nil +} + +func MinimumUAAAPIVersionCheck(current string, minimum string, customCommand ...string) error { + log.WithFields(log.Fields{"current": current, "minimum": minimum}).Debug("minimum api version") + var command string + if len(customCommand) > 0 { + command = customCommand[0] + } + + isOutdated, err := CheckVersionOutdated(current, minimum) + if err != nil { + return err + } + + if isOutdated { + log.WithFields(log.Fields{"current": current, "minimum": minimum}).Error("minimum not met") + return translatableerror.MinimumUAAAPIVersionNotMetError{ + Command: command, + MinimumVersion: minimum, + } + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/command/shared_actor.go b/vendor/code.cloudfoundry.org/cli/command/shared_actor.go new file mode 100644 index 0000000..79a2661 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/shared_actor.go @@ -0,0 +1,13 @@ +package command + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SharedActor + +type SharedActor interface { + IsLoggedIn() bool + IsSpaceTargeted() bool + IsOrgTargeted() bool + + CheckTarget(targetedOrganizationRequired bool, targetedSpaceRequired bool) error + RequireCurrentUser() (string, error) + RequireTargetedOrg() (string, error) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/account_locked_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/account_locked_error.go new file mode 100644 index 0000000..ee47a14 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/account_locked_error.go @@ -0,0 +1,13 @@ +package translatableerror + +type AccountLockedError struct { + Message string +} + +func (e AccountLockedError) Error() string { + return e.Message +} + +func (e AccountLockedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/add_plugin_repository_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/add_plugin_repository_error.go new file mode 100644 index 0000000..cf134c3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/add_plugin_repository_error.go @@ -0,0 +1,19 @@ +package translatableerror + +type AddPluginRepositoryError struct { + Name string + URL string + Message string +} + +func (AddPluginRepositoryError) Error() string { + return "Could not add repository '{{.RepositoryName}}' from {{.RepositoryURL}}: {{.Message}}" +} + +func (e AddPluginRepositoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RepositoryName": e.Name, + "RepositoryURL": e.URL, + "Message": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_not_found_error.go new file mode 100644 index 0000000..53c7d93 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type APINotFoundError struct { + URL string +} + +func (APINotFoundError) Error() string { + return "API endpoint not found at '{{.URL}}'" +} + +func (e APINotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "URL": e.URL, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_request_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_request_error.go new file mode 100644 index 0000000..71d1724 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/api_request_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type APIRequestError struct { + Err error +} + +func (APIRequestError) Error() string { + return "Request error: {{.Error}}\nTIP: If you are behind a firewall and require an HTTP proxy, verify the https_proxy environment variable is correctly set. Else, check your network connection." +} + +func (e APIRequestError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Error": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_name_or_manifest_required_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_name_or_manifest_required_error.go new file mode 100644 index 0000000..d9467e6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_name_or_manifest_required_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// AppNameOrManifestRequiredError represent an error caused by using two +// command line arguments that cannot be used together. +type AppNameOrManifestRequiredError struct { + Args []string +} + +func (AppNameOrManifestRequiredError) DisplayUsage() {} + +func (AppNameOrManifestRequiredError) Error() string { + return "Incorrect Usage: The push command requires an app name. The app name can be supplied as an argument or with a manifest.yml file." +} + +func (e AppNameOrManifestRequiredError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_not_found_in_manifest_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_not_found_in_manifest_error.go new file mode 100644 index 0000000..c3dc5c8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/app_not_found_in_manifest_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type AppNotFoundInManifestError struct { + Name string +} + +func (AppNotFoundInManifestError) Error() string { + return "Could not find app named '{{.AppName}}' in manifest" +} + +func (e AppNotFoundInManifestError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_found_error.go new file mode 100644 index 0000000..cb64263 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_found_error.go @@ -0,0 +1,20 @@ +package translatableerror + +type ApplicationNotFoundError struct { + GUID string + Name string +} + +func (e ApplicationNotFoundError) Error() string { + if e.GUID != "" { + return "Application with GUID {{.GUID}} not found." + } + return "App '{{.AppName}}' not found." +} + +func (e ApplicationNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "GUID": e.GUID, + "AppName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_started_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_started_error.go new file mode 100644 index 0000000..7296b91 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_not_started_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type ApplicationNotStartedError struct { + Name string +} + +func (ApplicationNotStartedError) Error() string { + return "Application '{{.AppName}}' is not in the STARTED state" +} + +func (e ApplicationNotStartedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_unable_to_start_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_unable_to_start_error.go new file mode 100644 index 0000000..0a9531a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/application_unable_to_start_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type ApplicationUnableToStartError struct { + AppName string + BinaryName string +} + +func (ApplicationUnableToStartError) Error() string { + return "Start unsuccessful\n\nTIP: use '{{.BinaryName}} logs {{.AppName}} --recent' for more information" +} + +func (e ApplicationUnableToStartError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_combination_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_combination_error.go new file mode 100644 index 0000000..1f7da28 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_combination_error.go @@ -0,0 +1,21 @@ +package translatableerror + +import "strings" + +// ArgumentCombinationError represent an error caused by using two command line +// arguments that cannot be used together. +type ArgumentCombinationError struct { + Args []string +} + +func (ArgumentCombinationError) DisplayUsage() {} + +func (ArgumentCombinationError) Error() string { + return "Incorrect Usage: The following arguments cannot be used together: {{.Args}}" +} + +func (e ArgumentCombinationError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Args": strings.Join(e.Args, ", "), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_manifest_mismatch_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_manifest_mismatch_error.go new file mode 100644 index 0000000..92afeb9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/argument_manifest_mismatch_error.go @@ -0,0 +1,26 @@ +package translatableerror + +// ArgumentManifestMismatchError represent an error caused by using a command line flag +// that conflicts with a given manifest property. +type ArgumentManifestMismatchError struct { + Arg string + ManifestProperty string + ManifestValue string +} + +func (ArgumentManifestMismatchError) DisplayUsage() {} + +func (e ArgumentManifestMismatchError) Error() string { + if e.ManifestValue == "" { + return "Incorrect Usage: The flag option {{.Arg}} cannot be used with the manifest property {{.Property}}" + } + return "Incorrect Usage: The flag option {{.Arg}} cannot be used with the manifest property {{.Property}} set to {{.ManifestValue}}" +} + +func (e ArgumentManifestMismatchError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Arg": e.Arg, + "Property": e.ManifestProperty, + "ManifestValue": e.ManifestValue, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/assign_droplet_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/assign_droplet_error.go new file mode 100644 index 0000000..50baf9b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/assign_droplet_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// AssignDropletError is returned when assigning the current droplet of an app +// fails +type AssignDropletError struct { + Message string +} + +func (AssignDropletError) Error() string { + return "Unable to assign droplet: {{.CloudControllerMessage}}" +} + +func (e AssignDropletError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "CloudControllerMessage": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/authorization_endpoint_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/authorization_endpoint_not_found_error.go new file mode 100644 index 0000000..e3b7b1a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/authorization_endpoint_not_found_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type AuthorizationEndpointNotFoundError struct { +} + +func (AuthorizationEndpointNotFoundError) Error() string { + return "No Authorization Endpoint Found" +} + +func (e AuthorizationEndpointNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_not_found_error.go new file mode 100644 index 0000000..1f6e666 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_not_found_error.go @@ -0,0 +1,20 @@ +package translatableerror + +type BuildpackNotFoundError struct { + BuildpackName string + StackName string +} + +func (e BuildpackNotFoundError) Error() string { + if len(e.StackName) == 0 { + return "Buildpack '{{.BuildpackName}}' not found" + } + return "Buildpack '{{.BuildpackName}}' with stack '{{.StackName}}' not found" +} + +func (e BuildpackNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "BuildpackName": e.BuildpackName, + "StackName": e.StackName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_stack_change_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_stack_change_error.go new file mode 100644 index 0000000..c566b39 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/buildpack_stack_change_error.go @@ -0,0 +1,19 @@ +package translatableerror + +import "fmt" + +type BuildpackStackChangeError struct { + BuildpackName string + BinaryName string +} + +func (e BuildpackStackChangeError) Error() string { + return fmt.Sprintf("Buildpack {{.BuildpackName}} already exists with a stack association\n\nTIP: Use '{{.BuildpackCommand}}' to view buildpack and stack associations") +} + +func (e BuildpackStackChangeError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "BuildpackName": e.BuildpackName, + "BuildpackCommand": fmt.Sprintf("%s buildpacks", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/cfnetworking_endpoint_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/cfnetworking_endpoint_not_found_error.go new file mode 100644 index 0000000..8f481ff --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/cfnetworking_endpoint_not_found_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type CFNetworkingEndpointNotFoundError struct { +} + +func (CFNetworkingEndpointNotFoundError) Error() string { + return "This command requires Network Policy API V1. Your targeted endpoint does not expose it." +} + +func (e CFNetworkingEndpointNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_args_with_multiple_apps_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_args_with_multiple_apps_error.go new file mode 100644 index 0000000..a047f6c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_args_with_multiple_apps_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type CommandLineArgsWithMultipleAppsError struct { +} + +func (CommandLineArgsWithMultipleAppsError) Error() string { + return "Incorrect Usage: Command line flags (except -f and --no-start) cannot be applied when pushing multiple apps from a manifest file." +} + +func (e CommandLineArgsWithMultipleAppsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_options_and_manifest_conflict_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_options_and_manifest_conflict_error.go new file mode 100644 index 0000000..3362fbd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/command_line_options_and_manifest_conflict_error.go @@ -0,0 +1,19 @@ +package translatableerror + +import "strings" + +type CommandLineOptionsAndManifestConflictError struct { + ManifestAttribute string + CommandLineOptions []string +} + +func (e CommandLineOptionsAndManifestConflictError) Error() string { + return "The following arguments cannot be used with an app manifest that declares routes using the '{{.ManifestAttribute}}' attribute: {{.CommandLineOptions}}" +} + +func (e CommandLineOptionsAndManifestConflictError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ManifestAttribute": e.ManifestAttribute, + "CommandLineOptions": strings.Join(e.CommandLineOptions, ", "), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/conflicting_buildpacks_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/conflicting_buildpacks_error.go new file mode 100644 index 0000000..72ff937 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/conflicting_buildpacks_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type ConflictingBuildpacksError struct { +} + +func (ConflictingBuildpacksError) Error() string { + return "Cannot specify 'null' or 'default' with other buildpacks" +} + +func (e ConflictingBuildpacksError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), nil) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/convert_to_translatable_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/convert_to_translatable_error.go new file mode 100644 index 0000000..4bcacac --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/convert_to_translatable_error.go @@ -0,0 +1,233 @@ +package translatableerror + +import ( + "encoding/json" + "fmt" + "strings" + + "code.cloudfoundry.org/cli/actor/actionerror" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/api/plugin/pluginerror" + "code.cloudfoundry.org/cli/api/uaa" + "code.cloudfoundry.org/cli/util/clissh/ssherror" + "code.cloudfoundry.org/cli/util/download" + "code.cloudfoundry.org/cli/util/manifest" + log "github.com/sirupsen/logrus" +) + +func ConvertToTranslatableError(err error) error { + log.WithField("err", fmt.Sprintf("%#v", err)).Debugf("convert to translatable error") + + switch e := err.(type) { + // Action Errors + case actionerror.AddPluginRepositoryError: + return AddPluginRepositoryError(e) + case actionerror.ApplicationNotFoundError: + return ApplicationNotFoundError(e) + case actionerror.ApplicationNotStartedError: + return ApplicationNotStartedError(e) + case actionerror.AppNotFoundInManifestError: + return AppNotFoundInManifestError(e) + case actionerror.AssignDropletError: + return AssignDropletError(e) + case actionerror.BuildpackNotFoundError: + return BuildpackNotFoundError(e) + case actionerror.BuildpackStackChangeError: + return BuildpackStackChangeError(e) + case actionerror.CommandLineOptionsWithMultipleAppsError: + return CommandLineArgsWithMultipleAppsError{} + case actionerror.DockerPasswordNotSetError: + return DockerPasswordNotSetError{} + case actionerror.DomainNotFoundError: + return DomainNotFoundError(e) + case manifest.EmptyBuildpacksError: + return EmptyBuildpacksError(e) + case actionerror.EmptyArchiveError: + return EmptyDirectoryError(e) + case actionerror.EmptyDirectoryError: + return EmptyDirectoryError(e) + case actionerror.EmptyBuildpackDirectoryError: + return EmptyBuildpackDirectoryError(e) + case actionerror.FileChangedError: + return FileChangedError(e) + case actionerror.GettingPluginRepositoryError: + return GettingPluginRepositoryError(e) + case actionerror.HostnameWithTCPDomainError: + return HostnameWithTCPDomainError(e) + case actionerror.HTTPHealthCheckInvalidError: + return HTTPHealthCheckInvalidError{} + case actionerror.InvalidBuildpacksError: + return InvalidBuildpacksError{} + case actionerror.InvalidHTTPRouteSettings: + return PortNotAllowedWithHTTPDomainError(e) + case actionerror.InvalidRouteError: + return InvalidRouteError(e) + case actionerror.InvalidTCPRouteSettings: + return HostAndPathNotAllowedWithTCPDomainError(e) + case actionerror.IsolationSegmentNotFoundError: + return IsolationSegmentNotFoundError(e) + case actionerror.MissingNameError: + return AppNameOrManifestRequiredError{} + case actionerror.MultipleBuildpacksFoundError: + return MultipleBuildpacksFoundError(e) + case actionerror.NoCompatibleBinaryError: + return NoCompatibleBinaryError{} + case actionerror.NoDomainsFoundError: + return NoDomainsFoundError{} + case actionerror.NoHostnameAndSharedDomainError: + return NoHostnameAndSharedDomainError{} + case actionerror.NoMatchingDomainError: + return NoMatchingDomainError(e) + case actionerror.NonexistentAppPathError: + return FileNotFoundError(e) + case actionerror.NoOrganizationTargetedError: + return NoOrganizationTargetedError(e) + case actionerror.NoSpaceTargetedError: + return NoSpaceTargetedError(e) + case actionerror.NotLoggedInError: + return NotLoggedInError(e) + case actionerror.OrganizationNotFoundError: + return OrganizationNotFoundError(e) + case actionerror.QuotaNotFoundForNameError: + return QuotaNotFoundForNameError(e) + case actionerror.PasswordGrantTypeLogoutRequiredError: + return PasswordGrantTypeLogoutRequiredError(e) + case actionerror.PluginCommandsConflictError: + return PluginCommandsConflictError(e) + case actionerror.PluginInvalidError: + return PluginInvalidError(e) + case actionerror.PluginNotFoundError: + return PluginNotFoundError(e) + case actionerror.ProcessInstanceNotFoundError: + return ProcessInstanceNotFoundError(e) + case actionerror.ProcessInstanceNotRunningError: + return ProcessInstanceNotRunningError(e) + case actionerror.ProcessNotFoundError: + return ProcessNotFoundError(e) + case actionerror.PropertyCombinationError: + return PropertyCombinationError(e) + case actionerror.RepositoryNameTakenError: + return RepositoryNameTakenError(e) + case actionerror.RepositoryNotRegisteredError: + return RepositoryNotRegisteredError(e) + case actionerror.RevisionNotFoundError: + return RevisionNotFoundError(e) + case actionerror.RevisionAmbiguousError: + return RevisionAmbiguousError(e) + case actionerror.RouteInDifferentSpaceError: + return RouteInDifferentSpaceError(e) + case actionerror.RoutePathWithTCPDomainError: + return RoutePathWithTCPDomainError(e) + case actionerror.RouterGroupNotFoundError: + return RouterGroupNotFoundError(e) + case actionerror.SecurityGroupNotFoundError: + return SecurityGroupNotFoundError(e) + case actionerror.ServiceInstanceNotFoundError: + return ServiceInstanceNotFoundError(e) + case actionerror.ServiceInstanceNotShareableError: + return ServiceInstanceNotShareableError{ + FeatureFlagEnabled: e.FeatureFlagEnabled, + ServiceBrokerSharingEnabled: e.ServiceBrokerSharingEnabled, + } + case actionerror.ServiceInstanceNotSharedToSpaceError: + return ServiceInstanceNotSharedToSpaceError{ServiceInstanceName: e.ServiceInstanceName} + case actionerror.ServicePlanNotFoundError: + return ServicePlanNotFoundError(e) + case actionerror.SharedServiceInstanceNotFoundError: + return SharedServiceInstanceNotFoundError(e) + case actionerror.SpaceNotFoundError: + return SpaceNotFoundError{Name: e.Name} + case actionerror.StackNotFoundError: + return StackNotFoundError(e) + case actionerror.StagingFailedError: + return StagingFailedError{Message: e.Reason} + case actionerror.StagingTimeoutError: + return StagingTimeoutError(e) + case actionerror.TaskWorkersUnavailableError: + return RunTaskError{Message: "Task workers are unavailable."} + case actionerror.TCPRouteOptionsNotProvidedError: + return TCPRouteOptionsNotProvidedError{} + case actionerror.TriggerLegacyPushError: + return TriggerLegacyPushError{DomainHostRelated: e.DomainHostRelated} + case actionerror.UploadFailedError: + return UploadFailedError{Err: ConvertToTranslatableError(e.Err)} + case actionerror.CommandLineOptionsAndManifestConflictError: + return CommandLineOptionsAndManifestConflictError{ + ManifestAttribute: e.ManifestAttribute, + CommandLineOptions: e.CommandLineOptions, + } + + // Wrapped Errors + case TipDecoratorError: + e.BaseError = ConvertToTranslatableError(e.BaseError) + return e + + // Generic CC Errors + case ccerror.APINotFoundError: + return APINotFoundError(e) + case ccerror.RequestError: + return APIRequestError(e) + case ccerror.SSLValidationHostnameError: + return SSLCertError(e) + case ccerror.UnverifiedServerError: + return InvalidSSLCertError{URL: e.URL, SuggestedCommand: "api"} + + // Specific CC Errors + case ccerror.V2JobFailedError: + return JobFailedError(e) + case ccerror.V3JobFailedError: + return JobFailedError{JobGUID: e.JobGUID, Message: e.Detail} + case ccerror.JobTimeoutError: + return JobTimeoutError{JobGUID: e.JobGUID} + case ccerror.JobFailedNoErrorError: + return JobFailedNoErrorError{JobGUID: e.JobGUID} + case ccerror.MultiError: + return MultiError{Messages: e.Details()} + case ccerror.UnprocessableEntityError: + if strings.Contains(e.Message, "Task must have a droplet. Specify droplet or assign current droplet to app.") { + return RunTaskError{Message: "App is not staged."} + } + + // JSON Errors + case *json.SyntaxError: + return JSONSyntaxError{Err: e} + + // Manifest Errors + case manifest.ManifestCreationError: + return FileCreationError(e) + case manifest.InheritanceFieldError: + return TriggerLegacyPushError{InheritanceRelated: true} + case manifest.GlobalFieldsError: + return TriggerLegacyPushError{GlobalRelated: e.Fields} + case manifest.InterpolationError: + return InterpolationError(e) + + // Plugin Execution Errors + case pluginerror.RawHTTPStatusError: + return DownloadPluginHTTPError{Message: e.Status} + case pluginerror.SSLValidationHostnameError: + return DownloadPluginHTTPError(e) + case pluginerror.UnverifiedServerError: + return DownloadPluginHTTPError{Message: e.Error()} + + // SSH Errors + case ssherror.UnableToAuthenticateError: + return SSHUnableToAuthenticateError{} + + // UAA Errors + case uaa.UnauthorizedError: + return UnauthorizedError(e) + case uaa.AccountLockedError: + return AccountLockedError(e) + case uaa.InsufficientScopeError: + return UnauthorizedToPerformActionError{} + case uaa.InvalidAuthTokenError: + return InvalidRefreshTokenError{} + + // Other Errors + case download.RawHTTPStatusError: + return HTTPStatusError{Status: e.Status} + } + + return err +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/curl_exit_22_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/curl_exit_22_error.go new file mode 100644 index 0000000..68c6da3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/curl_exit_22_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type CurlExit22Error struct { + StatusCode int +} + +func (e CurlExit22Error) Error() string { + return "The requested URL returned error: {{.StatusCode}}" +} + +func (e CurlExit22Error) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), + map[string]interface{}{"StatusCode": e.StatusCode}, + ) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/docker_password_not_set_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/docker_password_not_set_error.go new file mode 100644 index 0000000..dd92741 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/docker_password_not_set_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type DockerPasswordNotSetError struct{} + +func (DockerPasswordNotSetError) Error() string { + return "Environment variable CF_DOCKER_PASSWORD not set." +} + +func (e DockerPasswordNotSetError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/domain_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/domain_not_found_error.go new file mode 100644 index 0000000..03d16ef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/domain_not_found_error.go @@ -0,0 +1,24 @@ +package translatableerror + +type DomainNotFoundError struct { + Name string + GUID string +} + +func (e DomainNotFoundError) Error() string { + switch { + case e.Name != "": + return "Domain '{{.DomainName}}' not found." + case e.GUID != "": + return "Domain with GUID '{{.DomainGUID}}' not found." + default: + return "Domain not found." + } +} + +func (e DomainNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "DomainName": e.Name, + "DomainGUID": e.GUID, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/download_plugin_http_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/download_plugin_http_error.go new file mode 100644 index 0000000..9aaaa46 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/download_plugin_http_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type DownloadPluginHTTPError struct { + Message string +} + +func (DownloadPluginHTTPError) Error() string { + return "Download attempt failed; server returned {{.ErrorMessage}}\nUnable to install; plugin is not available from the given URL." +} + +func (e DownloadPluginHTTPError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ErrorMessage": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/droplet_file_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/droplet_file_error.go new file mode 100644 index 0000000..8470612 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/droplet_file_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type DropletFileError struct { + Err error +} + +func (DropletFileError) Error() string { + return "Error creating droplet file: {{.Error}}" +} + +func (e DropletFileError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Error": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpack_directory_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpack_directory_error.go new file mode 100644 index 0000000..8daac8e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpack_directory_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type EmptyBuildpackDirectoryError struct { + Path string +} + +func (EmptyBuildpackDirectoryError) Error() string { + return "The specified path '{{.Path}}' cannot be an empty directory." +} + +func (e EmptyBuildpackDirectoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Path": e.Path, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpacks_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpacks_error.go new file mode 100644 index 0000000..f9c9959 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_buildpacks_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type EmptyBuildpacksError struct{} + +func (EmptyBuildpacksError) Error() string { + return "Buildpacks property cannot be an empty string." +} + +func (e EmptyBuildpacksError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_config_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_config_error.go new file mode 100644 index 0000000..87d1dce --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_config_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type EmptyConfigError struct { + FilePath string +} + +func (EmptyConfigError) Error() string { + return "Warning: Error read/writing config: unexpected end of JSON input for {{.FilePath}}" +} + +func (e EmptyConfigError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "FilePath": e.FilePath, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_directory_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_directory_error.go new file mode 100644 index 0000000..170a42a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/empty_directory_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type EmptyDirectoryError struct { + Path string +} + +func (e EmptyDirectoryError) Error() string { + return "No app files found in '{{.Path}}'" +} + +func (e EmptyDirectoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Path": e.Path, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/feature_flag_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/feature_flag_not_found_error.go new file mode 100644 index 0000000..95fc25d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/feature_flag_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type FeatureFlagNotFoundError struct { + Name string +} + +func (e FeatureFlagNotFoundError) Error() string { + return "Feature Flag {{.FlagName}} not found" +} + +func (e FeatureFlagNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "FlagName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/fetching_plugin_info_from_repositories_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/fetching_plugin_info_from_repositories_error.go new file mode 100644 index 0000000..dce2de9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/fetching_plugin_info_from_repositories_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type FetchingPluginInfoFromRepositoriesError struct { + Message string + RepositoryName string +} + +func (FetchingPluginInfoFromRepositoriesError) Error() string { + return "Plugin list download failed; repository {{.RepositoryName}} returned {{.ErrorMessage}}." +} + +func (e FetchingPluginInfoFromRepositoriesError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RepositoryName": e.RepositoryName, + "ErrorMessage": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_changed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_changed_error.go new file mode 100644 index 0000000..a00e6f5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_changed_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type FileChangedError struct { + Filename string +} + +func (e FileChangedError) Error() string { + return "Aborting push: File {{.Filename}} has been modified since the start of push. Validate the correct state of the file and try again." +} + +func (e FileChangedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Filename": e.Filename, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_not_found_error.go new file mode 100644 index 0000000..33bdbcc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/file_not_found_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// FileNotFoundError is returned when a local plugin binary is not found during +// installation. +type FileNotFoundError struct { + Path string +} + +func (FileNotFoundError) Error() string { + return "File not found locally, make sure the file exists at given path {{.FilePath}}" +} + +func (e FileNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "FilePath": e.Path, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/flag_no_longer_supported_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/flag_no_longer_supported_error.go new file mode 100644 index 0000000..7c90c62 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/flag_no_longer_supported_error.go @@ -0,0 +1,16 @@ +package translatableerror + +// FlagNoLongerSupportedError can be used to indicate a flag is no longer supported +type FlagNoLongerSupportedError struct { + Flag string +} + +func (e FlagNoLongerSupportedError) Error() string { + return "Flag '{{.Flag}}' is no longer supported." +} + +func (e FlagNoLongerSupportedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Flag": e.Flag, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/getting_plugin_repository_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/getting_plugin_repository_error.go new file mode 100644 index 0000000..c945bf9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/getting_plugin_repository_error.go @@ -0,0 +1,16 @@ +package translatableerror + +// GettingPluginRepositoryError is returned when there's an error +// accessing the plugin repository +type GettingPluginRepositoryError struct { + Name string + Message string +} + +func (GettingPluginRepositoryError) Error() string { + return "Could not get plugin repository '{{.RepositoryName}}'\n{{.ErrorMessage}}" +} + +func (e GettingPluginRepositoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{"RepositoryName": e.Name, "ErrorMessage": e.Message}) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/godoc.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/godoc.go new file mode 100644 index 0000000..219ba3f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/godoc.go @@ -0,0 +1,6 @@ +// Package translatableerror contains all the command layer translatable +// errors. +// +// In order to prevent future import cycles, this package should **not** have +// any non-builtin dependencies!!! +package translatableerror diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/health_check_type_unsupported_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/health_check_type_unsupported_error.go new file mode 100644 index 0000000..08a1a3e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/health_check_type_unsupported_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import "strings" + +type HealthCheckTypeUnsupportedError struct { + SupportedTypes []string +} + +func (HealthCheckTypeUnsupportedError) Error() string { + return "Your target CF API version only supports health check type values {{.SupportedTypes}} and {{.LastSupportedType}}." +} + +func (e HealthCheckTypeUnsupportedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "SupportedTypes": strings.Join(e.SupportedTypes[:len(e.SupportedTypes)-1], ", "), + "LastSupportedType": e.SupportedTypes[len(e.SupportedTypes)-1], + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/host_and_path_not_allowed_with_tcp_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/host_and_path_not_allowed_with_tcp_domain_error.go new file mode 100644 index 0000000..23cebb4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/host_and_path_not_allowed_with_tcp_domain_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type HostAndPathNotAllowedWithTCPDomainError struct { + Domain string +} + +func (HostAndPathNotAllowedWithTCPDomainError) Error() string { + return "Host and path not allowed in route with TCP domain {{.Domain}}" +} + +func (e HostAndPathNotAllowedWithTCPDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Domain": e.Domain, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/hostname_with_tcp_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/hostname_with_tcp_domain_error.go new file mode 100644 index 0000000..63377d9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/hostname_with_tcp_domain_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type HostnameWithTCPDomainError struct{} + +func (HostnameWithTCPDomainError) Error() string { + return "The route is invalid: a hostname cannot be used with a TCP domain." +} + +func (e HostnameWithTCPDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_health_check_invalid_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_health_check_invalid_error.go new file mode 100644 index 0000000..714e077 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_health_check_invalid_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type HTTPHealthCheckInvalidError struct { +} + +func (HTTPHealthCheckInvalidError) Error() string { + return "Health check type must be 'http' to set a health check HTTP endpoint." +} + +func (e HTTPHealthCheckInvalidError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_status_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_status_error.go new file mode 100644 index 0000000..94f6fab --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/http_status_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type HTTPStatusError struct { + Status string +} + +func (e HTTPStatusError) Error() string { + return "Download attempt failed; server returned {{.Status}}\nUnable to install; buildpack is not available from the given URL." +} + +func (e HTTPStatusError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Status": e.Status, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/incorrect_usage_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/incorrect_usage_error.go new file mode 100644 index 0000000..5e694d4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/incorrect_usage_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type IncorrectUsageError struct { + Message string +} + +func (IncorrectUsageError) DisplayUsage() {} + +func (IncorrectUsageError) Error() string { + return "Incorrect Usage: {{.Message}}" +} + +func (e IncorrectUsageError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/interpolation_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/interpolation_error.go new file mode 100644 index 0000000..d4a6201 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/interpolation_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import ( + "fmt" + "strings" +) + +type InterpolationError struct { + Err error +} + +func (e InterpolationError) Error() string { + return fmt.Sprint(strings.Replace(e.Err.Error(), "\n", ", ", -1)) +} + +func (e InterpolationError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_buildpacks_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_buildpacks_error.go new file mode 100644 index 0000000..0b787f8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_buildpacks_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type InvalidBuildpacksError struct{} + +func (InvalidBuildpacksError) Error() string { + return "Multiple buildpacks flags cannot have null/default option." +} + +func (e InvalidBuildpacksError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_checksum_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_checksum_error.go new file mode 100644 index 0000000..7542d69 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_checksum_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type InvalidChecksumError struct{} + +func (InvalidChecksumError) Error() string { + return "Downloaded plugin binary's checksum does not match repo metadata.\nPlease try again or contact the plugin author." +} + +func (e InvalidChecksumError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_refresh_token_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_refresh_token_error.go new file mode 100644 index 0000000..edef497 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_refresh_token_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type InvalidRefreshTokenError struct { +} + +func (InvalidRefreshTokenError) Error() string { + return "The token expired, was revoked, or the token ID is incorrect. Please log back in to re-authenticate." +} + +func (e InvalidRefreshTokenError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_route_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_route_error.go new file mode 100644 index 0000000..72a3308 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_route_error.go @@ -0,0 +1,13 @@ +package translatableerror + +type InvalidRouteError struct { + Route string +} + +func (InvalidRouteError) Error() string { + return "The route '{{.Route}}' is not a properly formed URL" +} + +func (e InvalidRouteError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{"Route": e.Route}) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_ssl_cert_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_ssl_cert_error.go new file mode 100644 index 0000000..898af79 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_ssl_cert_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type InvalidSSLCertError struct { + URL string + SuggestedCommand string +} + +func (InvalidSSLCertError) Error() string { + return "Invalid SSL Cert for {{.API}}\nTIP: Use 'cf {{.SuggestedCommand}} --skip-ssl-validation' to continue with an insecure API endpoint" +} + +func (e InvalidSSLCertError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "API": e.URL, + "SuggestedCommand": e.SuggestedCommand, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_yaml_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_yaml_error.go new file mode 100644 index 0000000..78a1bfc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/invalid_yaml_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type InvalidYAMLError struct { + Err error +} + +func (e InvalidYAMLError) Error() string { + return "The option --vars-file expects a valid YAML file. {{.ErrorMessage}}" +} + +func (e InvalidYAMLError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ErrorMessage": e.Err.Error(), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/isolation_segment_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/isolation_segment_not_found_error.go new file mode 100644 index 0000000..4f35803 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/isolation_segment_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type IsolationSegmentNotFoundError struct { + Name string +} + +func (IsolationSegmentNotFoundError) Error() string { + return "Isolation segment '{{.Name}}' not found." +} + +func (e IsolationSegmentNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_error.go new file mode 100644 index 0000000..92874b4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type JobFailedError struct { + JobGUID string + Message string +} + +func (JobFailedError) Error() string { + return "Job ({{.JobGUID}}) failed: {{.Message}}" +} + +func (e JobFailedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + "JobGUID": e.JobGUID, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_no_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_no_error.go new file mode 100644 index 0000000..919aae8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_failed_no_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// RevisionAmbiguousError is returned when multiple revisions with the same +// version are returned +type JobFailedNoErrorError struct { + JobGUID string +} + +func (e JobFailedNoErrorError) Error() string { + return "Job {{.JobGUID}} failed with no error. This is unexpected, contact your operator for details." +} + +func (e JobFailedNoErrorError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "JobGUID": e.JobGUID, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_timeout_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_timeout_error.go new file mode 100644 index 0000000..c1c5550 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/job_timeout_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import "time" + +type JobTimeoutError struct { + JobGUID string + Timeout time.Duration +} + +func (JobTimeoutError) Error() string { + return "Job ({{.JobGUID}}) polling timeout has been reached. The operation may still be running on the CF instance. Your CF operator may have more information." +} + +func (e JobTimeoutError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "JobGUID": e.JobGUID, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/json_syntax_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/json_syntax_error.go new file mode 100644 index 0000000..7a724e8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/json_syntax_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type JSONSyntaxError struct { + Err error +} + +func (e JSONSyntaxError) Error() string { + return "Invalid JSON content from server: {{.Err}}" +} + +func (e JSONSyntaxError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Err": e.Err.Error(), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/lifecycle_minimum_api_version_not_met_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/lifecycle_minimum_api_version_not_met_error.go new file mode 100644 index 0000000..e085e70 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/lifecycle_minimum_api_version_not_met_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type LifecycleMinimumAPIVersionNotMetError struct { + CurrentVersion string + MinimumVersion string +} + +func (LifecycleMinimumAPIVersionNotMetError) Error() string { + return "Lifecycle value 'staging' requires CF API version {{.MinimumVersion}} or higher. Your target is {{.CurrentVersion}}." +} + +func (e LifecycleMinimumAPIVersionNotMetError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "CurrentVersion": e.CurrentVersion, + "MinimumVersion": e.MinimumVersion, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_creation_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_creation_error.go new file mode 100644 index 0000000..0fc0c9b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_creation_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type FileCreationError struct { + Err error +} + +func (FileCreationError) Error() string { + return "Error creating file: {{.Error}}" +} + +func (e FileCreationError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Error": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_file_not_found_in_directory_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_file_not_found_in_directory_error.go new file mode 100644 index 0000000..a5b0f25 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manifest_file_not_found_in_directory_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type ManifestFileNotFoundInDirectoryError struct { + PathToManifest string +} + +func (ManifestFileNotFoundInDirectoryError) Error() string { + return "Could not find 'manifest.yml' file in {{.PathToManifest}}" +} + +func (e ManifestFileNotFoundInDirectoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PathToManifest": e.PathToManifest, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/manual_client_credentials_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manual_client_credentials_error.go new file mode 100644 index 0000000..5278eff --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/manual_client_credentials_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type ManualClientCredentialsError struct{} + +func (e ManualClientCredentialsError) Error() string { + return "Error: Support for manually writing your client credentials to config.json has been removed. For similar functionality please use `cf auth --client-credentials`." +} + +func (e ManualClientCredentialsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cf_api_version_not_met_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cf_api_version_not_met_error.go new file mode 100644 index 0000000..ba4bc9a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cf_api_version_not_met_error.go @@ -0,0 +1,33 @@ +package translatableerror + +type MinimumCFAPIVersionNotMetError struct { + Command string + CurrentVersion string + MinimumVersion string +} + +func (e MinimumCFAPIVersionNotMetError) Error() string { + switch { + case e.Command != "" && e.CurrentVersion != "": + return "{{.Command}} requires CF API version {{.MinimumVersion}} or higher. Your target is {{.CurrentVersion}}." + case e.Command != "" && e.CurrentVersion == "": + return "{{.Command}} requires CF API version {{.MinimumVersion}} or higher." + case e.Command == "" && e.CurrentVersion != "": + return "This command requires CF API version {{.MinimumVersion}} or higher. Your target is {{.CurrentVersion}}." + default: + return "This command requires CF API version {{.MinimumVersion}} or higher." + } +} + +func (e MinimumCFAPIVersionNotMetError) Translate(translate func(string, ...interface{}) string) string { + vars := map[string]interface{}{ + "MinimumVersion": e.MinimumVersion, + } + if e.CurrentVersion != "" { + vars["CurrentVersion"] = e.CurrentVersion + } + if e.Command != "" { + vars["Command"] = e.Command + } + return translate(e.Error(), vars) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cli_version_not_met_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cli_version_not_met_error.go new file mode 100644 index 0000000..db4f164 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_cli_version_not_met_error.go @@ -0,0 +1,21 @@ +package translatableerror + +type MinimumCLIVersionNotMetError struct { + APIVersion string + MinCLIVersion string + BinaryVersion string +} + +func (e MinimumCLIVersionNotMetError) Error() string { + return "Cloud Foundry API version {{.APIVersion}} requires CLI version {{.MinCLIVersion}}. You are currently on version {{.BinaryVersion}}. To upgrade your CLI, please visit: https://github.com/cloudfoundry/cli#downloads" +} + +func (e MinimumCLIVersionNotMetError) Translate(translate func(string, ...interface{}) string) string { + vars := map[string]interface{}{ + "APIVersion": e.APIVersion, + "MinCLIVersion": e.MinCLIVersion, + "BinaryVersion": e.BinaryVersion, + } + + return translate(e.Error(), vars) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_uaa_api_version_not_met_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_uaa_api_version_not_met_error.go new file mode 100644 index 0000000..4b44d15 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/minimum_uaa_api_version_not_met_error.go @@ -0,0 +1,24 @@ +package translatableerror + +type MinimumUAAAPIVersionNotMetError struct { + Command string + MinimumVersion string +} + +func (e MinimumUAAAPIVersionNotMetError) Error() string { + if e.Command != "" { + return "{{.Command}} requires UAA API version {{.MinimumVersion}} or higher. Update your Cloud Foundry instance." + } + + return "This command requires UAA API version {{.MinimumVersion}} or higher. Update your Cloud Foundry instance." +} + +func (e MinimumUAAAPIVersionNotMetError) Translate(translate func(string, ...interface{}) string) string { + vars := map[string]interface{}{ + "MinimumVersion": e.MinimumVersion, + } + if e.Command != "" { + vars["Command"] = e.Command + } + return translate(e.Error(), vars) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/missing_credentials_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/missing_credentials_error.go new file mode 100644 index 0000000..b955fd7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/missing_credentials_error.go @@ -0,0 +1,23 @@ +package translatableerror + +type MissingCredentialsError struct { + MissingUsername bool + MissingPassword bool +} + +func (MissingCredentialsError) DisplayUsage() {} + +func (e MissingCredentialsError) Error() string { + switch { + case e.MissingUsername && !e.MissingPassword: + return "Username not provided." + case !e.MissingUsername && e.MissingPassword: + return "Password not provided." + default: + return "Username and password not provided." + } +} + +func (e MissingCredentialsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/multi_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/multi_error.go new file mode 100644 index 0000000..2bb7e41 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/multi_error.go @@ -0,0 +1,24 @@ +package translatableerror + +import ( + "fmt" + "strings" +) + +type MultiError struct { + Messages []string +} + +func (MultiError) Error() string { + return "Multiple errors occurred:\n{{.Errors}}" +} + +func (e MultiError) Translate(translate func(string, ...interface{}) string) string { + var formattedErrs []string + for _, err := range e.Messages { + formattedErrs = append(formattedErrs, fmt.Sprintf("- %s", err)) + } + return translate(e.Error(), map[string]interface{}{ + "Errors": strings.Join(formattedErrs, "\n"), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/multiple_buildpacks_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/multiple_buildpacks_found_error.go new file mode 100644 index 0000000..724b945 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/multiple_buildpacks_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type MultipleBuildpacksFoundError struct { + BuildpackName string +} + +func (MultipleBuildpacksFoundError) Error() string { + return "Multiple buildpacks named {{.BuildpackName}} found. Specify a stack name by using a '-s' flag." +} + +func (e MultipleBuildpacksFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "BuildpackName": e.BuildpackName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_destination_org_without_space_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_destination_org_without_space_error.go new file mode 100644 index 0000000..ed2ce5c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_destination_org_without_space_error.go @@ -0,0 +1,13 @@ +package translatableerror + +type NetworkPolicyDestinationOrgWithoutSpaceError struct{} + +func (NetworkPolicyDestinationOrgWithoutSpaceError) DisplayUsage() {} + +func (NetworkPolicyDestinationOrgWithoutSpaceError) Error() string { + return "Incorrect Usage: A space must be provided when an org is provided, but the '-s' flag was not specified." +} + +func (e NetworkPolicyDestinationOrgWithoutSpaceError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_protocol_or_port_not_provided_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_protocol_or_port_not_provided_error.go new file mode 100644 index 0000000..c04d644 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/network_policy_protocol_or_port_not_provided_error.go @@ -0,0 +1,13 @@ +package translatableerror + +type NetworkPolicyProtocolOrPortNotProvidedError struct{} + +func (NetworkPolicyProtocolOrPortNotProvidedError) DisplayUsage() {} + +func (NetworkPolicyProtocolOrPortNotProvidedError) Error() string { + return "Incorrect Usage: --protocol and --port flags must be specified together" +} + +func (e NetworkPolicyProtocolOrPortNotProvidedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_api_set_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_api_set_error.go new file mode 100644 index 0000000..f9d674d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_api_set_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import "fmt" + +type NoAPISetError struct { + BinaryName string +} + +func (NoAPISetError) Error() string { + return "No API endpoint set. Use '{{.LoginTip}}' or '{{.APITip}}' to target an endpoint." +} + +func (e NoAPISetError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "LoginTip": fmt.Sprintf("%s login", e.BinaryName), + "APITip": fmt.Sprintf("%s api", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_compatible_binary_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_compatible_binary_error.go new file mode 100644 index 0000000..0e87f4a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_compatible_binary_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type NoCompatibleBinaryError struct { +} + +func (e NoCompatibleBinaryError) Error() string { + return "Plugin requested has no binary available for your platform." +} + +func (e NoCompatibleBinaryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_current_droplet_for_app_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_current_droplet_for_app_error.go new file mode 100644 index 0000000..bb4a589 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_current_droplet_for_app_error.go @@ -0,0 +1,21 @@ +package translatableerror + +// NoDropletForAppError will default to current droplet if no droplet GUID is provided +type NoDropletForAppError struct { + AppName string + DropletGUID string +} + +func (e NoDropletForAppError) Error() string { + if e.DropletGUID != "" { + return "Droplet '{{.DropletGUID}}' not found for app '{{.AppName}}'" + } + return "App '{{.AppName}}' does not have a current droplet." +} + +func (e NoDropletForAppError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "DropletGUID": e.DropletGUID, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_domains_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_domains_found_error.go new file mode 100644 index 0000000..a80aa2e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_domains_found_error.go @@ -0,0 +1,14 @@ +package translatableerror + +import "fmt" + +type NoDomainsFoundError struct { +} + +func (NoDomainsFoundError) Error() string { + return fmt.Sprintf("No private or shared domains found in this organization") +} + +func (e NoDomainsFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_eligible_packages_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_eligible_packages_error.go new file mode 100644 index 0000000..b034f05 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_eligible_packages_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type NoEligiblePackagesError struct { + AppName string + BinaryName string +} + +func (NoEligiblePackagesError) Error() string { + return "App '{{.AppName}}' has no eligible packages.\n\nTIP: Use '{{.BinaryName}} packages {{.AppName}}' to list packages in your app. Use '{{.BinaryName}} create-package' to create one." +} + +func (e NoEligiblePackagesError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_hostname_shared_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_hostname_shared_domain_error.go new file mode 100644 index 0000000..6dfe89c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_hostname_shared_domain_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type NoHostnameAndSharedDomainError struct{} + +func (NoHostnameAndSharedDomainError) Error() string { + return "The route is invalid: a hostname is required for shared domains." +} + +func (e NoHostnameAndSharedDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_matching_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_matching_domain_error.go new file mode 100644 index 0000000..e7450a3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_matching_domain_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type NoMatchingDomainError struct { + Route string +} + +func (e NoMatchingDomainError) Error() string { + return "The route {{.RouteName}} did not match any existing domains." +} + +func (e NoMatchingDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RouteName": e.Route, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_organization_targeted_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_organization_targeted_error.go new file mode 100644 index 0000000..078ff38 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_organization_targeted_error.go @@ -0,0 +1,17 @@ +package translatableerror + +import "fmt" + +type NoOrganizationTargetedError struct { + BinaryName string +} + +func (NoOrganizationTargetedError) Error() string { + return "No org targeted, use '{{.Command}}' to target an org." +} + +func (e NoOrganizationTargetedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Command": fmt.Sprintf("%s target -o ORG", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_plugin_repositories_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_plugin_repositories_error.go new file mode 100644 index 0000000..1f654d7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_plugin_repositories_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type NoPluginRepositoriesError struct{} + +func (NoPluginRepositoriesError) Error() string { + return "No plugin repositories registered to search for plugin updates." +} + +func (e NoPluginRepositoriesError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_space_targeted_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_space_targeted_error.go new file mode 100644 index 0000000..7e9757e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/no_space_targeted_error.go @@ -0,0 +1,17 @@ +package translatableerror + +import "fmt" + +type NoSpaceTargetedError struct { + BinaryName string +} + +func (NoSpaceTargetedError) Error() string { + return "No space targeted, use '{{.Command}}' to target a space." +} + +func (e NoSpaceTargetedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Command": fmt.Sprintf("%s target -s SPACE", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_logged_in_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_logged_in_error.go new file mode 100644 index 0000000..e9140ef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_logged_in_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import "fmt" + +type NotLoggedInError struct { + BinaryName string +} + +func (NotLoggedInError) Error() string { + return "Not logged in. Use '{{.CFLoginCommand}}' or '{{.CFLoginCommandSSO}}' to log in." +} + +func (e NotLoggedInError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "CFLoginCommand": fmt.Sprintf("%s login", e.BinaryName), + "CFLoginCommandSSO": fmt.Sprintf("%s login --sso", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_shared_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_shared_domain_error.go new file mode 100644 index 0000000..04a86f1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_shared_domain_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type NotSharedDomainError struct { + DomainName string +} + +func (NotSharedDomainError) Error() string { + return "Domain '{{.DomainName}}' is a private domain, not a shared domain." +} + +func (e NotSharedDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "DomainName": e.DomainName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_supported_on_k8s_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_supported_on_k8s_error.go new file mode 100644 index 0000000..630edef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/not_supported_on_k8s_error.go @@ -0,0 +1,19 @@ +package translatableerror + +// NotSupportedOnKubernetesArgumentError represents an error caused by using an +// argument that is not supported on kubernetes +type NotSupportedOnKubernetesArgumentError struct { + Arg string +} + +func (NotSupportedOnKubernetesArgumentError) DisplayUsage() {} + +func (NotSupportedOnKubernetesArgumentError) Error() string { + return "The argument {{.Arg}} is not supported on Kubernetes" +} + +func (e NotSupportedOnKubernetesArgumentError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Arg": e.Arg, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_not_found_error.go new file mode 100644 index 0000000..1069ed9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_not_found_error.go @@ -0,0 +1,16 @@ +package translatableerror + +type OrganizationNotFoundError struct { + GUID string + Name string +} + +func (OrganizationNotFoundError) Error() string { + return "Organization '{{.Name}}' not found." +} + +func (e OrganizationNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_quota_not_found_for_name_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_quota_not_found_for_name_error.go new file mode 100644 index 0000000..ed36378 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_quota_not_found_for_name_error.go @@ -0,0 +1,16 @@ +package translatableerror + +// QuotaNotFoundForNameError is returned when a quota with the given name can't be found. +type QuotaNotFoundForNameError struct { + Name string +} + +func (e QuotaNotFoundForNameError) Error() string { + return "Quota {{.QuotaName}} not found" +} + +func (e QuotaNotFoundForNameError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "QuotaName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_with_space_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_with_space_not_found_error.go new file mode 100644 index 0000000..3b23226 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/organization_with_space_not_found_error.go @@ -0,0 +1,18 @@ +package translatableerror + +type OrganizationWithSpaceNotFoundError struct { + GUID string + Name string + SpaceName string +} + +func (OrganizationWithSpaceNotFoundError) Error() string { + return "Organization '{{.Name}}' containing space '{{.SpaceName}}' not found." +} + +func (e OrganizationWithSpaceNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + "SpaceName": e.SpaceName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/package_not_found_in_app_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/package_not_found_in_app_error.go new file mode 100644 index 0000000..9cb4647 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/package_not_found_in_app_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type PackageNotFoundInAppError struct { + AppName string + BinaryName string +} + +func (PackageNotFoundInAppError) Error() string { + return "Package not found in app '{{.AppName}}'.\n\nTIP: Use '{{.BinaryName}} packages {{.AppName}}' to list packages in your app. Use '{{.BinaryName}} create-package' to create one." +} + +func (e PackageNotFoundInAppError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/parse_argument_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/parse_argument_error.go new file mode 100644 index 0000000..c2a04ef --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/parse_argument_error.go @@ -0,0 +1,19 @@ +package translatableerror + +type ParseArgumentError struct { + ArgumentName string + ExpectedType string +} + +func (ParseArgumentError) DisplayUsage() {} + +func (ParseArgumentError) Error() string { + return "Incorrect usage: Value for {{.ArgumentName}} must be {{.ExpectedType}}" +} + +func (e ParseArgumentError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ArgumentName": e.ArgumentName, + "ExpectedType": e.ExpectedType, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_grant_type_logout_required_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_grant_type_logout_required_error.go new file mode 100644 index 0000000..b0d3b46 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_grant_type_logout_required_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type PasswordGrantTypeLogoutRequiredError struct{} + +func (PasswordGrantTypeLogoutRequiredError) Error() string { + return "Service account currently logged in. Use 'cf logout' to log out service account and try again." +} + +func (e PasswordGrantTypeLogoutRequiredError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_verification_failed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_verification_failed_error.go new file mode 100644 index 0000000..e10490e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/password_verification_failed_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type PasswordVerificationFailedError struct{} + +func (PasswordVerificationFailedError) Error() string { + return "Password verification does not match." +} + +func (e PasswordVerificationFailedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_already_installed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_already_installed_error.go new file mode 100644 index 0000000..6de1ca6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_already_installed_error.go @@ -0,0 +1,21 @@ +package translatableerror + +// PluginAlreadyInstalledError is returned when the plugin has the same name as +// an installed plugin. +type PluginAlreadyInstalledError struct { + BinaryName string + Name string + Version string +} + +func (PluginAlreadyInstalledError) Error() string { + return "Plugin {{.Name}} {{.Version}} could not be installed. A plugin with that name is already installed.\nTIP: Use '{{.BinaryName}} install-plugin -f' to force a reinstall." +} + +func (e PluginAlreadyInstalledError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "BinaryName": e.BinaryName, + "Name": e.Name, + "Version": e.Version, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binarly_uninstall_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binarly_uninstall_error.go new file mode 100644 index 0000000..ba4131c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binarly_uninstall_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// PluginBinaryUninstallError is returned when running the plugin's uninstall +// hook fails. +type PluginBinaryUninstallError struct { + Err error +} + +func (e PluginBinaryUninstallError) Error() string { + return "The plugin's uninstall method returned an unexpected error.\nThe plugin uninstall will proceed. Contact the plugin author if you need help.\n{{.Err}}" +} + +func (e PluginBinaryUninstallError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Err": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binary_remove_failed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binary_remove_failed_error.go new file mode 100644 index 0000000..5cd47cf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_binary_remove_failed_error.go @@ -0,0 +1,17 @@ +package translatableerror + +// PluginBinaryRemoveFailedError is returned when the removal of a plugin +// binary fails. +type PluginBinaryRemoveFailedError struct { + Err error +} + +func (e PluginBinaryRemoveFailedError) Error() string { + return "The plugin has been uninstalled but removing the plugin binary failed.\nRemove it manually or subsequent installations of the plugin may fail\n{{.Err}}" +} + +func (e PluginBinaryRemoveFailedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Err": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_commands_conflict_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_commands_conflict_error.go new file mode 100644 index 0000000..23bfd77 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_commands_conflict_error.go @@ -0,0 +1,35 @@ +package translatableerror + +import "strings" + +// PluginCommandsConflictError is returned when a plugin command name conflicts +// with a native or existing plugin command name. +type PluginCommandsConflictError struct { + PluginName string + PluginVersion string + CommandNames []string + CommandAliases []string +} + +func (e PluginCommandsConflictError) Error() string { + switch { + case len(e.CommandNames) > 0 && len(e.CommandAliases) > 0: + return "Plugin {{.PluginName}} v{{.PluginVersion}} could not be installed as it contains commands with names and aliases that are already used: {{.CommandNamesAndAliases}}." + case len(e.CommandNames) > 0: + return "Plugin {{.PluginName}} v{{.PluginVersion}} could not be installed as it contains commands with names that are already used: {{.CommandNames}}." + case len(e.CommandAliases) > 0: + return "Plugin {{.PluginName}} v{{.PluginVersion}} could not be installed as it contains commands with aliases that are already used: {{.CommandAliases}}." + default: + return "Plugin {{.PluginName}} v{{.PluginVersion}} could not be installed as it contains commands with names or aliases that are already used." + } +} + +func (e PluginCommandsConflictError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PluginName": e.PluginName, + "PluginVersion": e.PluginVersion, + "CommandNames": strings.Join(e.CommandNames, ", "), + "CommandAliases": strings.Join(e.CommandAliases, ", "), + "CommandNamesAndAliases": strings.Join(append(e.CommandNames, e.CommandAliases...), ", "), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_invalid_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_invalid_error.go new file mode 100644 index 0000000..50da0d2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_invalid_error.go @@ -0,0 +1,23 @@ +package translatableerror + +import "fmt" + +// PluginInvalidError is returned with a plugin is invalid because it is +// missing a name or has 0 commands. +type PluginInvalidError struct { + Err error +} + +func (e PluginInvalidError) Error() string { + baseErrString := "File is not a valid cf CLI plugin binary." + + if e.Err != nil { + return fmt.Sprintf("%s\n%s", e.Err, baseErrString) + } + + return baseErrString +} + +func (e PluginInvalidError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_error.go new file mode 100644 index 0000000..0b47558 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type PluginNotFoundError struct { + PluginName string +} + +func (e PluginNotFoundError) Error() string { + return "Plugin {{.PluginName}} does not exist." +} + +func (e PluginNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PluginName": e.PluginName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_in_repository_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_in_repository_error.go new file mode 100644 index 0000000..77b6cfd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_in_repository_error.go @@ -0,0 +1,19 @@ +package translatableerror + +type PluginNotFoundInRepositoryError struct { + BinaryName string + PluginName string + RepositoryName string +} + +func (e PluginNotFoundInRepositoryError) Error() string { + return "Plugin {{.PluginName}} not found in repository {{.RepositoryName}}.\nUse '{{.BinaryName}} repo-plugins -r {{.RepositoryName}}' to list plugins available in the repo." +} + +func (e PluginNotFoundInRepositoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PluginName": e.PluginName, + "RepositoryName": e.RepositoryName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_on_disk_or_in_any_repository_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_on_disk_or_in_any_repository_error.go new file mode 100644 index 0000000..f26a277 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/plugin_not_found_on_disk_or_in_any_repository_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type PluginNotFoundOnDiskOrInAnyRepositoryError struct { + PluginName string + BinaryName string +} + +func (e PluginNotFoundOnDiskOrInAnyRepositoryError) Error() string { + return "Plugin {{.PluginName}} not found on disk or in any registered repo.\nUse '{{.BinaryName}} repo-plugins' to list plugins available in the repos." +} + +func (e PluginNotFoundOnDiskOrInAnyRepositoryError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PluginName": e.PluginName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/port_not_allowed_with_http_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/port_not_allowed_with_http_domain_error.go new file mode 100644 index 0000000..4e767ca --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/port_not_allowed_with_http_domain_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type PortNotAllowedWithHTTPDomainError struct { + Domain string +} + +func (PortNotAllowedWithHTTPDomainError) Error() string { + return "Port not allowed in HTTP domain {{.Domain}}" +} + +func (e PortNotAllowedWithHTTPDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Domain": e.Domain, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_found_error.go new file mode 100644 index 0000000..0f96da4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_found_error.go @@ -0,0 +1,18 @@ +package translatableerror + +// ProcessInstanceNotFoundError is returned when a process type or process instance can't be found +type ProcessInstanceNotFoundError struct { + ProcessType string + InstanceIndex uint +} + +func (ProcessInstanceNotFoundError) Error() string { + return "Instance {{.InstanceIndex}} of process {{.ProcessType}} not found" +} + +func (e ProcessInstanceNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ProcessType": e.ProcessType, + "InstanceIndex": e.InstanceIndex, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_running_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_running_error.go new file mode 100644 index 0000000..8ad788a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_instance_not_running_error.go @@ -0,0 +1,19 @@ +package translatableerror + +// ProcessInstanceNotRunningError is returned when trying to perform an action +// on an instance that is not running +type ProcessInstanceNotRunningError struct { + ProcessType string + InstanceIndex uint +} + +func (ProcessInstanceNotRunningError) Error() string { + return "Instance {{.InstanceIndex}} of process {{.ProcessType}} not running" +} + +func (e ProcessInstanceNotRunningError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ProcessType": e.ProcessType, + "InstanceIndex": e.InstanceIndex, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_not_found_error.go new file mode 100644 index 0000000..2094569 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/process_not_found_error.go @@ -0,0 +1,16 @@ +package translatableerror + +// ProcessNotFoundError is returned when a process type can't be found +type ProcessNotFoundError struct { + ProcessType string +} + +func (ProcessNotFoundError) Error() string { + return "Process {{.ProcessType}} not found" +} + +func (e ProcessNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ProcessType": e.ProcessType, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/property_combination_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/property_combination_error.go new file mode 100644 index 0000000..f77952d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/property_combination_error.go @@ -0,0 +1,21 @@ +package translatableerror + +import ( + "strings" +) + +type PropertyCombinationError struct { + AppName string + Properties []string +} + +func (e PropertyCombinationError) Error() string { + return "Application {{.AppName}} cannot use the combination of properties: {{.Properties}}" +} + +func (e PropertyCombinationError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "Properties": strings.Join(e.Properties, ", "), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_name_taken_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_name_taken_error.go new file mode 100644 index 0000000..069605c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_name_taken_error.go @@ -0,0 +1,15 @@ +package translatableerror + +// RepositoryNameTakenError is returned when adding a plugin repository +// fails due to a repository already existing with the same name +type RepositoryNameTakenError struct { + Name string +} + +func (RepositoryNameTakenError) Error() string { + return "Plugin repo named '{{.RepositoryName}}' already exists, please use another name." +} + +func (e RepositoryNameTakenError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{"RepositoryName": e.Name}) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_not_registered_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_not_registered_error.go new file mode 100644 index 0000000..a5ff3e0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/repository_not_registered_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type RepositoryNotRegisteredError struct { + Name string +} + +func (RepositoryNotRegisteredError) Error() string { + return "Plugin repository {{.Name}} not found.\nUse 'cf list-plugin-repos' to list registered repos." +} + +func (e RepositoryNotRegisteredError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/request_creation_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/request_creation_error.go new file mode 100644 index 0000000..7c870ee --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/request_creation_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type RequestCreationError struct { + Err error +} + +func (RequestCreationError) Error() string { + return "Error creating request: {{.Error}}" +} + +func (e RequestCreationError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Error": e.Err, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_argument_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_argument_error.go new file mode 100644 index 0000000..a532689 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_argument_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type RequiredArgumentError struct { + ArgumentName string +} + +func (RequiredArgumentError) DisplayUsage() {} + +func (RequiredArgumentError) Error() string { + return "Incorrect Usage: the required argument `{{.ArgumentName}}` was not provided" +} + +func (e RequiredArgumentError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ArgumentName": e.ArgumentName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_flags_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_flags_error.go new file mode 100644 index 0000000..74feb1b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/required_flags_error.go @@ -0,0 +1,21 @@ +package translatableerror + +// RequiredFlagsError represent an error caused by using a command line +// argument that requires another flags to be used. +type RequiredFlagsError struct { + Arg1 string + Arg2 string +} + +func (RequiredFlagsError) DisplayUsage() {} + +func (RequiredFlagsError) Error() string { + return "Incorrect Usage: '{{.Arg1}}' and '{{.Arg2}}' must be used together." +} + +func (e RequiredFlagsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Arg1": e.Arg1, + "Arg2": e.Arg2, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_ambiguous.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_ambiguous.go new file mode 100644 index 0000000..b0a2430 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_ambiguous.go @@ -0,0 +1,17 @@ +package translatableerror + +// RevisionAmbiguousError is returned when multiple revisions with the same +// version are returned +type RevisionAmbiguousError struct { + Version int +} + +func (e RevisionAmbiguousError) Error() string { + return "More than one revision '{{.RevisionVersion}}' found" +} + +func (e RevisionAmbiguousError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RevisionVersion": e.Version, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_not_found.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_not_found.go new file mode 100644 index 0000000..ad35d35 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/revision_not_found.go @@ -0,0 +1,17 @@ +package translatableerror + +// RevisionNotFoundError is returned when a requested revision is not +// found. +type RevisionNotFoundError struct { + Version int +} + +func (e RevisionNotFoundError) Error() string { + return "Revision '{{.RevisionVersion}}' not found" +} + +func (e RevisionNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RevisionVersion": e.Version, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_in_different_space_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_in_different_space_error.go new file mode 100644 index 0000000..5e0e8cf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_in_different_space_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type RouteInDifferentSpaceError struct { + Route string +} + +func (e RouteInDifferentSpaceError) Error() string { + return "The app cannot be mapped to route {{.URL}} because the route exists in a different space." +} + +func (e RouteInDifferentSpaceError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "URL": e.Route, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_path_with_tcp_domain_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_path_with_tcp_domain_error.go new file mode 100644 index 0000000..8e1b39d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/route_path_with_tcp_domain_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type RoutePathWithTCPDomainError struct{} + +func (RoutePathWithTCPDomainError) Error() string { + return "The route is invalid: a route path cannot be used with a TCP domain." +} + +func (e RoutePathWithTCPDomainError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/router_group_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/router_group_not_found_error.go new file mode 100644 index 0000000..f81f1f4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/router_group_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type RouterGroupNotFoundError struct { + Name string +} + +func (e RouterGroupNotFoundError) Error() string { + return "Router group '{{.RouterGroupName}}' not found." +} + +func (e RouterGroupNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "RouterGroupName": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/run_task_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/run_task_error.go new file mode 100644 index 0000000..c357528 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/run_task_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type RunTaskError struct { + Message string +} + +func (RunTaskError) Error() string { + return "Error running task: {{.CloudControllerMessage}}" +} + +func (e RunTaskError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "CloudControllerMessage": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/security_group_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/security_group_not_found_error.go new file mode 100644 index 0000000..72648df --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/security_group_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type SecurityGroupNotFoundError struct { + Name string +} + +func (SecurityGroupNotFoundError) Error() string { + return "Security group '{{.Name}}' not found." +} + +func (e SecurityGroupNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_found_error.go new file mode 100644 index 0000000..5904e77 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_found_error.go @@ -0,0 +1,20 @@ +package translatableerror + +type ServiceInstanceNotFoundError struct { + GUID string + Name string +} + +func (e ServiceInstanceNotFoundError) Error() string { + if e.Name == "" { + return "Service instance (GUID: {{.GUID}}) not found" + } + return "Service instance '{{.ServiceInstance}}' not found" +} + +func (e ServiceInstanceNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "GUID": e.GUID, + "ServiceInstance": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shareable_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shareable_error.go new file mode 100644 index 0000000..1b972fb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shareable_error.go @@ -0,0 +1,25 @@ +package translatableerror + +// ServiceInstanceNotShareableError is returned when either the +// service_instance_sharing feature flag is disabled or the service broker has +// disabled sharing +type ServiceInstanceNotShareableError struct { + FeatureFlagEnabled bool + ServiceBrokerSharingEnabled bool +} + +func (e ServiceInstanceNotShareableError) Error() string { + switch { + case !e.FeatureFlagEnabled && !e.ServiceBrokerSharingEnabled: + return `The "service_instance_sharing" feature flag is disabled for this Cloud Foundry platform. Also, service instance sharing is disabled for this service.` + case !e.FeatureFlagEnabled && e.ServiceBrokerSharingEnabled: + return `The "service_instance_sharing" feature flag is disabled for this Cloud Foundry platform.` + case e.FeatureFlagEnabled && !e.ServiceBrokerSharingEnabled: + return "Service instance sharing is disabled for this service." + } + return "Unexpected ServiceInstanceNotShareableError: service instance is shareable." +} + +func (e ServiceInstanceNotShareableError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shared_to_space_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shared_to_space_error.go new file mode 100644 index 0000000..f307da7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_instance_not_shared_to_space_error.go @@ -0,0 +1,18 @@ +package translatableerror + +import "fmt" + +// ServiceInstanceNotSharedToSpaceError is returned when attempting to unshare a service instance from a space to which it is not shared. +type ServiceInstanceNotSharedToSpaceError struct { + ServiceInstanceName string +} + +func (e ServiceInstanceNotSharedToSpaceError) Error() string { + return fmt.Sprintf("Failed to unshare service instance '{{.ServiceInstance}}'. Ensure the space and specified org exist and that the service instance has been shared to this space.") +} + +func (e ServiceInstanceNotSharedToSpaceError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ServiceInstance": e.ServiceInstanceName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_plan_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_plan_not_found_error.go new file mode 100644 index 0000000..aefe130 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/service_plan_not_found_error.go @@ -0,0 +1,26 @@ +package translatableerror + +type ServicePlanNotFoundError struct { + PlanName string + OfferingName string + ServiceBrokerName string +} + +func (e ServicePlanNotFoundError) Error() string { + if e.OfferingName == "" { + return "Service plan '{{.PlanName}}' not found." + } + if e.OfferingName != "" && e.PlanName != "" && e.ServiceBrokerName != "" { + return "The plan '{{.PlanName}}' could not be found for service offering '{{.OfferingName}}' and broker '{{.ServiceBrokerName}}'." + } + + return "The plan '{{.PlanName}}' could not be found for service offering '{{.OfferingName}}'." +} + +func (e ServicePlanNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "PlanName": e.PlanName, + "OfferingName": e.OfferingName, + "ServiceBrokerName": e.ServiceBrokerName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/shared_service_instance_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/shared_service_instance_not_found_error.go new file mode 100644 index 0000000..b270f6c --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/shared_service_instance_not_found_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type SharedServiceInstanceNotFoundError struct { +} + +func (SharedServiceInstanceNotFoundError) Error() string { + return "Specified instance not found or not a managed service instance. Sharing is not supported for user provided services." +} + +func (e SharedServiceInstanceNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_not_found_error.go new file mode 100644 index 0000000..3827913 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_not_found_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type SpaceNotFoundError struct { + Name string +} + +func (SpaceNotFoundError) Error() string { + return "Space '{{.Name}}' not found." +} + +func (e SpaceNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_quota_not_found_for_name_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_quota_not_found_for_name_error.go new file mode 100644 index 0000000..a0192c1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/space_quota_not_found_for_name_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type SpaceQuotaNotFoundForNameError struct { + Name string +} + +func (SpaceQuotaNotFoundForNameError) Error() string { + return "Space quota with name '{{.Name}}' not found." +} + +func (e SpaceQuotaNotFoundForNameError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssh_unable_to_authenticate_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssh_unable_to_authenticate_error.go new file mode 100644 index 0000000..a98a67a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssh_unable_to_authenticate_error.go @@ -0,0 +1,11 @@ +package translatableerror + +type SSHUnableToAuthenticateError struct{} + +func (SSHUnableToAuthenticateError) Error() string { + return "Error opening SSH connection: You are not authorized to perform the requested action." +} + +func (e SSHUnableToAuthenticateError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssl_cert_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssl_cert_error.go new file mode 100644 index 0000000..6f2d65a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/ssl_cert_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type SSLCertError struct { + Message string +} + +func (SSLCertError) Error() string { + return "SSL Certificate Error {{.Message}}\nTIP: Use 'cf api --skip-ssl-validation' to continue with an insecure API endpoint" +} + +func (e SSLCertError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/stack_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/stack_not_found_error.go new file mode 100644 index 0000000..e0b7100 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/stack_not_found_error.go @@ -0,0 +1,21 @@ +package translatableerror + +type StackNotFoundError struct { + GUID string + Name string +} + +func (e StackNotFoundError) Error() string { + if e.Name == "" { + return "Stack with GUID '{{.GUID}}' not found" + } + + return "Stack '{{.Name}}' not found" +} + +func (e StackNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "GUID": e.GUID, + "Name": e.Name, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_error.go new file mode 100644 index 0000000..b0b2ab5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type StagingFailedError struct { + Message string +} + +func (StagingFailedError) Error() string { + return "Error staging application: {{.Message}}" +} + +func (e StagingFailedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_no_app_detected_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_no_app_detected_error.go new file mode 100644 index 0000000..32b63c7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_failed_no_app_detected_error.go @@ -0,0 +1,19 @@ +package translatableerror + +import "fmt" + +type StagingFailedNoAppDetectedError struct { + Message string + BinaryName string +} + +func (StagingFailedNoAppDetectedError) Error() string { + return "Error staging application: {{.Message}}\n\nTIP: Use '{{.BuildpackCommand}}' to see a list of supported buildpacks." +} + +func (e StagingFailedNoAppDetectedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + "BuildpackCommand": fmt.Sprintf("%s buildpacks", e.BinaryName), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_timeout_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_timeout_error.go new file mode 100644 index 0000000..7fe7422 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/staging_timeout_error.go @@ -0,0 +1,19 @@ +package translatableerror + +import "time" + +type StagingTimeoutError struct { + AppName string + Timeout time.Duration +} + +func (StagingTimeoutError) Error() string { + return `Error staging application {{.AppName}}: timed out after {{.Timeout}} minute(s)` +} + +func (e StagingTimeoutError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "Timeout": e.Timeout.Minutes(), + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/startup_timeout_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/startup_timeout_error.go new file mode 100644 index 0000000..bec1275 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/startup_timeout_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type StartupTimeoutError struct { + AppName string + BinaryName string +} + +func (StartupTimeoutError) Error() string { + return "Start app timeout\n\nTIP: Application must be listening on the right port. Instead of hard coding the port, use the $PORT environment variable.\n\nUse '{{.BinaryName}} logs {{.AppName}} --recent' for more information" +} + +func (e StartupTimeoutError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "AppName": e.AppName, + "BinaryName": e.BinaryName, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/tcp_route_options_not_provided_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/tcp_route_options_not_provided_error.go new file mode 100644 index 0000000..828a5f3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/tcp_route_options_not_provided_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type TCPRouteOptionsNotProvidedError struct { +} + +func (e TCPRouteOptionsNotProvidedError) Error() string { + return "The route is invalid: For TCP routes you must specify a port or request a random one." +} + +func (e TCPRouteOptionsNotProvidedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), nil) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/three_required_arguments_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/three_required_arguments_error.go new file mode 100644 index 0000000..8702fcc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/three_required_arguments_error.go @@ -0,0 +1,21 @@ +package translatableerror + +type ThreeRequiredArgumentsError struct { + ArgumentName1 string + ArgumentName2 string + ArgumentName3 string +} + +func (ThreeRequiredArgumentsError) DisplayUsage() {} + +func (ThreeRequiredArgumentsError) Error() string { + return "Incorrect Usage: the required arguments `{{.ArgumentName1}}`, `{{.ArgumentName2}}`, and `{{.ArgumentName3}}` were not provided" +} + +func (e ThreeRequiredArgumentsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ArgumentName1": e.ArgumentName1, + "ArgumentName2": e.ArgumentName2, + "ArgumentName3": e.ArgumentName3, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/tip_decorator_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/tip_decorator_error.go new file mode 100644 index 0000000..16fb742 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/tip_decorator_error.go @@ -0,0 +1,25 @@ +package translatableerror + +type TipDecoratorError struct { + Tip string + TipKeys map[string]interface{} + BaseError error +} + +func (e TipDecoratorError) Error() string { + return "{{.BaseError}}\n\nTIP: {{.Tip}}" +} + +func (e TipDecoratorError) Translate(translate func(string, ...interface{}) string) string { + baseError := e.BaseError.Error() + if translatableBaseError, ok := e.BaseError.(TranslatableError); ok { + baseError = translatableBaseError.Translate(translate) + } + + tip := translate(e.Tip, e.TipKeys) + + return translate(e.Error(), map[string]interface{}{ + "BaseError": baseError, + "Tip": tip, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/too_many_arguments_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/too_many_arguments_error.go new file mode 100644 index 0000000..d7c1d3e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/too_many_arguments_error.go @@ -0,0 +1,17 @@ +package translatableerror + +type TooManyArgumentsError struct { + ExtraArgument string +} + +func (TooManyArgumentsError) Error() string { + return `Incorrect Usage: unexpected argument "{{.ExtraArgument}}"` +} + +func (e TooManyArgumentsError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "ExtraArgument": e.ExtraArgument, + }) +} + +func (TooManyArgumentsError) DisplayUsage() {} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/translatable_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/translatable_error.go new file mode 100644 index 0000000..a9791c3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/translatable_error.go @@ -0,0 +1,11 @@ +package translatableerror + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . TranslatableError + +// TranslatableError it wraps the error interface adding a way to set the +// translation function on the error +type TranslatableError interface { + // Returns the untranslated error string + Error() string + Translate(func(string, ...interface{}) string) string +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/trigger_legacy_push_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/trigger_legacy_push_error.go new file mode 100644 index 0000000..0a15392 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/trigger_legacy_push_error.go @@ -0,0 +1,40 @@ +package translatableerror + +import ( + "fmt" + "strings" +) + +type TriggerLegacyPushError struct { + DomainHostRelated []string + GlobalRelated []string + InheritanceRelated bool + RandomRouteRelated bool +} + +func (TriggerLegacyPushError) LegacyMain() {} + +func (e TriggerLegacyPushError) Error() string { + switch { + case len(e.DomainHostRelated) > 0: + return fmt.Sprintf(`Deprecation warning: Route component attributes 'domain', 'domains', 'host', 'hosts' and 'no-hostname' are deprecated. Found: %s. +Please see https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#deprecated for the currently supported syntax and other app manifest deprecations. This feature will be removed in the future. +`, strings.Join(e.DomainHostRelated, ", ")) + case len(e.GlobalRelated) > 0: + return fmt.Sprintf(`Deprecation warning: Specifying app manifest attributes at the top level is deprecated. Found: %s. +Please see https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#deprecated for alternatives and other app manifest deprecations. This feature will be removed in the future. +`, strings.Join(e.GlobalRelated, ", ")) + + case e.InheritanceRelated: + return `Deprecation warning: App manifest inheritance is deprecated. +Please see https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#deprecated for alternatives and other app manifest deprecations. This feature will be removed in the future. +` + + default: + return "" + } +} + +func (e TriggerLegacyPushError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/uaa_endpoint_not_found_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/uaa_endpoint_not_found_error.go new file mode 100644 index 0000000..9773207 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/uaa_endpoint_not_found_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type UAAEndpointNotFoundError struct { +} + +func (UAAEndpointNotFoundError) Error() string { + return "No UAA Endpoint Found" +} + +func (e UAAEndpointNotFoundError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_error.go new file mode 100644 index 0000000..885d110 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_error.go @@ -0,0 +1,26 @@ +package translatableerror + +const ( + BadCredentialMessage = "Bad credentials" + InvalidOriginMessage = "The origin provided in the login hint is invalid." + UnmatchedOriginMessage = "The origin provided in the login_hint does not match an active Identity Provider, that supports password grant." +) + +type UnauthorizedError struct { + Message string +} + +func (e UnauthorizedError) Error() string { + switch e.Message { + case BadCredentialMessage: + return "Credentials were rejected, please try again." + case InvalidOriginMessage, UnmatchedOriginMessage: + return "The origin provided is invalid." + default: + return e.Message + } +} + +func (e UnauthorizedError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_to_perform_action_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_to_perform_action_error.go new file mode 100644 index 0000000..fb4393e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unauthorized_to_perform_action_error.go @@ -0,0 +1,12 @@ +package translatableerror + +type UnauthorizedToPerformActionError struct { +} + +func (UnauthorizedToPerformActionError) Error() string { + return "You are not authorized to perform the requested action." +} + +func (e UnauthorizedToPerformActionError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), nil) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/unrefactored_command_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unrefactored_command_error.go new file mode 100644 index 0000000..95928be --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unrefactored_command_error.go @@ -0,0 +1,9 @@ +package translatableerror + +type UnrefactoredCommandError struct{} + +func (UnrefactoredCommandError) LegacyMain() {} + +func (e UnrefactoredCommandError) Error() string { + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/unsupported_url_scheme_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unsupported_url_scheme_error.go new file mode 100644 index 0000000..4c1a3d1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/unsupported_url_scheme_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type UnsupportedURLSchemeError struct { + UnsupportedURL string +} + +func (e UnsupportedURLSchemeError) Error() string { + return "This command does not support the URL scheme in {{.UnsupportedURL}}." +} + +func (e UnsupportedURLSchemeError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "UnsupportedURL": e.UnsupportedURL, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/upload_failed_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/upload_failed_error.go new file mode 100644 index 0000000..e0829fe --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/upload_failed_error.go @@ -0,0 +1,22 @@ +package translatableerror + +type UploadFailedError struct { + Err error +} + +func (UploadFailedError) Error() string { + return "Uploading files have failed after a number of retries due to: {{.Error}}" +} + +func (e UploadFailedError) Translate(translate func(string, ...interface{}) string) string { + message := translate("UNKNOWN REASON") + if err, ok := e.Err.(TranslatableError); ok { + message = err.Translate(translate) + } else if e.Err != nil { + message = e.Err.Error() + } + + return translate(e.Error(), map[string]interface{}{ + "Error": message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_api_does_not_exist_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_api_does_not_exist_error.go new file mode 100644 index 0000000..b81aae9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_api_does_not_exist_error.go @@ -0,0 +1,15 @@ +package translatableerror + +type V3APIDoesNotExistError struct { + Message string +} + +func (V3APIDoesNotExistError) Error() string { + return "{{.Message}}\nThis command requires CF API version 3.0.0 or higher." +} + +func (e V3APIDoesNotExistError) Translate(translate func(string, ...interface{}) string) string { + return translate(e.Error(), map[string]interface{}{ + "Message": e.Message, + }) +} diff --git a/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_v2_switch_error.go b/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_v2_switch_error.go new file mode 100644 index 0000000..b935497 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/translatableerror/v3_v2_switch_error.go @@ -0,0 +1,8 @@ +package translatableerror + +type V3V2SwitchError struct { +} + +func (e V3V2SwitchError) Error() string { + return "" +} diff --git a/vendor/code.cloudfoundry.org/cli/command/ui.go b/vendor/code.cloudfoundry.org/cli/command/ui.go new file mode 100644 index 0000000..aedbe16 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/command/ui.go @@ -0,0 +1,49 @@ +package command + +import ( + "io" + "time" + + "code.cloudfoundry.org/cli/util/ui" +) + +// UI is the interface to STDOUT, STDERR, and STDIN. +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UI +type UI interface { + DeferText(template string, data ...map[string]interface{}) + DisplayBoolPrompt(defaultResponse bool, template string, templateValues ...map[string]interface{}) (bool, error) + DisplayChangesForPush(changeSet []ui.Change) error + DisplayDeprecationWarning() + DisplayDiffAddition(line string, depth int, addHyphen bool) + DisplayDiffRemoval(line string, depth int, addHyphen bool) + DisplayDiffUnchanged(line string, depth int, addHyphen bool) + DisplayError(err error) + DisplayFileDeprecationWarning() + DisplayHeader(text string) + DisplayInstancesTableForApp(table [][]string) + DisplayJSON(name string, jsonData interface{}) error + DisplayKeyValueTable(prefix string, table [][]string, padding int) + DisplayKeyValueTableForApp(table [][]string) + DisplayLogMessage(message ui.LogMessage, displayHeader bool) + DisplayNewline() + DisplayNonWrappingTable(prefix string, table [][]string, padding int) + DisplayOK() + DisplayOptionalTextPrompt(defaultValue string, template string, templateValues ...map[string]interface{}) (string, error) + DisplayPasswordPrompt(template string, templateValues ...map[string]interface{}) (string, error) + DisplayTableWithHeader(prefix string, table [][]string, padding int) + DisplayText(template string, data ...map[string]interface{}) + DisplayTextMenu(choices []string, promptTemplate string, templateValues ...map[string]interface{}) (string, error) + DisplayTextPrompt(template string, templateValues ...map[string]interface{}) (string, error) + DisplayTextWithBold(text string, keys ...map[string]interface{}) + DisplayTextWithFlavor(text string, keys ...map[string]interface{}) + DisplayWarning(formattedString string, keys ...map[string]interface{}) + DisplayWarnings(warnings []string) + GetErr() io.Writer + GetIn() io.Reader + GetOut() io.Writer + RequestLoggerFileWriter(filePaths []string) *ui.RequestLoggerFileWriter + RequestLoggerTerminalDisplay() *ui.RequestLoggerTerminalDisplay + TranslateText(template string, data ...map[string]interface{}) string + UserFriendlyDate(input time.Time) string + Writer() io.Writer +} diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/README.md b/vendor/code.cloudfoundry.org/cli/i18n/resources/README.md new file mode 100644 index 0000000..e2cfa23 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/README.md @@ -0,0 +1,8 @@ +# DO NOT CHANGE ANYTHING IN THIS DIRECTORY +This directory will get populated by the pipeline during the `build-binaries` job. Do NOT modify otherwise. + +## How this file was generated +``` +$ cd code.cloudfoundry.org/cli/i18n +$ go-bindata -nometadata -pkg resources -ignore ".go" -o resources/i18n_resources.go resources/*.all.json +``` diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/de-de.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/de-de.all.json new file mode 100644 index 0000000..d1fd5dd --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/de-de.all.json @@ -0,0 +1,77 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nApp gestartet\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "Temporärer Authentifizierungscode ( Hier erhalten {{.AuthenticationEndpoint}}/passcode )", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/en-us.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/en-us.all.json new file mode 100644 index 0000000..5789ff6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/en-us.all.json @@ -0,0 +1,72 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nApp started\n" + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org" + }, + { + "id": "Name", + "translation": "Name" + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist." + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS" + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'" + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted." + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes" + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n" + }, + { + "id": "api endpoint:", + "translation": "api endpoint:" + }, + { + "id": "api version:", + "translation": "api version:" + }, + { + "id": "user:", + "translation": "user:" + }, + { + "id": "org:", + "translation": "org:" + }, + { + "id": "space:api version:", + "translation": "space:api version:" + }, + { + "id": "Email", + "translation": "Email", + "modified": false + }, + { + "id": "Password", + "translation": "Password", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )" + } +] diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/es-es.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/es-es.all.json new file mode 100644 index 0000000..48f4b5b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/es-es.all.json @@ -0,0 +1,87 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nApp iniciada\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + }, + { + "id": "Email", + "translation": "Correo electrónico", + "modified": false + }, + { + "id": "Password", + "translation": "Contraseña", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "Código de autenticación temporal (obtenlo en {{.AuthenticationEndpoint}}/passcode )", + "modified": false + } +] diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/fr-fr.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/fr-fr.all.json new file mode 100644 index 0000000..33cac24 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/fr-fr.all.json @@ -0,0 +1,93 @@ +[ + { + "id": "Push a new app or sync changes to an existing app", + "translation": "Envoyer par commande push une nouvelle application ou synchroniser les modifications dans une application existante" + }, + { + "id": "USAGE:", + "translation": "SYNTAXE :" + }, + { + "id": "Path to app directory or to a zip file of the contents of the app directory", + "translation": "Chemin d'accès au répertoire de l'application ou à un fichier zip du contenu du répertoire de l'application" + }, + { + "id": "Number of instances", + "translation": "Nombre d'instances" + }, + { + "id": "\nApp started\n", + "translation": "\nApplication démarrée\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nL'application {{.AppName}} a été démarrée avec la commande `some-command-name`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nASTUCE : utilisez '{{.Command}}' pour cibler une nouvelle organisation", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " Affichez les quotas pouvant être alloués avec 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' et '{{.VersionLong}}' sont également acceptés.\n", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Supprimer aussi les routes mappées\n", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "L'application {{.AppName}} n'existe pas.\n", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "INDICATEURS DE FONCTION", + "modified": false + }, + { + "id": "Name", + "translation": "Nom", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "Code d’authentication temporaire ( obtenez nouveau à {{.AuthenticationEndpoint}}/passcode )", + "modified": false + } +] diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/i18n_resources.go b/vendor/code.cloudfoundry.org/cli/i18n/resources/i18n_resources.go new file mode 100644 index 0000000..3ba2b2f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/i18n_resources.go @@ -0,0 +1,444 @@ +// Code generated by go-bindata. +// sources: +// resources/de-de.all.json +// resources/en-us.all.json +// resources/es-es.all.json +// resources/fr-fr.all.json +// resources/it-it.all.json +// resources/ja-jp.all.json +// resources/ko-kr.all.json +// resources/pt-br.all.json +// resources/zh-hans.all.json +// resources/zh-hant.all.json +// DO NOT EDIT! + +package resources + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _resourcesDeDeAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\x4d\x6f\xd4\x30\x10\x86\xef\xfd\x15\xaf\xf6\x92\x4b\xb5\x3f\x20\xb7\xa8\xda\x45\x48\xa5\x42\xf4\xe3\x42\x11\x1d\xe2\x69\xd6\x52\xe2\x31\xf6\x84\x80\xa2\xfc\x77\x64\x96\x8a\x6d\xc1\x8b\x5b\xf5\x12\x45\x33\xe3\xe7\x7d\x26\x1f\x1f\x4f\x00\xcc\xe9\x02\x60\x65\xcd\xaa\xc6\xea\xd6\x35\xde\x23\x2a\x05\x65\x73\xeb\x56\xa7\x0f\x6d\x0d\xe4\x62\x4f\x6a\xc5\xfd\x99\xeb\x78\x3f\xa9\x87\x93\x83\x18\x7b\x6f\x39\xe1\xee\xa9\x8f\x9c\xea\xcb\x69\x36\x6b\x9e\xd7\x8d\xf7\x17\x34\xf0\xb2\x60\xa2\xf8\x10\x8e\x31\x5a\xd7\x41\x77\x36\xa2\x95\x61\x20\x67\x70\x37\xcf\xeb\xb3\xfd\xfd\xb2\xdc\xfd\x57\xef\x75\xd0\xcf\xd8\xe7\xea\xed\xfb\x1a\xd7\x91\x51\x1d\xd2\x2a\xa8\x40\x29\x74\xac\x70\x3c\x41\x42\x77\x44\xfc\x05\x8c\x62\x43\x00\x37\x96\x27\x50\xdf\xcb\x44\x5f\x7a\xc6\xd7\x51\x94\x22\x26\xab\x3b\x54\x67\xdb\xcf\x17\xcd\xbb\xcd\xef\x62\x95\x95\x7c\x29\xa6\xd8\x33\xad\x7e\xc3\x21\x5a\x71\x97\x3b\x09\x9a\xf6\x4f\x2f\xe9\xa0\x7e\x2e\xae\xfb\x55\x0e\x0c\xea\xa3\x80\xda\x96\xbd\xb2\x59\x67\xb5\x5f\x89\x5a\xbc\x45\x93\x00\x86\x7b\x56\x06\xb9\x1f\x18\xc8\x7b\x36\x08\x32\x2a\xc7\xac\x65\xe1\xa9\x72\x8b\xa7\x3f\x82\x11\x8e\x70\xa2\xe0\xef\x36\x6a\xfe\x71\x95\x1f\x2c\x76\xd9\x6e\x9a\xab\xeb\x0f\x1b\x6c\xcf\x9b\x37\x97\xd9\xe0\xcc\x54\x71\x4a\xd2\xcd\xc2\x1f\x37\x8b\x99\xe4\x2d\xd8\x19\x2f\xd6\x69\x9d\x85\x67\xa6\x9e\x95\xf2\x6d\xff\x25\x1e\x0f\xf9\x7b\xa8\x38\x43\x42\x97\x67\x3f\x6e\x16\x33\xa3\xa7\x96\xeb\x22\xfb\x63\xa3\xc5\x79\x63\xe4\x90\x8f\x78\xd2\xfd\x27\xf5\xe4\xd3\xcf\x00\x00\x00\xff\xff\xf6\x15\xfb\x1f\xfe\x06\x00\x00") + +func resourcesDeDeAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesDeDeAllJson, + "resources/de-de.all.json", + ) +} + +func resourcesDeDeAllJson() (*asset, error) { + bytes, err := resourcesDeDeAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/de-de.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesEnUsAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\xcd\x6e\xdb\x30\x10\x84\xef\x7a\x8a\x81\x2f\xbe\x04\x7e\x00\xdf\x84\xc0\x2e\x0a\xa4\x41\xd0\xfc\x5c\x9a\xa2\xd9\x9a\x1b\x99\x00\x45\xb2\xdc\x75\xd5\x42\xd0\xbb\x17\xb2\x93\x22\x86\xc8\xfc\xc0\x57\xce\xcc\xb7\x2b\xed\xee\xb7\x0a\xe8\x2b\x00\x98\x59\x33\x5b\x62\x76\xef\xeb\x18\x21\x4a\x49\xd9\xdc\xfb\xd9\xd9\x41\xd4\x44\x5e\x1c\xa9\x0d\x3e\xe7\xaa\x80\xe1\x6c\x8a\xba\xf9\x7c\xb5\xc4\xad\x30\xe6\x7d\xbf\x38\x0f\x6d\x4b\xde\x0c\xc3\x1c\x1a\xa0\x94\x1a\x56\x78\xee\x10\x52\x53\x2c\xf3\x7e\x42\xb6\x85\x4b\x6a\xb9\xc0\xde\x4b\xd9\xd0\xf8\x69\x7d\xbf\xa8\x63\x1c\x3d\xc3\x00\x13\x58\xe0\x83\x82\xff\x58\xd1\x45\x01\xf8\x66\x2c\x5b\x6c\xbd\xaa\x6f\x6e\xbf\xae\xb0\xbe\xa8\x3f\x5d\x17\xc8\xc7\x9e\x2c\x06\xc0\x9d\xe5\x0e\xe4\x5c\xe8\xe8\xa7\x63\xfc\xda\x05\x25\x41\x67\x75\x8b\xf9\xf9\xfa\xc7\x65\xfd\x65\xf5\xf4\x38\x2f\xd4\xf9\x20\x24\xdb\xc8\x38\xa7\x3b\x4e\x62\x83\xbf\xde\x86\xa4\xe3\xb0\xc8\x1b\xbc\x78\xbf\x08\xbe\xd9\x3f\x27\x06\x39\x09\xa0\xcd\x86\xa3\xb2\x29\xfd\xd9\xd3\x98\xf9\x19\x8f\x1e\xc3\x8e\x95\x41\xfe\x2f\x5a\x8a\x91\x0d\x52\xd8\x29\x4b\x69\xc0\xaf\x66\x0a\x27\x30\xd9\x8a\x8e\xe4\xf9\x70\xb0\x13\xeb\x1b\xe8\xd6\x0a\x36\x87\xdd\xc6\xc3\xcb\x3d\x7f\x78\xe3\x00\x4f\x02\x67\x1b\xa6\x68\xc1\xde\xc4\x60\xbd\x2e\x0b\xb5\x8f\x3d\x45\xcc\xef\xc3\x64\x5e\xa3\xfc\xb7\x64\x21\x3b\xe1\x54\x4a\x1f\xb4\x6c\x2c\xa4\xa6\x94\xda\x4b\xd9\x90\x44\xda\xf0\xf2\x1d\x6d\x67\x8c\xc7\xc0\x67\xe2\xaa\x25\xeb\x9e\x20\x13\xca\xb1\xd8\x06\x63\x1f\x2d\x8f\xb1\x47\x72\xc2\x79\xe0\x15\x89\x74\x21\x99\x12\x73\xa2\x4f\xb1\x43\xf5\xbd\xfa\x17\x00\x00\xff\xff\xcf\x2f\x17\x9b\xf2\x05\x00\x00") + +func resourcesEnUsAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesEnUsAllJson, + "resources/en-us.all.json", + ) +} + +func resourcesEnUsAllJson() (*asset, error) { + bytes, err := resourcesEnUsAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/en-us.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesEsEsAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\xcd\x6a\xdb\x40\x10\xc7\xef\x79\x8a\x3f\xbe\xf8\x12\xfc\x00\xbe\x09\x63\x97\x42\x1a\x42\xf3\x71\x69\x4a\x33\xd5\x4e\xec\x05\x69\x67\xbb\x33\xae\x5a\x84\x1e\xaa\xf4\x11\xf2\x62\x45\x4d\x43\x9d\x84\x75\x36\x26\x17\x21\x66\x66\x7f\xff\xdf\xe8\xe3\xd3\x11\x80\x7e\xbc\x00\x98\x78\x37\x99\x63\x72\x1d\xaa\x18\xa1\x46\xc9\xd8\x5d\x87\xc9\xf1\x43\xdb\x12\x05\x6d\xc8\xbc\x84\xff\x73\x3e\xf8\xda\x93\xa3\xdd\xc1\x56\x9c\xbf\xf5\x3c\xd2\x6e\xa9\x51\x1e\xeb\xc3\x71\x36\xaa\xef\x67\x55\x8c\xa7\xd4\xf2\x30\xa0\x23\x7d\xc8\xc6\x56\x7d\x58\xc3\x36\x5e\x51\x4b\xdb\x52\x70\xb8\xe9\xfb\xd9\xe2\xfe\x7e\x18\x6e\x5e\xb4\x7b\x1b\xf4\x2b\xf6\xb9\x78\x7f\x36\xc7\xa5\x32\xa6\xbb\xb4\x29\x4c\x60\x94\xd6\x6c\x08\xdc\x41\xd2\x7a\x8f\xf8\x01\x8c\x62\x43\x00\x57\x9e\x3b\x50\xd3\x48\x47\x5f\x1b\xc6\xb7\xad\x18\x29\x3a\x6f\x1b\x4c\x17\xab\x2f\xa7\xd5\x87\xe5\xbf\xe2\x34\x2b\x79\x28\xa6\xd8\x73\x5c\xfd\x8a\x93\x7a\x09\xe7\x1b\x49\x36\xee\x3f\xbe\xa4\x9d\xfa\x89\x84\xf5\xdf\x72\x62\x50\xa3\x02\xaa\x6b\x8e\xc6\x6e\x96\xd5\x7e\x23\x6a\xf1\x16\xd5\x08\x70\xdc\xb0\x31\x28\xfc\x44\x4b\x31\xb2\x43\x92\xad\xb1\x66\x2d\x0b\x4f\x95\x5b\x3c\xfd\x11\x9c\xb0\x22\x88\x81\x7f\x78\xb5\xfc\xe3\x2a\x3f\x58\xec\xb2\x5a\x56\x17\x97\x1f\x97\x58\x9d\x54\xef\xce\xb3\xc1\x99\xa9\xe2\x94\x51\x37\x0b\x7f\xdc\x2c\x66\x52\xf4\xe0\xe0\xa2\xf8\x60\xf3\x2c\x3c\x33\xf5\xaa\x94\xef\xf7\x5f\xe2\xfe\x90\xe7\x43\xc5\x19\x92\xd6\x79\xf6\xe3\x66\x31\x53\x23\xd5\x3c\x2f\xb2\xdf\x37\x5a\x9c\xb7\x55\x4e\xf9\x88\x27\xdd\x62\xea\xb2\x25\xdf\x64\xa9\x0b\x49\x89\x05\xdc\x70\x6d\xe9\xee\x77\xf0\xb5\x1c\x90\x71\x46\xaa\x9d\x24\xb7\x27\x26\x58\x22\xe5\xbb\x5f\xf4\x02\xfe\xe8\xf3\x9f\x00\x00\x00\xff\xff\xd2\x34\xa6\x99\xc0\x07\x00\x00") + +func resourcesEsEsAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesEsEsAllJson, + "resources/es-es.all.json", + ) +} + +func resourcesEsEsAllJson() (*asset, error) { + bytes, err := resourcesEsEsAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/es-es.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesFrFrAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x95\xc1\x6e\xdb\x46\x10\x86\xef\x7e\x8a\x1f\xba\xe8\x92\xf8\x01\x74\x23\x14\x3a\x30\xe0\x2a\x46\x24\x05\x2d\x9a\xa2\x1e\x93\x23\x71\x01\x72\x77\xbb\xb3\x2b\xd7\x16\xf4\x2e\x3d\x96\x7d\x0d\xbe\x58\xb1\x94\xdc\x48\xae\x56\x51\x74\x31\xc4\xe5\xcc\xf7\xff\x33\x9c\x59\xff\x7a\x05\x60\x1d\xff\x00\x18\xa8\x72\x30\xc2\xe0\x3e\x48\x05\x82\xe6\x27\x90\xb5\x30\x0e\xf2\xac\x0b\x14\x15\xe9\x25\x0b\xbc\x01\x69\xf0\x9f\x4a\xbc\xd2\xcb\x18\x32\x78\xf7\x0a\xf0\x8e\xb4\xd4\xe4\x95\xd1\x91\x94\xeb\x95\x79\x66\x07\x4b\x0e\x85\x69\x1a\xd2\x25\xc3\x46\x7c\xd0\x0c\x6d\xc2\x8a\xeb\x9a\x23\xa2\x56\x45\x9f\x05\x13\x7a\xb5\xca\x19\xad\x84\x1d\x6a\x16\x34\xa6\x54\x8b\x5d\x80\xa0\x24\x2d\x7d\xfe\x7e\x5a\x6f\x87\xb4\xe7\x41\xb4\xb2\x79\x77\xa4\xac\xf9\x34\xfb\x98\x8f\x92\x5e\xa7\xbf\x4c\x66\xd9\xcf\x39\x46\x69\xc2\x3d\xf9\xaa\x2f\xdf\x5a\x94\xca\x71\xe1\x8d\x7b\x8e\xfd\x89\x67\x78\x51\x16\x0b\x55\x33\xcc\x02\xbe\x62\x14\x46\x7b\xd6\x5e\x5e\x9f\x0f\xb2\x92\x36\xc6\x15\x37\x4a\xa3\x1c\x52\x51\x74\x7f\x0b\x28\xc0\x75\xad\x65\xe7\x8d\x72\x8c\x92\x51\x0f\xdf\xf4\xab\xfb\x0b\x41\x63\xa1\x8a\x4a\xb1\xeb\x6d\x94\x61\xa7\x1e\xe2\xcf\x53\xf9\xe9\x62\x27\xa1\x79\x64\x17\xcd\x2b\x1d\x5b\x5b\xb0\x24\x4d\x4f\x4c\xf3\x18\xe1\xc3\x6f\xa1\x49\xee\x57\x9d\x59\x0b\xf1\xe4\x3c\x97\x5f\x75\x92\xd9\xc7\xfd\x57\x66\xd9\xb5\x0d\x39\xd7\xb5\xbc\x9f\xb2\x1d\x0c\x8e\xdc\x05\xd5\xc2\xdf\x11\x5d\xaf\xaf\x33\x6b\x27\xd4\xf0\x66\x83\x27\x92\x57\x17\x08\x12\x27\xd9\x57\x4a\x5e\xc7\x14\x0f\xeb\xf5\xf5\x78\xfb\x7b\xb3\x79\x38\xe9\xf3\xee\xe0\x83\x1c\x88\x10\xba\xd6\x77\xed\x9e\x7d\xd0\x8a\x0b\xd4\xf4\x6d\x1f\x1e\xc4\x34\xfc\x7e\xf7\xf8\x5e\x53\xc3\x0f\x17\xd6\x38\xbb\xbd\x1f\x61\x2e\x8c\xe1\xbe\xf9\x61\x1c\x4f\x4f\x6e\xc9\xbe\xdf\x69\xe3\x96\xa7\x9a\x3e\x9d\xcd\xc7\x39\x46\x08\x5e\xd5\x4a\xf8\xe5\x2d\xcc\x9a\xe0\x50\xa8\xc7\x9a\xdd\xe1\x16\x1b\xb7\x24\xad\x64\xcb\xfa\x71\xfb\x00\xbe\xa8\x78\xe5\xd4\xb5\x79\xa2\xc7\x9a\xf1\x47\x30\x9e\x04\x4f\xca\x57\x18\x8e\x6f\x7e\x9f\x64\x3f\xe5\xbb\xc3\x61\xb2\x02\x00\xd9\x22\xee\x02\xbf\xf4\x77\xc7\x0e\x62\x4d\x58\x91\xf6\xe8\xfe\xf1\x8e\x7b\x8d\xd0\xb5\xb2\xfd\x18\x69\xf6\xd9\xe6\x63\x8f\xbe\xb0\x13\x65\xf4\xb4\x32\xce\xc7\x46\xc5\x29\xda\x3b\xbf\x33\x7a\xd9\x1f\xf7\xfa\x62\x40\x45\xc1\xd6\x73\x79\x9d\xac\xe5\x18\x95\xfd\x31\xa8\x98\x58\x5b\xbb\xa4\x9a\x1b\xd6\x7e\xc7\xee\x5a\xb9\xbe\x68\x94\xb2\xe8\xaf\xe4\x9a\x3d\x83\xf4\x33\x1a\xb2\x96\x4b\x38\x13\xfc\x89\x5b\x60\x1a\xac\x75\xaa\x61\x07\x0a\x22\xaa\x6f\xff\x36\xa5\x07\x74\x2d\xcb\x65\x6e\xde\xae\x6e\x69\x58\xa0\x8d\xdf\xde\xfa\xe9\xfe\x9d\x58\x4c\x3d\xec\x73\x19\x96\x2e\xec\xd1\x4d\x9e\xcd\xe6\x9f\x73\xdc\xdc\x65\x1f\xa7\x49\x0b\xb7\x93\x0f\xb7\xe3\x6c\x96\xcf\x3f\x4f\xf1\x21\xc7\xcd\xa7\xc9\x78\x76\xfb\x69\x72\x81\x5e\x34\x7e\xea\x02\xbe\x00\x49\x56\x81\x75\x69\x8d\xd2\x3e\xfd\x8f\x31\x11\xf5\x43\x2a\xab\xed\xb8\x9e\x16\xf9\x7f\xd0\xd9\x1a\xc6\x2d\xd3\xec\xc3\x97\x67\x33\xc5\x52\xc1\xa3\xb3\xdc\x9f\x0a\x3d\x5b\x2f\x08\xbb\xb4\xc4\x9b\xb7\x47\xa9\x57\xbf\x5d\xfd\x1b\x00\x00\xff\xff\xe5\x46\x71\xdf\xd0\x09\x00\x00") + +func resourcesFrFrAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesFrFrAllJson, + "resources/fr-fr.all.json", + ) +} + +func resourcesFrFrAllJson() (*asset, error) { + bytes, err := resourcesFrFrAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/fr-fr.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesItItAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\x4d\x6f\x13\x31\x10\x86\xef\xfd\x15\xaf\x72\xc9\xa5\xca\x0f\xc8\x6d\x55\x25\x08\xa9\x54\x88\x7e\x5c\x28\xa2\xc3\x7a\xba\xb1\xe4\xf5\x18\x7b\x92\x05\x56\xfb\xdf\x91\x29\x45\x69\xc1\xc1\xad\x72\x59\xad\x66\xc6\xcf\xfb\xcc\x7e\x7c\x3c\x01\x30\xe6\x0b\x80\x99\x35\xb3\x25\x66\xb7\xbe\x09\x01\x49\x29\x2a\x9b\x5b\x3f\x3b\x7d\x6c\x6b\x24\x9f\x1c\xa9\x15\xff\x67\xce\xd9\x96\x7e\x58\xf1\x0c\xda\xed\x2c\x29\xed\x1f\xe8\xc5\xd8\x7b\xcb\x99\x7a\x4f\x2e\x71\xae\x4f\xa7\xc5\xc8\x71\x5c\x34\x21\x5c\x50\xcf\xd3\x84\x81\xd2\xa3\x03\xb6\xc9\xfa\x0e\xba\xb1\x09\xad\xf4\x3d\x79\x83\xbb\x71\x5c\x9c\x3d\xdc\x4f\xd3\xdd\xff\x2c\x8f\x84\x7e\xc1\x3e\x57\x6f\xdf\x2f\x71\x9d\x18\xf3\x7d\xda\x1c\x2a\x50\x8a\x1d\x2b\x3c\x0f\x90\xd8\x1d\x10\x7f\x05\xa3\xda\x10\xc0\x8d\xe5\x01\xe4\x9c\x0c\xf4\xc5\x31\xbe\x6e\x45\x29\x61\xb0\xba\xc1\xfc\x6c\xfd\xf9\xa2\x79\xb7\xfa\x5d\x9c\x17\x25\x5f\x8b\xa9\xf6\xcc\xab\xdf\x70\x4c\x56\xfc\xe5\x46\xa2\xe6\xfd\xf3\x4b\xda\xab\x9f\x8b\xef\x7e\x95\x23\x83\x5c\x12\x50\xdb\x72\x50\x36\x8b\xa2\xf6\x91\xa8\xd5\x5b\x34\x19\x60\xd8\xb1\x32\xc8\x7f\x47\x4f\x21\xb0\x41\x94\xad\x72\x2a\x5a\x56\x9e\xaa\xb7\x78\xfe\x23\x18\xe1\x04\x2f\x0a\xfe\x66\x93\x96\x1f\x57\xfd\xc1\x6a\x97\xf5\xaa\xb9\xba\xfe\xb0\xc2\xfa\xbc\x79\x73\x59\x0c\x2e\x4c\x55\xa7\x64\xdd\x22\xfc\x69\xb3\x9a\x49\xc1\x82\xbd\x09\x62\xbd\x2e\x8b\xf0\xc2\xd4\x8b\x52\x76\x0f\x5f\xe2\xe1\x90\xbf\x87\xaa\x33\x24\x76\x65\xf6\xd3\x66\x35\x33\x05\x6a\x79\x59\x65\x7f\x68\xb4\x3a\x6f\x9b\x38\x96\x23\x9e\x75\xff\x49\x3d\xf9\xf4\x33\x00\x00\xff\xff\xdc\xca\x3a\xfd\x05\x07\x00\x00") + +func resourcesItItAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesItItAllJson, + "resources/it-it.all.json", + ) +} + +func resourcesItItAllJson() (*asset, error) { + bytes, err := resourcesItItAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/it-it.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesJaJpAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\xcd\x6a\x14\x4d\x14\x86\xf7\xb9\x8a\x97\xd9\xcc\x26\xcc\x05\xcc\xae\x09\x33\x1f\x1f\xc4\x20\xe6\x67\x63\xc4\x1c\xa7\x4e\x7a\x0a\xba\xab\xca\xaa\x33\xb6\xd2\xf4\xa2\x93\x65\xb2\xd5\x2c\x05\x37\x82\x17\xe1\xcd\x14\x2e\xbc\x0b\x69\xc7\xc0\x24\x5a\x43\x25\x64\xd3\x34\xe7\x9c\x7a\xde\xe7\xf4\xcf\xcb\x1d\x00\xed\x70\x01\x30\xd2\x6a\x34\xc5\xe8\xd4\x14\xce\x21\x08\x79\x61\x75\x6a\x46\xbb\xb7\x6d\xf1\x64\x42\x45\xa2\xad\x59\xcf\xc5\x8b\x2f\xf1\xf2\x26\x5e\x7e\x8b\xfd\xf5\xcf\x4f\x57\x3f\xbe\x5e\xc5\xfe\x63\xbc\xb8\x8e\xfd\xf7\xd8\xdf\xc4\xfe\xf3\xe6\xe9\xda\x2a\x7d\xae\x79\x88\x38\xa7\x2a\xf0\x50\xef\x76\x93\xf9\x6d\x3b\x29\x9c\x3b\xa0\x9a\xbb\x0e\x0d\x85\x5b\x21\xac\x82\x36\x25\x64\xa9\x03\x16\xb6\xae\xc9\x28\x9c\xb5\xed\x64\x6f\x7d\xdf\x75\x67\x5b\x95\x9f\x0e\xfd\x80\x7d\x8e\xfe\x7f\x3e\xc5\x71\x60\x8c\x37\x69\x63\x88\x85\x90\x2f\x59\x60\xb8\x81\xf5\xe5\x16\xf1\x47\x30\xb2\x0d\x01\x9c\x68\x6e\x40\x55\x65\x1b\x7a\x53\x31\xde\xae\xac\x50\x40\xa3\x65\x89\xf1\xde\xfc\xf5\x41\xf1\x6c\xf6\xa7\x38\x4e\x4a\x3e\x16\x93\xed\x39\xac\x7e\xc2\x3e\x68\x6b\x0e\x97\xd6\xcb\xb0\xff\xf0\x92\x36\xea\xfb\xd6\x94\xbf\xcb\x9e\x41\x55\xb0\xa0\xc5\x82\x9d\xb0\x9a\x24\xb5\x9f\x88\x9a\xbd\x45\x31\x00\x14\x57\x2c\x0c\x32\x1f\x50\x93\x73\xac\xe0\xed\x4a\x38\x24\x2d\x33\x4f\xe5\x5b\xdc\xff\x11\x94\xe5\x00\x63\x05\xfc\x5e\x07\x49\x3f\xae\xfc\x83\xd9\x2e\xf3\x59\x71\x74\xfc\x62\x86\xf9\x7e\xf1\xdf\x61\x32\x38\x31\x95\x9d\x32\xe8\x26\xe1\x77\x9b\xd9\x4c\x72\x1a\x6c\x94\xb3\xda\xc8\x34\x09\x4f\x4c\x3d\x28\xe5\xdd\xfa\x4b\xdc\x1e\xf2\xf7\x50\x76\x86\xf5\x65\x9a\x7d\xb7\x99\xcd\x0c\x8e\x16\x3c\xcd\xb2\xdf\x36\x9a\x9d\xb7\x0a\xec\xd3\x11\xf7\xba\xff\xa4\xee\xbc\xfa\x15\x00\x00\xff\xff\x04\xa3\x79\xe1\x12\x07\x00\x00") + +func resourcesJaJpAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesJaJpAllJson, + "resources/ja-jp.all.json", + ) +} + +func resourcesJaJpAllJson() (*asset, error) { + bytes, err := resourcesJaJpAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/ja-jp.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesKoKrAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\xbd\x6e\x13\x41\x10\xc7\xfb\x3c\xc5\x5f\x6e\xdc\x44\x7e\x00\x77\xa7\xc8\x46\x48\x21\x42\xe4\xa3\x21\x88\x0c\xde\xc9\x79\xa5\xbb\x9d\x65\x77\xcc\x81\x4e\xf7\x04\x34\x50\xd0\x21\x6a\x5a\x9e\x0b\x3f\x04\x5a\x4c\x24\x27\x64\x4f\x9b\x28\xcd\xe9\x34\x33\xfb\xfb\xff\xe6\x3e\x5e\x1f\x00\xe8\xd3\x05\xc0\xc4\x9a\xc9\x1c\x93\x4b\x57\x79\x8f\xa8\x14\x94\xcd\xa5\x9b\x1c\xde\xb4\x35\x90\x8b\x0d\xa9\x15\xb7\x9b\xdb\x7e\xfb\x85\xed\xe7\xef\xdb\x1f\x5f\x7f\x7f\xf9\xb9\x3f\xd9\x8a\xb1\xd7\x96\x13\xee\x9a\x9a\xc8\xa9\x3e\x1c\x66\xb3\xfa\x7e\x56\x79\x7f\x42\x2d\x0f\x03\x3a\x8a\x37\xe1\xd8\x44\xeb\x6a\xe8\xda\x46\xac\xa4\x6d\xc9\x19\x5c\xf5\xfd\xec\x68\x77\x3f\x0c\x57\xa3\x7a\x4f\x87\x7e\xc0\x3e\x67\xcf\x5f\xce\x71\x1e\x19\xd3\x7d\xda\x14\x2a\x50\x0a\x35\x2b\x1c\x77\x90\x50\x8f\x88\x3f\x82\x51\x6c\x08\xe0\xc2\x72\x07\x6a\x1a\xe9\xe8\x5d\xc3\x78\xbf\x11\xa5\x88\xce\xea\x1a\xd3\xa3\xe5\xdb\x93\xea\xc5\xe2\x5f\x71\x9a\x95\x7c\x2c\xa6\xd8\x33\xad\x7e\xc1\x21\x5a\x71\xa7\x6b\x09\x9a\xf6\x4f\x2f\x69\xaf\x7e\x2c\xae\xfe\x5b\x0e\x0c\x6a\xa2\x80\x56\x2b\xf6\xca\x66\x96\xd5\x7e\x22\x6a\xf1\x16\x55\x02\x18\x6e\x58\x19\xe4\x3e\xa1\x25\xef\xd9\x20\xc8\x46\x39\x66\x2d\x0b\x4f\x95\x5b\xdc\xfd\x11\x8c\x70\x84\x13\x05\x7f\xb4\x51\xf3\x8f\xab\xfc\x60\xb1\xcb\x72\x51\x9d\x9d\xbf\x5a\x60\x79\x5c\x3d\x3b\xcd\x06\x67\xa6\x8a\x53\x92\x6e\x16\x7e\xbb\x59\xcc\x24\x6f\xc1\xce\x78\xb1\x4e\xe7\x59\x78\x66\xea\x41\x29\x1f\x76\x5f\xe2\x78\xc8\xff\x43\xc5\x19\x12\xea\x3c\xfb\x76\xb3\x98\x19\x3d\xad\x78\x5e\x64\x3f\x36\x5a\x9c\xb7\x89\x1c\xf2\x11\x77\xba\xf7\x52\x0f\xde\xfc\x09\x00\x00\xff\xff\xc9\xe7\x7a\x82\xfe\x06\x00\x00") + +func resourcesKoKrAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesKoKrAllJson, + "resources/ko-kr.all.json", + ) +} + +func resourcesKoKrAllJson() (*asset, error) { + bytes, err := resourcesKoKrAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/ko-kr.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesPtBrAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\x4d\x6f\xd4\x30\x10\x86\xef\xfd\x15\xaf\xf6\x92\x4b\xb5\x3f\x20\xb7\xa8\xda\x45\x48\xa5\x42\xf4\xe3\x42\x11\x1d\xe2\x69\xd6\x52\xe2\x31\xf6\x84\x80\xa2\xfc\x77\x64\x4a\xc5\xb6\xe0\xc5\xad\xf6\x12\x45\x33\xe3\xe7\x7d\x26\x1f\x1f\x4f\x00\xcc\xe9\x02\x60\x65\xcd\xaa\xc6\xea\xd6\x35\xde\x23\x2a\x05\x65\x73\xeb\x56\xa7\x8f\x6d\x0d\xe4\x62\x4f\x6a\xc5\xfd\x99\xb3\xce\xb6\x96\x8c\xec\x0f\x0e\x62\xec\xbd\xe5\x44\xbb\xa7\x3e\x72\xaa\x2f\xa7\xd9\xa8\x79\x5e\x37\xde\x5f\xd0\xc0\xcb\x82\x89\xe2\x63\x36\xc6\x68\x5d\x07\xdd\xd9\x88\x56\x86\x81\x9c\xc1\xdd\x3c\xaf\xcf\x1e\xee\x97\xe5\xee\xbf\x76\xc7\x41\xbf\x60\x9f\xab\xb7\xef\x6b\x5c\x47\x46\xb5\x4f\xab\xa0\x02\xa5\xd0\xb1\xc2\xf1\x04\x09\xdd\x01\xf1\x57\x30\x8a\x0d\x01\xdc\x58\x9e\x40\x7d\x2f\x13\x7d\xe9\x19\x5f\x47\x51\x8a\x98\xac\xee\x50\x9d\x6d\x3f\x5f\x34\xef\x36\xbf\x8b\x55\x56\xf2\xb5\x98\x62\xcf\xb4\xfa\x0d\x87\x68\xc5\x5d\xee\x24\x68\xda\x3f\xbd\xa4\xbd\xfa\xb9\xb8\xee\x57\x39\x30\xa8\x8f\x02\x6a\x5b\xf6\xca\x66\x9d\xd5\x3e\x12\xb5\x78\x8b\x26\x01\x0c\xf7\xac\x0c\x72\x3f\x30\x90\xf7\x6c\x10\x64\x54\x8e\x59\xcb\xc2\x53\xe5\x16\xcf\x7f\x04\x23\x1c\xe1\x44\xc1\xdf\x6d\xd4\xfc\xe3\x2a\x3f\x58\xec\xb2\xdd\x34\x57\xd7\x1f\x36\xd8\x9e\x37\x6f\x2e\xb3\xc1\x99\xa9\xe2\x94\xa4\x9b\x85\x3f\x6d\x16\x33\xc9\x5b\xb0\x33\x5e\xac\xd3\x3a\x0b\xcf\x4c\xbd\x28\xe5\xdb\xc3\x97\x78\x38\xe4\xef\xa1\xe2\x0c\x09\x5d\x9e\xfd\xb4\x59\xcc\x8c\x9e\x5a\xae\x8b\xec\x0f\x8d\x16\xe7\x8d\x91\x43\x3e\xe2\x59\xf7\x9f\xd4\x93\x4f\x3f\x03\x00\x00\xff\xff\xbc\x94\x72\xe2\xfd\x06\x00\x00") + +func resourcesPtBrAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesPtBrAllJson, + "resources/pt-br.all.json", + ) +} + +func resourcesPtBrAllJson() (*asset, error) { + bytes, err := resourcesPtBrAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/pt-br.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesZhHansAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\xcd\x6a\xdb\x40\x10\xc7\xef\x79\x8a\x3f\xbe\xf8\x12\xfc\x00\xbe\x89\x60\x97\x42\x1a\x4a\xf3\x71\x69\x4a\x33\xf5\x4e\xe4\x05\x69\x67\xbb\x3b\xae\x5a\x84\x5e\xa0\x3d\xb4\x87\x3c\x84\x6f\x85\x5e\x0a\x79\x1f\x91\xd7\x28\xaa\x1b\x70\xd2\xac\xd9\x84\x5c\x84\x98\x99\xfd\xfd\x7f\xa3\x8f\xb7\x7b\x00\xda\xe1\x02\x60\x64\xcd\x68\x8a\xd1\xb9\x2b\xbc\x47\x54\x0a\xca\xe6\xdc\x8d\xf6\x6f\xdb\x1a\xc8\xc5\x8a\xd4\x8a\xdb\xcc\xf5\xd7\x57\x37\x57\xeb\x9b\xf5\xb7\xfe\xfa\x7b\xff\xfb\x57\xff\xe3\x67\xff\x75\xbd\x7d\xa2\x16\x63\x2f\x2d\x0f\xd8\x4b\xaa\x22\x0f\xf5\x6e\x3f\x99\xd9\xb6\x93\xc2\xfb\x23\xaa\xb9\xeb\xd0\x50\xbc\x95\xc0\x2a\x5a\x57\x42\x97\x36\x62\x21\x75\x4d\xce\xe0\xa2\x6d\x27\x07\x9b\xfb\xae\xbb\xd8\xa9\xf9\x7c\xe8\x47\xec\x73\xf2\xf2\xf5\x14\xa7\x91\x31\xde\xa6\x8d\xa1\x02\xa5\x50\xb2\xc2\x71\x03\x09\xe5\x0e\xf1\x27\x30\xb2\x0d\x01\x9c\x59\x6e\x40\x55\x25\x0d\x7d\xa8\x18\x1f\x57\xa2\x14\xd1\x58\x5d\x62\x7c\x30\x7f\x7f\x54\xbc\x9a\xfd\x2b\x8e\x93\x92\x4f\xc5\x64\x7b\x0e\xab\x9f\x71\x88\x56\xdc\xf1\x52\x82\x0e\xfb\x0f\x2f\x69\xab\x7e\x28\xae\xfc\x5b\x0e\x0c\xaa\xa2\x80\x16\x0b\xf6\xca\x66\x92\xd4\x7e\x26\x6a\xf6\x16\xc5\x00\x30\x5c\xb1\x32\xc8\x7d\x41\x4d\xde\xb3\x41\x90\x95\x72\x4c\x5a\x66\x9e\xca\xb7\xb8\xff\x23\x18\xe1\x08\x27\x0a\xfe\x6c\xa3\xa6\x1f\x57\xfe\xc1\x6c\x97\xf9\xac\x38\x39\x7d\x33\xc3\xfc\xb0\x78\x71\x9c\x0c\x4e\x4c\x65\xa7\x0c\xba\x49\xf8\xdd\x66\x36\x93\xbc\x05\x3b\xe3\xc5\x3a\x9d\x26\xe1\x89\xa9\x47\xa5\x7c\xda\x7c\x89\xbb\x43\xfe\x1f\xca\xce\x90\x50\xa6\xd9\x77\x9b\xd9\xcc\xe8\x69\xc1\xd3\x2c\xfb\x5d\xa3\xd9\x79\xab\xc8\x21\x1d\x71\xaf\xfb\x20\x75\xef\xdd\x9f\x00\x00\x00\xff\xff\x0c\xe7\xa4\xba\x06\x07\x00\x00") + +func resourcesZhHansAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesZhHansAllJson, + "resources/zh-hans.all.json", + ) +} + +func resourcesZhHansAllJson() (*asset, error) { + bytes, err := resourcesZhHansAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/zh-hans.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _resourcesZhHantAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x93\xbd\x6e\x13\x41\x10\xc7\xfb\x3c\xc5\x5f\x6e\xdc\x44\x7e\x00\x77\xa7\xc8\x46\x48\x21\x42\xe4\xa3\x21\x88\x0c\xde\xc9\x79\xa5\xbb\x9d\x65\x77\xcc\x81\x4e\x57\x23\x94\x82\x86\xd4\xb4\xa9\x69\x68\x78\x1d\x93\xd7\x40\x87\x89\xe4\x84\xec\x69\x13\xa5\x39\x9d\x66\x66\x7f\xff\xdf\xdc\xc7\xeb\x1d\x00\x6d\x7f\x01\x30\xb2\x66\x34\xc5\xe8\xd4\x15\xde\x23\x2a\x05\x65\x73\xea\x46\xbb\x37\x6d\x0d\xe4\x62\x45\x6a\xc5\x6d\xe6\xd6\x3f\x7f\xac\x2f\xbf\xaf\x2f\x2e\x7f\x7f\xfe\x72\xfd\xed\xea\xfa\xea\x62\xfd\xeb\xeb\xf6\x89\x5a\x8c\x3d\xb7\xdc\x63\xcf\xa9\x8a\xdc\xd7\xbb\xdd\x64\x66\xdb\x4e\x0a\xef\x0f\xa8\xe6\xae\x43\x43\xf1\x46\x02\xab\x68\x5d\x09\x5d\xda\x88\x85\xd4\x35\x39\x83\xb3\xb6\x9d\xec\x6d\xee\xbb\xee\x6c\x50\xf3\xe9\xd0\x0f\xd8\xe7\xe8\xf9\xcb\x29\x8e\x23\x63\xbc\x4d\x1b\x43\x05\x4a\xa1\x64\x85\xe3\x06\x12\xca\x01\xf1\x47\x30\xb2\x0d\x01\x9c\x58\x6e\x40\x55\x25\x0d\xbd\xab\x18\xef\x57\xa2\x14\xd1\x58\x5d\x62\xbc\x37\x7f\x7b\x50\xbc\x98\xfd\x2b\x8e\x93\x92\x8f\xc5\x64\x7b\xf6\xab\x9f\x70\x88\x56\xdc\xe1\x52\x82\xf6\xfb\xf7\x2f\x69\xab\xbe\x2f\xae\xfc\x5b\x0e\x0c\xaa\xa2\x80\x16\x0b\xf6\xca\x66\x92\xd4\x7e\x22\x6a\xf6\x16\x45\x0f\x30\x5c\xb1\x32\xc8\x7d\x42\x4d\xde\xb3\x41\x90\x95\x72\x4c\x5a\x66\x9e\xca\xb7\xb8\xfb\x23\x18\xe1\x08\x27\x0a\xfe\x68\xa3\xa6\x1f\x57\xfe\xc1\x6c\x97\xf9\xac\x38\x3a\x7e\x35\xc3\x7c\xbf\x78\x76\x98\x0c\x4e\x4c\x65\xa7\xf4\xba\x49\xf8\xed\x66\x36\x93\xbc\x05\x3b\xe3\xc5\x3a\x9d\x26\xe1\x89\xa9\x07\xa5\x7c\xd8\x7c\x89\xc3\x21\xff\x0f\x65\x67\x48\x28\xd3\xec\xdb\xcd\x6c\x66\xf4\xb4\xe0\x69\x96\xfd\xd0\x68\x76\xde\x2a\x72\x48\x47\xdc\xe9\xde\x4b\xdd\x79\xf3\x27\x00\x00\xff\xff\xa1\x62\x3d\xd9\x06\x07\x00\x00") + +func resourcesZhHantAllJsonBytes() ([]byte, error) { + return bindataRead( + _resourcesZhHantAllJson, + "resources/zh-hant.all.json", + ) +} + +func resourcesZhHantAllJson() (*asset, error) { + bytes, err := resourcesZhHantAllJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "resources/zh-hant.all.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "resources/de-de.all.json": resourcesDeDeAllJson, + "resources/en-us.all.json": resourcesEnUsAllJson, + "resources/es-es.all.json": resourcesEsEsAllJson, + "resources/fr-fr.all.json": resourcesFrFrAllJson, + "resources/it-it.all.json": resourcesItItAllJson, + "resources/ja-jp.all.json": resourcesJaJpAllJson, + "resources/ko-kr.all.json": resourcesKoKrAllJson, + "resources/pt-br.all.json": resourcesPtBrAllJson, + "resources/zh-hans.all.json": resourcesZhHansAllJson, + "resources/zh-hant.all.json": resourcesZhHantAllJson, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "resources": &bintree{nil, map[string]*bintree{ + "de-de.all.json": &bintree{resourcesDeDeAllJson, map[string]*bintree{}}, + "en-us.all.json": &bintree{resourcesEnUsAllJson, map[string]*bintree{}}, + "es-es.all.json": &bintree{resourcesEsEsAllJson, map[string]*bintree{}}, + "fr-fr.all.json": &bintree{resourcesFrFrAllJson, map[string]*bintree{}}, + "it-it.all.json": &bintree{resourcesItItAllJson, map[string]*bintree{}}, + "ja-jp.all.json": &bintree{resourcesJaJpAllJson, map[string]*bintree{}}, + "ko-kr.all.json": &bintree{resourcesKoKrAllJson, map[string]*bintree{}}, + "pt-br.all.json": &bintree{resourcesPtBrAllJson, map[string]*bintree{}}, + "zh-hans.all.json": &bintree{resourcesZhHansAllJson, map[string]*bintree{}}, + "zh-hant.all.json": &bintree{resourcesZhHantAllJson, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/it-it.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/it-it.all.json new file mode 100644 index 0000000..9e4b443 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/it-it.all.json @@ -0,0 +1,72 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nApplicazione avviata\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/ja-jp.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/ja-jp.all.json new file mode 100644 index 0000000..d0a5aa3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/ja-jp.all.json @@ -0,0 +1,72 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nアプリが開始されました\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/ko-kr.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/ko-kr.all.json new file mode 100644 index 0000000..f464583 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/ko-kr.all.json @@ -0,0 +1,72 @@ +[ + { + "id": "\nApp started\n", + "translation": "\n앱 시작됨\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/pt-br.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/pt-br.all.json new file mode 100644 index 0000000..14be10b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/pt-br.all.json @@ -0,0 +1,72 @@ +[ + { + "id": "\nApp started\n", + "translation": "\nApp iniciado\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hans.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hans.all.json new file mode 100644 index 0000000..404c208 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hans.all.json @@ -0,0 +1,77 @@ +[ + { + "id": "\nApp started\n", + "translation": "\n应用程序已启动\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "临时验证码(从{{.AuthenticationEndpoint}}/passcode获取)", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hant.all.json b/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hant.all.json new file mode 100644 index 0000000..6ab37c1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/i18n/resources/zh-hant.all.json @@ -0,0 +1,77 @@ +[ + { + "id": "\nApp started\n", + "translation": "\n已啟動應用程式\n", + "modified": false + }, + { + "id": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "translation": "\nApp {{.AppName}} was started using this command `{{.Command}}`\n", + "modified": false + }, + { + "id": "\nTIP: Use '{{.Command}}' to target new org", + "translation": "\nTIP: Use '{{.Command}}' to target new org", + "modified": false + }, + { + "id": " View allowable quotas with 'CF_NAME quotas'", + "translation": " View allowable quotas with 'CF_NAME quotas'", + "modified": false + }, + { + "id": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "translation": "'{{.VersionShort}}' and '{{.VersionLong}}' are also accepted.", + "modified": false + }, + { + "id": "Also delete any mapped routes", + "translation": "Also delete any mapped routes", + "modified": false + }, + { + "id": "App {{.AppName}} does not exist.", + "translation": "App {{.AppName}} does not exist.", + "modified": false + }, + { + "id": "FEATURE FLAGS", + "translation": "FEATURE FLAGS", + "modified": false + }, + { + "id": "Name", + "translation": "Name", + "modified": false + }, + { + "id": "api endpoint:", + "translation": "api endpoint:", + "modified": false + }, + { + "id": "api version:", + "translation": "api version:", + "modified": false + }, + { + "id": "org:", + "translation": "org:", + "modified": false + }, + { + "id": "space:api version:", + "translation": "space:api version:", + "modified": false + }, + { + "id": "user:", + "translation": "user:", + "modified": false + }, + { + "id": "Temporary Authentication Code ( Get one at {{.AuthenticationEndpoint}}/passcode )", + "translation": "臨時驗證碼(從{{.AuthenticationEndpoint}}/passcode獲取)", + "modified": false + } +] \ No newline at end of file diff --git a/vendor/code.cloudfoundry.org/cli/resources/api_links_resource.go b/vendor/code.cloudfoundry.org/cli/resources/api_links_resource.go new file mode 100644 index 0000000..cfb2c49 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/api_links_resource.go @@ -0,0 +1,27 @@ +package resources + +// APILink represents a generic link from a response object. +type APILink struct { + // HREF is the fully qualified URL for the link. + HREF string `json:"href"` + // Method indicate the desired action to be performed on the identified + // resource. + Method string `json:"method"` + + // Meta contains additional metadata about the API. + Meta APILinkMeta `json:"meta"` +} + +type APILinkMeta struct { + // Version of the API + Version string `json:"version"` + + // Fingerprint to authenticate api with + HostKeyFingerprint string `json:"host_key_fingerprint"` + + // Identifier for UAA queries + OAuthClient string `json:"oath_client"` +} + +// APILinks is a directory of follow-up urls for the resource. +type APILinks map[string]APILink diff --git a/vendor/code.cloudfoundry.org/cli/resources/application_feature_resource.go b/vendor/code.cloudfoundry.org/cli/resources/application_feature_resource.go new file mode 100644 index 0000000..218ab53 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/application_feature_resource.go @@ -0,0 +1,8 @@ +package resources + +type ApplicationFeature struct { + // Name of the application feature + Name string + Enabled bool + //Reason string `json:omitempty` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/application_resource.go b/vendor/code.cloudfoundry.org/cli/resources/application_resource.go new file mode 100644 index 0000000..b663ce8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/application_resource.go @@ -0,0 +1,138 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "encoding/json" +) + +// Application represents a Cloud Controller V3 Application. +type Application struct { + // GUID is the unique application identifier. + GUID string + // StackName is the name of the stack on which the application runs. + StackName string + // LifecycleBuildpacks is a list of the names of buildpacks. + LifecycleBuildpacks []string + // LifecycleType is the type of the lifecycle. + LifecycleType constant.AppLifecycleType + // Metadata is used for custom tagging of API resources + Metadata *Metadata + // Name is the name given to the application. + Name string + // SpaceGUID is the unique identifier of the parent space. + SpaceGUID string + // State is the desired state of the application. + State constant.ApplicationState +} + +// MarshalJSON converts an Application into a Cloud Controller Application. +func (a Application) MarshalJSON() ([]byte, error) { + ccApp := ccApplication{ + Name: a.Name, + Metadata: a.Metadata, + } + + if a.SpaceGUID != "" { + ccApp.Relationships = Relationships{ + constant.RelationshipTypeSpace: Relationship{GUID: a.SpaceGUID}, + } + } + + if a.LifecycleType == constant.AppLifecycleTypeDocker { + ccApp.setDockerLifecycle() + } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack { + if len(a.LifecycleBuildpacks) > 0 || a.StackName != "" { + if a.hasAutodetectedBuildpack() { + ccApp.setAutodetectedBuildpackLifecycle(a) + } else { + ccApp.setBuildpackLifecycle(a) + } + } + } + + return json.Marshal(ccApp) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Application response. +func (a *Application) UnmarshalJSON(data []byte) error { + lifecycle := ccLifecycle{} + ccApp := ccApplication{ + Lifecycle: &lifecycle, + } + + err := cloudcontroller.DecodeJSON(data, &ccApp) + if err != nil { + return err + } + + a.GUID = ccApp.GUID + a.StackName = lifecycle.Data.Stack + a.LifecycleBuildpacks = lifecycle.Data.Buildpacks + a.LifecycleType = lifecycle.Type + a.Name = ccApp.Name + a.SpaceGUID = ccApp.Relationships[constant.RelationshipTypeSpace].GUID + a.State = ccApp.State + a.Metadata = ccApp.Metadata + + return nil +} + +func (a Application) Started() bool { + return a.State == constant.ApplicationStarted +} + +func (a Application) Stopped() bool { + return a.State == constant.ApplicationStopped +} + +func (a Application) hasAutodetectedBuildpack() bool { + if len(a.LifecycleBuildpacks) == 0 { + return false + } + return a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueDefault || a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueNull +} + +type ccLifecycle struct { + Type constant.AppLifecycleType `json:"type,omitempty"` + Data struct { + Buildpacks []string `json:"buildpacks,omitempty"` + Stack string `json:"stack,omitempty"` + } `json:"data"` +} + +type ccApplication struct { + Name string `json:"name,omitempty"` + Relationships Relationships `json:"relationships,omitempty"` + Lifecycle interface{} `json:"lifecycle,omitempty"` + GUID string `json:"guid,omitempty"` + State constant.ApplicationState `json:"state,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (ccApp *ccApplication) setAutodetectedBuildpackLifecycle(a Application) { + var nullBuildpackLifecycle struct { + Type constant.AppLifecycleType `json:"type,omitempty"` + Data struct { + Buildpacks []string `json:"buildpacks"` + Stack string `json:"stack,omitempty"` + } `json:"data"` + } + nullBuildpackLifecycle.Type = constant.AppLifecycleTypeBuildpack + nullBuildpackLifecycle.Data.Stack = a.StackName + ccApp.Lifecycle = nullBuildpackLifecycle +} + +func (ccApp *ccApplication) setBuildpackLifecycle(a Application) { + var lifecycle ccLifecycle + lifecycle.Type = a.LifecycleType + lifecycle.Data.Buildpacks = a.LifecycleBuildpacks + lifecycle.Data.Stack = a.StackName + ccApp.Lifecycle = lifecycle +} + +func (ccApp *ccApplication) setDockerLifecycle() { + ccApp.Lifecycle = ccLifecycle{ + Type: constant.AppLifecycleTypeDocker, + } +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/build_resource.go b/vendor/code.cloudfoundry.org/cli/resources/build_resource.go new file mode 100644 index 0000000..e190de9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/build_resource.go @@ -0,0 +1,69 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Build represent the process of staging an application package. +type Build struct { + // CreatedAt is the time with zone when the build was created. + CreatedAt string + // DropletGUID is the unique identifier for the resulting droplet from the + // staging process. + DropletGUID string + // Error describes errors during the build process. + Error string + // GUID is the unique build identifier. + GUID string + // PackageGUID is the unique identifier for package that is the input to the + // staging process. + PackageGUID string + // State is the state of the build. + State constant.BuildState +} + +// MarshalJSON converts a Build into a Cloud Controller Application. +func (b Build) MarshalJSON() ([]byte, error) { + var ccBuild struct { + Package struct { + GUID string `json:"guid"` + } `json:"package"` + } + + ccBuild.Package.GUID = b.PackageGUID + + return json.Marshal(ccBuild) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Build response. +func (b *Build) UnmarshalJSON(data []byte) error { + var ccBuild struct { + CreatedAt string `json:"created_at,omitempty"` + GUID string `json:"guid,omitempty"` + Error string `json:"error"` + Package struct { + GUID string `json:"guid"` + } `json:"package"` + State constant.BuildState `json:"state,omitempty"` + Droplet struct { + GUID string `json:"guid"` + } `json:"droplet"` + } + + err := cloudcontroller.DecodeJSON(data, &ccBuild) + if err != nil { + return err + } + + b.GUID = ccBuild.GUID + b.CreatedAt = ccBuild.CreatedAt + b.Error = ccBuild.Error + b.PackageGUID = ccBuild.Package.GUID + b.State = ccBuild.State + b.DropletGUID = ccBuild.Droplet.GUID + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/buildpack_resource.go b/vendor/code.cloudfoundry.org/cli/resources/buildpack_resource.go new file mode 100644 index 0000000..04d29e2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/buildpack_resource.go @@ -0,0 +1,94 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/types" +) + +// Buildpack represents a Cloud Controller V3 buildpack. +type Buildpack struct { + // Enabled is true when the buildpack can be used for staging. + Enabled types.NullBool + // Filename is the uploaded filename of the buildpack. + Filename string + // GUID is the unique identifier for the buildpack. + GUID string + // Locked is true when the buildpack cannot be updated. + Locked types.NullBool + // Name is the name of the buildpack. To be used by app buildpack field. + // (only alphanumeric characters) + Name string + // Position is the order in which the buildpacks are checked during buildpack + // auto-detection. + Position types.NullInt + // Stack is the name of the stack that the buildpack will use. + Stack string + // State is the current state of the buildpack. + State string + // Links are links to related resources. + Links APILinks + // Metadata is used for custom tagging of API resources + Metadata *Metadata +} + +// MarshalJSON converts a Package into a Cloud Controller Package. +func (buildpack Buildpack) MarshalJSON() ([]byte, error) { + ccBuildpack := struct { + Name string `json:"name,omitempty"` + Stack string `json:"stack,omitempty"` + Position *int `json:"position,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Locked *bool `json:"locked,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` + }{ + Name: buildpack.Name, + Stack: buildpack.Stack, + } + + if buildpack.Position.IsSet { + ccBuildpack.Position = &buildpack.Position.Value + } + if buildpack.Enabled.IsSet { + ccBuildpack.Enabled = &buildpack.Enabled.Value + } + if buildpack.Locked.IsSet { + ccBuildpack.Locked = &buildpack.Locked.Value + } + + return json.Marshal(ccBuildpack) +} + +func (buildpack *Buildpack) UnmarshalJSON(data []byte) error { + var ccBuildpack struct { + GUID string `json:"guid,omitempty"` + Links APILinks `json:"links,omitempty"` + Name string `json:"name,omitempty"` + Filename string `json:"filename,omitempty"` + Stack string `json:"stack,omitempty"` + State string `json:"state,omitempty"` + Enabled types.NullBool `json:"enabled"` + Locked types.NullBool `json:"locked"` + Position types.NullInt `json:"position"` + Metadata *Metadata `json:"metadata"` + } + + err := cloudcontroller.DecodeJSON(data, &ccBuildpack) + if err != nil { + return err + } + + buildpack.Enabled = ccBuildpack.Enabled + buildpack.Filename = ccBuildpack.Filename + buildpack.GUID = ccBuildpack.GUID + buildpack.Locked = ccBuildpack.Locked + buildpack.Name = ccBuildpack.Name + buildpack.Position = ccBuildpack.Position + buildpack.Stack = ccBuildpack.Stack + buildpack.State = ccBuildpack.State + buildpack.Links = ccBuildpack.Links + buildpack.Metadata = ccBuildpack.Metadata + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/deployment_resource.go b/vendor/code.cloudfoundry.org/cli/resources/deployment_resource.go new file mode 100644 index 0000000..144ac07 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/deployment_resource.go @@ -0,0 +1,80 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +type Deployment struct { + GUID string + State constant.DeploymentState + StatusValue constant.DeploymentStatusValue + StatusReason constant.DeploymentStatusReason + RevisionGUID string + DropletGUID string + CreatedAt string + UpdatedAt string + Relationships Relationships + NewProcesses []Process +} + +// MarshalJSON converts a Deployment into a Cloud Controller Deployment. +func (d Deployment) MarshalJSON() ([]byte, error) { + type Revision struct { + GUID string `json:"guid,omitempty"` + } + type Droplet struct { + GUID string `json:"guid,omitempty"` + } + + var ccDeployment struct { + Droplet *Droplet `json:"droplet,omitempty"` + Revision *Revision `json:"revision,omitempty"` + Relationships Relationships `json:"relationships,omitempty"` + } + + if d.DropletGUID != "" { + ccDeployment.Droplet = &Droplet{d.DropletGUID} + } + + if d.RevisionGUID != "" { + ccDeployment.Revision = &Revision{d.RevisionGUID} + } + + ccDeployment.Relationships = d.Relationships + + return json.Marshal(ccDeployment) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Deployment response. +func (d *Deployment) UnmarshalJSON(data []byte) error { + var ccDeployment struct { + GUID string `json:"guid,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Relationships Relationships `json:"relationships,omitempty"` + State constant.DeploymentState `json:"state,omitempty"` + Status struct { + Value constant.DeploymentStatusValue `json:"value"` + Reason constant.DeploymentStatusReason `json:"reason"` + } `json:"status"` + Droplet Droplet `json:"droplet,omitempty"` + NewProcesses []Process `json:"new_processes,omitempty"` + } + err := cloudcontroller.DecodeJSON(data, &ccDeployment) + if err != nil { + return err + } + + d.GUID = ccDeployment.GUID + d.CreatedAt = ccDeployment.CreatedAt + d.Relationships = ccDeployment.Relationships + d.State = ccDeployment.State + d.StatusValue = ccDeployment.Status.Value + d.StatusReason = ccDeployment.Status.Reason + d.DropletGUID = ccDeployment.Droplet.GUID + d.NewProcesses = ccDeployment.NewProcesses + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/domain_resource.go b/vendor/code.cloudfoundry.org/cli/resources/domain_resource.go new file mode 100644 index 0000000..35dda7d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/domain_resource.go @@ -0,0 +1,69 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/jsonry" +) + +type Domain struct { + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + Internal types.NullBool `json:"internal,omitempty"` + OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` + RouterGroup string `jsonry:"router_group.guid,omitempty"` + Protocols []string `jsonry:"supported_protocols,omitempty"` + + // Metadata is used for custom tagging of API resources + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (d Domain) MarshalJSON() ([]byte, error) { + type domainWithBoolPointer struct { + GUID string `jsonry:"guid,omitempty"` + Name string `jsonry:"name"` + Internal *bool `jsonry:"internal,omitempty"` + OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` + RouterGroup string `jsonry:"router_group.guid,omitempty"` + Protocols []string `jsonry:"supported_protocols,omitempty"` + } + + clone := domainWithBoolPointer{ + GUID: d.GUID, + Name: d.Name, + OrganizationGUID: d.OrganizationGUID, + RouterGroup: d.RouterGroup, + Protocols: d.Protocols, + } + + if d.Internal.IsSet { + clone.Internal = &d.Internal.Value + } + return jsonry.Marshal(clone) +} + +func (d *Domain) UnmarshalJSON(data []byte) error { + type alias Domain + var defaultUnmarshalledDomain alias + err := jsonry.Unmarshal(data, &defaultUnmarshalledDomain) + if err != nil { + return err + } + + *d = Domain(defaultUnmarshalledDomain) + + return nil +} + +func (d Domain) Shared() bool { + return d.OrganizationGUID == "" +} + +func (d *Domain) IsTCP() bool { + for _, p := range d.Protocols { + if p == "tcp" { + return true + } + } + + return false +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/droplet_resource.go b/vendor/code.cloudfoundry.org/cli/resources/droplet_resource.go new file mode 100644 index 0000000..515bfc6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/droplet_resource.go @@ -0,0 +1,37 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Droplet represents a Cloud Controller droplet's metadata. A droplet is a set of +// compiled bits for a given application. +type Droplet struct { + //Buildpacks are the detected buildpacks from the staging process. + Buildpacks []DropletBuildpack `json:"buildpacks,omitempty"` + // CreatedAt is the timestamp that the Cloud Controller created the droplet. + CreatedAt string `json:"created_at"` + // GUID is the unique droplet identifier. + GUID string `json:"guid"` + // Image is the Docker image name. + Image string `json:"image"` + // Stack is the root filesystem to use with the buildpack. + Stack string `json:"stack,omitempty"` + // State is the current state of the droplet. + State constant.DropletState `json:"state"` + // IsCurrent does not exist on the API layer, only on the actor layer; we ignore it w.r.t. JSON + IsCurrent bool `json:"-"` +} + +// DropletBuildpack is the name and output of a buildpack used to create a +// droplet. +type DropletBuildpack struct { + // Name is the buildpack name. + Name string `json:"name"` + // BuildpackName is the the name reported by the buildpack. + BuildpackName string `json:"buildpack_name"` + // DetectOutput is the output of the buildpack detect script. + DetectOutput string `json:"detect_output"` + // Version is the version of the detected buildpack. + Version string `json:"version"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/environment_variables_resource.go b/vendor/code.cloudfoundry.org/cli/resources/environment_variables_resource.go new file mode 100644 index 0000000..357641d --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/environment_variables_resource.go @@ -0,0 +1,47 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/types" +) + +type EnvironmentVariables map[string]types.FilteredString + +func (variables EnvironmentVariables) MarshalJSON() ([]byte, error) { + ccEnvVars := struct { + Var map[string]types.FilteredString `json:"var"` + }{ + Var: variables, + } + + return json.Marshal(ccEnvVars) +} + +func (variables *EnvironmentVariables) UnmarshalJSON(data []byte) error { + var ccEnvVars struct { + Var map[string]types.FilteredInterface `json:"var"` + } + + err := cloudcontroller.DecodeJSON(data, &ccEnvVars) + + *variables = EnvironmentVariables{} + + for envVarName, envVarValue := range ccEnvVars.Var { + var valueAsString string + if str, ok := envVarValue.Value.(string); ok { + valueAsString = str + } else { + bytes, err := json.Marshal(envVarValue.Value) + if err != nil { + return err + } + valueAsString = string(bytes) + } + + (*variables)[envVarName] = types.FilteredString{Value: valueAsString, IsSet: true} + } + + return err +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/feature_flag_resource.go b/vendor/code.cloudfoundry.org/cli/resources/feature_flag_resource.go new file mode 100644 index 0000000..f6d24c5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/feature_flag_resource.go @@ -0,0 +1,18 @@ +package resources + +import "encoding/json" + +type FeatureFlag struct { + Name string `json:"name"` + Enabled bool `json:"enabled"` +} + +func (f FeatureFlag) MarshalJSON() ([]byte, error) { + var bodyFlag struct { + Enabled bool `json:"enabled"` + } + + bodyFlag.Enabled = f.Enabled + + return json.Marshal(bodyFlag) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/isolation_segment_resource.go b/vendor/code.cloudfoundry.org/cli/resources/isolation_segment_resource.go new file mode 100644 index 0000000..4ad2827 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/isolation_segment_resource.go @@ -0,0 +1,9 @@ +package resources + +// IsolationSegment represents a Cloud Controller Isolation Segment. +type IsolationSegment struct { + //GUID is the unique ID of the isolation segment. + GUID string `json:"guid,omitempty"` + //Name is the name of the isolation segment. + Name string `json:"name"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/last_operation_resource.go b/vendor/code.cloudfoundry.org/cli/resources/last_operation_resource.go new file mode 100644 index 0000000..03b24dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/last_operation_resource.go @@ -0,0 +1,34 @@ +package resources + +type LastOperationType string + +const ( + CreateOperation LastOperationType = "create" + UpdateOperation LastOperationType = "update" + DeleteOperation LastOperationType = "delete" +) + +type LastOperationState string + +const ( + OperationInProgress LastOperationState = "in progress" + OperationSucceeded LastOperationState = "succeeded" + OperationFailed LastOperationState = "failed" +) + +type LastOperation struct { + // Type is either "create", "update" or "delete" + Type LastOperationType `json:"type,omitempty"` + // State is either "in progress", "succeeded", or "failed" + State LastOperationState `json:"state,omitempty"` + // Description contains more details + Description string `json:"description,omitempty"` + // CreatedAt is the time when the operation started + CreatedAt string `json:"created_at,omitempty"` + // UpdatedAt is the time when the operation was last updated + UpdatedAt string `json:"updated_at,omitempty"` +} + +func (l LastOperation) OmitJSONry() bool { + return l == LastOperation{} +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/manifest_diff_resource.go b/vendor/code.cloudfoundry.org/cli/resources/manifest_diff_resource.go new file mode 100644 index 0000000..fff5376 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/manifest_diff_resource.go @@ -0,0 +1,18 @@ +package resources + +type DiffOperation string + +const AddOperation DiffOperation = "add" +const ReplaceOperation DiffOperation = "replace" +const RemoveOperation DiffOperation = "remove" + +type Diff struct { + Op DiffOperation `json:"op"` + Path string `json:"path"` + Was interface{} `json:"was"` + Value interface{} `json:"value"` +} + +type ManifestDiff struct { + Diffs []Diff `json:"diff"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/metadata_resource.go b/vendor/code.cloudfoundry.org/cli/resources/metadata_resource.go new file mode 100644 index 0000000..414fe14 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/metadata_resource.go @@ -0,0 +1,11 @@ +package resources + +import "code.cloudfoundry.org/cli/types" + +type Metadata struct { + Labels map[string]types.NullString `json:"labels,omitempty"` +} + +type ResourceMetadata struct { + Metadata *Metadata `json:"metadata,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/organization_quota_resource.go b/vendor/code.cloudfoundry.org/cli/resources/organization_quota_resource.go new file mode 100644 index 0000000..0f146c8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/organization_quota_resource.go @@ -0,0 +1,6 @@ +package resources + +// OrganizationQuota represents a Cloud Controller organization quota. +type OrganizationQuota struct { + Quota +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/organization_resource.go b/vendor/code.cloudfoundry.org/cli/resources/organization_resource.go new file mode 100644 index 0000000..187bb1b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/organization_resource.go @@ -0,0 +1,48 @@ +package resources + +import ( + "encoding/json" +) + +// Organization represents a Cloud Controller V3 Organization. +type Organization struct { + // GUID is the unique organization identifier. + GUID string `json:"guid,omitempty"` + // Name is the name of the organization. + Name string `json:"name"` + // QuotaGUID is the GUID of the organization Quota applied to this Organization + QuotaGUID string `json:"-"` + + // Metadata is used for custom tagging of API resources + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (org *Organization) UnmarshalJSON(data []byte) error { + type alias Organization + var aliasOrg alias + err := json.Unmarshal(data, &aliasOrg) + if err != nil { + return err + } + + *org = Organization(aliasOrg) + + remainingFields := new(struct { + Relationships struct { + Quota struct { + Data struct { + GUID string + } + } + } + }) + + err = json.Unmarshal(data, &remainingFields) + if err != nil { + return err + } + + org.QuotaGUID = remainingFields.Relationships.Quota.Data.GUID + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/package_resource.go b/vendor/code.cloudfoundry.org/cli/resources/package_resource.go new file mode 100644 index 0000000..c17e66a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/package_resource.go @@ -0,0 +1,105 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Package represents a Cloud Controller V3 Package. +type Package struct { + // CreatedAt is the time with zone when the object was created. + CreatedAt string + + // DockerImage is the registry address of the docker image. + DockerImage string + + // DockerPassword is the password for the docker image's registry. + DockerPassword string + + // DockerUsername is the username for the docker image's registry. + DockerUsername string + + // GUID is the unique identifier of the package. + GUID string + + // Links are links to related resources. + Links APILinks + + // Relationships are a list of relationships to other resources. + Relationships Relationships + + // State is the state of the package. + State constant.PackageState + + // Type is the package type. + Type constant.PackageType +} + +// MarshalJSON converts a Package into a Cloud Controller Package. +func (p Package) MarshalJSON() ([]byte, error) { + type ccPackageData struct { + Image string `json:"image,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + } + var ccPackage struct { + GUID string `json:"guid,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Links APILinks `json:"links,omitempty"` + Relationships Relationships `json:"relationships,omitempty"` + State constant.PackageState `json:"state,omitempty"` + Type constant.PackageType `json:"type,omitempty"` + Data *ccPackageData `json:"data,omitempty"` + } + + ccPackage.GUID = p.GUID + ccPackage.CreatedAt = p.CreatedAt + ccPackage.Links = p.Links + ccPackage.Relationships = p.Relationships + ccPackage.State = p.State + ccPackage.Type = p.Type + if p.DockerImage != "" { + ccPackage.Data = &ccPackageData{ + Image: p.DockerImage, + Username: p.DockerUsername, + Password: p.DockerPassword, + } + } + + return json.Marshal(ccPackage) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Package response. +func (p *Package) UnmarshalJSON(data []byte) error { + var ccPackage struct { + GUID string `json:"guid,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Links APILinks `json:"links,omitempty"` + Relationships Relationships `json:"relationships,omitempty"` + State constant.PackageState `json:"state,omitempty"` + Type constant.PackageType `json:"type,omitempty"` + Data struct { + Image string `json:"image"` + Username string `json:"username"` + Password string `json:"password"` + } `json:"data"` + } + err := cloudcontroller.DecodeJSON(data, &ccPackage) + if err != nil { + return err + } + + p.GUID = ccPackage.GUID + p.CreatedAt = ccPackage.CreatedAt + p.Links = ccPackage.Links + p.Relationships = ccPackage.Relationships + p.State = ccPackage.State + p.Type = ccPackage.Type + p.DockerImage = ccPackage.Data.Image + p.DockerUsername = ccPackage.Data.Username + p.DockerPassword = ccPackage.Data.Password + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/process_resource.go b/vendor/code.cloudfoundry.org/cli/resources/process_resource.go new file mode 100644 index 0000000..5376f8e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/process_resource.go @@ -0,0 +1,131 @@ +package resources + +import ( + "encoding/json" + "fmt" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/types" +) + +type Process struct { + GUID string + Type string + // Command is the process start command. Note: This value will be obfuscated when obtained from listing. + Command types.FilteredString + HealthCheckType constant.HealthCheckType + HealthCheckEndpoint string + HealthCheckInvocationTimeout int64 + HealthCheckTimeout int64 + Instances types.NullInt + MemoryInMB types.NullUint64 + DiskInMB types.NullUint64 + AppGUID string +} + +func (p Process) MarshalJSON() ([]byte, error) { + var ccProcess marshalProcess + + marshalCommand(p, &ccProcess) + marshalInstances(p, &ccProcess) + marshalMemory(p, &ccProcess) + marshalDisk(p, &ccProcess) + marshalHealthCheck(p, &ccProcess) + + return json.Marshal(ccProcess) +} + +func (p *Process) UnmarshalJSON(data []byte) error { + var ccProcess struct { + Command types.FilteredString `json:"command"` + DiskInMB types.NullUint64 `json:"disk_in_mb"` + GUID string `json:"guid"` + Instances types.NullInt `json:"instances"` + MemoryInMB types.NullUint64 `json:"memory_in_mb"` + Type string `json:"type"` + Relationships Relationships `json:"relationships"` + + HealthCheck struct { + Type constant.HealthCheckType `json:"type"` + Data struct { + Endpoint string `json:"endpoint"` + InvocationTimeout int64 `json:"invocation_timeout"` + Timeout int64 `json:"timeout"` + } `json:"data"` + } `json:"health_check"` + } + + err := cloudcontroller.DecodeJSON(data, &ccProcess) + if err != nil { + return err + } + + p.Command = ccProcess.Command + p.DiskInMB = ccProcess.DiskInMB + p.GUID = ccProcess.GUID + p.HealthCheckEndpoint = ccProcess.HealthCheck.Data.Endpoint + p.HealthCheckInvocationTimeout = ccProcess.HealthCheck.Data.InvocationTimeout + p.HealthCheckTimeout = ccProcess.HealthCheck.Data.Timeout + p.HealthCheckType = ccProcess.HealthCheck.Type + p.Instances = ccProcess.Instances + p.MemoryInMB = ccProcess.MemoryInMB + p.Type = ccProcess.Type + p.AppGUID = ccProcess.Relationships[constant.RelationshipTypeApplication].GUID + + return nil +} + +type healthCheck struct { + Type constant.HealthCheckType `json:"type,omitempty"` + Data struct { + Endpoint interface{} `json:"endpoint,omitempty"` + InvocationTimeout int64 `json:"invocation_timeout,omitempty"` + Timeout int64 `json:"timeout,omitempty"` + } `json:"data"` +} + +type marshalProcess struct { + Command interface{} `json:"command,omitempty"` + Instances json.Number `json:"instances,omitempty"` + MemoryInMB json.Number `json:"memory_in_mb,omitempty"` + DiskInMB json.Number `json:"disk_in_mb,omitempty"` + + HealthCheck *healthCheck `json:"health_check,omitempty"` +} + +func marshalCommand(p Process, ccProcess *marshalProcess) { + if p.Command.IsSet { + ccProcess.Command = &p.Command + } +} + +func marshalDisk(p Process, ccProcess *marshalProcess) { + if p.DiskInMB.IsSet { + ccProcess.DiskInMB = json.Number(fmt.Sprint(p.DiskInMB.Value)) + } +} + +func marshalHealthCheck(p Process, ccProcess *marshalProcess) { + if p.HealthCheckType != "" || p.HealthCheckEndpoint != "" || p.HealthCheckInvocationTimeout != 0 || p.HealthCheckTimeout != 0 { + ccProcess.HealthCheck = new(healthCheck) + ccProcess.HealthCheck.Type = p.HealthCheckType + ccProcess.HealthCheck.Data.InvocationTimeout = p.HealthCheckInvocationTimeout + ccProcess.HealthCheck.Data.Timeout = p.HealthCheckTimeout + if p.HealthCheckEndpoint != "" { + ccProcess.HealthCheck.Data.Endpoint = p.HealthCheckEndpoint + } + } +} + +func marshalInstances(p Process, ccProcess *marshalProcess) { + if p.Instances.IsSet { + ccProcess.Instances = json.Number(fmt.Sprint(p.Instances.Value)) + } +} + +func marshalMemory(p Process, ccProcess *marshalProcess) { + if p.MemoryInMB.IsSet { + ccProcess.MemoryInMB = json.Number(fmt.Sprint(p.MemoryInMB.Value)) + } +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/quota_resource.go b/vendor/code.cloudfoundry.org/cli/resources/quota_resource.go new file mode 100644 index 0000000..f78ec80 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/quota_resource.go @@ -0,0 +1,120 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/types" +) + +type Quota struct { + // GUID is the unique ID of the organization quota. + GUID string `json:"guid,omitempty"` + // Name is the name of the organization quota + Name string `json:"name"` + // Apps contain the various limits that are associated with applications + Apps AppLimit `json:"apps"` + // Services contain the various limits that are associated with services + Services ServiceLimit `json:"services"` + // Routes contain the various limits that are associated with routes + Routes RouteLimit `json:"routes"` +} + +type AppLimit struct { + TotalMemory *types.NullInt `json:"total_memory_in_mb,omitempty"` + InstanceMemory *types.NullInt `json:"per_process_memory_in_mb,omitempty"` + TotalAppInstances *types.NullInt `json:"total_instances,omitempty"` +} + +func (al *AppLimit) UnmarshalJSON(rawJSON []byte) error { + type Alias AppLimit + + var aux Alias + err := json.Unmarshal(rawJSON, &aux) + if err != nil { + return err + } + + *al = AppLimit(aux) + + if al.TotalMemory == nil { + al.TotalMemory = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + if al.InstanceMemory == nil { + al.InstanceMemory = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + if al.TotalAppInstances == nil { + al.TotalAppInstances = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + return nil +} + +type ServiceLimit struct { + TotalServiceInstances *types.NullInt `json:"total_service_instances,omitempty"` + PaidServicePlans *bool `json:"paid_services_allowed,omitempty"` +} + +func (sl *ServiceLimit) UnmarshalJSON(rawJSON []byte) error { + type Alias ServiceLimit + + var aux Alias + err := json.Unmarshal(rawJSON, &aux) + if err != nil { + return err + } + + *sl = ServiceLimit(aux) + + if sl.TotalServiceInstances == nil { + sl.TotalServiceInstances = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + return nil +} + +type RouteLimit struct { + TotalRoutes *types.NullInt `json:"total_routes,omitempty"` + TotalReservedPorts *types.NullInt `json:"total_reserved_ports,omitempty"` +} + +func (sl *RouteLimit) UnmarshalJSON(rawJSON []byte) error { + type Alias RouteLimit + + var aux Alias + err := json.Unmarshal(rawJSON, &aux) + if err != nil { + return err + } + + *sl = RouteLimit(aux) + + if sl.TotalRoutes == nil { + sl.TotalRoutes = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + if sl.TotalReservedPorts == nil { + sl.TotalReservedPorts = &types.NullInt{ + IsSet: false, + Value: 0, + } + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/relationship_resource.go b/vendor/code.cloudfoundry.org/cli/resources/relationship_resource.go new file mode 100644 index 0000000..322fe2a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/relationship_resource.go @@ -0,0 +1,89 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Relationships represent associations between resources. Relationships is a +// map of RelationshipTypes to Relationship. +type Relationships map[constant.RelationshipType]Relationship + +// Relationship represents a one to one relationship. +// An empty GUID will be marshaled as `null`. +type Relationship struct { + GUID string +} + +func (r Relationship) MarshalJSON() ([]byte, error) { + if r.GUID == "" { + var emptyCCRelationship struct { + Data interface{} `json:"data"` + } + return json.Marshal(emptyCCRelationship) + } + + var ccRelationship struct { + Data struct { + GUID string `json:"guid"` + } `json:"data"` + } + + ccRelationship.Data.GUID = r.GUID + return json.Marshal(ccRelationship) +} + +func (r *Relationship) UnmarshalJSON(data []byte) error { + var ccRelationship struct { + Data struct { + GUID string `json:"guid"` + } `json:"data"` + } + + err := cloudcontroller.DecodeJSON(data, &ccRelationship) + if err != nil { + return err + } + + r.GUID = ccRelationship.Data.GUID + return nil +} + +// RelationshipList represents a one to many relationship. +type RelationshipList struct { + GUIDs []string +} + +func (r RelationshipList) MarshalJSON() ([]byte, error) { + var ccRelationship struct { + Data []map[string]string `json:"data"` + } + + for _, guid := range r.GUIDs { + ccRelationship.Data = append( + ccRelationship.Data, + map[string]string{ + "guid": guid, + }) + } + + return json.Marshal(ccRelationship) +} + +func (r *RelationshipList) UnmarshalJSON(data []byte) error { + var ccRelationships struct { + Data []map[string]string `json:"data"` + } + + err := cloudcontroller.DecodeJSON(data, &ccRelationships) + if err != nil { + return err + } + + for _, partner := range ccRelationships.Data { + r.GUIDs = append(r.GUIDs, partner["guid"]) + } + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/revision_resource.go b/vendor/code.cloudfoundry.org/cli/resources/revision_resource.go new file mode 100644 index 0000000..39d577a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/revision_resource.go @@ -0,0 +1,11 @@ +package resources + +type Revision struct { + GUID string `json:"guid"` + Version int `json:"version"` + Deployable bool `json:"deployable"` + Description string `json:"description"` + Droplet Droplet `json:"droplet"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/role_resource.go b/vendor/code.cloudfoundry.org/cli/resources/role_resource.go new file mode 100644 index 0000000..4896367 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/role_resource.go @@ -0,0 +1,109 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// IncludedUsers represent a set of users included on an API response. +type IncludedUsers map[constant.IncludedType]User + +type Role struct { + // GUID is the unique identifier for the role. + GUID string `json:"guid"` + // Type is the type of the role. + Type constant.RoleType `json:"type"` + // UserGUID is the unique identifier of the user who has this role. + UserGUID string + // Username is the name of the user who has this role, e.g. "admin", "user@example.com" + Username string + // Origin is the identity server, default "uaa". Active Directory can also be an origin + Origin string + // OrgGUID is the unique identifier of the org where this role applies, + // if it is an org role. + OrgGUID string + // SpaceGUID is the unique identifier of the space where this role applies, + // if it is a space role. + SpaceGUID string +} + +// MarshalJSON converts a Role into a Cloud Controller Application. +func (r Role) MarshalJSON() ([]byte, error) { + type data struct { + GUID string `json:"guid"` + } + + type orgOrSpaceJSON struct { + Data data `json:"data"` + } + var ccRole struct { + GUID string `json:"guid,omitempty"` + Type string `json:"type"` + Relationships struct { + Organization *orgOrSpaceJSON `json:"organization,omitempty"` + Space *orgOrSpaceJSON `json:"space,omitempty"` + User struct { + Data struct { + GUID string `json:"guid,omitempty"` + Username string `json:"username,omitempty"` + Origin string `json:"origin,omitempty"` + } `json:"data"` + } `json:"user"` + } `json:"relationships"` + } + + ccRole.GUID = r.GUID + ccRole.Type = string(r.Type) + if r.OrgGUID != "" { + ccRole.Relationships.Organization = &orgOrSpaceJSON{ + Data: data{GUID: r.OrgGUID}, + } + } + if r.SpaceGUID != "" { + ccRole.Relationships.Space = &orgOrSpaceJSON{ + Data: data{GUID: r.SpaceGUID}, + } + } + if r.Username != "" { + ccRole.Relationships.User.Data.Username = r.Username + ccRole.Relationships.User.Data.Origin = r.Origin + } else { + ccRole.Relationships.User.Data.GUID = r.UserGUID + } + + return json.Marshal(ccRole) +} + +// UnmarshalJSON helps unmarshal a Cloud Controller Role response. +func (r *Role) UnmarshalJSON(data []byte) error { + var ccRole struct { + GUID string `json:"guid"` + Type string `json:"type"` + Relationships Relationships + IncludedUsers IncludedUsers + } + + err := cloudcontroller.DecodeJSON(data, &ccRole) + if err != nil { + return err + } + + r.GUID = ccRole.GUID + r.Type = constant.RoleType(ccRole.Type) + if userRelationship, ok := ccRole.Relationships[constant.RelationshipTypeUser]; ok { + r.UserGUID = userRelationship.GUID + } + if spaceRelationship, ok := ccRole.Relationships[constant.RelationshipTypeSpace]; ok { + r.SpaceGUID = spaceRelationship.GUID + } + if orgRelationship, ok := ccRole.Relationships[constant.RelationshipTypeOrganization]; ok { + r.OrgGUID = orgRelationship.GUID + } + + if includedUsers, ok := ccRole.IncludedUsers[constant.IncludedTypeUsers]; ok { + r.Username = includedUsers.Username + } + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/route_binding.go b/vendor/code.cloudfoundry.org/cli/resources/route_binding.go new file mode 100644 index 0000000..cb71b99 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/route_binding.go @@ -0,0 +1,23 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/jsonry" +) + +type RouteBinding struct { + GUID string `jsonry:"guid,omitempty"` + RouteServiceURL string `jsonry:"route_service_url,omitempty"` + ServiceInstanceGUID string `jsonry:"relationships.service_instance.data.guid,omitempty"` + RouteGUID string `jsonry:"relationships.route.data.guid,omitempty"` + LastOperation LastOperation `jsonry:"last_operation"` + Parameters types.OptionalObject `jsonry:"parameters"` +} + +func (s RouteBinding) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(s) +} + +func (s *RouteBinding) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/route_resource.go b/vendor/code.cloudfoundry.org/cli/resources/route_resource.go new file mode 100644 index 0000000..5bf31b4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/route_resource.go @@ -0,0 +1,120 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/cli/api/cloudcontroller" +) + +type RouteDestinationApp struct { + GUID string + Process struct { + Type string + } +} + +type RouteDestination struct { + GUID string + App RouteDestinationApp + Port int + Protocol string +} + +type Route struct { + GUID string + SpaceGUID string + DomainGUID string + Host string + Path string + Protocol string + Port int + URL string + Destinations []RouteDestination + Metadata *Metadata +} + +func (r Route) MarshalJSON() ([]byte, error) { + type Data struct { + GUID string `json:"guid,omitempty"` + } + + type RelationshipData struct { + Data Data `json:"data,omitempty"` + } + + type Relationships struct { + Space RelationshipData `json:"space,omitempty"` + Domain RelationshipData `json:"domain,omitempty"` + } + + // Building up the request body in ccRoute + type ccRoute struct { + GUID string `json:"guid,omitempty"` + Host string `json:"host,omitempty"` + Path string `json:"path,omitempty"` + Protocol string `json:"protocol,omitempty"` + Port int `json:"port,omitempty"` + Relationships *Relationships `json:"relationships,omitempty"` + } + + ccR := ccRoute{ + GUID: r.GUID, + Host: r.Host, + Path: r.Path, + Protocol: r.Protocol, + Port: r.Port, + } + + if r.SpaceGUID != "" { + ccR.Relationships = &Relationships{ + Space: RelationshipData{Data{GUID: r.SpaceGUID}}, + Domain: RelationshipData{Data{GUID: r.DomainGUID}}, + } + } + + return json.Marshal(ccR) +} + +func (r *Route) UnmarshalJSON(data []byte) error { + var alias struct { + GUID string `json:"guid,omitempty"` + Protocol string `json:"protocol,omitempty"` + Host string `json:"host,omitempty"` + Path string `json:"path,omitempty"` + Port int `json:"port,omitempty"` + URL string `json:"url,omitempty"` + Destinations []RouteDestination `json:"destinations,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` + + Relationships struct { + Space struct { + Data struct { + GUID string `json:"guid,omitempty"` + } `json:"data,omitempty"` + } `json:"space,omitempty"` + Domain struct { + Data struct { + GUID string `json:"guid,omitempty"` + } `json:"data,omitempty"` + } `json:"domain,omitempty"` + } `json:"relationships,omitempty"` + } + + err := cloudcontroller.DecodeJSON(data, &alias) + if err != nil { + return err + } + + r.GUID = alias.GUID + r.Protocol = alias.Protocol + r.Host = alias.Host + r.SpaceGUID = alias.Relationships.Space.Data.GUID + r.DomainGUID = alias.Relationships.Domain.Data.GUID + r.Path = alias.Path + r.Port = alias.Port + r.URL = alias.URL + r.Destinations = alias.Destinations + r.Metadata = alias.Metadata + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/security_group_resource.go b/vendor/code.cloudfoundry.org/cli/resources/security_group_resource.go new file mode 100644 index 0000000..df1f4b3 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/security_group_resource.go @@ -0,0 +1,80 @@ +package resources + +import ( + "encoding/json" + + "code.cloudfoundry.org/jsonry" +) + +type SecurityGroup struct { + Name string `jsonry:"name,omitempty"` + GUID string `jsonry:"guid,omitempty"` + Rules []Rule `jsonry:"rules,omitempty"` + StagingGloballyEnabled *bool `jsonry:"globally_enabled.staging,omitempty"` + RunningGloballyEnabled *bool `jsonry:"globally_enabled.running,omitempty"` + StagingSpaceGUIDs []string `jsonry:"relationships.staging_spaces.data[].guid,omitempty"` + RunningSpaceGUIDs []string `jsonry:"relationships.running_spaces.data[].guid,omitempty"` +} + +func (sg SecurityGroup) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(sg) +} + +func (sg *SecurityGroup) UnmarshalJSON(data []byte) error { + type alias SecurityGroup + var defaultUnmarshalledSecurityGroup alias + err := json.Unmarshal(data, &defaultUnmarshalledSecurityGroup) + if err != nil { + return err + } + + *sg = SecurityGroup(defaultUnmarshalledSecurityGroup) + + type RemainingFieldsStruct struct { + GloballyEnabled struct { + Staging *bool + Running *bool + } `json:"globally_enabled"` + Relationships struct { + StagingSpaces struct { + Data []struct { + Guid string + } + } `json:"staging_spaces"` + RunningSpaces struct { + Data []struct { + Guid string + } + } `json:"running_spaces"` + } + } + + var remainingFields RemainingFieldsStruct + err = json.Unmarshal(data, &remainingFields) + if err != nil { + return err + } + + for _, stagingSpace := range remainingFields.Relationships.StagingSpaces.Data { + sg.StagingSpaceGUIDs = append(sg.StagingSpaceGUIDs, stagingSpace.Guid) + } + + for _, runningSpace := range remainingFields.Relationships.RunningSpaces.Data { + sg.RunningSpaceGUIDs = append(sg.RunningSpaceGUIDs, runningSpace.Guid) + } + + sg.StagingGloballyEnabled = remainingFields.GloballyEnabled.Staging + sg.RunningGloballyEnabled = remainingFields.GloballyEnabled.Running + + return nil +} + +type Rule struct { + Protocol string `json:"protocol"` + Destination string `json:"destination"` + Ports *string `json:"ports,omitempty"` + Type *int `json:"type,omitempty"` + Code *int `json:"code,omitempty"` + Description *string `json:"description,omitempty"` + Log *bool `json:"log,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_broker_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_broker_resource.go new file mode 100644 index 0000000..c8789f2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_broker_resource.go @@ -0,0 +1,38 @@ +package resources + +import ( + "code.cloudfoundry.org/jsonry" +) + +type ServiceBrokerCredentialsType string + +const ( + ServiceBrokerBasicCredentials ServiceBrokerCredentialsType = "basic" +) + +type ServiceBroker struct { + // GUID is a unique service broker identifier. + GUID string `json:"guid,omitempty"` + // Name is the name of the service broker. + Name string `json:"name,omitempty"` + // URL is the url of the service broker. + URL string `json:"url,omitempty"` + // CredentialsType is always "basic" + CredentialsType ServiceBrokerCredentialsType `jsonry:"authentication.type,omitempty"` + // Username is the Basic Auth username for the service broker. + Username string `jsonry:"authentication.credentials.username,omitempty"` + // Password is the Basic Auth password for the service broker. + Password string `jsonry:"authentication.credentials.password,omitempty"` + // Space GUID for the space that the broker is in. Empty when not a space-scoped service broker. + SpaceGUID string `jsonry:"relationships.space.data.guid,omitempty"` + + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (s ServiceBroker) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(s) +} + +func (s *ServiceBroker) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_details_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_details_resource.go new file mode 100644 index 0000000..8b5eb3b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_details_resource.go @@ -0,0 +1,5 @@ +package resources + +type ServiceCredentialBindingDetails struct { + Credentials map[string]interface{} `json:"credentials"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_resource.go new file mode 100644 index 0000000..0cd9bb9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_credential_binding_resource.go @@ -0,0 +1,42 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/jsonry" +) + +type ServiceCredentialBindingType string + +const ( + AppBinding ServiceCredentialBindingType = "app" + KeyBinding ServiceCredentialBindingType = "key" +) + +type ServiceCredentialBinding struct { + // Type is either "app" or "key" + Type ServiceCredentialBindingType `jsonry:"type,omitempty"` + // GUID is a unique service credential binding identifier. + GUID string `jsonry:"guid,omitempty"` + // Name is the name of the service credential binding. + Name string `jsonry:"name,omitempty"` + // ServiceInstanceGUID is the service instance that this binding originates from + ServiceInstanceGUID string `jsonry:"relationships.service_instance.data.guid,omitempty"` + // AppGUID is the application that this binding is attached to + AppGUID string `jsonry:"relationships.app.data.guid,omitempty"` + // AppName is the application name. It is not part of the API response, and is here as pragmatic convenience. + AppName string `jsonry:"-"` + // AppSpaceGUID is the space guid of the app. It is not part of the API response, and is here as pragmatic convenience. + AppSpaceGUID string `jsonry:"-"` + // LastOperation is the last operation on the service credential binding + LastOperation LastOperation `jsonry:"last_operation"` + // Parameters can be specified when creating a binding + Parameters types.OptionalObject `jsonry:"parameters"` +} + +func (s ServiceCredentialBinding) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(s) +} + +func (s *ServiceCredentialBinding) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_instance_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_instance_resource.go new file mode 100644 index 0000000..3259c3e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_instance_resource.go @@ -0,0 +1,54 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/jsonry" +) + +type ServiceInstanceType string + +const ( + UserProvidedServiceInstance ServiceInstanceType = "user-provided" + ManagedServiceInstance ServiceInstanceType = "managed" +) + +type ServiceInstance struct { + // Type is either "user-provided" or "managed" + Type ServiceInstanceType `jsonry:"type,omitempty"` + // GUID is a unique service instance identifier. + GUID string `jsonry:"guid,omitempty"` + // Name is the name of the service instance. + Name string `jsonry:"name,omitempty"` + // SpaceGUID is the space that this service instance relates to + SpaceGUID string `jsonry:"relationships.space.data.guid,omitempty"` + // ServicePlanGUID is the service plan that this service instance relates to + ServicePlanGUID string `jsonry:"relationships.service_plan.data.guid,omitempty"` + // Tags are used by apps to identify service instances. + Tags types.OptionalStringSlice `jsonry:"tags"` + // SyslogDrainURL is where logs are streamed + SyslogDrainURL types.OptionalString `jsonry:"syslog_drain_url"` + // RouteServiceURL is where requests for bound routes will be forwarded + RouteServiceURL types.OptionalString `jsonry:"route_service_url"` + // DashboardURL is where the service can be monitored + DashboardURL types.OptionalString `jsonry:"dashboard_url"` + // Credentials are passed to the app + Credentials types.OptionalObject `jsonry:"credentials"` + // UpgradeAvailable says whether the plan is at a higher version + UpgradeAvailable types.OptionalBoolean `json:"upgrade_available"` + // MaintenanceInfoVersion is the version this service is at + MaintenanceInfoVersion string `jsonry:"maintenance_info.version,omitempty"` + // Parameters are passed to the service broker + Parameters types.OptionalObject `jsonry:"parameters"` + // LastOperation is the last operation on the service instance + LastOperation LastOperation `jsonry:"last_operation"` + + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (s ServiceInstance) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(s) +} + +func (s *ServiceInstance) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_instance_usage_summary_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_instance_usage_summary_resource.go new file mode 100644 index 0000000..45be72e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_instance_usage_summary_resource.go @@ -0,0 +1,22 @@ +package resources + +import ( + "code.cloudfoundry.org/jsonry" +) + +type ServiceInstanceUsageSummaryList struct { + UsageSummary []ServiceInstanceUsageSummary `jsonry:"usage_summary"` +} + +func (s *ServiceInstanceUsageSummaryList) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} + +type ServiceInstanceUsageSummary struct { + SpaceGUID string `jsonry:"space.guid""` + BoundAppCount int `jsonry:"bound_app_count"` +} + +func (s *ServiceInstanceUsageSummary) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_offering_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_offering_resource.go new file mode 100644 index 0000000..dbdc8da --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_offering_resource.go @@ -0,0 +1,31 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/types" + "code.cloudfoundry.org/jsonry" +) + +type ServiceOffering struct { + // GUID is a unique service offering identifier. + GUID string `json:"guid"` + // Name is the name of the service offering. + Name string `json:"name"` + // Description of the service offering + Description string `json:"description"` + // DocumentationURL of the service offering + DocumentationURL string `json:"documentation_url"` + // Tags are used by apps to identify service instances. + Tags types.OptionalStringSlice `jsonry:"tags"` + // ServiceBrokerGUID is the guid of the service broker + ServiceBrokerGUID string `jsonry:"relationships.service_broker.data.guid"` + // ServiceBrokerName is the name of the service broker + ServiceBrokerName string `json:"-"` + // Shareable if the offering support service instance sharing + AllowsInstanceSharing bool `json:"shareable"` + + Metadata *Metadata `json:"metadata"` +} + +func (s *ServiceOffering) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_plan_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_plan_resource.go new file mode 100644 index 0000000..2c708aa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_plan_resource.go @@ -0,0 +1,40 @@ +package resources + +import "code.cloudfoundry.org/jsonry" + +type ServicePlanCost struct { + Amount float64 `json:"amount"` + Currency string `json:"currency"` + Unit string `json:"unit"` +} + +type ServicePlan struct { + // GUID is a unique service plan identifier. + GUID string `json:"guid"` + // Name is the name of the service plan. + Name string `json:"name"` + // Description of the Service Plan. + Description string `json:"description"` + // Whether the Service Plan is available + Available bool `json:"available"` + // VisibilityType can be "public", "admin", "organization" or "space" + VisibilityType ServicePlanVisibilityType `json:"visibility_type"` + // Free shows whether or not the Service Plan is free of charge. + Free bool `json:"free"` + // Cost shows the cost of a paid service plan + Costs []ServicePlanCost `json:"costs"` + // ServicePlanGUID is the GUID of the service offering + ServiceOfferingGUID string `jsonry:"relationships.service_offering.data.guid"` + // SpaceGUID is the space that a plan from a space-scoped broker relates to + SpaceGUID string `jsonry:"relationships.space.data.guid"` + // MaintenanceInfoDescription is the description of the associated version + MaintenanceInfoDescription string `jsonry:"maintenance_info.description"` + // MaintenanceInfoVersion is the version of the service plan + MaintenanceInfoVersion string `jsonry:"maintenance_info.version"` + + Metadata *Metadata `json:"metadata"` +} + +func (p *ServicePlan) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, p) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/service_plan_visibility_resource.go b/vendor/code.cloudfoundry.org/cli/resources/service_plan_visibility_resource.go new file mode 100644 index 0000000..2ee1c81 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/service_plan_visibility_resource.go @@ -0,0 +1,45 @@ +package resources + +import ( + "code.cloudfoundry.org/jsonry" +) + +type ServicePlanVisibilityType string + +const ( + ServicePlanVisibilityPublic ServicePlanVisibilityType = "public" + ServicePlanVisibilityOrganization ServicePlanVisibilityType = "organization" + ServicePlanVisibilitySpace ServicePlanVisibilityType = "space" + ServicePlanVisibilityAdmin ServicePlanVisibilityType = "admin" +) + +type ServicePlanVisibilityDetail struct { + // Name is the organization name + Name string `json:"name,omitempty"` + // GUID of the organization + GUID string `json:"guid"` +} + +func (s ServicePlanVisibilityDetail) OmitJSONry() bool { + return s == ServicePlanVisibilityDetail{} +} + +// ServicePlanVisibility represents a Cloud Controller V3 Service Plan Visibility. +type ServicePlanVisibility struct { + // Type is one of 'public', 'organization', 'space' or 'admin' + Type ServicePlanVisibilityType `json:"type"` + + // Organizations list of organizations for the service plan + Organizations []ServicePlanVisibilityDetail `json:"organizations,omitempty"` + + // Space that the plan is visible in + Space ServicePlanVisibilityDetail `json:"space"` +} + +func (s *ServicePlanVisibility) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} + +func (s ServicePlanVisibility) MarshalJSON() ([]byte, error) { + return jsonry.Marshal(s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/shared_to_spaces_resource.go b/vendor/code.cloudfoundry.org/cli/resources/shared_to_spaces_resource.go new file mode 100644 index 0000000..b6ec971 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/shared_to_spaces_resource.go @@ -0,0 +1,15 @@ +package resources + +import ( + "code.cloudfoundry.org/jsonry" +) + +type SharedToSpacesListWrapper struct { + SharedToSpaceGUIDs []string `jsonry:"data[].guid"` + Spaces []Space `jsonry:"included.spaces"` + Organizations []Organization `jsonry:"included.organizations"` +} + +func (s *SharedToSpacesListWrapper) UnmarshalJSON(data []byte) error { + return jsonry.Unmarshal(data, s) +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/sidecar_resource.go b/vendor/code.cloudfoundry.org/cli/resources/sidecar_resource.go new file mode 100644 index 0000000..fc3c53f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/sidecar_resource.go @@ -0,0 +1,9 @@ +package resources + +import "code.cloudfoundry.org/cli/types" + +type Sidecar struct { + GUID string `json:"guid"` + Name string `json:"name"` + Command types.FilteredString `json:"command"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/space_feature_resource.go b/vendor/code.cloudfoundry.org/cli/resources/space_feature_resource.go new file mode 100644 index 0000000..3c00a25 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/space_feature_resource.go @@ -0,0 +1,6 @@ +package resources + +type SpaceFeature struct { + Name string + Enabled bool +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/space_quota_resource.go b/vendor/code.cloudfoundry.org/cli/resources/space_quota_resource.go new file mode 100644 index 0000000..0fc2a11 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/space_quota_resource.go @@ -0,0 +1,118 @@ +package resources + +import ( + "encoding/json" +) + +type SpaceQuota struct { + Quota + // OrgGUID is the unique ID of the owning organization + OrgGUID string + // SpaceGUIDs are the list of unique ID's of the associated spaces + SpaceGUIDs []string +} + +func (sq SpaceQuota) MarshalJSON() ([]byte, error) { + appLimits := map[string]interface{}{} + if sq.Apps.TotalMemory != nil { + appLimits["total_memory_in_mb"] = sq.Apps.TotalMemory + } + if sq.Apps.InstanceMemory != nil { + appLimits["per_process_memory_in_mb"] = sq.Apps.InstanceMemory + } + if sq.Apps.TotalAppInstances != nil { + appLimits["total_instances"] = sq.Apps.TotalAppInstances + } + + serviceLimits := map[string]interface{}{} + if sq.Services.PaidServicePlans != nil { + serviceLimits["paid_services_allowed"] = sq.Services.PaidServicePlans + } + if sq.Services.TotalServiceInstances != nil { + serviceLimits["total_service_instances"] = sq.Services.TotalServiceInstances + } + + routeLimits := map[string]interface{}{} + if sq.Routes.TotalRoutes != nil { + routeLimits["total_routes"] = sq.Routes.TotalRoutes + } + if sq.Routes.TotalReservedPorts != nil { + routeLimits["total_reserved_ports"] = sq.Routes.TotalReservedPorts + } + + relationships := map[string]interface{}{} + + if sq.OrgGUID != "" { + relationships["organization"] = map[string]interface{}{ + "data": map[string]interface{}{ + "guid": sq.OrgGUID, + }, + } + } + + if len(sq.SpaceGUIDs) > 0 { + spaceData := make([]map[string]interface{}, len(sq.SpaceGUIDs)) + for i, spaceGUID := range sq.SpaceGUIDs { + spaceData[i] = map[string]interface{}{ + "guid": spaceGUID, + } + } + + relationships["spaces"] = map[string]interface{}{ + "data": spaceData, + } + } + + jsonMap := map[string]interface{}{ + "name": sq.Name, + "apps": appLimits, + "services": serviceLimits, + "routes": routeLimits, + } + + if len(relationships) != 0 { + jsonMap["relationships"] = relationships + } + + return json.Marshal(jsonMap) +} + +func (sq *SpaceQuota) UnmarshalJSON(data []byte) error { + type alias SpaceQuota + var defaultUnmarshalledSpaceQuota alias + err := json.Unmarshal(data, &defaultUnmarshalledSpaceQuota) + if err != nil { + return err + } + + *sq = SpaceQuota(defaultUnmarshalledSpaceQuota) + + type RemainingFieldsStruct struct { + Relationships struct { + Organization struct { + Data struct { + Guid string + } + } + Spaces struct { + Data []struct { + Guid string + } + } + } + } + + var remainingFields RemainingFieldsStruct + err = json.Unmarshal(data, &remainingFields) + if err != nil { + return err + } + + sq.OrgGUID = remainingFields.Relationships.Organization.Data.Guid + + for _, spaceData := range remainingFields.Relationships.Spaces.Data { + sq.SpaceGUIDs = append(sq.SpaceGUIDs, spaceData.Guid) + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/space_resource.go b/vendor/code.cloudfoundry.org/cli/resources/space_resource.go new file mode 100644 index 0000000..aeaf4ff --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/space_resource.go @@ -0,0 +1,13 @@ +package resources + +// Space represents a Cloud Controller V3 Space. +type Space struct { + // GUID is a unique space identifier. + GUID string `json:"guid,omitempty"` + // Name is the name of the space. + Name string `json:"name"` + // Relationships list the relationships to the space. + Relationships Relationships `json:"relationships,omitempty"` + // Metadata is used for custom tagging of API resources + Metadata *Metadata `json:"metadata,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/stack_resource.go b/vendor/code.cloudfoundry.org/cli/resources/stack_resource.go new file mode 100644 index 0000000..e312504 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/stack_resource.go @@ -0,0 +1,13 @@ +package resources + +type Stack struct { + // GUID is a unique stack identifier. + GUID string `json:"guid"` + // Name is the name of the stack. + Name string `json:"name"` + // Description is the description for the stack + Description string `json:"description"` + + // Metadata is used for custom tagging of API resources + Metadata *Metadata `json:"metadata,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/task_resource.go b/vendor/code.cloudfoundry.org/cli/resources/task_resource.go new file mode 100644 index 0000000..4bc1f96 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/task_resource.go @@ -0,0 +1,41 @@ +package resources + +import ( + "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" +) + +// Task represents a Cloud Controller V3 Task. +type Task struct { + // Command represents the command that will be executed. May be excluded + // based on the user's role. + Command string `json:"command,omitempty"` + // CreatedAt represents the time with zone when the object was created. + CreatedAt string `json:"created_at,omitempty"` + // DiskInMB represents the disk in MB allocated for the task. + DiskInMB uint64 `json:"disk_in_mb,omitempty"` + // GUID represents the unique task identifier. + GUID string `json:"guid,omitempty"` + // MemoryInMB represents the memory in MB allocated for the task. + MemoryInMB uint64 `json:"memory_in_mb,omitempty"` + // Name represents the name of the task. + Name string `json:"name,omitempty"` + // SequenceID represents the user-facing id of the task. This number is + // unique for every task associated with a given app. + SequenceID int64 `json:"sequence_id,omitempty"` + // State represents the task state. + State constant.TaskState `json:"state,omitempty"` + // Tasks can use a process as a template to fill in + // command, memory, disk values + // + // Using a pointer so that it can be set to nil to prevent + // json serialization when no template is used + Template *TaskTemplate `json:"template,omitempty"` +} + +type TaskTemplate struct { + Process TaskProcessTemplate `json:"process,omitempty"` +} + +type TaskProcessTemplate struct { + Guid string `json:"guid,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/resources/user_resource.go b/vendor/code.cloudfoundry.org/cli/resources/user_resource.go new file mode 100644 index 0000000..602aaa6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/resources/user_resource.go @@ -0,0 +1,15 @@ +package resources + +// User represents a Cloud Controller User. +type User struct { + // GUID is the unique user identifier. + GUID string `json:"guid"` + Username string `json:"username"` + PresentationName string `json:"presentation_name"` + Origin string `json:"origin"` +} + +type K8sUser struct { + Name string `json:"name"` + Kind string `json:"kind"` +} diff --git a/vendor/code.cloudfoundry.org/cli/types/filtered_interface.go b/vendor/code.cloudfoundry.org/cli/types/filtered_interface.go new file mode 100644 index 0000000..51a01b7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/filtered_interface.go @@ -0,0 +1,30 @@ +package types + +import ( + "encoding/json" +) + +type FilteredInterface struct { + IsSet bool + Value interface{} +} + +func (n *FilteredInterface) UnmarshalJSON(rawJSON []byte) error { + var value interface{} + err := json.Unmarshal(rawJSON, &value) + if err != nil { + return err + } + + n.Value = value + n.IsSet = true + return nil +} + +func (n FilteredInterface) MarshalJSON() ([]byte, error) { + if n.IsSet { + return json.Marshal(n.Value) + } + + return json.Marshal(new(json.RawMessage)) +} diff --git a/vendor/code.cloudfoundry.org/cli/types/filtered_string.go b/vendor/code.cloudfoundry.org/cli/types/filtered_string.go new file mode 100644 index 0000000..ff4d5f0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/filtered_string.go @@ -0,0 +1,92 @@ +package types + +import ( + "encoding/json" + "strings" +) + +// FilteredString is a wrapper around string values that can be null/default or an +// actual value. Use IsSet to check if the value is provided, instead of +// checking against the empty string. +type FilteredString struct { + IsSet bool + Value string +} + +type FilteredStrings []FilteredString + +func NewFilteredString(val string) *FilteredString { + var result FilteredString + + result.ParseValue(val) + + return &result +} + +// ParseValue is used to parse a user provided flag argument. +func (n *FilteredString) ParseValue(val string) { + if val == "" { + n.IsSet = false + n.Value = "" + return + } + + n.IsSet = true + + switch val { + case "null", "default": + n.Value = "" + default: + n.Value = val + } +} + +func (n FilteredString) IsDefault() bool { + return n.IsSet && n.Value == "" +} + +func (n *FilteredString) UnmarshalJSON(rawJSON []byte) error { + var value *string + err := json.Unmarshal(rawJSON, &value) + if err != nil { + return err + } + + if value != nil { + n.Value = *value + n.IsSet = true + return nil + } + + n.Value = "" + n.IsSet = false + return nil +} + +// MarshalJSON marshals the value field if it's not empty, otherwise returns an +// null. +func (n FilteredString) MarshalJSON() ([]byte, error) { + if n.Value != "" { + return json.Marshal(n.Value) + } + + return json.Marshal(new(json.RawMessage)) +} + +func (n FilteredString) String() string { + if n.IsSet { + return n.Value + } + + return "" +} + +func (n FilteredStrings) String() string { + var ss []string + + for _, fs := range n { + ss = append(ss, fs.Value) + } + + return strings.Join(ss, ", ") +} diff --git a/vendor/code.cloudfoundry.org/cli/types/json_object.go b/vendor/code.cloudfoundry.org/cli/types/json_object.go new file mode 100644 index 0000000..b8adfa4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/json_object.go @@ -0,0 +1,16 @@ +package types + +import "encoding/json" + +// JSONObject represents a JSON object. When not initialized it serializes to `{}`, +// whereas a `map[string]interface{}` serializes to `null`. +type JSONObject map[string]interface{} + +func (j JSONObject) MarshalJSON() ([]byte, error) { + switch len(j) { + case 0: + return []byte("{}"), nil + default: + return json.Marshal(map[string]interface{}(j)) + } +} diff --git a/vendor/code.cloudfoundry.org/cli/types/null_bool.go b/vendor/code.cloudfoundry.org/cli/types/null_bool.go new file mode 100644 index 0000000..8e93bb4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/null_bool.go @@ -0,0 +1,69 @@ +package types + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// NullBool is a wrapper around bool values that can be null or an bool. +// Use IsSet to check if the value is provided, instead of checking against false. +type NullBool struct { + IsSet bool + Value bool +} + +// ParseStringValue is used to parse a user provided flag argument. +func (n *NullBool) ParseStringValue(val string) error { + if val == "" { + return nil + } + + boolVal, err := strconv.ParseBool(val) + if err != nil { + return err + } + + n.Value = boolVal + n.IsSet = true + + return nil +} + +// ParseBoolValue is used to parse a user provided *bool argument. +func (n *NullBool) ParseBoolValue(val *bool) { + if val == nil { + n.IsSet = false + n.Value = false + return + } + + n.Value = *val + n.IsSet = true +} + +func (n *NullBool) UnmarshalJSON(rawJSON []byte) error { + var value *bool + err := json.Unmarshal(rawJSON, &value) + if err != nil { + return err + } + + if value == nil { + n.Value = false + n.IsSet = false + return nil + } + + n.Value = *value + n.IsSet = true + + return nil +} + +func (n NullBool) MarshalJSON() ([]byte, error) { + if n.IsSet { + return []byte(fmt.Sprint(n.Value)), nil + } + return []byte(JsonNull), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/types/null_bytesize_in_mb.go b/vendor/code.cloudfoundry.org/cli/types/null_bytesize_in_mb.go new file mode 100644 index 0000000..da8a1c6 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/null_bytesize_in_mb.go @@ -0,0 +1,88 @@ +package types + +import ( + "encoding/json" + "strconv" + + "code.cloudfoundry.org/bytefmt" +) + +// NullByteSizeInMb represents size in a byte format in megabytes. +type NullByteSizeInMb struct { + IsSet bool + + // Value is a size in MB + Value uint64 +} + +func (b NullByteSizeInMb) String() string { + if !b.IsSet { + return "" + } + + return bytefmt.ByteSize(b.Value * bytefmt.MEGABYTE) +} + +func (b *NullByteSizeInMb) ParseStringValue(value string) error { + if value == "" { + b.IsSet = false + b.Value = 0 + return nil + } + + byteSize, fmtErr := bytefmt.ToMegabytes(value) + if fmtErr != nil { + return fmtErr + } + + b.IsSet = true + b.Value = byteSize + + return nil +} + +// ParseUint64Value is used to parse a user provided *uint64 argument. +func (b *NullByteSizeInMb) ParseUint64Value(val *uint64) { + if val == nil { + b.IsSet = false + b.Value = 0 + return + } + + b.Value = *val + b.IsSet = true +} + +func (b *NullByteSizeInMb) UnmarshalJSON(rawJSON []byte) error { + if len(rawJSON) == 0 { + b.Value = 0 + b.IsSet = false + return nil + } + + var value json.Number + err := json.Unmarshal(rawJSON, &value) + if err != nil { + return err + } + + if jsonNumberIsUninitialized(value) { + b.Value = 0 + b.IsSet = false + return nil + } + + valueInt, err := strconv.ParseUint(value.String(), 10, 64) + if err != nil { + return err + } + + b.Value = valueInt + b.IsSet = true + + return nil +} + +func jsonNumberIsUninitialized(value json.Number) bool { + return value.String() == "" +} diff --git a/vendor/code.cloudfoundry.org/cli/types/null_int.go b/vendor/code.cloudfoundry.org/cli/types/null_int.go new file mode 100644 index 0000000..9b34940 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/null_int.go @@ -0,0 +1,81 @@ +package types + +import ( + "fmt" + "strconv" + + "github.com/jessevdk/go-flags" +) + +const JsonNull = "null" + +// NullInt is a wrapper around integer values that can be null or an integer. +// Use IsSet to check if the value is provided, instead of checking against 0. +type NullInt struct { + IsSet bool + Value int +} + +// ParseStringValue is used to parse a user provided flag argument. +func (n *NullInt) ParseStringValue(val string) error { + if val == "" { + n.IsSet = false + n.Value = 0 + return nil + } + + intVal, err := strconv.Atoi(val) + if err != nil { + n.IsSet = false + n.Value = 0 + return &flags.Error{ + Type: flags.ErrMarshal, + Message: fmt.Sprintf("invalid integer value `%s`", val), + } + } + + n.Value = intVal + n.IsSet = true + + return nil +} + +// IsValidValue returns an error if the input value is not an integer. +func (n *NullInt) IsValidValue(val string) error { + return n.ParseStringValue(val) +} + +// ParseIntValue is used to parse a user provided *int argument. +func (n *NullInt) ParseIntValue(val *int) { + if val == nil { + n.IsSet = false + n.Value = 0 + return + } + + n.Value = *val + n.IsSet = true +} + +func (n *NullInt) UnmarshalFlag(val string) error { + return n.ParseStringValue(val) +} + +func (n *NullInt) UnmarshalJSON(rawJSON []byte) error { + stringValue := string(rawJSON) + + if stringValue == JsonNull { + n.Value = 0 + n.IsSet = false + return nil + } + + return n.ParseStringValue(stringValue) +} + +func (n NullInt) MarshalJSON() ([]byte, error) { + if n.IsSet { + return []byte(fmt.Sprint(n.Value)), nil + } + return []byte(JsonNull), nil +} diff --git a/vendor/code.cloudfoundry.org/cli/types/null_string.go b/vendor/code.cloudfoundry.org/cli/types/null_string.go new file mode 100644 index 0000000..e1dbc39 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/null_string.go @@ -0,0 +1,47 @@ +package types + +import ( + "encoding/json" +) + +type NullString struct { + Value string + IsSet bool +} + +func NewNullString(optionalValue ...string) NullString { + switch len(optionalValue) { + case 0: + return NullString{IsSet: false} + case 1: + return NullString{Value: optionalValue[0], IsSet: true} + default: + panic("Too many strings passed to nullable string constructor") + } +} + +func (n NullString) MarshalJSON() ([]byte, error) { + if n.IsSet { + return json.Marshal(n.Value) + } + return json.Marshal(nil) +} + +func (n *NullString) UnmarshalJSON(rawJSON []byte) error { + var value *string + err := json.Unmarshal(rawJSON, &value) + if err != nil { + return err + } + + if value == nil { + n.Value = "" + n.IsSet = false + return nil + } + + n.Value = *value + n.IsSet = true + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/types/null_uint64.go b/vendor/code.cloudfoundry.org/cli/types/null_uint64.go new file mode 100644 index 0000000..276c269 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/null_uint64.go @@ -0,0 +1,45 @@ +package types + +import ( + "strconv" +) + +// NullUint64 is a wrapper around uint64 values that can be null or an unint64. +// Use IsSet to check if the value is provided, instead of checking against 0. +type NullUint64 struct { + IsSet bool + Value uint64 +} + +// ParseStringValue is used to parse a user provided flag argument. +func (n *NullUint64) ParseStringValue(val string) error { + if val == "" { + n.Value = 0 + n.IsSet = false + return nil + } + + uint64Val, err := strconv.ParseUint(val, 10, 64) + if err != nil { + n.Value = 0 + n.IsSet = false + return err + } + + n.Value = uint64Val + n.IsSet = true + + return nil +} + +func (n *NullUint64) UnmarshalJSON(rawJSON []byte) error { + stringValue := string(rawJSON) + + if stringValue == JsonNull { + n.Value = 0 + n.IsSet = false + return nil + } + + return n.ParseStringValue(stringValue) +} diff --git a/vendor/code.cloudfoundry.org/cli/types/optional_boolean.go b/vendor/code.cloudfoundry.org/cli/types/optional_boolean.go new file mode 100644 index 0000000..d82bf66 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/optional_boolean.go @@ -0,0 +1,34 @@ +package types + +import ( + "encoding/json" +) + +type OptionalBoolean struct { + IsSet bool + Value bool +} + +func NewOptionalBoolean(value bool) OptionalBoolean { + return OptionalBoolean{ + IsSet: true, + Value: value, + } +} + +func (o *OptionalBoolean) UnmarshalJSON(rawJSON []byte) error { + if err := json.Unmarshal(rawJSON, &o.Value); err != nil { + return err + } + + o.IsSet = true + return nil +} + +func (o OptionalBoolean) MarshalJSON() ([]byte, error) { + return json.Marshal(o.Value) +} + +func (o OptionalBoolean) OmitJSONry() bool { + return !o.IsSet +} diff --git a/vendor/code.cloudfoundry.org/cli/types/optional_object.go b/vendor/code.cloudfoundry.org/cli/types/optional_object.go new file mode 100644 index 0000000..f3e4bf0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/optional_object.go @@ -0,0 +1,43 @@ +package types + +import "encoding/json" + +// OptionalObject is for situations where we want to differentiate between an +// empty object, and the object not having been set. An example would be an +// optional command line option where we want to tell the difference between +// it being set to an empty object, and it not being specified at all. +type OptionalObject struct { + IsSet bool + Value map[string]interface{} +} + +func NewOptionalObject(v map[string]interface{}) OptionalObject { + if v == nil { + // This ensures that when IsSet==true, we always have an empty map as the value which + // marshals to `{}` and not a nil map which marshals to `null` + v = make(map[string]interface{}) + } + + return OptionalObject{ + IsSet: true, + Value: v, + } +} + +func (o *OptionalObject) UnmarshalJSON(rawJSON []byte) error { + var receiver map[string]interface{} + if err := json.Unmarshal(rawJSON, &receiver); err != nil { + return err + } + + *o = NewOptionalObject(receiver) + return nil +} + +func (o OptionalObject) MarshalJSON() ([]byte, error) { + return json.Marshal(o.Value) +} + +func (o OptionalObject) OmitJSONry() bool { + return !o.IsSet +} diff --git a/vendor/code.cloudfoundry.org/cli/types/optional_string.go b/vendor/code.cloudfoundry.org/cli/types/optional_string.go new file mode 100644 index 0000000..1b6c603 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/optional_string.go @@ -0,0 +1,34 @@ +package types + +import ( + "encoding/json" +) + +type OptionalString struct { + IsSet bool + Value string +} + +func NewOptionalString(v string) OptionalString { + return OptionalString{ + IsSet: true, + Value: v, + } +} + +func (o *OptionalString) UnmarshalJSON(rawJSON []byte) error { + o.IsSet = true + return json.Unmarshal(rawJSON, &o.Value) +} + +func (o OptionalString) MarshalJSON() ([]byte, error) { + return json.Marshal(o.Value) +} + +func (o OptionalString) OmitJSONry() bool { + return !o.IsSet +} + +func (o OptionalString) String() string { + return o.Value +} diff --git a/vendor/code.cloudfoundry.org/cli/types/optional_string_slice.go b/vendor/code.cloudfoundry.org/cli/types/optional_string_slice.go new file mode 100644 index 0000000..4b20942 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/types/optional_string_slice.go @@ -0,0 +1,52 @@ +package types + +import ( + "encoding/json" + "strings" +) + +type OptionalStringSlice struct { + IsSet bool + Value []string +} + +func NewOptionalStringSlice(s ...string) OptionalStringSlice { + return OptionalStringSlice{ + IsSet: true, + Value: s, + } +} + +func (o *OptionalStringSlice) UnmarshalJSON(rawJSON []byte) error { + var receiver []string + if err := json.Unmarshal(rawJSON, &receiver); err != nil { + return err + } + + // This ensures that the empty state is always a nil slice, not an allocated (but empty) slice + switch len(receiver) { + case 0: + o.Value = nil + default: + o.Value = receiver + } + + o.IsSet = true + return nil +} + +func (o OptionalStringSlice) MarshalJSON() ([]byte, error) { + if len(o.Value) > 0 { + return json.Marshal(o.Value) + } + + return []byte(`[]`), nil +} + +func (o OptionalStringSlice) OmitJSONry() bool { + return !o.IsSet +} + +func (o OptionalStringSlice) String() string { + return strings.Join(o.Value, ", ") +} diff --git a/vendor/code.cloudfoundry.org/cli/util/batcher/batcher.go b/vendor/code.cloudfoundry.org/cli/util/batcher/batcher.go new file mode 100644 index 0000000..ad5ad47 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/batcher/batcher.go @@ -0,0 +1,29 @@ +package batcher + +import "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + +const BatchSize = 200 + +type callback func(guids []string) (ccv3.Warnings, error) + +func RequestByGUID(guids []string, cb callback) (ccv3.Warnings, error) { + var allWarnings ccv3.Warnings + + for len(guids) > 0 { + remaining := len(guids) + if remaining > BatchSize { + remaining = BatchSize + } + + batch := guids[:remaining] + guids = guids[remaining:] + + warnings, err := cb(batch) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + } + + return allWarnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/checksum.go b/vendor/code.cloudfoundry.org/cli/util/checksum.go new file mode 100644 index 0000000..81169e7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/checksum.go @@ -0,0 +1,58 @@ +package util + +import ( + "crypto/sha1" + "fmt" + "io" + "os" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Sha1Checksum + +type Sha1Checksum interface { + ComputeFileSha1() ([]byte, error) + CheckSha1(string) bool + SetFilePath(string) +} + +type sha1Checksum struct { + filepath string +} + +func NewSha1Checksum(filepath string) Sha1Checksum { + return &sha1Checksum{ + filepath: filepath, + } +} + +func (c *sha1Checksum) CheckSha1(targetSha1 string) bool { + sha1, err := c.ComputeFileSha1() + if err != nil { + return false + } + + if fmt.Sprintf("%x", sha1) == targetSha1 { + return true + } + return false +} + +func (c *sha1Checksum) ComputeFileSha1() ([]byte, error) { + hash := sha1.New() + + f, err := os.Open(c.filepath) + if err != nil { + return []byte{}, err + } + defer f.Close() + + if _, err := io.Copy(hash, f); err != nil { + return []byte{}, err + } + + return hash.Sum(nil), nil +} + +func (c *sha1Checksum) SetFilePath(filepath string) { + c.filepath = filepath +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/listener_factory.go b/vendor/code.cloudfoundry.org/cli/util/clissh/listener_factory.go new file mode 100644 index 0000000..2e04cf7 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/listener_factory.go @@ -0,0 +1,19 @@ +package clissh + +import "net" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ListenerFactory + +type ListenerFactory interface { + Listen(network, address string) (net.Listener, error) +} + +type listenerFactory struct{} + +func DefaultListenerFactory() listenerFactory { + return listenerFactory{} +} + +func (listenerFactory) Listen(network, address string) (net.Listener, error) { + return net.Listen(network, address) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/secure_client.go b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_client.go new file mode 100644 index 0000000..f0e0af5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_client.go @@ -0,0 +1,41 @@ +package clissh + +import ( + "net" + + "golang.org/x/crypto/ssh" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SecureClient + +type SecureClient interface { + NewSession() (SecureSession, error) + Conn() ssh.Conn + Dial(network, address string) (net.Conn, error) + Wait() error + Close() error +} + +type secureClient struct { + client *ssh.Client +} + +func (sc secureClient) Close() error { + return sc.client.Close() +} + +func (sc secureClient) Conn() ssh.Conn { + return sc.client.Conn +} + +func (sc secureClient) Dial(n, addr string) (net.Conn, error) { + return sc.client.Dial(n, addr) +} + +func (sc secureClient) NewSession() (SecureSession, error) { + return sc.client.NewSession() +} + +func (sc secureClient) Wait() error { + return sc.client.Wait() +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/secure_dialer.go b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_dialer.go new file mode 100644 index 0000000..8acf397 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_dialer.go @@ -0,0 +1,33 @@ +package clissh + +import ( + "golang.org/x/crypto/ssh" + "golang.org/x/net/proxy" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SecureDialer + +type SecureDialer interface { + Dial(network, address string, config *ssh.ClientConfig) (SecureClient, error) +} + +type secureDialer struct{} + +func DefaultSecureDialer() secureDialer { + return secureDialer{} +} + +func (secureDialer) Dial(network string, address string, config *ssh.ClientConfig) (SecureClient, error) { + conn, err := proxy.FromEnvironment().Dial(network, address) + if err != nil { + return secureClient{}, err + } + + c, chans, reqs, err := ssh.NewClientConn(conn, address, config) + if err != nil { + return secureClient{}, err + } + client := ssh.NewClient(c, chans, reqs) + + return secureClient{client: client}, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/secure_session.go b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_session.go new file mode 100644 index 0000000..a010c47 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/secure_session.go @@ -0,0 +1,21 @@ +package clissh + +import ( + "io" + + "golang.org/x/crypto/ssh" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . SecureSession + +type SecureSession interface { + RequestPty(term string, height, width int, termModes ssh.TerminalModes) error + SendRequest(name string, wantReply bool, payload []byte) (bool, error) + StdinPipe() (io.WriteCloser, error) + StdoutPipe() (io.Reader, error) + StderrPipe() (io.Reader, error) + Start(command string) error + Shell() error + Wait() error + Close() error +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/ssh.go b/vendor/code.cloudfoundry.org/cli/util/clissh/ssh.go new file mode 100644 index 0000000..43fd4f1 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/ssh.go @@ -0,0 +1,409 @@ +package clissh + +import ( + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "encoding/base64" + "errors" + "fmt" + "io" + "net" + "os" + "os/signal" + "runtime" + "strings" + "sync" + "syscall" + "time" + + "code.cloudfoundry.org/cli/cf/ssh/sigwinch" + "code.cloudfoundry.org/cli/util/clissh/ssherror" + "github.com/moby/moby/pkg/term" + log "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh" +) + +const ( + md5FingerprintLength = 47 // inclusive of space between bytes + hexSha1FingerprintLength = 59 // inclusive of space between bytes + base64Sha256FingerprintLength = 43 + + DefaultKeepAliveInterval = 30 * time.Second +) + +type LocalPortForward struct { + LocalAddress string + RemoteAddress string +} + +type SecureShell struct { + secureDialer SecureDialer + secureClient SecureClient + terminalHelper TerminalHelper + listenerFactory ListenerFactory + + localListeners []net.Listener + keepAliveInterval time.Duration +} + +func NewDefaultSecureShell() *SecureShell { + defaultSecureDialer := DefaultSecureDialer() + defaultTerminalHelper := DefaultTerminalHelper() + defaultListenerFactory := DefaultListenerFactory() + return &SecureShell{ + secureDialer: defaultSecureDialer, + terminalHelper: defaultTerminalHelper, + listenerFactory: defaultListenerFactory, + keepAliveInterval: DefaultKeepAliveInterval, + localListeners: []net.Listener{}, + } +} + +func NewSecureShell( + secureDialer SecureDialer, + terminalHelper TerminalHelper, + listenerFactory ListenerFactory, + keepAliveInterval time.Duration, +) *SecureShell { + return &SecureShell{ + secureDialer: secureDialer, + terminalHelper: terminalHelper, + listenerFactory: listenerFactory, + keepAliveInterval: keepAliveInterval, + localListeners: []net.Listener{}, + } +} + +func (c *SecureShell) Close() error { + for _, listener := range c.localListeners { + listener.Close() + } + return c.secureClient.Close() +} + +func (c *SecureShell) Connect(username string, passcode string, appSSHEndpoint string, appSSHHostKeyFingerprint string, skipHostValidation bool) error { + hostKeyCallbackFunction := fingerprintCallback(skipHostValidation, appSSHHostKeyFingerprint) + + clientConfig := &ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ssh.Password(passcode)}, + HostKeyCallback: hostKeyCallbackFunction, + } + + secureClient, err := c.secureDialer.Dial("tcp", appSSHEndpoint, clientConfig) + if err != nil { + if strings.Contains(err.Error(), "ssh: unable to authenticate") { + return ssherror.UnableToAuthenticateError{Err: err} + } + return err + } + + c.secureClient = secureClient + return nil +} + +func (c *SecureShell) InteractiveSession(commands []string, terminalRequest TTYRequest) error { + session, err := c.secureClient.NewSession() + if err != nil { + return fmt.Errorf("SSH session allocation failed: %s", err.Error()) + } + defer session.Close() + + stdin, stdout, stderr := c.terminalHelper.StdStreams() + + inPipe, err := session.StdinPipe() + if err != nil { + return err + } + + outPipe, err := session.StdoutPipe() + if err != nil { + return err + } + + errPipe, err := session.StderrPipe() + if err != nil { + return err + } + + stdinFd, stdinIsTerminal := c.terminalHelper.GetFdInfo(stdin) + stdoutFd, stdoutIsTerminal := c.terminalHelper.GetFdInfo(stdout) + + if c.shouldAllocateTerminal(commands, terminalRequest, stdinIsTerminal) { + modes := ssh.TerminalModes{ + ssh.ECHO: 1, + ssh.TTY_OP_ISPEED: 115200, + ssh.TTY_OP_OSPEED: 115200, + } + + width, height := c.getWindowDimensions(stdoutFd) + + err = session.RequestPty(c.terminalType(), height, width, modes) + if err != nil { + return err + } + + var state *term.State + state, err = c.terminalHelper.SetRawTerminal(stdinFd) + if err == nil { + defer func() { + err := c.terminalHelper.RestoreTerminal(stdinFd, state) + log.Errorln("restore terminal", err) + }() + } + } + + if len(commands) > 0 { + cmd := strings.Join(commands, " ") + err = session.Start(cmd) + if err != nil { + return err + } + } else { + err = session.Shell() + if err != nil { + return err + } + } + + wg := &sync.WaitGroup{} + wg.Add(2) + + go copyAndClose(nil, inPipe, stdin) + go copyAndDone(wg, stdout, outPipe) + go copyAndDone(wg, stderr, errPipe) + + if stdoutIsTerminal { + resized := make(chan os.Signal, 16) + + if runtime.GOOS == "windows" { + ticker := time.NewTicker(250 * time.Millisecond) + defer ticker.Stop() + + go func() { + for range ticker.C { + resized <- syscall.Signal(-1) + } + close(resized) + }() + } else { + signal.Notify(resized, sigwinch.SIGWINCH()) + defer func() { signal.Stop(resized); close(resized) }() + } + + go c.resize(resized, session, stdoutFd) + } + + keepaliveStopCh := make(chan struct{}) + defer close(keepaliveStopCh) + + go keepalive(c.secureClient.Conn(), time.NewTicker(c.keepAliveInterval), keepaliveStopCh) + + result := session.Wait() + wg.Wait() + return result +} + +func (c *SecureShell) LocalPortForward(localPortForwardSpecs []LocalPortForward) error { + for _, spec := range localPortForwardSpecs { + listener, err := c.listenerFactory.Listen("tcp", spec.LocalAddress) + if err != nil { + return err + } + c.localListeners = append(c.localListeners, listener) + + go c.localForwardAcceptLoop(listener, spec.RemoteAddress) + } + + return nil +} + +func (c *SecureShell) Wait() error { + keepaliveStopCh := make(chan struct{}) + defer close(keepaliveStopCh) + + go keepalive(c.secureClient.Conn(), time.NewTicker(c.keepAliveInterval), keepaliveStopCh) + + return c.secureClient.Wait() +} + +func (c *SecureShell) getWindowDimensions(terminalFd uintptr) (width int, height int) { + winSize, err := c.terminalHelper.GetWinsize(terminalFd) + if err != nil { + winSize = &term.Winsize{ + Width: 80, + Height: 43, + } + } + + return int(winSize.Width), int(winSize.Height) +} + +func (c *SecureShell) handleForwardConnection(conn net.Conn, targetAddr string) { + defer conn.Close() + + target, err := c.secureClient.Dial("tcp", targetAddr) + if err != nil { + fmt.Printf("connect to %s failed: %s\n", targetAddr, err.Error()) + return + } + defer target.Close() + + wg := &sync.WaitGroup{} + wg.Add(2) + + go copyAndClose(wg, conn, target) + go copyAndClose(wg, target, conn) + wg.Wait() +} + +func (c *SecureShell) localForwardAcceptLoop(listener net.Listener, addr string) { + defer listener.Close() + + for { + conn, err := listener.Accept() + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Temporary() { + time.Sleep(100 * time.Millisecond) + continue + } + return + } + + go c.handleForwardConnection(conn, addr) + } +} + +func (c *SecureShell) resize(resized <-chan os.Signal, session SecureSession, terminalFd uintptr) { + type resizeMessage struct { + Width uint32 + Height uint32 + PixelWidth uint32 + PixelHeight uint32 + } + + var previousWidth, previousHeight int + + for range resized { + width, height := c.getWindowDimensions(terminalFd) + + if width == previousWidth && height == previousHeight { + continue + } + + message := resizeMessage{ + Width: uint32(width), + Height: uint32(height), + } + + _, err := session.SendRequest("window-change", false, ssh.Marshal(message)) + if err != nil { + log.Errorln("window-change:", err) + } + + previousWidth = width + previousHeight = height + } +} + +func (c *SecureShell) shouldAllocateTerminal(commands []string, terminalRequest TTYRequest, stdinIsTerminal bool) bool { + switch terminalRequest { + case RequestTTYForce: + return true + case RequestTTYNo: + return false + case RequestTTYYes: + return stdinIsTerminal + case RequestTTYAuto: + return len(commands) == 0 && stdinIsTerminal + default: + return false + } +} + +func (c *SecureShell) terminalType() string { + term := os.Getenv("TERM") + if term == "" { + term = "xterm" + } + return term +} + +func base64Sha256Fingerprint(key ssh.PublicKey) string { + sum := sha256.Sum256(key.Marshal()) + return base64.RawStdEncoding.EncodeToString(sum[:]) +} + +func copyAndClose(wg *sync.WaitGroup, dest io.WriteCloser, src io.Reader) { + _, err := io.Copy(dest, src) + if err != nil { + log.Errorln("copy and close:", err) + } + _ = dest.Close() + if wg != nil { + wg.Done() + } +} + +func copyAndDone(wg *sync.WaitGroup, dest io.Writer, src io.Reader) { + _, err := io.Copy(dest, src) + if err != nil { + log.Errorln("copy and done:", err) + } + wg.Done() +} + +func fingerprintCallback(skipHostValidation bool, expectedFingerprint string) ssh.HostKeyCallback { + return func(hostname string, remote net.Addr, key ssh.PublicKey) error { + if skipHostValidation { + return nil + } + + var fingerprint string + + switch len(expectedFingerprint) { + case base64Sha256FingerprintLength: + fingerprint = base64Sha256Fingerprint(key) + case hexSha1FingerprintLength: + fingerprint = hexSha1Fingerprint(key) + case md5FingerprintLength: + fingerprint = md5Fingerprint(key) + case 0: + fingerprint = md5Fingerprint(key) + return fmt.Errorf("Unable to verify identity of host.\n\nThe fingerprint of the received key was %q.", fingerprint) + default: + return errors.New("Unsupported host key fingerprint format") + } + + if fingerprint != expectedFingerprint { + return fmt.Errorf("Host key verification failed.\n\nThe fingerprint of the received key was %q.", fingerprint) + } + return nil + } +} + +func hexSha1Fingerprint(key ssh.PublicKey) string { + sum := sha1.Sum(key.Marshal()) + return strings.Replace(fmt.Sprintf("% x", sum), " ", ":", -1) +} + +func keepalive(conn ssh.Conn, ticker *time.Ticker, stopCh chan struct{}) { + for { + select { + case <-ticker.C: + _, _, err := conn.SendRequest("keepalive@cloudfoundry.org", true, nil) + if err != nil { + log.Errorln("err sending keep alive:", err) + } + case <-stopCh: + ticker.Stop() + return + } + } +} + +func md5Fingerprint(key ssh.PublicKey) string { + sum := md5.Sum(key.Marshal()) + return strings.Replace(fmt.Sprintf("% x", sum), " ", ":", -1) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/ssherror/unable_to_authenticate_error.go b/vendor/code.cloudfoundry.org/cli/util/clissh/ssherror/unable_to_authenticate_error.go new file mode 100644 index 0000000..0b842fa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/ssherror/unable_to_authenticate_error.go @@ -0,0 +1,9 @@ +package ssherror + +type UnableToAuthenticateError struct { + Err error +} + +func (e UnableToAuthenticateError) Error() string { + return e.Err.Error() +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/terminal_helper.go b/vendor/code.cloudfoundry.org/cli/util/clissh/terminal_helper.go new file mode 100644 index 0000000..092fe49 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/terminal_helper.go @@ -0,0 +1,43 @@ +package clissh + +import ( + "io" + + "github.com/moby/moby/pkg/term" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . TerminalHelper + +type TerminalHelper interface { + GetFdInfo(in interface{}) (fd uintptr, isTerminal bool) + SetRawTerminal(fd uintptr) (*term.State, error) + RestoreTerminal(fd uintptr, state *term.State) error + GetWinsize(fd uintptr) (*term.Winsize, error) + StdStreams() (stdin io.ReadCloser, stdout io.Writer, stderr io.Writer) +} + +type terminalHelper struct{} + +func DefaultTerminalHelper() terminalHelper { + return terminalHelper{} +} + +func (terminalHelper) GetFdInfo(in interface{}) (uintptr, bool) { + return term.GetFdInfo(in) +} + +func (terminalHelper) GetWinsize(fd uintptr) (*term.Winsize, error) { + return term.GetWinsize(fd) +} + +func (terminalHelper) RestoreTerminal(fd uintptr, state *term.State) error { + return term.RestoreTerminal(fd, state) +} + +func (terminalHelper) SetRawTerminal(fd uintptr) (*term.State, error) { + return term.SetRawTerminal(fd) +} + +func (terminalHelper) StdStreams() (io.ReadCloser, io.Writer, io.Writer) { + return term.StdStreams() +} diff --git a/vendor/code.cloudfoundry.org/cli/util/clissh/tty_request.go b/vendor/code.cloudfoundry.org/cli/util/clissh/tty_request.go new file mode 100644 index 0000000..052dcae --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/clissh/tty_request.go @@ -0,0 +1,10 @@ +package clissh + +type TTYRequest int + +const ( + RequestTTYAuto TTYRequest = iota + RequestTTYNo + RequestTTYYes + RequestTTYForce +) diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/color.go b/vendor/code.cloudfoundry.org/cli/util/configv3/color.go new file mode 100644 index 0000000..50301cc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/color.go @@ -0,0 +1,49 @@ +package configv3 + +import "strconv" + +const ( + // DefaultColorEnabled is the default CFConfig value for ColorEnabled. + DefaultColorEnabled = "" + + // ColorDisabled means that no colors/bolding will be displayed. + ColorDisabled ColorSetting = iota + + // ColorEnabled means colors/bolding will be displayed. + ColorEnabled + + // ColorAuto means that the UI should decide if colors/bolding will be + // enabled. + ColorAuto +) + +// ColorSetting is a trinary operator that represents if the display should +// have colors enabled, disabled, or automatically detected. +type ColorSetting int + +// ColorEnabled returns the color setting based off: +// 1. The $CF_COLOR environment variable if set (0/1/t/f/true/false) +// 2. The 'ColorEnabled' value in the .cf/config.json if set +// 3. Defaults to ColorAuto if nothing is set +func (config *Config) ColorEnabled() ColorSetting { + if config.ENV.CFColor != "" { + val, err := strconv.ParseBool(config.ENV.CFColor) + if err == nil { + return config.boolToColorSetting(val) + } + } + + val, err := strconv.ParseBool(config.ConfigFile.ColorEnabled) + if err != nil { + return ColorAuto + } + return config.boolToColorSetting(val) +} + +func (config *Config) boolToColorSetting(val bool) ColorSetting { + if val { + return ColorEnabled + } + + return ColorDisabled +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/config.go new file mode 100644 index 0000000..c6afb35 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/config.go @@ -0,0 +1,112 @@ +// Package configv3 package contains everything related to the CF CLI Configuration. +package configv3 + +import ( + "path/filepath" + "strconv" + + "code.cloudfoundry.org/cli/version" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . UserConfig + +type UserConfig interface { + CurrentUser() (User, error) + CurrentUserName() (string, error) +} + +// Config combines the settings taken from the .cf/config.json, os.ENV, and the +// plugin config. +type Config struct { + // ConfigFile stores the configuration from the .cf/config + ConfigFile JSONConfig + + // ENV stores the configuration from os.ENV + ENV EnvOverride + + // Flags stores the configuration from global flags + Flags FlagOverride + + // detectedSettings are settings detected when the config is loaded. + detectedSettings detectedSettings + + pluginsConfig PluginsConfig + + UserConfig +} + +// BinaryVersion is the current version of the CF binary. +func (config *Config) BinaryVersion() string { + return version.VersionString() +} + +// IsTTY returns true based off of: +// - The $FORCE_TTY is set to true/t/1 +// - Detected from the STDOUT stream +func (config *Config) IsTTY() bool { + if config.ENV.ForceTTY != "" { + envVal, err := strconv.ParseBool(config.ENV.ForceTTY) + if err == nil { + return envVal + } + } + + return config.detectedSettings.tty +} + +// TerminalWidth returns the width of the terminal from when the config +// was loaded. If the terminal width has changed since the config has loaded, +// it will **not** return the new width. +func (config *Config) TerminalWidth() int { + return config.detectedSettings.terminalWidth +} + +// Verbose returns true if verbose should be displayed to terminal, in addition +// a slice of absolute paths in which verbose text will appear. This is based +// off of: +// - The config file's trace value (true/false/file path) +// - The $CF_TRACE environment variable if set (true/false/file path) +// - The '-v/--verbose' global flag +// - Defaults to false +func (config *Config) Verbose() (bool, []string) { + var ( + verbose bool + envOverride bool + filePath []string + ) + if config.ENV.CFTrace != "" { + envVal, err := strconv.ParseBool(config.ENV.CFTrace) + verbose = envVal + if err != nil { + filePath = []string{config.ENV.CFTrace} + } else { + envOverride = true + } + } + if config.ConfigFile.Trace != "" { + envVal, err := strconv.ParseBool(config.ConfigFile.Trace) + if !envOverride { + verbose = envVal || verbose + } + if err != nil { + filePath = append(filePath, config.ConfigFile.Trace) + } + } + verbose = config.Flags.Verbose || verbose + + for i, path := range filePath { + if !filepath.IsAbs(path) { + filePath[i] = filepath.Join(config.detectedSettings.currentDirectory, path) + } + resolvedPath, err := filepath.EvalSymlinks(filePath[i]) + if err == nil { + filePath[i] = resolvedPath + } + } + + return verbose, filePath +} + +func (config *Config) SetKubernetesAuthInfo(authInfo string) { + config.ConfigFile.CFOnK8s.AuthInfo = authInfo +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/default_user_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/default_user_config.go new file mode 100644 index 0000000..f2d96df --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/default_user_config.go @@ -0,0 +1,58 @@ +package configv3 + +import ( + "github.com/SermoDigital/jose/jws" +) + +type DefaultUserConfig struct { + // ConfigFile stores the configuration from the .cf/config + ConfigFile *JSONConfig +} + +// CurrentUser returns user information decoded from the JWT access token in +// .cf/config.json. +func (config DefaultUserConfig) CurrentUser() (User, error) { + return decodeUserFromJWT(config.ConfigFile.AccessToken) +} + +// CurrentUserName returns the name of a user as returned by CurrentUser() +func (config DefaultUserConfig) CurrentUserName() (string, error) { + user, err := config.CurrentUser() + if err != nil { + return "", err + } + return user.Name, nil +} + +func decodeUserFromJWT(accessToken string) (User, error) { + if accessToken == "" { + return User{}, nil + } + + token, err := jws.ParseJWT([]byte(accessToken[7:])) + if err != nil { + return User{}, err + } + + claims := token.Claims() + + var name, GUID, origin string + var isClient bool + if claims.Has("user_name") { + name = claims.Get("user_name").(string) + GUID = claims.Get("user_id").(string) + origin = claims.Get("origin").(string) + isClient = false + } else { + name = claims.Get("client_id").(string) + GUID = name + isClient = true + } + + return User{ + Name: name, + GUID: GUID, + Origin: origin, + IsClient: isClient, + }, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/defaults.go b/vendor/code.cloudfoundry.org/cli/util/configv3/defaults.go new file mode 100644 index 0000000..83c147a --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/defaults.go @@ -0,0 +1,74 @@ +package configv3 + +import "time" + +const ( + // CurrentConfigVersion is the version field for the main config file + CurrentConfigVersion = 4 + + // DefaultDialTimeout is the default timeout for the dial. + DefaultDialTimeout = 6 * time.Second + + // DefaultNOAARetryCount is the default number of request retries. + DefaultNOAARetryCount = 5 + + // DefaultOverallPollingTimeout is the default maximum time that the CLI will + // poll a job running on the Cloud Controller. By default it's infinite, + // which is represented by MaxInt64. + DefaultOverallPollingTimeout = time.Duration(1 << 62) + // Developer Note: Due to bugs in using MaxInt64 during comparison, the above + // was chosen as a replacement. + + // DefaultPollingInterval is the time between consecutive polls of a status. + DefaultPollingInterval = 3 * time.Second + + // DefaultStagingTimeout is the default timeout for application staging. + DefaultStagingTimeout = 15 * time.Minute + + // DefaultStartupTimeout is the default timeout for application starting. + DefaultStartupTimeout = 5 * time.Minute + + // DefaultTarget is the default CFConfig value for Target. + DefaultTarget = "" + + // DefaultSSHOAuthClient is the default oauth client ID for SSHing into an + // application/process container + DefaultSSHOAuthClient = "ssh-proxy" + + // DefaultUAADisableKeepAlives is the default value that the UAA client will + // use for Transport.DisableKeepAlives. UAA connections should always be + // closed after every request because UAA communication is infrequent. + DefaultUAADisableKeepAlives = true + + // DefaultUAAOAuthClient is the default client ID for the CLI when + // communicating with the UAA. + DefaultUAAOAuthClient = "cf" + + // DefaultUAAOAuthClientSecret is the default client secret for the CLI when + // communicating with the UAA. + DefaultUAAOAuthClientSecret = "" + + // DefaultRetryCount is the default number of request retries. + DefaultRetryCount = 2 +) + +// NOAARequestRetryCount returns the number of request retries. +func (*Config) NOAARequestRetryCount() int { + return DefaultNOAARetryCount +} + +// PollingInterval returns the time between polls. +func (config *Config) PollingInterval() time.Duration { + return DefaultPollingInterval +} + +// RequestRetryCount returns the number of request retries. +func (*Config) RequestRetryCount() int { + return DefaultRetryCount +} + +// UAADisableKeepAlives returns true when TCP connections should not be reused +// for UAA. +func (*Config) UAADisableKeepAlives() bool { + return DefaultUAADisableKeepAlives +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/detected_settings.go b/vendor/code.cloudfoundry.org/cli/util/configv3/detected_settings.go new file mode 100644 index 0000000..02352d8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/detected_settings.go @@ -0,0 +1,8 @@ +package configv3 + +// detectedSettings are automatically detected settings determined by the CLI. +type detectedSettings struct { + currentDirectory string + terminalWidth int + tty bool +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/dynamic_user_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/dynamic_user_config.go new file mode 100644 index 0000000..86c6ea5 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/dynamic_user_config.go @@ -0,0 +1,22 @@ +package configv3 + +type DynamicUserConfig struct { + ConfigFile *JSONConfig + DefaultUserConfig UserConfig + KubernetesUserConfig UserConfig +} + +func (config DynamicUserConfig) CurrentUser() (User, error) { + return config.pickConfig().CurrentUser() +} + +func (config DynamicUserConfig) CurrentUserName() (string, error) { + return config.pickConfig().CurrentUserName() +} + +func (config DynamicUserConfig) pickConfig() UserConfig { + if config.ConfigFile.CFOnK8s.Enabled { + return config.KubernetesUserConfig + } + return config.DefaultUserConfig +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/env.go b/vendor/code.cloudfoundry.org/cli/util/configv3/env.go new file mode 100644 index 0000000..031be34 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/env.go @@ -0,0 +1,145 @@ +package configv3 + +import ( + "strconv" + "strings" + "time" +) + +// EnvOverride represents all the environment variables read by the CF CLI +type EnvOverride struct { + BinaryName string + CFColor string + CFDialTimeout string + CFHome string + CFLogLevel string + CFPassword string + CFPluginHome string + CFStagingTimeout string + CFStartupTimeout string + CFTrace string + CFUsername string + DockerPassword string + Experimental string + ForceTTY string + HTTPSProxy string + Lang string + LCAll string +} + +// BinaryName returns the running name of the CF CLI +func (config *Config) BinaryName() string { + return config.ENV.BinaryName +} + +// CFPassword returns the value of the "CF_PASSWORD" environment variable. +func (config *Config) CFPassword() string { + return config.ENV.CFPassword +} + +// CFUsername returns the value of the "CF_USERNAME" environment variable. +func (config *Config) CFUsername() string { + return config.ENV.CFUsername +} + +// DialTimeout returns the timeout to use when dialing. This is based off of: +// 1. The $CF_DIAL_TIMEOUT environment variable if set +// 2. Falling back to the default +func (config *Config) DialTimeout() time.Duration { + if config.ENV.CFDialTimeout != "" { + envVal, err := strconv.ParseInt(config.ENV.CFDialTimeout, 10, 64) + if err == nil { + return time.Duration(envVal) * time.Second + } + } + + return DefaultDialTimeout +} + +// DockerPassword returns the docker password from the environment. +func (config *Config) DockerPassword() string { + return config.ENV.DockerPassword +} + +// Experimental returns whether or not to run experimental CLI commands. This +// is based on the following: +// 1. The $CF_CLI_EXPERIMENTAL environment variable if set +// 2. Defaults to false +func (config *Config) Experimental() bool { + if config.ENV.Experimental != "" { + envVal, err := strconv.ParseBool(config.ENV.Experimental) + if err == nil { + return envVal + } + } + + return false +} + +// HTTPSProxy returns the proxy url that the CLI should use. The url is based +// off of: +// 1. The $https_proxy environment variable if set +// 2. Defaults to the empty string +func (config *Config) HTTPSProxy() string { + return config.ENV.HTTPSProxy +} + +// LogLevel returns the global log level. The levels follow Logrus's log level +// scheme. This value is based off of: +// - The $CF_LOG_LEVEL and an int/warn/info/etc... +// - Defaults to PANIC/0 (ie no logging) +func (config *Config) LogLevel() int { + if config.ENV.CFLogLevel != "" { + envVal, err := strconv.ParseInt(config.ENV.CFLogLevel, 10, 32) + if err == nil { + return int(envVal) + } + + switch strings.ToLower(config.ENV.CFLogLevel) { + case "fatal": + return 1 + case "error": + return 2 + case "warn": + return 3 + case "info": + return 4 + case "debug": + return 5 + } + } + + return 0 +} + +// StagingTimeout returns the max time an application staging should take. The +// time is based off of: +// 1. The $CF_STAGING_TIMEOUT environment variable if set +// 2. Defaults to the DefaultStagingTimeout +func (config *Config) StagingTimeout() time.Duration { + if config.ENV.CFStagingTimeout != "" { + timeoutInMin, err := strconv.ParseFloat(config.ENV.CFStagingTimeout, 64) + timeoutInSec := int64(timeoutInMin * 60) + if err == nil { + return time.Duration(timeoutInSec) * time.Second + } + } + + return DefaultStagingTimeout +} + +// StartupTimeout returns the max time an application should take to start. The +// time is based off of: +// 1. The $CF_STARTUP_TIMEOUT environment variable if set +// 2. Defaults to the DefaultStartupTimeout +func (config *Config) StartupTimeout() time.Duration { + if config.ENV.CFStartupTimeout != "" { + timeoutInMin, err := strconv.ParseFloat(config.ENV.CFStartupTimeout, 64) + timeoutInSec := int64(timeoutInMin * 60) + if err == nil { + return time.Duration(timeoutInSec) * time.Second + } + } + + return DefaultStartupTimeout +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/flag_overrides.go b/vendor/code.cloudfoundry.org/cli/util/configv3/flag_overrides.go new file mode 100644 index 0000000..3507c08 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/flag_overrides.go @@ -0,0 +1,6 @@ +package configv3 + +// FlagOverride represents all the global flags passed to the CF CLI +type FlagOverride struct { + Verbose bool +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_unix.go b/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_unix.go new file mode 100644 index 0000000..b735d7b --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_unix.go @@ -0,0 +1,29 @@ +//go:build !windows +// +build !windows + +package configv3 + +import ( + "os" + "path/filepath" +) + +// ConfigFilePath returns the location of the config file +func ConfigFilePath() string { + return filepath.Join(configDirectory(), "config.json") +} + +func configDirectory() string { + return filepath.Join(homeDirectory(), ".cf") +} + +func homeDirectory() string { + var homeDir string + switch { + case os.Getenv("CF_HOME") != "": + homeDir = os.Getenv("CF_HOME") + default: + homeDir = os.Getenv("HOME") + } + return homeDir +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_windows.go b/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_windows.go new file mode 100644 index 0000000..18b1eee --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/home_dir_windows.go @@ -0,0 +1,33 @@ +//go:build windows +// +build windows + +package configv3 + +import ( + "os" + "path/filepath" +) + +// ConfigFilePath returns the location of the config file +func ConfigFilePath() string { + return filepath.Join(homeDirectory(), ".cf", "config.json") +} + +func configDirectory() string { + return filepath.Join(homeDirectory(), ".cf") +} + +// See: http://stackoverflow.com/questions/7922270/obtain-users-home-directory +// we can't cross compile using cgo and use user.Current() +func homeDirectory() string { + var homeDir string + switch { + case os.Getenv("CF_HOME") != "": + homeDir = os.Getenv("CF_HOME") + case os.Getenv("HOMEDRIVE")+os.Getenv("HOMEPATH") != "": + homeDir = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + default: + homeDir = os.Getenv("USERPROFILE") + } + return homeDir +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/json_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/json_config.go new file mode 100644 index 0000000..c672de9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/json_config.go @@ -0,0 +1,316 @@ +package configv3 + +import ( + "time" +) + +// JSONConfig represents .cf/config.json. +type JSONConfig struct { + AccessToken string `json:"AccessToken"` + APIVersion string `json:"APIVersion"` + AsyncTimeout int `json:"AsyncTimeout"` + AuthorizationEndpoint string `json:"AuthorizationEndpoint"` + CFOnK8s CFOnK8s `json:"CFOnK8s"` + ColorEnabled string `json:"ColorEnabled"` + ConfigVersion int `json:"ConfigVersion"` + DopplerEndpoint string `json:"DopplerEndPoint"` + Locale string `json:"Locale"` + LogCacheEndpoint string `json:"LogCacheEndPoint"` + MinCLIVersion string `json:"MinCLIVersion"` + MinRecommendedCLIVersion string `json:"MinRecommendedCLIVersion"` + NetworkPolicyV1Endpoint string `json:"NetworkPolicyV1Endpoint"` + TargetedOrganization Organization `json:"OrganizationFields"` + PluginRepositories []PluginRepository `json:"PluginRepos"` + RefreshToken string `json:"RefreshToken"` + RoutingEndpoint string `json:"RoutingAPIEndpoint"` + TargetedSpace Space `json:"SpaceFields"` + SSHOAuthClient string `json:"SSHOAuthClient"` + SkipSSLValidation bool `json:"SSLDisabled"` + Target string `json:"Target"` + Trace string `json:"Trace"` + UAAEndpoint string `json:"UaaEndpoint"` + UAAGrantType string `json:"UAAGrantType"` + UAAOAuthClient string `json:"UAAOAuthClient"` + UAAOAuthClientSecret string `json:"UAAOAuthClientSecret"` +} + +// Organization contains basic information about the targeted organization. +type Organization struct { + GUID string `json:"GUID"` + Name string `json:"Name"` +} + +// Space contains basic information about the targeted space. +type Space struct { + GUID string `json:"GUID"` + Name string `json:"Name"` + AllowSSH bool `json:"AllowSSH"` +} + +// User represents the user information provided by the JWT access token. +type User struct { + Name string + GUID string + Origin string + IsClient bool +} + +// AccessToken returns the access token for making authenticated API calls. +func (config *Config) AccessToken() string { + return config.ConfigFile.AccessToken +} + +// APIVersion returns the CC API Version. +func (config *Config) APIVersion() string { + return config.ConfigFile.APIVersion +} + +// AuthorizationEndpoint returns the authorization endpoint +func (config *Config) AuthorizationEndpoint() string { + return config.ConfigFile.AuthorizationEndpoint +} + +// HasTargetedOrganization returns true if the organization is set. +func (config *Config) HasTargetedOrganization() bool { + return config.ConfigFile.TargetedOrganization.GUID != "" +} + +// HasTargetedSpace returns true if the space is set. +func (config *Config) HasTargetedSpace() bool { + return config.ConfigFile.TargetedSpace.GUID != "" +} + +// LogCacheEndpoint returns the log cache endpoint. +func (config *Config) LogCacheEndpoint() string { + return config.ConfigFile.LogCacheEndpoint +} + +// MinCLIVersion returns the minimum CLI version required by the CC. +func (config *Config) MinCLIVersion() string { + return config.ConfigFile.MinCLIVersion +} + +// OverallPollingTimeout returns the overall polling timeout for async +// operations. The time is based off of: +// 1. The config file's AsyncTimeout value (integer) is > 0 +// 2. Defaults to the DefaultOverallPollingTimeout +func (config *Config) OverallPollingTimeout() time.Duration { + if config.ConfigFile.AsyncTimeout == 0 { + return DefaultOverallPollingTimeout + } + return time.Duration(config.ConfigFile.AsyncTimeout) * time.Minute +} + +// NetworkPolicyV1Endpoint returns the endpoint for V1 of the networking API +func (config *Config) NetworkPolicyV1Endpoint() string { + return config.ConfigFile.NetworkPolicyV1Endpoint +} + +// RefreshToken returns the refresh token for getting a new access token. +func (config *Config) RefreshToken() string { + return config.ConfigFile.RefreshToken +} + +// RoutingEndpoint returns the endpoint for the router API +func (config *Config) RoutingEndpoint() string { + return config.ConfigFile.RoutingEndpoint +} + +// SetAsyncTimeout sets the async timeout. +func (config *Config) SetAsyncTimeout(timeout int) { + config.ConfigFile.AsyncTimeout = timeout +} + +// SetAccessToken sets the current access token. +func (config *Config) SetAccessToken(accessToken string) { + config.ConfigFile.AccessToken = accessToken +} + +// SetColorEnabled sets the color enabled feature to true or false +func (config *Config) SetColorEnabled(enabled string) { + config.ConfigFile.ColorEnabled = enabled +} + +// SetLocale sets the locale, or clears the field if requested +func (config *Config) SetLocale(locale string) { + if locale == "CLEAR" { + config.ConfigFile.Locale = "" + } else { + config.ConfigFile.Locale = locale + } +} + +// SetMinCLIVersion sets the minimum CLI version required by the CC. +func (config *Config) SetMinCLIVersion(minVersion string) { + config.ConfigFile.MinCLIVersion = minVersion +} + +// SetOrganizationInformation sets the currently targeted organization. +func (config *Config) SetOrganizationInformation(guid string, name string) { + config.ConfigFile.TargetedOrganization.GUID = guid + config.ConfigFile.TargetedOrganization.Name = name +} + +// SetRefreshToken sets the current refresh token. +func (config *Config) SetRefreshToken(refreshToken string) { + config.ConfigFile.RefreshToken = refreshToken +} + +// SetSpaceInformation sets the currently targeted space. +// The "AllowSSH" field is not returned by v3, and is never read from the config. +// Persist `true` to maintain compatibility in the config file. +// TODO: this field should be removed entirely in v7 +func (config *Config) SetSpaceInformation(guid string, name string, allowSSH bool) { + config.V7SetSpaceInformation(guid, name) + config.ConfigFile.TargetedSpace.AllowSSH = allowSSH +} + +type TargetInformationArgs struct { + Api string + ApiVersion string + Auth string + Doppler string + LogCache string + MinCLIVersion string + NetworkPolicyV1 string + Routing string + SkipSSLValidation bool + UAA string + CFOnK8s bool +} + +// SetTargetInformation sets the currently targeted CC API and related other +// related API URLs. +func (config *Config) SetTargetInformation(args TargetInformationArgs) { + config.ConfigFile.Target = args.Api + config.ConfigFile.APIVersion = args.ApiVersion + config.SetMinCLIVersion(args.MinCLIVersion) + config.ConfigFile.DopplerEndpoint = args.Doppler + config.ConfigFile.LogCacheEndpoint = args.LogCache + config.ConfigFile.RoutingEndpoint = args.Routing + config.ConfigFile.SkipSSLValidation = args.SkipSSLValidation + config.ConfigFile.NetworkPolicyV1Endpoint = args.NetworkPolicyV1 + + config.ConfigFile.UAAEndpoint = args.UAA + config.ConfigFile.AuthorizationEndpoint = args.Auth + + // NOTE: This gets written to the config file, but I do not believe it is currently + // ever read from there. + config.ConfigFile.AuthorizationEndpoint = args.Auth + + config.ConfigFile.CFOnK8s.Enabled = args.CFOnK8s + + config.UnsetOrganizationAndSpaceInformation() +} + +// SetTokenInformation sets the current token/user information. +func (config *Config) SetTokenInformation(accessToken string, refreshToken string, sshOAuthClient string) { + config.ConfigFile.AccessToken = accessToken + config.ConfigFile.RefreshToken = refreshToken + config.ConfigFile.SSHOAuthClient = sshOAuthClient +} + +// SetTrace sets the trace field to either true, false, or a path to a file. +func (config *Config) SetTrace(trace string) { + config.ConfigFile.Trace = trace +} + +// SetUAAClientCredentials sets the client credentials. +func (config *Config) SetUAAClientCredentials(client string, clientSecret string) { + config.ConfigFile.UAAOAuthClient = client + config.ConfigFile.UAAOAuthClientSecret = clientSecret +} + +// SetUAAEndpoint sets the UAA endpoint that is obtained from hitting +// /login. +func (config *Config) SetUAAEndpoint(uaaEndpoint string) { + config.ConfigFile.UAAEndpoint = uaaEndpoint +} + +// SetUAAGrantType sets the UAA grant type for logging in and refreshing the +// token. +func (config *Config) SetUAAGrantType(uaaGrantType string) { + config.ConfigFile.UAAGrantType = uaaGrantType +} + +// SkipSSLValidation returns whether or not to skip SSL validation when +// targeting an API endpoint. +func (config *Config) SkipSSLValidation() bool { + return config.ConfigFile.SkipSSLValidation +} + +// SSHOAuthClient returns the OAuth client id used for SSHing into +// application/process containers. +func (config *Config) SSHOAuthClient() string { + return config.ConfigFile.SSHOAuthClient +} + +// Target returns the CC API URL. +func (config *Config) Target() string { + return config.ConfigFile.Target +} + +// TargetedOrganization returns the currently targeted organization. +func (config *Config) TargetedOrganization() Organization { + return config.ConfigFile.TargetedOrganization +} + +// TargetedOrganizationName returns the name of the targeted organization. +func (config *Config) TargetedOrganizationName() string { + return config.TargetedOrganization().Name +} + +// TargetedSpace returns the currently targeted space. +func (config *Config) TargetedSpace() Space { + return config.ConfigFile.TargetedSpace +} + +// UAAEndpoint returns the UAA endpoint +func (config *Config) UAAEndpoint() string { + return config.ConfigFile.UAAEndpoint +} + +// UAAGrantType returns the grant type of the supplied UAA credentials. +func (config *Config) UAAGrantType() string { + return config.ConfigFile.UAAGrantType +} + +// UAAOAuthClient returns the CLI's UAA client ID. +func (config *Config) UAAOAuthClient() string { + return config.ConfigFile.UAAOAuthClient +} + +// UAAOAuthClientSecret returns the CLI's UAA client secret. +func (config *Config) UAAOAuthClientSecret() string { + return config.ConfigFile.UAAOAuthClientSecret +} + +// UnsetOrganizationAndSpaceInformation resets the organization and space +// values to default. +func (config *Config) UnsetOrganizationAndSpaceInformation() { + config.SetOrganizationInformation("", "") + config.UnsetSpaceInformation() +} + +// UnsetSpaceInformation resets the space values to default. +func (config *Config) UnsetSpaceInformation() { + config.SetSpaceInformation("", "", false) +} + +// UnsetUserInformation resets the access token, refresh token, UAA grant type, +// UAA client credentials, and targeted org/space information. +func (config *Config) UnsetUserInformation() { + config.SetAccessToken("") + config.SetRefreshToken("") + config.SetUAAGrantType("") + config.SetUAAClientCredentials(DefaultUAAOAuthClient, DefaultUAAOAuthClientSecret) + config.SetKubernetesAuthInfo("") + + config.UnsetOrganizationAndSpaceInformation() +} + +// V7SetSpaceInformation sets the currently targeted space. +func (config *Config) V7SetSpaceInformation(guid string, name string) { + config.ConfigFile.TargetedSpace.GUID = guid + config.ConfigFile.TargetedSpace.Name = name +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/k8s.go b/vendor/code.cloudfoundry.org/cli/util/configv3/k8s.go new file mode 100644 index 0000000..e7e69aa --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/k8s.go @@ -0,0 +1,10 @@ +package configv3 + +type CFOnK8s struct { + Enabled bool `json:"Enabled"` + AuthInfo string `json:"AuthInfo"` +} + +func (config *Config) IsCFOnK8s() bool { + return config.ConfigFile.CFOnK8s.Enabled +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/kubernetes_user_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/kubernetes_user_config.go new file mode 100644 index 0000000..0ae5f48 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/kubernetes_user_config.go @@ -0,0 +1,17 @@ +package configv3 + +type KubernetesUserConfig struct { + // ConfigFile stores the configuration from the .cf/config + ConfigFile *JSONConfig +} + +// CurrentUser returns user information decoded from the JWT access token in +// .cf/config.json. +func (config KubernetesUserConfig) CurrentUser() (User, error) { + return User{Name: config.ConfigFile.CFOnK8s.AuthInfo}, nil +} + +// CurrentUserName returns the name of a user as returned by CurrentUser() +func (config KubernetesUserConfig) CurrentUserName() (string, error) { + return config.ConfigFile.CFOnK8s.AuthInfo, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/load_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/load_config.go new file mode 100644 index 0000000..90470e2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/load_config.go @@ -0,0 +1,192 @@ +package configv3 + +import ( + "encoding/json" + "io/ioutil" + "math" + "os" + "path/filepath" + + "code.cloudfoundry.org/cli/command/translatableerror" + "golang.org/x/crypto/ssh/terminal" +) + +func (c *Config) loadPluginConfig() error { + pluginFilePath := filepath.Join(c.PluginHome(), "config.json") + if _, err := os.Stat(pluginFilePath); os.IsNotExist(err) { + c.pluginsConfig = PluginsConfig{ + Plugins: make(map[string]Plugin), + } + } else { + var file []byte + file, err = ioutil.ReadFile(pluginFilePath) + if err != nil { + return err + } + + err = json.Unmarshal(file, &c.pluginsConfig) + if err != nil { + return err + } + + for name, plugin := range c.pluginsConfig.Plugins { + plugin.Name = name + c.pluginsConfig.Plugins[name] = plugin + } + } + return nil +} + +func GetCFConfig() (*Config, error) { + cfConfig, configErr := LoadConfig() + if configErr != nil { + if _, ok := configErr.(translatableerror.EmptyConfigError); !ok { + return nil, configErr + } + } + return cfConfig, nil +} + +// LoadConfig loads the config from the .cf/config.json and os.ENV. If the +// config.json does not exists, it will use a default config in its place. +// Takes in an optional FlagOverride, will only use the first one passed, that +// can override the given flag values. +// +// The '.cf' directory will be read in one of the following locations on UNIX +// Systems: +// 1. $CF_HOME/.cf if $CF_HOME is set +// 2. $HOME/.cf as the default +// +// The '.cf' directory will be read in one of the following locations on +// Windows Systems: +// 1. CF_HOME\.cf if CF_HOME is set +// 2. HOMEDRIVE\HOMEPATH\.cf if HOMEDRIVE or HOMEPATH is set +// 3. USERPROFILE\.cf as the default +func LoadConfig(flags ...FlagOverride) (*Config, error) { + err := removeOldTempConfigFiles() + if err != nil { + return nil, err + } + + configFilePath := ConfigFilePath() + + config := Config{ + ConfigFile: JSONConfig{ + ConfigVersion: CurrentConfigVersion, + Target: DefaultTarget, + ColorEnabled: DefaultColorEnabled, + PluginRepositories: []PluginRepository{{ + Name: DefaultPluginRepoName, + URL: DefaultPluginRepoURL, + }}, + }, + } + + var jsonError error + + if _, err = os.Stat(configFilePath); err == nil || !os.IsNotExist(err) { + var file []byte + file, err = ioutil.ReadFile(configFilePath) + if err != nil { + return nil, err + } + + if len(file) == 0 { + // TODO: change this to not use translatableerror + jsonError = translatableerror.EmptyConfigError{FilePath: configFilePath} + } else { + var configFile JSONConfig + err = json.Unmarshal(file, &configFile) + if err != nil { + return nil, err + } + if configFile.ConfigVersion == CurrentConfigVersion { + config.ConfigFile = configFile + } + } + } + + if config.ConfigFile.SSHOAuthClient == "" { + config.ConfigFile.SSHOAuthClient = DefaultSSHOAuthClient + } + + if config.ConfigFile.UAAOAuthClient == "" { + config.ConfigFile.UAAOAuthClient = DefaultUAAOAuthClient + config.ConfigFile.UAAOAuthClientSecret = DefaultUAAOAuthClientSecret + } + + config.ENV = EnvOverride{ + BinaryName: filepath.Base(os.Args[0]), + CFColor: os.Getenv("CF_COLOR"), + CFDialTimeout: os.Getenv("CF_DIAL_TIMEOUT"), + CFLogLevel: os.Getenv("CF_LOG_LEVEL"), + CFPassword: os.Getenv("CF_PASSWORD"), + CFPluginHome: os.Getenv("CF_PLUGIN_HOME"), + CFStagingTimeout: os.Getenv("CF_STAGING_TIMEOUT"), + CFStartupTimeout: os.Getenv("CF_STARTUP_TIMEOUT"), + CFTrace: os.Getenv("CF_TRACE"), + CFUsername: os.Getenv("CF_USERNAME"), + DockerPassword: os.Getenv("CF_DOCKER_PASSWORD"), + Experimental: os.Getenv("CF_CLI_EXPERIMENTAL"), + ForceTTY: os.Getenv("FORCE_TTY"), + HTTPSProxy: os.Getenv("https_proxy"), + Lang: os.Getenv("LANG"), + LCAll: os.Getenv("LC_ALL"), + } + + err = config.loadPluginConfig() + if err != nil { + return nil, err + } + + if len(flags) > 0 { + config.Flags = flags[0] + } + + pwd, err := os.Getwd() + if err != nil { + return nil, err + } + + // Developer Note: The following is untested! Change at your own risk. + isTTY := terminal.IsTerminal(int(os.Stdout.Fd())) + terminalWidth := math.MaxInt32 + + if isTTY { + var err error + terminalWidth, _, err = terminal.GetSize(int(os.Stdout.Fd())) + if err != nil { + return nil, err + } + } + + config.detectedSettings = detectedSettings{ + currentDirectory: pwd, + terminalWidth: terminalWidth, + tty: isTTY, + } + + config.UserConfig = DynamicUserConfig{ + ConfigFile: &config.ConfigFile, + DefaultUserConfig: DefaultUserConfig{ConfigFile: &config.ConfigFile}, + KubernetesUserConfig: KubernetesUserConfig{ConfigFile: &config.ConfigFile}, + } + + return &config, jsonError +} + +func removeOldTempConfigFiles() error { + oldTempFileNames, err := filepath.Glob(filepath.Join(configDirectory(), "temp-config?*")) + if err != nil { + return err + } + + for _, oldTempFileName := range oldTempFileNames { + err = os.Remove(oldTempFileName) + if err != nil { + return err + } + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/locale.go b/vendor/code.cloudfoundry.org/cli/util/configv3/locale.go new file mode 100644 index 0000000..99da3e0 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/locale.go @@ -0,0 +1,35 @@ +package configv3 + +import "strings" + +const ( + // DefaultLocale is the default CFConfig value for Locale. + DefaultLocale = "" +) + +// Locale returns the locale/language the UI should be displayed in. This value +// is based off of: +// 1. The 'Locale' setting in the .cf/config.json +// 2. The $LC_ALL environment variable if set +// 3. The $LANG environment variable if set +// 4. Defaults to DefaultLocale +func (config *Config) Locale() string { + if config.ConfigFile.Locale != "" { + return config.ConfigFile.Locale + } + + if config.ENV.LCAll != "" { + return config.convertLocale(config.ENV.LCAll) + } + + if config.ENV.Lang != "" { + return config.convertLocale(config.ENV.Lang) + } + + return DefaultLocale +} + +func (config *Config) convertLocale(local string) string { + lang := strings.Split(local, ".")[0] + return strings.Replace(lang, "_", "-", -1) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/plugin_repository.go b/vendor/code.cloudfoundry.org/cli/util/configv3/plugin_repository.go new file mode 100644 index 0000000..43fc720 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/plugin_repository.go @@ -0,0 +1,37 @@ +package configv3 + +import ( + "sort" + "strings" +) + +const ( + // DefaultPluginRepoName is the name of the preinstalled plugin repository. + DefaultPluginRepoName = "CF-Community" + + // DefaultPluginRepoURL is the URL of the preinstalled plugin repository. + DefaultPluginRepoURL = "https://plugins.cloudfoundry.org" +) + +// PluginRepository is a saved plugin repository +type PluginRepository struct { + Name string `json:"Name"` + URL string `json:"URL"` +} + +// AddPluginRepository adds an new repository to the plugin config. It does not +// add duplicates to the config. +func (config *Config) AddPluginRepository(name string, url string) { + config.ConfigFile.PluginRepositories = append(config.ConfigFile.PluginRepositories, + PluginRepository{Name: name, URL: url}) +} + +// PluginRepositories returns the currently configured plugin repositories from the +// .cf/config.json. +func (config *Config) PluginRepositories() []PluginRepository { + repos := config.ConfigFile.PluginRepositories + sort.Slice(repos, func(i, j int) bool { + return strings.ToLower(repos[i].Name) < strings.ToLower(repos[j].Name) + }) + return repos +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/plugins_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/plugins_config.go new file mode 100644 index 0000000..d5776e9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/plugins_config.go @@ -0,0 +1,161 @@ +package configv3 + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + + "code.cloudfoundry.org/cli/util" +) + +const notApplicable = "N/A" + +// PluginsConfig represents the plugin configuration +type PluginsConfig struct { + Plugins map[string]Plugin `json:"Plugins"` +} + +// Plugin represents the plugin as a whole, not be confused with PluginCommand +type Plugin struct { + Name string + Location string `json:"Location"` + Version PluginVersion `json:"Version"` + LibraryVersion PluginVersion `json:"LibraryVersion"` + Commands []PluginCommand `json:"Commands"` +} + +// CalculateSHA1 returns the SHA1 value of the plugin executable. If an error +// is encountered calculating SHA1, N/A is returned +func (p Plugin) CalculateSHA1() string { + fileSHA, err := util.NewSha1Checksum(p.Location).ComputeFileSha1() + + if err != nil { + return notApplicable + } + + return fmt.Sprintf("%x", fileSHA) +} + +// PluginCommands returns the plugin's commands sorted by command name. +func (p Plugin) PluginCommands() []PluginCommand { + sort.Slice(p.Commands, func(i, j int) bool { + return strings.ToLower(p.Commands[i].Name) < strings.ToLower(p.Commands[j].Name) + }) + return p.Commands +} + +// PluginVersion is the plugin version information +type PluginVersion struct { + Major int `json:"Major"` + Minor int `json:"Minor"` + Build int `json:"Build"` +} + +// String returns the plugin's version in the format x.y.z. +func (v PluginVersion) String() string { + if v.Major == 0 && v.Minor == 0 && v.Build == 0 { + return notApplicable + } + return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Build) +} + +// PluginCommand represents an individual command inside a plugin +type PluginCommand struct { + Name string `json:"Name"` + Alias string `json:"Alias"` + HelpText string `json:"HelpText"` + UsageDetails PluginUsageDetails `json:"UsageDetails"` +} + +// CommandName returns the name of the plugin. The name is concatenated with +// alias if alias is specified. +func (c PluginCommand) CommandName() string { + if c.Name != "" && c.Alias != "" { + return fmt.Sprintf("%s, %s", c.Name, c.Alias) + } + return c.Name +} + +// PluginUsageDetails contains the usage metadata provided by the plugin +type PluginUsageDetails struct { + Usage string `json:"Usage"` + Options map[string]string `json:"Options"` +} + +// AddPlugin adds the specified plugin to PluginsConfig +func (config *Config) AddPlugin(plugin Plugin) { + config.pluginsConfig.Plugins[plugin.Name] = plugin +} + +func (config *Config) CreatePluginHome() error { + return os.MkdirAll(config.PluginHome(), 0700) +} + +// GetPlugin returns the requested plugin and true if it exists. +func (config *Config) GetPlugin(pluginName string) (Plugin, bool) { + plugin, exists := config.pluginsConfig.Plugins[pluginName] + return plugin, exists +} + +// GetPluginCaseInsensitive finds the first matching plugin name case +// insensitive and returns true if it exists. +func (config *Config) GetPluginCaseInsensitive(pluginName string) (Plugin, bool) { + for name, plugin := range config.pluginsConfig.Plugins { + if strings.EqualFold(name, pluginName) { + return plugin, true + } + } + + return Plugin{}, false +} + +// PluginHome returns the plugin configuration directory to: +// 1. The $CF_PLUGIN_HOME/.cf/plugins environment variable if set +// 2. Defaults to the home directory (outlined in LoadConfig)/.cf/plugins +func (config *Config) PluginHome() string { + if config.ENV.CFPluginHome != "" { + return filepath.Join(config.ENV.CFPluginHome, ".cf", "plugins") + } + + return filepath.Join(homeDirectory(), ".cf", "plugins") +} + +// Plugins returns installed plugins from the config sorted by name (case-insensitive). +func (config *Config) Plugins() []Plugin { + plugins := []Plugin{} + for _, plugin := range config.pluginsConfig.Plugins { + plugins = append(plugins, plugin) + } + sort.Slice(plugins, func(i, j int) bool { + return strings.ToLower(plugins[i].Name) < strings.ToLower(plugins[j].Name) + }) + return plugins +} + +// RemovePlugin removes the specified plugin from PluginsConfig idempotently +func (config *Config) RemovePlugin(pluginName string) { + delete(config.pluginsConfig.Plugins, pluginName) +} + +// WritePluginConfig writes the plugin config to config.json in the plugin home +// directory. +func (config *Config) WritePluginConfig() error { + // Marshal JSON + rawConfig, err := json.MarshalIndent(config.pluginsConfig, "", " ") + if err != nil { + return err + } + + pluginFileDir := filepath.Join(config.PluginHome()) + err = os.MkdirAll(pluginFileDir, 0700) + if err != nil { + return err + } + + // Write to file + return ioutil.WriteFile(filepath.Join(pluginFileDir, "config.json"), rawConfig, 0600) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/configv3/write_config.go b/vendor/code.cloudfoundry.org/cli/util/configv3/write_config.go new file mode 100644 index 0000000..15f0263 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/configv3/write_config.go @@ -0,0 +1,67 @@ +package configv3 + +import ( + "encoding/json" + "io/ioutil" + "os" + "os/signal" + "syscall" + "time" +) + +// WriteConfig creates the .cf directory and then writes the config.json. The +// location of .cf directory is written in the same way LoadConfig reads .cf +// directory. +func (c *Config) WriteConfig() error { + rawConfig, err := json.MarshalIndent(c.ConfigFile, "", " ") + if err != nil { + return err + } + + dir := configDirectory() + err = os.MkdirAll(dir, 0700) + if err != nil { + return err + } + + // Developer Note: The following is untested! Change at your own risk. + // Setup notifications of termination signals to channel sig, create a process to + // watch for these signals so we can remove transient config temp files. + sig := make(chan os.Signal, 10) + signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, os.Interrupt) + defer signal.Stop(sig) + + tempConfigFile, err := ioutil.TempFile(dir, "temp-config") + if err != nil { + return err + } + tempConfigFile.Close() + tempConfigFileName := tempConfigFile.Name() + + go catchSignal(sig, tempConfigFileName) + + err = ioutil.WriteFile(tempConfigFileName, rawConfig, 0600) + if err != nil { + return err + } + + for i := 0; i < 5; i++ { + if err := os.Rename(tempConfigFileName, ConfigFilePath()); err == nil { + return nil + } + + time.Sleep(50 * time.Millisecond) + } + + return os.Rename(tempConfigFileName, ConfigFilePath()) +} + +// catchSignal tries to catch SIGHUP, SIGINT, SIGKILL, SIGQUIT and SIGTERM, and +// Interrupt for removing temporarily created config files before the program +// ends. Note: we cannot intercept a `kill -9`, so a well-timed `kill -9` +// will allow a temp config file to linger. +func catchSignal(sig chan os.Signal, tempConfigFileName string) { + <-sig + _ = os.Remove(tempConfigFileName) + os.Exit(2) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/download/downloader.go b/vendor/code.cloudfoundry.org/cli/util/download/downloader.go new file mode 100644 index 0000000..3656046 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/download/downloader.go @@ -0,0 +1,68 @@ +package download + +import ( + "io" + "io/ioutil" + "net" + "net/http" + "os" + "path/filepath" + "time" + + "code.cloudfoundry.org/cli/util" +) + +type Downloader struct { + HTTPClient HTTPClient +} + +func NewDownloader(dialTimeout time.Duration) *Downloader { + tr := &http.Transport{ + TLSClientConfig: util.NewTLSConfig(nil, false), + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + KeepAlive: 30 * time.Second, + Timeout: dialTimeout, + }).DialContext, + } + + return &Downloader{ + HTTPClient: &http.Client{ + Transport: tr, + }, + } +} + +func (downloader Downloader) Download(url string, tmpDirPath string) (string, error) { + bpFileName := filepath.Join(tmpDirPath, filepath.Base(url)) + + resp, err := downloader.HTTPClient.Get(url) + if err != nil { + return bpFileName, err + } + defer resp.Body.Close() + + if resp.StatusCode >= 400 { + rawBytes, readErr := ioutil.ReadAll(resp.Body) + if readErr != nil { + return bpFileName, readErr + } + return bpFileName, RawHTTPStatusError{ + Status: resp.Status, + RawResponse: rawBytes, + } + } + + file, err := os.Create(bpFileName) + if err != nil { + return bpFileName, err + } + defer file.Close() + + _, err = io.Copy(file, resp.Body) + if err != nil { + return bpFileName, err + } + + return bpFileName, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/download/http_client.go b/vendor/code.cloudfoundry.org/cli/util/download/http_client.go new file mode 100644 index 0000000..8ffc025 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/download/http_client.go @@ -0,0 +1,9 @@ +package download + +import "net/http" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . HTTPClient + +type HTTPClient interface { + Get(url string) (resp *http.Response, err error) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/download/progress_bar.go b/vendor/code.cloudfoundry.org/cli/util/download/progress_bar.go new file mode 100644 index 0000000..6f84a15 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/download/progress_bar.go @@ -0,0 +1,16 @@ +package download + +import ( + "io" + + pb "gopkg.in/cheggaaa/pb.v1" +) + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . ProgressBar + +type ProgressBar interface { + Finish() + NewProxyReader(r io.Reader) *pb.Reader + SetTotal(total int) *pb.ProgressBar + Start() *pb.ProgressBar +} diff --git a/vendor/code.cloudfoundry.org/cli/util/download/raw_http_status_error.go b/vendor/code.cloudfoundry.org/cli/util/download/raw_http_status_error.go new file mode 100644 index 0000000..374c5d8 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/download/raw_http_status_error.go @@ -0,0 +1,13 @@ +package download + +import "fmt" + +// RawHTTPStatusError represents any response with a 4xx or 5xx status code. +type RawHTTPStatusError struct { + Status string + RawResponse []byte +} + +func (r RawHTTPStatusError) Error() string { + return fmt.Sprintf("HTTP Response: %s\nHTTP Response Body: %s", r.Status, r.RawResponse) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/extract/extract.go b/vendor/code.cloudfoundry.org/cli/util/extract/extract.go new file mode 100644 index 0000000..917960e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/extract/extract.go @@ -0,0 +1,64 @@ +package extract + +import ( + "reflect" + "strings" + + "code.cloudfoundry.org/cli/util/unique" +) + +type appender func(string) + +func UniqueList(expr string, input interface{}) []string { + return unique.StringSlice(List(expr, input)) +} + +func First(expr string, input interface{}) string { + l := List(expr, input) + if len(l) > 0 { + return l[0] + } + return "" +} + +func List(expr string, input interface{}) []string { + var result []string + app := func(v string) { + result = append(result, v) + } + + path := strings.Split(expr, ".") + val := reflect.ValueOf(input) + + extract(app, path, val) + return result +} + +func extract(app appender, path []string, input reflect.Value) { + switch input.Kind() { + case reflect.Struct: + extractStruct(app, path, input) + case reflect.Slice: + extractSlice(app, path, input) + case reflect.Interface: + extract(app, path, input.Elem()) + } +} + +func extractSlice(app appender, path []string, input reflect.Value) { + for i := 0; i < input.Len(); i++ { + extract(app, path, input.Index(i)) + } +} + +func extractStruct(app appender, path []string, input reflect.Value) { + v := input.FieldByName(path[0]) + if v.IsValid() { + switch v.Kind() { + case reflect.String: + app(v.String()) + default: + extract(app, path[1:], v) + } + } +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/architecture.go b/vendor/code.cloudfoundry.org/cli/util/generic/architecture.go new file mode 100644 index 0000000..3dc90dc --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/architecture.go @@ -0,0 +1,18 @@ +package generic + +func GeneratePlatform(runtimeGOOS string, runtimeGOARCH string) string { + switch { + case runtimeGOOS == "linux" && runtimeGOARCH == "amd64": + return "linux64" + case runtimeGOOS == "linux" && runtimeGOARCH == "386": + return "linux32" + case runtimeGOOS == "windows" && runtimeGOARCH == "amd64": + return "win64" + case runtimeGOOS == "windows" && runtimeGOARCH == "386": + return "win32" + case runtimeGOOS == "darwin": + return "osx" + default: + return "" + } +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_unix.go b/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_unix.go new file mode 100644 index 0000000..65de127 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_unix.go @@ -0,0 +1,10 @@ +//go:build !windows +// +build !windows + +package generic + +// ExecutableFilename appends does something on Windows, but it is a no-op +// on the many flavors of UNIX. +func ExecutableFilename(name string) string { + return name +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_windows.go b/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_windows.go new file mode 100644 index 0000000..12b3910 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/executable_filename_windows.go @@ -0,0 +1,18 @@ +//go:build windows +// +build windows + +package generic + +import ( + "fmt" + "strings" +) + +// ExecutableFilename appends '.exe' to a filename when necessary in order to +// make it executable on Windows +func ExecutableFilename(name string) string { + if strings.HasSuffix(name, ".exe") { + return name + } + return fmt.Sprintf("%s.exe", name) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/map.go b/vendor/code.cloudfoundry.org/cli/util/generic/map.go new file mode 100644 index 0000000..8d747a4 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/map.go @@ -0,0 +1,153 @@ +package generic + +import ( + "fmt" + "reflect" +) + +type Map interface { + IsEmpty() bool + Count() int + Keys() []interface{} + Has(key interface{}) bool + Except(keys []interface{}) Map + IsNil(key interface{}) bool + NotNil(key interface{}) bool + Get(key interface{}) interface{} + Set(key interface{}, value interface{}) + Delete(key interface{}) + String() string +} + +func NewMap(data ...interface{}) Map { + if len(data) == 0 { + return newEmptyMap() + } else if len(data) > 1 { + panic("NewMap called with more than one argument") + } + + switch data := data[0].(type) { + case nil: + return newEmptyMap() + case Map: + return data + case map[string]string: + stringMap := newEmptyMap() + for key, val := range data { + stringMap.Set(key, val) + } + return stringMap + case map[string]interface{}: + stringToInterfaceMap := newEmptyMap() + for key, val := range data { + stringToInterfaceMap.Set(key, val) + } + return stringToInterfaceMap + case map[interface{}]interface{}: + mapp := ConcreteMap(data) + return &mapp + } + + fmt.Printf("\n\n map: %T", data) + panic("NewMap called with unexpected argument") +} + +type Iterator func(key, val interface{}) + +func newEmptyMap() Map { + return &ConcreteMap{} +} + +type ConcreteMap map[interface{}]interface{} + +func (data *ConcreteMap) Count() int { + return len(*data) +} + +func (data *ConcreteMap) Delete(key interface{}) { + delete(*data, key) +} + +func (data *ConcreteMap) Except(keys []interface{}) Map { + otherMap := NewMap() + Each(data, func(key, value interface{}) { + if !Contains(keys, key) { + otherMap.Set(key, value) + } + }) + return otherMap +} + +func (data *ConcreteMap) Get(key interface{}) interface{} { + return (*data)[key] +} + +func (data *ConcreteMap) Has(key interface{}) bool { + _, ok := (*data)[key] + return ok +} + +func (data *ConcreteMap) IsEmpty() bool { + return data.Count() == 0 +} + +func (data *ConcreteMap) IsNil(key interface{}) bool { + maybe, ok := (*data)[key] + return ok && maybe == nil +} + +func (data *ConcreteMap) Keys() (keys []interface{}) { + keys = make([]interface{}, 0, data.Count()) + for key := range *data { + keys = append(keys, key) + } + + return +} + +func (data *ConcreteMap) NotNil(key interface{}) bool { + maybe, ok := (*data)[key] + return ok && maybe != nil +} + +func (data *ConcreteMap) Set(key, value interface{}) { + (*data)[key] = value +} + +func (data *ConcreteMap) String() string { + return fmt.Sprintf("% v", *data) +} + +func Contains(collection, item interface{}) bool { + switch collection := collection.(type) { + case Map: + return collection.Has(item) + case []interface{}: + for _, val := range collection { + if val == item { + return true + } + } + return false + } + + panic("unexpected type passed to Contains") +} + +func Each(collection Map, cb Iterator) { + for _, key := range collection.Keys() { + cb(key, collection.Get(key)) + } +} + +func IsMappable(value interface{}) bool { + if value == nil { + return false + } + switch value.(type) { + case Map: + return true + default: + return reflect.TypeOf(value).Kind() == reflect.Map + } +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/merge_reduce.go b/vendor/code.cloudfoundry.org/cli/util/generic/merge_reduce.go new file mode 100644 index 0000000..a21f473 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/merge_reduce.go @@ -0,0 +1,52 @@ +package generic + +type Reducer func(key, val interface{}, reducedVal Map) Map + +func DeepMerge(maps ...Map) Map { + mergedMap := NewMap() + return Reduce(maps, mergedMap, mergeReducer) +} + +func Merge(collection, otherCollection Map) Map { + mergedMap := NewMap() + + iterator := func(key, value interface{}) { + mergedMap.Set(key, value) + } + + Each(collection, iterator) + Each(otherCollection, iterator) + + return mergedMap +} + +func Reduce(collections []Map, resultVal Map, cb Reducer) Map { + for _, collection := range collections { + for _, key := range collection.Keys() { + resultVal = cb(key, collection.Get(key), resultVal) + } + } + return resultVal +} + +func mergeReducer(key, val interface{}, reduced Map) Map { + switch { + case reduced.Has(key) == false: + reduced.Set(key, val) + return reduced + + case IsMappable(val): + maps := []Map{NewMap(reduced.Get(key)), NewMap(val)} + mergedMap := Reduce(maps, NewMap(), mergeReducer) + reduced.Set(key, mergedMap) + return reduced + + case IsSliceable(val): + reduced.Set(key, append(reduced.Get(key).([]interface{}), val.([]interface{})...)) + return reduced + + default: + reduced.Set(key, val) + return reduced + } +} diff --git a/vendor/code.cloudfoundry.org/cli/util/generic/slice.go b/vendor/code.cloudfoundry.org/cli/util/generic/slice.go new file mode 100644 index 0000000..d523660 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/generic/slice.go @@ -0,0 +1,10 @@ +package generic + +import "reflect" + +func IsSliceable(value interface{}) bool { + if value == nil { + return false + } + return reflect.TypeOf(value).Kind() == reflect.Slice +} diff --git a/vendor/code.cloudfoundry.org/cli/util/lookuptable/name_from_guid.go b/vendor/code.cloudfoundry.org/cli/util/lookuptable/name_from_guid.go new file mode 100644 index 0000000..472f624 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/lookuptable/name_from_guid.go @@ -0,0 +1,20 @@ +package lookuptable + +import "reflect" + +func NameFromGUID(input interface{}) map[string]string { + val := reflect.ValueOf(input) + if val.Kind() != reflect.Slice || val.Type().Elem().Kind() != reflect.Struct { + return nil + } + + result := make(map[string]string) + for i := 0; i < val.Len(); i++ { + element := val.Index(i) + guid := element.FieldByName("GUID") + name := element.FieldByName("Name") + result[guid.String()] = name.String() + } + + return result +} diff --git a/vendor/code.cloudfoundry.org/cli/util/lookuptable/resource_from_guid.go b/vendor/code.cloudfoundry.org/cli/util/lookuptable/resource_from_guid.go new file mode 100644 index 0000000..878a6b9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/lookuptable/resource_from_guid.go @@ -0,0 +1,27 @@ +package lookuptable + +import "code.cloudfoundry.org/cli/resources" + +func OrgFromGUID(orgs []resources.Organization) map[string]resources.Organization { + result := make(map[string]resources.Organization) + for _, org := range orgs { + result[org.GUID] = org + } + return result +} + +func SpaceFromGUID(spaces []resources.Space) map[string]resources.Space { + result := make(map[string]resources.Space) + for _, space := range spaces { + result[space.GUID] = space + } + return result +} + +func AppFromGUID(apps []resources.Application) map[string]resources.Application { + result := make(map[string]resources.Application) + for _, app := range apps { + result[app.GUID] = app + } + return result +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/application.go b/vendor/code.cloudfoundry.org/cli/util/manifest/application.go new file mode 100644 index 0000000..e539a71 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/application.go @@ -0,0 +1,182 @@ +package manifest + +import ( + "fmt" + "strings" + + "code.cloudfoundry.org/cli/types" +) + +type Application struct { + Buildpack types.FilteredString + Buildpacks []string + Command types.FilteredString + DiskQuota types.NullByteSizeInMb + DockerImage string + DockerPassword string + DockerUsername string + Domain string + DropletPath string + // EnvironmentVariables can be any valid json type (ie, strings not + // guaranteed, although CLI only ships strings). + EnvironmentVariables map[string]string + HealthCheckHTTPEndpoint string + // HealthCheckTimeout attribute defines the number of seconds that is allocated + // for starting an application. + HealthCheckTimeout uint64 + // HealthCheckType specifies the mechanism used to determine if the application + // is healthy (e.g., an open port or an HTTP endpoint). + HealthCheckType string + Hostname string + Instances types.NullInt + Memory types.NullByteSizeInMb + Name string + NoHostname bool + NoRoute bool + Path string + RandomRoute bool + Routes []string + RoutePath string + Services []string + StackName string + + DeprecatedDomain interface{} + DeprecatedDomains interface{} + DeprecatedHost interface{} + DeprecatedHosts interface{} + DeprecatedNoHostname interface{} +} + +func (app Application) MarshalYAML() (interface{}, error) { + var m = rawManifestApplication{ + Buildpack: app.Buildpack.Value, + Buildpacks: app.Buildpacks, + Command: app.Command.Value, + Docker: rawDockerInfo{Image: app.DockerImage, Username: app.DockerUsername}, + DropletPath: app.DropletPath, + EnvironmentVariables: app.EnvironmentVariables, + HealthCheckHTTPEndpoint: app.HealthCheckHTTPEndpoint, + HealthCheckType: app.HealthCheckType, + Name: app.Name, + NoRoute: app.NoRoute, + Path: app.Path, + Services: app.Services, + StackName: app.StackName, + Timeout: app.HealthCheckTimeout, + } + + m.DiskQuota = app.DiskQuota.String() + m.Memory = app.Memory.String() + + if app.Instances.IsSet { + m.Instances = &app.Instances.Value + } + + for _, route := range app.Routes { + m.Routes = append(m.Routes, rawManifestRoute{Route: route}) + } + + return m, nil +} + +func (app Application) String() string { + return fmt.Sprintf( + "App Name: '%s', Buildpack IsSet: %t, Buildpack: '%s', Buildpacks: [%s], Command IsSet: %t, Command: '%s', Disk Quota: '%s', Docker Image: '%s', Droplet Path: '%s', Health Check HTTP Endpoint: '%s', Health Check Timeout: '%d', Health Check Type: '%s', Hostname: '%s', Instances IsSet: %t, Instances: '%d', Memory: '%s', No-Hostname: %t, No-Route: %t, Path: '%s', RandomRoute: %t, RoutePath: '%s', Routes: [%s], Services: [%s], Stack Name: '%s'", + app.Name, + app.Buildpack.IsSet, + app.Buildpack.Value, + strings.Join(app.Buildpacks, ", "), + app.Command.IsSet, + app.Command.Value, + app.DiskQuota, + app.DockerImage, + app.DropletPath, + app.HealthCheckHTTPEndpoint, + app.HealthCheckTimeout, + app.HealthCheckType, + app.Hostname, + app.Instances.IsSet, + app.Instances.Value, + app.Memory, + app.NoHostname, + app.NoRoute, + app.Path, + app.RandomRoute, + app.RoutePath, + strings.Join(app.Routes, ", "), + strings.Join(app.Services, ", "), + app.StackName, + ) +} + +func (app *Application) UnmarshalYAML(unmarshaller func(interface{}) error) error { + var m rawManifestApplication + + err := unmarshaller(&m) + if err != nil { + return err + } + app.DeprecatedDomain = m.DeprecatedDomain + app.DeprecatedDomains = m.DeprecatedDomains + app.DeprecatedHost = m.DeprecatedHost + app.DeprecatedHosts = m.DeprecatedHosts + app.DeprecatedNoHostname = m.DeprecatedNoHostname + app.DockerImage = m.Docker.Image + app.DockerUsername = m.Docker.Username + app.DropletPath = m.DropletPath + app.HealthCheckHTTPEndpoint = m.HealthCheckHTTPEndpoint + app.HealthCheckType = m.HealthCheckType + app.Name = m.Name + app.NoRoute = m.NoRoute + app.Path = m.Path + app.RandomRoute = m.RandomRoute + app.Services = m.Services + app.StackName = m.StackName + app.HealthCheckTimeout = m.Timeout + app.EnvironmentVariables = m.EnvironmentVariables + + app.Instances.ParseIntValue(m.Instances) + + if fmtErr := app.DiskQuota.ParseStringValue(m.DiskQuota); fmtErr != nil { + return fmtErr + } + + if fmtErr := app.Memory.ParseStringValue(m.Memory); fmtErr != nil { + return fmtErr + } + + for _, route := range m.Routes { + app.Routes = append(app.Routes, route.Route) + } + + // "null" values are identical to non-existant values in YAML. In order to + // detect if an explicit null is given, a manual existance check is required. + exists := map[string]interface{}{} + err = unmarshaller(&exists) + if err != nil { + return err + } + + if _, ok := exists["buildpack"]; ok { + app.Buildpack.ParseValue(m.Buildpack) + app.Buildpack.IsSet = true + } + + if buildpacks, ok := exists["buildpacks"]; ok { + if buildpacks == nil { + return EmptyBuildpacksError{} + } + + app.Buildpacks = []string{} + for _, buildpack := range m.Buildpacks { + app.Buildpacks = append(app.Buildpacks, buildpack) + } + } + + if _, ok := exists["command"]; ok { + app.Command.ParseValue(m.Command) + app.Command.IsSet = true + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/creation_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/creation_error.go new file mode 100644 index 0000000..a7fe396 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/creation_error.go @@ -0,0 +1,11 @@ +package manifest + +import "fmt" + +type ManifestCreationError struct { + Err error +} + +func (e ManifestCreationError) Error() string { + return fmt.Sprintf("Error creating manifest file: %s", e.Err.Error()) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/empty_buildpacks_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/empty_buildpacks_error.go new file mode 100644 index 0000000..578540f --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/empty_buildpacks_error.go @@ -0,0 +1,7 @@ +package manifest + +type EmptyBuildpacksError struct{} + +func (EmptyBuildpacksError) Error() string { + return "Buildpacks property cannot be an empty string." +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/global_fields_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/global_fields_error.go new file mode 100644 index 0000000..af4a1a9 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/global_fields_error.go @@ -0,0 +1,14 @@ +package manifest + +import ( + "fmt" + "strings" +) + +type GlobalFieldsError struct { + Fields []string +} + +func (e GlobalFieldsError) Error() string { + return fmt.Sprintf("unsupported global fields: %s", strings.Join(e.Fields, ", ")) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/inheritance_field_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/inheritance_field_error.go new file mode 100644 index 0000000..c1d0023 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/inheritance_field_error.go @@ -0,0 +1,7 @@ +package manifest + +type InheritanceFieldError struct{} + +func (InheritanceFieldError) Error() string { + return "unsupported inheritance" +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/interpolation_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/interpolation_error.go new file mode 100644 index 0000000..30e8973 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/interpolation_error.go @@ -0,0 +1,14 @@ +package manifest + +import ( + "fmt" + "strings" +) + +type InterpolationError struct { + Err error +} + +func (e InterpolationError) Error() string { + return fmt.Sprint(strings.Replace(e.Err.Error(), "\n", ", ", -1)) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/invalid_yaml_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/invalid_yaml_error.go new file mode 100644 index 0000000..e24f27e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/invalid_yaml_error.go @@ -0,0 +1,11 @@ +package manifest + +import "fmt" + +type InvalidYAMLError struct { + Err error +} + +func (e InvalidYAMLError) Error() string { + return fmt.Sprintf("The option --vars-file expects a valid YAML file. %s", e.Err) +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/manifest.go b/vendor/code.cloudfoundry.org/cli/util/manifest/manifest.go new file mode 100644 index 0000000..e993b11 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/manifest.go @@ -0,0 +1,114 @@ +package manifest + +import ( + "io/ioutil" + "path/filepath" + + "github.com/cloudfoundry/bosh-cli/director/template" + yaml "gopkg.in/yaml.v2" +) + +type Manifest struct { + Applications []Application `yaml:"applications"` +} + +func (manifest *Manifest) UnmarshalYAML(unmarshal func(interface{}) error) error { + var raw rawManifest + err := unmarshal(&raw) + if err != nil { + return err + } + + if raw.containsInheritanceField() { + return InheritanceFieldError{} + } + + if globals := raw.containsGlobalFields(); len(globals) > 0 { + return GlobalFieldsError{Fields: globals} + } + + manifest.Applications = raw.Applications + return nil +} + +// ReadAndInterpolateManifest reads the manifest at the provided paths, +// interpolates variables if a vars file is provided, and returns a fully +// merged set of applications. +func ReadAndInterpolateManifest(pathToManifest string, pathsToVarsFiles []string, vars []template.VarKV) ([]Application, error) { + rawManifest, err := ReadAndInterpolateRawManifest(pathToManifest, pathsToVarsFiles, vars) + if err != nil { + return nil, err + } + + var manifest Manifest + err = yaml.Unmarshal(rawManifest, &manifest) + if err != nil { + return nil, err + } + + for i, app := range manifest.Applications { + if app.Path != "" && !filepath.IsAbs(app.Path) { + manifest.Applications[i].Path = filepath.Join(filepath.Dir(pathToManifest), app.Path) + } + } + + return manifest.Applications, err +} + +// ReadAndInterpolateRawManifest reads the manifest at the provided paths, +// interpolates variables if a vars file is provided, and returns the +// Unmarshalled result. +func ReadAndInterpolateRawManifest(pathToManifest string, pathsToVarsFiles []string, vars []template.VarKV) ([]byte, error) { + rawManifest, err := ioutil.ReadFile(pathToManifest) + if err != nil { + return nil, err + } + + tpl := template.NewTemplate(rawManifest) + fileVars := template.StaticVariables{} + + for _, path := range pathsToVarsFiles { + rawVarsFile, ioerr := ioutil.ReadFile(path) + if ioerr != nil { + return nil, ioerr + } + + var sv template.StaticVariables + + err = yaml.Unmarshal(rawVarsFile, &sv) + if err != nil { + return nil, InvalidYAMLError{Err: err} + } + + for k, v := range sv { + fileVars[k] = v + } + } + + for _, kv := range vars { + fileVars[kv.Name] = kv.Value + } + + rawManifest, err = tpl.Evaluate(fileVars, nil, template.EvaluateOpts{ExpectAllKeys: true}) + if err != nil { + return nil, InterpolationError{Err: err} + } + return rawManifest, nil +} + +// WriteApplicationManifest writes the provided application to the given +// filepath. If the filepath does not exist, it will create it. +func WriteApplicationManifest(application Application, filePath string) error { + manifest := Manifest{Applications: []Application{application}} + manifestBytes, err := yaml.Marshal(manifest) + if err != nil { + return ManifestCreationError{Err: err} + } + + err = ioutil.WriteFile(filePath, manifestBytes, 0644) + if err != nil { + return ManifestCreationError{Err: err} + } + + return nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest.go b/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest.go new file mode 100644 index 0000000..ab81831 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest.go @@ -0,0 +1,105 @@ +package manifest + +type rawManifest struct { + Applications []Application `yaml:"applications"` + + GlobalBuildpack interface{} `yaml:"buildpack"` + GlobalCommand interface{} `yaml:"command"` + GlobalDiskQuota interface{} `yaml:"disk_quota"` + GlobalDocker interface{} `yaml:"docker"` + GlobalDomain interface{} `yaml:"domain"` + GlobalDomains interface{} `yaml:"domains"` + GlobalEnv interface{} `yaml:"env"` + GlobalHealthCheckHTTPEndpoint interface{} `yaml:"health-check-http-endpoint"` + GlobalHealthCheckTimeout interface{} `yaml:"timeout"` + GlobalHealthCheckType interface{} `yaml:"health-check-type"` + GlobalHost interface{} `yaml:"host"` + GlobalHosts interface{} `yaml:"hosts"` + GlobalInstances interface{} `yaml:"instances"` + GlobalMemory interface{} `yaml:"memory"` + GlobalName interface{} `yaml:"name"` + GlobalNoHostname interface{} `yaml:"no-hostname"` + GlobalNoRoute interface{} `yaml:"no-route"` + GlobalPath interface{} `yaml:"path"` + GlobalRandomRoute interface{} `yaml:"random-route"` + GlobalRoutes interface{} `yaml:"routes"` + GlobalServices interface{} `yaml:"services"` + GlobalStack interface{} `yaml:"stack"` + Inherit interface{} `yaml:"inherit"` +} + +func (raw rawManifest) containsGlobalFields() []string { + globalFields := []string{} + + if raw.GlobalBuildpack != nil { + globalFields = append(globalFields, "buildpack") + } + if raw.GlobalCommand != nil { + globalFields = append(globalFields, "command") + } + if raw.GlobalDiskQuota != nil { + globalFields = append(globalFields, "disk_quota") + } + if raw.GlobalDocker != nil { + globalFields = append(globalFields, "docker") + } + if raw.GlobalDomain != nil { + globalFields = append(globalFields, "domain") + } + if raw.GlobalDomains != nil { + globalFields = append(globalFields, "domains") + } + if raw.GlobalEnv != nil { + globalFields = append(globalFields, "env") + } + if raw.GlobalHealthCheckHTTPEndpoint != nil { + globalFields = append(globalFields, "health-check-http-endpoint") + } + if raw.GlobalHealthCheckTimeout != nil { + globalFields = append(globalFields, "timeout") + } + if raw.GlobalHealthCheckType != nil { + globalFields = append(globalFields, "health-check-type") + } + if raw.GlobalHost != nil { + globalFields = append(globalFields, "host") + } + if raw.GlobalHosts != nil { + globalFields = append(globalFields, "hosts") + } + if raw.GlobalInstances != nil { + globalFields = append(globalFields, "instances") + } + if raw.GlobalMemory != nil { + globalFields = append(globalFields, "memory") + } + if raw.GlobalName != nil { + globalFields = append(globalFields, "name") + } + if raw.GlobalNoHostname != nil { + globalFields = append(globalFields, "no-hostname") + } + if raw.GlobalNoRoute != nil { + globalFields = append(globalFields, "no-route") + } + if raw.GlobalPath != nil { + globalFields = append(globalFields, "path") + } + if raw.GlobalRandomRoute != nil { + globalFields = append(globalFields, "random-route") + } + if raw.GlobalRoutes != nil { + globalFields = append(globalFields, "routes") + } + if raw.GlobalServices != nil { + globalFields = append(globalFields, "services") + } + if raw.GlobalStack != nil { + globalFields = append(globalFields, "stack") + } + return globalFields +} + +func (raw rawManifest) containsInheritanceField() bool { + return raw.Inherit != nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest_application.go b/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest_application.go new file mode 100644 index 0000000..8e03bdf --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/raw_manifest_application.go @@ -0,0 +1,37 @@ +package manifest + +type rawManifestApplication struct { + Name string `yaml:"name,omitempty"` + Buildpack string `yaml:"buildpack,omitempty"` + Buildpacks []string `yaml:"buildpacks,omitempty"` + Command string `yaml:"command,omitempty"` + DeprecatedDomain interface{} `yaml:"domain,omitempty"` + DeprecatedDomains interface{} `yaml:"domains,omitempty"` + DeprecatedHost interface{} `yaml:"host,omitempty"` + DeprecatedHosts interface{} `yaml:"hosts,omitempty"` + DeprecatedNoHostname interface{} `yaml:"no-hostname,omitempty"` + DiskQuota string `yaml:"disk_quota,omitempty"` + Docker rawDockerInfo `yaml:"docker,omitempty"` + DropletPath string `yaml:"droplet-path,omitempty"` + EnvironmentVariables map[string]string `yaml:"env,omitempty"` + HealthCheckHTTPEndpoint string `yaml:"health-check-http-endpoint,omitempty"` + HealthCheckType string `yaml:"health-check-type,omitempty"` + Instances *int `yaml:"instances,omitempty"` + Memory string `yaml:"memory,omitempty"` + NoRoute bool `yaml:"no-route,omitempty"` + Path string `yaml:"path,omitempty"` + RandomRoute bool `yaml:"random-route,omitempty"` + Routes []rawManifestRoute `yaml:"routes,omitempty"` + Services []string `yaml:"services,omitempty"` + StackName string `yaml:"stack,omitempty"` + Timeout uint64 `yaml:"timeout,omitempty"` +} + +type rawManifestRoute struct { + Route string `yaml:"route"` +} + +type rawDockerInfo struct { + Image string `yaml:"image,omitempty"` + Username string `yaml:"username,omitempty"` +} diff --git a/vendor/code.cloudfoundry.org/cli/util/manifest/unsupported_fields_error.go b/vendor/code.cloudfoundry.org/cli/util/manifest/unsupported_fields_error.go new file mode 100644 index 0000000..f25f741 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/manifest/unsupported_fields_error.go @@ -0,0 +1,8 @@ +package manifest + +type UnsupportedFieldsError struct { +} + +func (e UnsupportedFieldsError) Error() string { + return "using unsupported fields in manifest" +} diff --git a/vendor/code.cloudfoundry.org/cli/util/railway/railway.go b/vendor/code.cloudfoundry.org/cli/util/railway/railway.go new file mode 100644 index 0000000..1564004 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/railway/railway.go @@ -0,0 +1,19 @@ +package railway + +import "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" + +type funcWithWarningsAndError = func() (ccv3.Warnings, error) + +func Sequentially(tracks ...funcWithWarningsAndError) (ccv3.Warnings, error) { + var warnings ccv3.Warnings + + for _, track := range tracks { + trackWarnings, err := track() + warnings = append(warnings, trackWarnings...) + if err != nil { + return warnings, err + } + } + + return warnings, nil +} diff --git a/vendor/code.cloudfoundry.org/cli/util/sorting/alphabetic.go b/vendor/code.cloudfoundry.org/cli/util/sorting/alphabetic.go new file mode 100644 index 0000000..727a803 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/sorting/alphabetic.go @@ -0,0 +1,42 @@ +package sorting + +import ( + "unicode" +) + +type AlphabetSorter func([]string) func(i, j int) bool + +// LessIgnoreCase returns true if first is alphabetically less than second. +func LessIgnoreCase(first string, second string) bool { + iRunes := []rune(first) + jRunes := []rune(second) + + max := len(iRunes) + if max > len(jRunes) { + max = len(jRunes) + } + + for idx := 0; idx < max; idx++ { + ir := iRunes[idx] + jr := jRunes[idx] + + lir := unicode.ToLower(ir) + ljr := unicode.ToLower(jr) + + if lir == ljr { + continue + } + + return lir < ljr + } + + return false +} + +// SortAlphabeticFunc returns a `less()` comparator for sorting strings while +// respecting case. +func SortAlphabeticFunc(list []string) func(i, j int) bool { + return func(i, j int) bool { + return LessIgnoreCase(list[i], list[j]) + } +} diff --git a/vendor/code.cloudfoundry.org/cli/util/tls.go b/vendor/code.cloudfoundry.org/cli/util/tls.go new file mode 100644 index 0000000..885d9fb --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/tls.go @@ -0,0 +1,26 @@ +package util + +import ( + "crypto/tls" + "crypto/x509" + + "code.cloudfoundry.org/tlsconfig" +) + +func NewTLSConfig(trustedCerts []*x509.Certificate, skipTLSValidation bool) *tls.Config { + config := &tls.Config{} + + _ = tlsconfig.WithExternalServiceDefaults()(config) //nolint - always returns nil + + if len(trustedCerts) > 0 { + certPool := x509.NewCertPool() + for _, tlsCert := range trustedCerts { + certPool.AddCert(tlsCert) + } + config.RootCAs = certPool + } + + config.InsecureSkipVerify = skipTLSValidation + + return config +} diff --git a/vendor/code.cloudfoundry.org/cli/util/ui/config.go b/vendor/code.cloudfoundry.org/cli/util/ui/config.go new file mode 100644 index 0000000..f17cd6e --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/ui/config.go @@ -0,0 +1,17 @@ +package ui + +import "code.cloudfoundry.org/cli/util/configv3" + +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Config + +// Config is the UI configuration. +type Config interface { + // ColorEnabled enables or disabled color + ColorEnabled() configv3.ColorSetting + // Locale is the language to translate the output to + Locale() string + // IsTTY returns true when the ui has a TTY + IsTTY() bool + // TerminalWidth returns the width of the terminal + TerminalWidth() int +} diff --git a/vendor/code.cloudfoundry.org/cli/util/ui/display.go b/vendor/code.cloudfoundry.org/cli/util/ui/display.go new file mode 100644 index 0000000..5b1faa2 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/ui/display.go @@ -0,0 +1 @@ +package ui diff --git a/vendor/code.cloudfoundry.org/cli/util/ui/i18n.go b/vendor/code.cloudfoundry.org/cli/util/ui/i18n.go new file mode 100644 index 0000000..38b5c10 --- /dev/null +++ b/vendor/code.cloudfoundry.org/cli/util/ui/i18n.go @@ -0,0 +1,137 @@ +package ui + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" + "text/template" + + "code.cloudfoundry.org/cli/i18n/resources" + log "github.com/sirupsen/logrus" + "golang.org/x/text/language" +) + +const ( + // assetPath is the path of the translation file inside the asset loader. + assetPath = "resources/%s.all.json" + // chineseBase is the language code for Chinese. + chineseBase = "zh" + // defaultLocale is the default locale used when one is not configured. + defaultLocale = "en-us" + // unspecifiedScript is what is returned by language#Script objects when the + // script cannot be determined. + unspecifiedScript = "Zzzz" +) + +type LocaleReader interface { + Locale() string +} + +// TranslationEntry is the expected format of the translation file. +type TranslationEntry struct { + // ID is the original English string. + ID string `json:"id"` + // Translation is the translation of the ID. + Translation string `json:"translation"` +} + +// TranslateFunc returns the translation of the string identified by +// translationID. +// +// If there is no translation for translationID, then the translationID is used +// as the translation. +type TranslateFunc func(translationID string, args ...interface{}) string + +// GetTranslationFunc will return back a function that can be used to translate +// strings into the currently set locale. +func GetTranslationFunc(reader LocaleReader) (TranslateFunc, error) { + locale, err := determineLocale(reader) + if err != nil { + locale = defaultLocale + } + + rawTranslation, err := loadAssetFromResources(locale) + if err != nil { + rawTranslation, err = loadAssetFromResources(defaultLocale) + if err != nil { + return nil, err + } + } + + return generateTranslationFunc(rawTranslation) +} + +// ParseLocale will return a locale formatted as "-" for all non-Chinese lanagues. For Chinese, it will return +// "zh-