diff --git a/cli/cmd/apply/apply.go b/cli/cmd/apply/apply.go index 6b98d36f9..7c6e24aff 100644 --- a/cli/cmd/apply/apply.go +++ b/cli/cmd/apply/apply.go @@ -3,8 +3,8 @@ package apply import ( "os" - "github.com/rancher/norman/pkg/types/convert" "github.com/rancher/rio/cli/cmd/util" + "github.com/rancher/wrangler/pkg/data/convert" "github.com/rancher/wrangler/pkg/yaml" ) diff --git a/cli/cmd/stacks/info.go b/cli/cmd/stacks/info.go index 674d2b98d..ac0c8863b 100644 --- a/cli/cmd/stacks/info.go +++ b/cli/cmd/stacks/info.go @@ -3,10 +3,10 @@ package stacks import ( "fmt" - "github.com/rancher/norman/pkg/types/convert" "github.com/rancher/rio/cli/pkg/clicontext" "github.com/rancher/rio/cli/pkg/table" riov1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" + "github.com/rancher/wrangler/pkg/data/convert" ) type info struct { diff --git a/cli/pkg/table/writer.go b/cli/pkg/table/writer.go index a19d9a8d6..32344c36e 100644 --- a/cli/pkg/table/writer.go +++ b/cli/pkg/table/writer.go @@ -13,8 +13,8 @@ import ( "github.com/Masterminds/sprig" "github.com/davecgh/go-spew/spew" "github.com/docker/go-units" - "github.com/rancher/norman/pkg/types/convert" "github.com/rancher/rio/cli/pkg/types" + "github.com/rancher/wrangler/pkg/data/convert" "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/cli/pkg/up/questions/questions.go b/cli/pkg/up/questions/questions.go index 77f4f06c8..06e4642a1 100644 --- a/cli/pkg/up/questions/questions.go +++ b/cli/pkg/up/questions/questions.go @@ -10,11 +10,11 @@ import ( "github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty" "github.com/pkg/errors" - "github.com/rancher/norman/pkg/parse/builder" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" v1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" + "github.com/rancher/wrangler/pkg/data/convert" "github.com/rancher/wrangler/pkg/kv" + "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/validation" "golang.org/x/crypto/ssh/terminal" ) @@ -221,7 +221,7 @@ func (q *question) prompt() (string, error) { } func validate(val string, q v1.Question) error { - field := &types.Field{} + field := &schemas.Field{} err := convert.ToObj(q, field) if err != nil { return err @@ -231,12 +231,12 @@ func validate(val string, q v1.Question) error { field.Type = "string" } - converted, err := builder.ConvertSimple(field.Type, val, builder.Create) + converted, err := validation.ConvertSimple(field.Type, val) if err != nil { return err } - return builder.CheckFieldCriteria(q.Variable, *field, converted) + return validation.CheckFieldCriteria(q.Variable, *field, converted) } type condition struct { diff --git a/go.mod b/go.mod index 1c67a7280..317f195dd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/rancher/rio -go 1.12 +go 1.13 replace ( github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.2.0+incompatible @@ -77,9 +77,8 @@ require ( github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 // indirect github.com/radovskyb/watcher v1.0.7 // indirect github.com/rancher/gitwatcher v0.4.4 - github.com/rancher/norman v0.0.0-20191114233102-966e8db9e670 github.com/rancher/rdns-server v0.5.7-0.20190927164127-7128efe7d065 - github.com/rancher/wrangler v0.2.1-0.20191109002915-2a833f7e410d + github.com/rancher/wrangler v0.4.1 github.com/rancher/wrangler-api v0.2.1-0.20191025043713-b1ca9c21825a github.com/sclevine/spec v1.4.0 github.com/sirupsen/logrus v1.4.2 @@ -89,15 +88,16 @@ require ( github.com/stretchr/testify v1.4.0 github.com/tektoncd/pipeline v0.8.0 github.com/urfave/cli v1.22.2 + github.com/urfave/cli/v2 v2.1.1 github.com/wercker/stern v1.11.0 golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 golang.org/x/sync v0.0.0-20190423024810-112230192c58 gopkg.in/inf.v0 v0.9.1 gopkg.in/yaml.v2 v2.2.4 gotest.tools v2.2.0+incompatible - k8s.io/api v0.0.0 - k8s.io/apiextensions-apiserver v0.0.0 - k8s.io/apimachinery v0.0.0 + k8s.io/api v0.17.0 + k8s.io/apiextensions-apiserver v0.17.0 + k8s.io/apimachinery v0.17.0 k8s.io/apiserver v0.0.0 k8s.io/cli-runtime v0.0.0 k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible diff --git a/go.sum b/go.sum index 70d02f7be..915da14cc 100644 --- a/go.sum +++ b/go.sum @@ -862,16 +862,14 @@ github.com/rancher/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.16.2- github.com/rancher/kubernetes/staging/src/k8s.io/legacy-cloud-providers v1.16.2-k3s.1/go.mod h1:OpqDei2/Qdg+5YGQYPiEuQ4vlFoiAJy0Ysn8aLKP7Cs= github.com/rancher/kubernetes/staging/src/k8s.io/metrics v1.16.2-k3s.1/go.mod h1:vQHTmz0IaEb7/OXPSor1uga8Er0V+2M5aSdXG832NbU= github.com/rancher/kubernetes/staging/src/k8s.io/sample-apiserver v1.16.2-k3s.1/go.mod h1:E3i4wscD52Qj6PEcgUjvCd81Tl6Mghk1GHtEzoaaqwU= -github.com/rancher/norman v0.0.0-20191114233102-966e8db9e670 h1:EM5VxDfLyKFTEPVV6rEWoPHE3gn/fbd2AXS9KE7U3rE= -github.com/rancher/norman v0.0.0-20191114233102-966e8db9e670/go.mod h1:zOBq0bQmo9slllyM1kcKpKr1RH5IWodjySaffLKSOx0= github.com/rancher/rdns-server v0.5.7-0.20190927164127-7128efe7d065 h1:K2/79Jdw0viw+ryWSJQcIMYJf2vc5yQXlEHPTbpVPVs= github.com/rancher/rdns-server v0.5.7-0.20190927164127-7128efe7d065/go.mod h1:/yw1tSnAWDSDSmhKpYNA/FBA49fbbtNfh/IHT31v7jE= github.com/rancher/stern v0.0.0-20191213223518-59c2bf84f705 h1:LD7T78U5A4/tAZ+3jMRy6c6iJhhb+TARG29DdCtWF2Y= github.com/rancher/stern v0.0.0-20191213223518-59c2bf84f705/go.mod h1:aaP5eLMmFcyJUsZB6FwAO+0eILWeBKvupuHeeEuY0qQ= github.com/rancher/wrangler v0.2.1-0.20191015042916-f2a6ecca4f20/go.mod h1:w9jivI6vlBZmqzizNQM0Li/ZwoNTBeDpIv+NtBoFiMI= github.com/rancher/wrangler v0.2.1-0.20191025041946-1fd360590735/go.mod h1:zmXTOSzU0vhumCyl0+Acq2FEP5WJOJRqnCQDegknyWA= -github.com/rancher/wrangler v0.2.1-0.20191109002915-2a833f7e410d h1:lz9Aef0JEy2xmJhbU0jMfQ3Mh3pUFM9AP00pgUsQAlk= -github.com/rancher/wrangler v0.2.1-0.20191109002915-2a833f7e410d/go.mod h1:zmXTOSzU0vhumCyl0+Acq2FEP5WJOJRqnCQDegknyWA= +github.com/rancher/wrangler v0.4.1 h1:kQLE6syPbX4ciwU4OF+EHIPT9zj6r6pyN83u9Gsv5eg= +github.com/rancher/wrangler v0.4.1/go.mod h1:1cR91WLhZgkZ+U4fV9nVuXqKurWbgXcIReU4wnQvTN8= github.com/rancher/wrangler-api v0.2.1-0.20191015045805-d3635aa0853a/go.mod h1:Z6EJS8Z3aaptGHvr96E2FPTkRL6UgOURCR4YZbz8D5Q= github.com/rancher/wrangler-api v0.2.1-0.20191025043713-b1ca9c21825a h1:dH3D71jzKuYRY7qLe9AKuwz8DKO6G9PCfkeafETMmZo= github.com/rancher/wrangler-api v0.2.1-0.20191025043713-b1ca9c21825a/go.mod h1:U4nfgObQ7EERMwljGhCfQIbh2ql/t8suINX8/VfWiko= @@ -982,9 +980,10 @@ github.com/ugorji/go/codec v0.0.0-20190309163734-c4a1c341dc93/go.mod h1:iT03XoTw github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= @@ -1160,6 +1159,7 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191017205301-920acffc3e65 h1:GwXwgmbrvlcHLDsENMqrQTTIC2C0kIPszsq929NruKI= golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1262,6 +1262,8 @@ k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e h1:HqlU9dKk5YVs7R84jmq6U3Wo/XslpkxHpBv2iWHLtLc= +k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM= k8s.io/helm v2.12.2+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= k8s.io/helm v2.13.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= @@ -1270,7 +1272,6 @@ k8s.io/klog v0.0.0-20181108234604-8139d8cb77af/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUc k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.2/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0 h1:lCJCxf/LIowc2IGS9TPjWDyXY4nOmdGdfcwwDQCOURQ= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= diff --git a/main.go b/main.go index 9bc290b67..d95953470 100644 --- a/main.go +++ b/main.go @@ -13,8 +13,7 @@ import ( "os" "github.com/rancher/rio/pkg/config" - - "github.com/rancher/norman/pkg/debug" + "github.com/rancher/rio/pkg/debug" "github.com/rancher/rio/pkg/server" "github.com/rancher/rio/pkg/version" "github.com/rancher/wrangler/pkg/signals" diff --git a/vendor/github.com/rancher/norman/pkg/debug/cli.go b/pkg/debug/cli.go similarity index 76% rename from vendor/github.com/rancher/norman/pkg/debug/cli.go rename to pkg/debug/cli.go index c98dff7c1..a3e9bbdb3 100644 --- a/vendor/github.com/rancher/norman/pkg/debug/cli.go +++ b/pkg/debug/cli.go @@ -6,6 +6,7 @@ import ( "github.com/sirupsen/logrus" "github.com/urfave/cli" + cliv2 "github.com/urfave/cli/v2" "k8s.io/klog" ) @@ -55,3 +56,17 @@ func Flags(config *Config) []cli.Flag { }, } } + +func FlagsV2(config *Config) []cliv2.Flag { + return []cliv2.Flag{ + &cliv2.BoolFlag{ + Name: "debug", + Destination: &config.Debug, + }, + &cliv2.IntFlag{ + Name: "debug-level", + Value: 7, + Destination: &config.DebugLevel, + }, + } +} diff --git a/pkg/generated/controllers/admin.rio.cattle.io/v1/clusterdomain.go b/pkg/generated/controllers/admin.rio.cattle.io/v1/clusterdomain.go index 466a02046..ec356ac74 100644 --- a/pkg/generated/controllers/admin.rio.cattle.io/v1/clusterdomain.go +++ b/pkg/generated/controllers/admin.rio.cattle.io/v1/clusterdomain.go @@ -277,14 +277,15 @@ func (a *clusterDomainStatusHandler) sync(key string, obj *v1.ClusterDomain) (*v return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *clusterDomainStatusHandler) sync(key string, obj *v1.ClusterDomain) (*v a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/admin.rio.cattle.io/v1/publicdomain.go b/pkg/generated/controllers/admin.rio.cattle.io/v1/publicdomain.go index e8159bf5f..e234ec0d5 100644 --- a/pkg/generated/controllers/admin.rio.cattle.io/v1/publicdomain.go +++ b/pkg/generated/controllers/admin.rio.cattle.io/v1/publicdomain.go @@ -277,14 +277,15 @@ func (a *publicDomainStatusHandler) sync(key string, obj *v1.PublicDomain) (*v1. return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *publicDomainStatusHandler) sync(key string, obj *v1.PublicDomain) (*v1. a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/admin.rio.cattle.io/v1/rioinfo.go b/pkg/generated/controllers/admin.rio.cattle.io/v1/rioinfo.go index 44f0e26f3..80b5bbc3f 100644 --- a/pkg/generated/controllers/admin.rio.cattle.io/v1/rioinfo.go +++ b/pkg/generated/controllers/admin.rio.cattle.io/v1/rioinfo.go @@ -277,14 +277,15 @@ func (a *rioInfoStatusHandler) sync(key string, obj *v1.RioInfo) (*v1.RioInfo, e return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *rioInfoStatusHandler) sync(key string, obj *v1.RioInfo) (*v1.RioInfo, e a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/management.cattle.io/v3/user.go b/pkg/generated/controllers/management.cattle.io/v3/user.go index b1e430680..1903252b6 100644 --- a/pkg/generated/controllers/management.cattle.io/v3/user.go +++ b/pkg/generated/controllers/management.cattle.io/v3/user.go @@ -277,14 +277,15 @@ func (a *userStatusHandler) sync(key string, obj *v3.User) (*v3.User, error) { return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *userStatusHandler) sync(key string, obj *v3.User) (*v3.User, error) { a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/rio.cattle.io/v1/externalservice.go b/pkg/generated/controllers/rio.cattle.io/v1/externalservice.go index 9c0184a7a..e964bdda2 100644 --- a/pkg/generated/controllers/rio.cattle.io/v1/externalservice.go +++ b/pkg/generated/controllers/rio.cattle.io/v1/externalservice.go @@ -277,14 +277,15 @@ func (a *externalServiceStatusHandler) sync(key string, obj *v1.ExternalService) return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *externalServiceStatusHandler) sync(key string, obj *v1.ExternalService) a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/rio.cattle.io/v1/router.go b/pkg/generated/controllers/rio.cattle.io/v1/router.go index fd754dd6c..0b751852c 100644 --- a/pkg/generated/controllers/rio.cattle.io/v1/router.go +++ b/pkg/generated/controllers/rio.cattle.io/v1/router.go @@ -277,14 +277,15 @@ func (a *routerStatusHandler) sync(key string, obj *v1.Router) (*v1.Router, erro return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *routerStatusHandler) sync(key string, obj *v1.Router) (*v1.Router, erro a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/rio.cattle.io/v1/service.go b/pkg/generated/controllers/rio.cattle.io/v1/service.go index 3ce4dbed0..9fd45947b 100644 --- a/pkg/generated/controllers/rio.cattle.io/v1/service.go +++ b/pkg/generated/controllers/rio.cattle.io/v1/service.go @@ -277,14 +277,15 @@ func (a *serviceStatusHandler) sync(key string, obj *v1.Service) (*v1.Service, e return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *serviceStatusHandler) sync(key string, obj *v1.Service) (*v1.Service, e a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/generated/controllers/rio.cattle.io/v1/stack.go b/pkg/generated/controllers/rio.cattle.io/v1/stack.go index 98b7a9df7..19ccfb012 100644 --- a/pkg/generated/controllers/rio.cattle.io/v1/stack.go +++ b/pkg/generated/controllers/rio.cattle.io/v1/stack.go @@ -277,14 +277,15 @@ func (a *stackStatusHandler) sync(key string, obj *v1.Stack) (*v1.Stack, error) return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -292,9 +293,8 @@ func (a *stackStatusHandler) sync(key string, obj *v1.Stack) (*v1.Stack, error) a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/pkg/riofile/mappers/configmap.go b/pkg/riofile/mappers/configmap.go index 3319ea280..d5f2f1184 100644 --- a/pkg/riofile/mappers/configmap.go +++ b/pkg/riofile/mappers/configmap.go @@ -1,10 +1,10 @@ package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/mapper" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" ) type ConfigMapMapper struct { diff --git a/pkg/riofile/mappers/duration.go b/pkg/riofile/mappers/duration.go index a54c1fac1..fba4cca96 100644 --- a/pkg/riofile/mappers/duration.go +++ b/pkg/riofile/mappers/duration.go @@ -1,10 +1,10 @@ package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/mapper" "github.com/rancher/rio/pkg/riofile/stringers" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/riofile/mappers/envmap.go b/pkg/riofile/mappers/envmap.go index 60e11df43..2761fd5d5 100644 --- a/pkg/riofile/mappers/envmap.go +++ b/pkg/riofile/mappers/envmap.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/mapper" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" ) type EnvMapper struct { diff --git a/pkg/riofile/mappers/hostnetwork.go b/pkg/riofile/mappers/hostnetwork.go index 7662d31c2..4fd78284a 100644 --- a/pkg/riofile/mappers/hostnetwork.go +++ b/pkg/riofile/mappers/hostnetwork.go @@ -1,8 +1,8 @@ package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type HostNetwork struct { diff --git a/pkg/riofile/mappers/labels.go b/pkg/riofile/mappers/labels.go index e02dd9e17..89cd26805 100644 --- a/pkg/riofile/mappers/labels.go +++ b/pkg/riofile/mappers/labels.go @@ -3,14 +3,13 @@ package mappers import ( "strings" - "github.com/rancher/norman/pkg/types/mapper" - - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/mappers" ) type LabelCleaner struct { - mapper.DefaultMapper + mappers.DefaultMapper } func (d LabelCleaner) FromInternal(data data.Object) { diff --git a/pkg/riofile/mappers/object.go b/pkg/riofile/mappers/object.go index c9eb398b6..7b2bffec1 100644 --- a/pkg/riofile/mappers/object.go +++ b/pkg/riofile/mappers/object.go @@ -1,8 +1,8 @@ package mappers import ( - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/mapper" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" ) func NewObject(kind, apiVersion string) types.Mapper { diff --git a/pkg/riofile/mappers/objects_to_slice.go b/pkg/riofile/mappers/objects_to_slice.go index 089b7f0d7..b0cdeebfc 100644 --- a/pkg/riofile/mappers/objects_to_slice.go +++ b/pkg/riofile/mappers/objects_to_slice.go @@ -1,10 +1,10 @@ package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/mapper" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" "github.com/sirupsen/logrus" ) diff --git a/pkg/riofile/mappers/quantity.go b/pkg/riofile/mappers/quantity.go index 7ffdfdf5e..8201f609f 100644 --- a/pkg/riofile/mappers/quantity.go +++ b/pkg/riofile/mappers/quantity.go @@ -1,10 +1,10 @@ package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/mapper" "github.com/rancher/rio/pkg/riofile/stringers" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" ) type QuantityMapper struct { diff --git a/pkg/riofile/mappers/shlex.go b/pkg/riofile/mappers/shlex.go index c4e9746ec..b1c34c828 100644 --- a/pkg/riofile/mappers/shlex.go +++ b/pkg/riofile/mappers/shlex.go @@ -2,10 +2,10 @@ package mappers import ( "github.com/mattn/go-shellwords" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/mapper" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" ) type Shlex struct { diff --git a/pkg/riofile/riofile.go b/pkg/riofile/riofile.go index d14cfe898..d44267ec8 100644 --- a/pkg/riofile/riofile.go +++ b/pkg/riofile/riofile.go @@ -5,11 +5,11 @@ import ( "encoding/json" "strings" - "github.com/rancher/norman/pkg/types/convert" "github.com/rancher/rio/cli/pkg/table" riov1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" "github.com/rancher/rio/pkg/riofile/schema" "github.com/rancher/rio/pkg/template" + "github.com/rancher/wrangler/pkg/data/convert" "github.com/rancher/wrangler/pkg/gvk" "github.com/rancher/wrangler/pkg/yaml" v1 "k8s.io/api/core/v1" diff --git a/pkg/riofile/schema/schema.go b/pkg/riofile/schema/schema.go index 9228afbf8..60bf303ae 100644 --- a/pkg/riofile/schema/schema.go +++ b/pkg/riofile/schema/schema.go @@ -1,11 +1,11 @@ package schema import ( - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/mapper" v1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" m "github.com/rancher/rio/pkg/riofile/mappers" "github.com/rancher/rio/pkg/riofile/stringers" + types "github.com/rancher/wrangler/pkg/schemas" + mapper "github.com/rancher/wrangler/pkg/schemas/mappers" corev1 "k8s.io/api/core/v1" ) diff --git a/pkg/server/crds.go b/pkg/server/crds.go index 2157486d9..0598e14b4 100644 --- a/pkg/server/crds.go +++ b/pkg/server/crds.go @@ -5,11 +5,11 @@ import ( "strconv" "strings" - "github.com/rancher/norman/pkg/openapi" rioadminv1 "github.com/rancher/rio/pkg/apis/admin.rio.cattle.io/v1" v1 "github.com/rancher/rio/pkg/apis/rio.cattle.io/v1" "github.com/rancher/wrangler/pkg/crd" "github.com/rancher/wrangler/pkg/kv" + "github.com/rancher/wrangler/pkg/schemas/openapi" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" ) diff --git a/vendor/github.com/rancher/norman/LICENSE b/vendor/github.com/rancher/norman/LICENSE deleted file mode 100644 index f433b1a53..000000000 --- a/vendor/github.com/rancher/norman/LICENSE +++ /dev/null @@ -1,177 +0,0 @@ - - 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 diff --git a/vendor/github.com/rancher/norman/pkg/httperror/error.go b/vendor/github.com/rancher/norman/pkg/httperror/error.go deleted file mode 100644 index 73b10acd7..000000000 --- a/vendor/github.com/rancher/norman/pkg/httperror/error.go +++ /dev/null @@ -1,114 +0,0 @@ -package httperror - -import ( - "fmt" -) - -var ( - Unauthorized = ErrorCode{"Unauthorized", 401} - PermissionDenied = ErrorCode{"PermissionDenied", 403} - NotFound = ErrorCode{"NotFound", 404} - MethodNotAllowed = ErrorCode{"MethodNotAllow", 405} - Conflict = ErrorCode{"Conflict", 409} - - InvalidDateFormat = ErrorCode{"InvalidDateFormat", 422} - InvalidFormat = ErrorCode{"InvalidFormat", 422} - InvalidReference = ErrorCode{"InvalidReference", 422} - NotNullable = ErrorCode{"NotNullable", 422} - NotUnique = ErrorCode{"NotUnique", 422} - MinLimitExceeded = ErrorCode{"MinLimitExceeded", 422} - MaxLimitExceeded = ErrorCode{"MaxLimitExceeded", 422} - MinLengthExceeded = ErrorCode{"MinLengthExceeded", 422} - MaxLengthExceeded = ErrorCode{"MaxLengthExceeded", 422} - InvalidOption = ErrorCode{"InvalidOption", 422} - InvalidCharacters = ErrorCode{"InvalidCharacters", 422} - MissingRequired = ErrorCode{"MissingRequired", 422} - InvalidCSRFToken = ErrorCode{"InvalidCSRFToken", 422} - InvalidAction = ErrorCode{"InvalidAction", 422} - InvalidBodyContent = ErrorCode{"InvalidBodyContent", 422} - InvalidType = ErrorCode{"InvalidType", 422} - ActionNotAvailable = ErrorCode{"ActionNotAvailable", 404} - InvalidState = ErrorCode{"InvalidState", 422} - - ServerError = ErrorCode{"ServerError", 500} - ClusterUnavailable = ErrorCode{"ClusterUnavailable", 503} -) - -type ErrorCode struct { - Code string - Status int -} - -func (e ErrorCode) String() string { - return fmt.Sprintf("%s %d", e.Code, e.Status) -} - -type APIError struct { - Code ErrorCode - Message string - Cause error - FieldName string -} - -func NewAPIErrorLong(status int, code, message string) error { - return NewAPIError(ErrorCode{ - Code: code, - Status: status, - }, message) -} - -func NewAPIError(code ErrorCode, message string) error { - return &APIError{ - Code: code, - Message: message, - } -} - -func NewFieldAPIError(code ErrorCode, fieldName, message string) error { - return &APIError{ - Code: code, - Message: message, - FieldName: fieldName, - } -} - -// WrapFieldAPIError will cause the API framework to log the underlying err before returning the APIError as a response. -// err WILL NOT be in the API response -func WrapFieldAPIError(err error, code ErrorCode, fieldName, message string) error { - return &APIError{ - Cause: err, - Code: code, - Message: message, - FieldName: fieldName, - } -} - -// WrapAPIError will cause the API framework to log the underlying err before returning the APIError as a response. -// err WILL NOT be in the API response -func WrapAPIError(err error, code ErrorCode, message string) error { - return &APIError{ - Code: code, - Message: message, - Cause: err, - } -} - -func (a *APIError) Error() string { - if a.FieldName != "" { - return fmt.Sprintf("%s=%s: %s", a.FieldName, a.Code, a.Message) - } - return fmt.Sprintf("%s: %s", a.Code, a.Message) -} - -func IsAPIError(err error) bool { - _, ok := err.(*APIError) - return ok -} - -func IsConflict(err error) bool { - if apiError, ok := err.(*APIError); ok { - return apiError.Code.Status == 409 - } - - return false -} diff --git a/vendor/github.com/rancher/norman/pkg/parse/builder/builder.go b/vendor/github.com/rancher/norman/pkg/parse/builder/builder.go deleted file mode 100644 index d0a0c8b34..000000000 --- a/vendor/github.com/rancher/norman/pkg/parse/builder/builder.go +++ /dev/null @@ -1,512 +0,0 @@ -package builder - -import ( - "errors" - "fmt" - "strings" - - "github.com/rancher/norman/pkg/httperror" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/definition" - "k8s.io/apimachinery/pkg/util/validation" -) - -var ( - Create = Operation("create") - Update = Operation("update") - Action = Operation("action") - List = Operation("list") - ListForCreate = Operation("listcreate") - ErrComplexType = errors.New("complex type") -) - -type Operation string - -func (o Operation) IsList() bool { - return strings.HasPrefix(string(o), "list") -} - -type Builder interface { - Construct(schema *types.Schema, input types.APIObject, op Operation) (types.APIObject, error) -} - -type builder struct { - apiOp *types.APIRequest - Schemas *types.Schemas - RefValidator types.ReferenceValidator - edit bool - export bool - yaml bool -} - -func NewBuilder(apiOp *types.APIRequest) *builder { - return &builder{ - apiOp: apiOp, - yaml: apiOp.ResponseFormat == "yaml", - edit: apiOp.Option("edit") == "true", - export: apiOp.Option("export") == "true", - Schemas: apiOp.Schemas, - RefValidator: apiOp.ReferenceValidator, - } -} - -func (b *builder) Construct(schema *types.Schema, input types.APIObject, op Operation) (types.APIObject, error) { - resultMap, err := b.copyFields(schema, input.Map(), op) - if err != nil { - return types.APIObject{}, err - } - result := types.ToAPI(resultMap) - if (op == Create || op == Update) && schema.Validator != nil { - if err := schema.Validator(b.apiOp, schema, result); err != nil { - return types.APIObject{}, err - } - } - return result, nil -} - -func (b *builder) copyInputs(schema *types.Schema, input map[string]interface{}, op Operation, result map[string]interface{}) error { - for fieldName, value := range input { - field, ok := schema.ResourceFields[fieldName] - if !ok { - continue - } - - if !fieldMatchesOp(field, op) { - continue - } - - wasNull := value == nil && (field.Nullable || field.Default == nil) - value, err := b.convert(field.Type, value, op) - if err != nil { - return httperror.WrapFieldAPIError(err, httperror.InvalidFormat, fieldName, err.Error()) - } - - if value != nil || wasNull { - if !op.IsList() { - if slice, ok := value.([]interface{}); ok { - for _, sliceValue := range slice { - if sliceValue == nil { - return httperror.NewFieldAPIError(httperror.NotNullable, fieldName, "Individual array values can not be null") - } - if err := CheckFieldCriteria(fieldName, field, sliceValue); err != nil { - return err - } - } - } else { - if err := CheckFieldCriteria(fieldName, field, value); err != nil { - return err - } - } - } - result[fieldName] = value - - if op.IsList() && field.Type == "date" && value != "" && !b.edit { - ts, err := convert.ToTimestamp(value) - if err == nil { - result[fieldName+"TS"] = ts - } - } - } - } - - if op.IsList() && !b.edit && !b.export { - if !convert.IsEmptyValue(input["id"]) { - result["id"] = input["id"] - } - } - - return nil -} - -func (b *builder) checkDefaultAndRequired(schema *types.Schema, input map[string]interface{}, op Operation, result map[string]interface{}) error { - for fieldName, field := range schema.ResourceFields { - val, hasKey := result[fieldName] - if op == Create && (!hasKey || val == "") && field.Default != nil { - result[fieldName] = field.Default - } - - _, hasKey = result[fieldName] - if op == Create && fieldMatchesOp(field, Create) && field.Required { - if !hasKey { - return httperror.NewFieldAPIError(httperror.MissingRequired, fieldName, "") - } - - if definition.IsArrayType(field.Type) { - slice, err := b.convertArray(field.Type, result[fieldName], op) - if err != nil { - return err - } - if len(slice) == 0 { - return httperror.NewFieldAPIError(httperror.MissingRequired, fieldName, "") - } - } - } - - if op.IsList() && fieldMatchesOp(field, List) && definition.IsReferenceType(field.Type) && !hasKey { - result[fieldName] = nil - } else if op.IsList() && fieldMatchesOp(field, List) && !hasKey && field.Default != nil { - result[fieldName] = field.Default - } - } - - if op.IsList() && b.edit { - b.populateMissingFieldsForEdit(schema, result) - } - - if op.IsList() && b.export { - b.dropDefaultsAndReadOnly(schema, result) - } - - return nil -} - -func (b *builder) dropDefaultsAndReadOnly(schema *types.Schema, result map[string]interface{}) { - for name, existingVal := range result { - field, ok := schema.ResourceFields[name] - if !ok { - delete(result, name) - } - - if !field.Create { - delete(result, name) - continue - } - - if field.Default == existingVal { - delete(result, name) - continue - } - - val, err := b.convert(field.Type, nil, List) - if err == nil && val == existingVal { - delete(result, name) - continue - } - - if convert.IsEmptyValue(existingVal) { - delete(result, name) - continue - } - } -} - -func (b *builder) populateMissingFieldsForEdit(schema *types.Schema, result map[string]interface{}) { - for name, field := range schema.ResourceFields { - if !field.Update { - if name != "name" { - delete(result, name) - } - continue - } - - desc := field.Description - if len(desc) > 0 { - desc += " " - } - - value, hasKey := result[name] - if hasKey { - if field.Default != nil && field.Default == value { - delete(result, name) - result["zzz#("+desc+")("+field.Type+")"+name] = value - } - continue - } - - if field.Default != nil { - result["zzz#("+desc+")("+field.Type+")"+name] = field.Default - } else { - val, err := b.convert(field.Type, nil, List) - if err == nil { - result["zzz#("+desc+")("+field.Type+")"+name] = val - } - } - } -} - -func (b *builder) copyFields(schema *types.Schema, input map[string]interface{}, op Operation) (map[string]interface{}, error) { - result := map[string]interface{}{} - - if schema.Dynamic { - for k, v := range input { - result[k] = v - } - return result, nil - } - if err := b.copyInputs(schema, input, op, result); err != nil { - return nil, err - } - - return result, b.checkDefaultAndRequired(schema, input, op, result) -} - -func CheckFieldCriteria(fieldName string, field types.Field, value interface{}) error { - numVal, isNum := value.(int64) - strVal := "" - hasStrVal := false - - if value == nil && field.Default != nil { - value = field.Default - } - - if value != nil && value != "" { - hasStrVal = true - strVal = fmt.Sprint(value) - } - - if (value == nil || value == "") && !field.Nullable { - if field.Default == nil { - return httperror.NewFieldAPIError(httperror.NotNullable, fieldName, "") - } - } - - if isNum { - if field.Min != nil && numVal < *field.Min { - return httperror.NewFieldAPIError(httperror.MinLimitExceeded, fieldName, "") - } - if field.Max != nil && numVal > *field.Max { - return httperror.NewFieldAPIError(httperror.MaxLimitExceeded, fieldName, "") - } - } - - if hasStrVal || value == "" { - if field.MinLength != nil && int64(len(strVal)) < *field.MinLength { - return httperror.NewFieldAPIError(httperror.MinLengthExceeded, fieldName, "") - } - if field.MaxLength != nil && int64(len(strVal)) > *field.MaxLength { - return httperror.NewFieldAPIError(httperror.MaxLengthExceeded, fieldName, "") - } - } - - if len(field.Options) > 0 { - if hasStrVal || !field.Nullable { - found := false - for _, option := range field.Options { - if strVal == option { - found = true - break - } - } - - if !found { - return httperror.NewFieldAPIError(httperror.InvalidOption, fieldName, "") - } - } - } - - if len(field.ValidChars) > 0 && hasStrVal { - for _, c := range strVal { - if !strings.ContainsRune(field.ValidChars, c) { - return httperror.NewFieldAPIError(httperror.InvalidCharacters, fieldName, "") - } - - } - } - - if len(field.InvalidChars) > 0 && hasStrVal { - if strings.ContainsAny(strVal, field.InvalidChars) { - return httperror.NewFieldAPIError(httperror.InvalidCharacters, fieldName, "") - } - } - - return nil -} - -func ConvertSimple(fieldType string, value interface{}, op Operation) (interface{}, error) { - if value == nil { - return value, nil - } - - switch fieldType { - case "json": - return value, nil - case "date": - v := convert.ToString(value) - if v == "" { - return nil, nil - } - return v, nil - case "boolean": - return convert.ToBool(value), nil - case "enum": - return convert.ToString(value), nil - case "int": - return convert.ToNumber(value) - case "float": - return convert.ToFloat(value) - case "password": - return convert.ToString(value), nil - case "string": - if op.IsList() { - return convert.ToStringNoTrim(value), nil - } - return convert.ToString(value), nil - case "dnsLabel": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1123Label(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "dnsLabelRestricted": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1035Label(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "hostname": - str := convert.ToString(value) - if str == "" { - return "", nil - } - if op == Create || op == Update { - if errs := validation.IsDNS1123Subdomain(str); len(errs) != 0 { - return value, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("invalid value %s: %s", value, - strings.Join(errs, ","))) - } - } - return str, nil - case "intOrString": - num, err := convert.ToNumber(value) - if err == nil { - return num, nil - } - return convert.ToString(value), nil - case "base64": - return convert.ToString(value), nil - case "reference": - return convert.ToString(value), nil - } - - return nil, ErrComplexType -} - -func (b *builder) convert(fieldType string, value interface{}, op Operation) (interface{}, error) { - if value == nil { - return value, nil - } - - switch { - case definition.IsMapType(fieldType): - return b.convertMap(fieldType, value, op) - case definition.IsArrayType(fieldType): - return b.convertArray(fieldType, value, op) - case definition.IsReferenceType(fieldType): - return b.convertReferenceType(fieldType, value) - } - - newValue, err := ConvertSimple(fieldType, value, op) - if err == ErrComplexType { - return b.convertType(fieldType, value, op) - } - return newValue, err -} - -func (b *builder) convertType(fieldType string, value interface{}, op Operation) (interface{}, error) { - schema := b.Schemas.Schema(fieldType) - if schema == nil { - return nil, httperror.NewAPIError(httperror.InvalidType, "Failed to find type "+fieldType) - } - - mapValue, ok := value.(map[string]interface{}) - if !ok { - return nil, httperror.NewAPIError(httperror.InvalidFormat, fmt.Sprintf("Value can not be converted to type %s: %v", fieldType, value)) - } - - result, err := b.Construct(schema, types.ToAPI(mapValue), op) - if err != nil { - return nil, err - } - return result.Map(), nil -} - -func (b *builder) convertReferenceType(fieldType string, value interface{}) (string, error) { - subType := definition.SubType(fieldType) - strVal := convert.ToString(value) - if b.RefValidator != nil && !b.RefValidator.Validate(subType, strVal) { - return "", httperror.NewAPIError(httperror.InvalidReference, fmt.Sprintf("Not found type: %s id: %s", subType, strVal)) - } - return strVal, nil -} - -func (b *builder) convertArray(fieldType string, value interface{}, op Operation) ([]interface{}, error) { - if strSliceValue, ok := value.([]string); ok { - // Form data will be []string - var result []interface{} - for _, value := range strSliceValue { - result = append(result, value) - } - return result, nil - } - - sliceValue, ok := value.([]interface{}) - if !ok { - return nil, nil - } - - var result []interface{} - subType := definition.SubType(fieldType) - - for _, value := range sliceValue { - val, err := b.convert(subType, value, op) - if err != nil { - return nil, err - } - result = append(result, val) - } - - return result, nil -} - -func (b *builder) convertMap(fieldType string, value interface{}, op Operation) (map[string]interface{}, error) { - mapValue, ok := value.(map[string]interface{}) - if !ok { - return nil, nil - } - - result := map[string]interface{}{} - subType := definition.SubType(fieldType) - - for key, value := range mapValue { - val, err := b.convert(subType, value, op) - if err != nil { - return nil, httperror.WrapAPIError(err, httperror.InvalidFormat, err.Error()) - } - result[key] = val - } - - return result, nil -} - -func fieldMatchesOp(field types.Field, op Operation) bool { - switch op { - case Create: - return field.Create - case Update: - return field.Update - case List: - if field.Type == "password" { - return false - } - return !field.WriteOnly - case ListForCreate: - if field.Type == "password" { - return false - } - return true - default: - return false - } -} diff --git a/vendor/github.com/rancher/norman/pkg/types/condition.go b/vendor/github.com/rancher/norman/pkg/types/condition.go deleted file mode 100644 index fe6bc355c..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/condition.go +++ /dev/null @@ -1,121 +0,0 @@ -package types - -import ( - "github.com/rancher/norman/pkg/types/convert" -) - -var ( - CondEQ = QueryConditionType{ModifierEQ, 1} - CondNE = QueryConditionType{ModifierNE, 1} - CondNull = QueryConditionType{ModifierNull, 0} - CondNotNull = QueryConditionType{ModifierNotNull, 0} - CondIn = QueryConditionType{ModifierIn, -1} - CondNotIn = QueryConditionType{ModifierNotIn, -1} - CondOr = QueryConditionType{ModifierType("or"), 1} - CondAnd = QueryConditionType{ModifierType("and"), 1} - - mods = map[ModifierType]QueryConditionType{ - CondEQ.Name: CondEQ, - CondNE.Name: CondNE, - CondNull.Name: CondNull, - CondNotNull.Name: CondNotNull, - CondIn.Name: CondIn, - CondNotIn.Name: CondNotIn, - CondOr.Name: CondOr, - CondAnd.Name: CondAnd, - } -) - -type QueryConditionType struct { - Name ModifierType - Args int -} - -type QueryCondition struct { - Field string - Value string - Values map[string]bool - conditionType QueryConditionType - left, right *QueryCondition -} - -func (q *QueryCondition) Valid(schema *Schema, data map[string]interface{}) bool { - switch q.conditionType { - case CondAnd: - if q.left == nil || q.right == nil { - return false - } - return q.left.Valid(schema, data) && q.right.Valid(schema, data) - case CondOr: - if q.left == nil || q.right == nil { - return false - } - return q.left.Valid(schema, data) || q.right.Valid(schema, data) - case CondEQ: - return q.Value == convert.ToString(valueOrDefault(schema, data, q)) - case CondNE: - return q.Value != convert.ToString(valueOrDefault(schema, data, q)) - case CondIn: - return q.Values[convert.ToString(valueOrDefault(schema, data, q))] - case CondNotIn: - return !q.Values[convert.ToString(valueOrDefault(schema, data, q))] - case CondNotNull: - return convert.ToString(valueOrDefault(schema, data, q)) != "" - case CondNull: - return convert.ToString(valueOrDefault(schema, data, q)) == "" - } - - return false -} - -func valueOrDefault(schema *Schema, data map[string]interface{}, q *QueryCondition) interface{} { - value := data[q.Field] - if value == nil { - value = schema.ResourceFields[q.Field].Default - } - - return value -} - -func (q *QueryCondition) ToCondition() Condition { - cond := Condition{ - Modifier: q.conditionType.Name, - } - if q.conditionType.Args == 1 { - cond.Value = q.Value - } else if q.conditionType.Args == -1 { - stringValues := []string{} - for val := range q.Values { - stringValues = append(stringValues, val) - } - cond.Value = stringValues - } - - return cond -} - -func ValidMod(mod ModifierType) bool { - _, ok := mods[mod] - return ok -} - -func EQ(key, value string) *QueryCondition { - return NewConditionFromString(key, ModifierEQ, value) -} - -func NewConditionFromString(field string, mod ModifierType, values ...string) *QueryCondition { - q := &QueryCondition{ - Field: field, - conditionType: mods[mod], - Values: map[string]bool{}, - } - - for i, value := range values { - if i == 0 { - q.Value = value - } - q.Values[value] = true - } - - return q -} diff --git a/vendor/github.com/rancher/norman/pkg/types/convert/ref.go b/vendor/github.com/rancher/norman/pkg/types/convert/ref.go deleted file mode 100644 index b269a76cd..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/convert/ref.go +++ /dev/null @@ -1,11 +0,0 @@ -package convert - -import "fmt" - -func ToReference(typeName string) string { - return fmt.Sprintf("reference[%s]", typeName) -} - -func ToFullReference(path, typeName string) string { - return fmt.Sprintf("reference[%s/schemas/%s]", path, typeName) -} diff --git a/vendor/github.com/rancher/norman/pkg/types/convert/transform.go b/vendor/github.com/rancher/norman/pkg/types/convert/transform.go deleted file mode 100644 index 3fd9b9247..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/convert/transform.go +++ /dev/null @@ -1,45 +0,0 @@ -package convert - -const ( - ArrayKey = "{ARRAY}" - MapKey = "{MAP}" -) - -type TransformerFunc func(input interface{}) interface{} - -func Transform(data map[string]interface{}, path []string, transformer TransformerFunc) { - if len(path) == 0 || len(data) == 0 { - return - } - - key := path[0] - path = path[1:] - value := data[key] - - if value == nil { - return - } - - if len(path) == 0 { - data[key] = transformer(value) - return - } - - // You can't end a path with ARRAY/MAP. Not supported right now - if len(path) > 1 { - switch path[0] { - case ArrayKey: - for _, valueMap := range ToMapSlice(value) { - Transform(valueMap, path[1:], transformer) - } - return - case MapKey: - for _, valueMap := range ToMapInterface(value) { - Transform(ToMapInterface(valueMap), path[1:], transformer) - } - return - } - } - - Transform(ToMapInterface(value), path, transformer) -} diff --git a/vendor/github.com/rancher/norman/pkg/types/convert/value_set_string.go b/vendor/github.com/rancher/norman/pkg/types/convert/value_set_string.go deleted file mode 100644 index d9b329fa0..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/convert/value_set_string.go +++ /dev/null @@ -1,18 +0,0 @@ -package convert - -import ( - "regexp" - "strings" -) - -var ( - splitRegexp = regexp.MustCompile("[[:space:]]*,[[:space:]]*") -) - -func ToValuesSlice(value string) []string { - value = strings.TrimSpace(value) - if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") { - return splitRegexp.Split(value[1:len(value)-1], -1) - } - return []string{value} -} diff --git a/vendor/github.com/rancher/norman/pkg/types/encoder.go b/vendor/github.com/rancher/norman/pkg/types/encoder.go deleted file mode 100644 index 1e5128cdc..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/encoder.go +++ /dev/null @@ -1,32 +0,0 @@ -package types - -import ( - "encoding/json" - "io" - "regexp" - - "github.com/ghodss/yaml" -) - -var ( - commenter = regexp.MustCompile("(?m)^( *)zzz#\\((.*)\\)\\((.*)\\)([a-z]+.*):(.*)") -) - -func JSONEncoder(writer io.Writer, v interface{}) error { - return json.NewEncoder(writer).Encode(v) -} - -func YAMLEncoder(writer io.Writer, v interface{}) error { - data, err := json.Marshal(v) - if err != nil { - return err - } - buf, err := yaml.JSONToYAML(data) - if err != nil { - return err - } - //buf = commenter.ReplaceAll(buf, []byte("${1}# ${2}type: ${3}\n${1}# ${4}:${5}")) - buf = commenter.ReplaceAll(buf, []byte("${1}# ${4}:${5}")) - _, err = writer.Write(buf) - return err -} diff --git a/vendor/github.com/rancher/norman/pkg/types/id.go b/vendor/github.com/rancher/norman/pkg/types/id.go deleted file mode 100644 index 9c6618d17..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/id.go +++ /dev/null @@ -1,19 +0,0 @@ -package types - -import ( - "fmt" - "regexp" - "strings" - - utilrand "k8s.io/apimachinery/pkg/util/rand" -) - -var ( - lowerChars = regexp.MustCompile("[a-z]+") -) - -func GenerateName(typeName string) string { - base := typeName[0:1] + lowerChars.ReplaceAllString(typeName[1:], "") - last := utilrand.String(5) - return fmt.Sprintf("%s-%s", strings.ToLower(base), last) -} diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/read_only.go b/vendor/github.com/rancher/norman/pkg/types/mapper/read_only.go deleted file mode 100644 index 22323df69..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/read_only.go +++ /dev/null @@ -1,57 +0,0 @@ -package mapper - -import ( - "github.com/rancher/norman/pkg/types" -) - -type ReadOnly struct { - Field string - Optional bool - SubFields bool -} - -func (r ReadOnly) FromInternal(data map[string]interface{}) { -} - -func (r ReadOnly) ToInternal(data map[string]interface{}) error { - return nil -} - -func (r ReadOnly) readOnly(field types.Field, schema *types.Schema, schemas *types.Schemas) types.Field { - field.Create = false - field.Update = false - - if r.SubFields { - subSchema := schemas.Schema(field.Type) - if subSchema != nil { - for name, field := range subSchema.ResourceFields { - field.Create = false - field.Update = false - subSchema.ResourceFields[name] = field - } - } - } - - return field -} - -func (r ReadOnly) ModifySchema(schema *types.Schema, schemas *types.Schemas) error { - if r.Field == "*" { - for name, field := range schema.ResourceFields { - schema.ResourceFields[name] = r.readOnly(field, schema, schemas) - } - return nil - } - - if err := ValidateField(r.Field, schema); err != nil { - if r.Optional { - return nil - } - return err - } - - field := schema.ResourceFields[r.Field] - schema.ResourceFields[r.Field] = r.readOnly(field, schema, schemas) - - return nil -} diff --git a/vendor/github.com/rancher/norman/pkg/types/schema_funcs.go b/vendor/github.com/rancher/norman/pkg/types/schema_funcs.go deleted file mode 100644 index cd51b36fd..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/schema_funcs.go +++ /dev/null @@ -1,67 +0,0 @@ -package types - -import ( - "net/http" - - "github.com/rancher/norman/pkg/httperror" - "github.com/rancher/norman/pkg/types/slice" -) - -func (s *Schema) MustCustomizeField(name string, f func(f Field) Field) *Schema { - field, ok := s.ResourceFields[name] - if !ok { - panic("Failed to find field " + name + " on schema " + s.ID) - } - s.ResourceFields[name] = f(field) - return s -} - -func (s *Schema) CanList(context *APIRequest) error { - if context == nil { - if slice.ContainsString(s.CollectionMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not list "+s.ID) - } - return context.AccessControl.CanList(context, s) -} - -func (s *Schema) CanGet(context *APIRequest) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodGet) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not get "+s.ID) - } - return context.AccessControl.CanGet(context, s) -} - -func (s *Schema) CanCreate(context *APIRequest) error { - if context == nil { - if slice.ContainsString(s.CollectionMethods, http.MethodPost) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not create "+s.ID) - } - return context.AccessControl.CanCreate(context, s) -} - -func (s *Schema) CanUpdate(context *APIRequest) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodPut) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not update "+s.ID) - } - return context.AccessControl.CanUpdate(context, APIObject{}, s) -} - -func (s *Schema) CanDelete(context *APIRequest) error { - if context == nil { - if slice.ContainsString(s.ResourceMethods, http.MethodDelete) { - return nil - } - return httperror.NewAPIError(httperror.PermissionDenied, "can not delete "+s.ID) - } - return context.AccessControl.CanDelete(context, APIObject{}, s) -} diff --git a/vendor/github.com/rancher/norman/pkg/types/server_types.go b/vendor/github.com/rancher/norman/pkg/types/server_types.go deleted file mode 100644 index 1a1648436..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/server_types.go +++ /dev/null @@ -1,361 +0,0 @@ -package types - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "reflect" - - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/values" - "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/endpoints/request" -) - -type RawResource struct { - ID string `json:"id,omitempty" yaml:"id,omitempty"` - Type string `json:"type,omitempty" yaml:"type,omitempty"` - Schema *Schema `json:"-" yaml:"-"` - Links map[string]string `json:"links,omitempty" yaml:"links,omitempty"` - Actions map[string]string `json:"actions,omitempty" yaml:"actions,omitempty"` - Values map[string]interface{} `json:",inline" yaml:",inline"` - ActionLinks bool `json:"-" yaml:"-"` - DropReadOnly bool `json:"-" yaml:"-"` -} - -func (r *RawResource) AddAction(apiOp *APIRequest, name string) { - r.Actions[name] = apiOp.URLBuilder.Action(r.Schema, r.ID, name) -} - -func (r *RawResource) MarshalJSON() ([]byte, error) { - return json.Marshal(r.ToMap()) -} - -func (r *RawResource) ToMap() map[string]interface{} { - data := data.New() - for k, v := range r.Values { - data[k] = v - } - - if r.ID != "" && !r.DropReadOnly { - data["id"] = r.ID - } - - if r.Type != "" && !r.DropReadOnly { - data["type"] = r.Type - } - - if len(r.Links) > 0 && !r.DropReadOnly { - data["links"] = r.Links - } - - if len(r.Actions) > 0 && !r.DropReadOnly { - if r.ActionLinks { - data["actionLinks"] = r.Actions - } else { - data["actions"] = r.Actions - } - } - return data -} - -type ActionHandler func(actionName string, action *Action, request *APIRequest) error - -type RequestHandler func(request *APIRequest) (APIObject, error) - -type QueryFilter func(opts *QueryOptions, schema *Schema, data APIObject) APIObject - -type Validator func(request *APIRequest, schema *Schema, data APIObject) error - -type InputFormatter func(request *APIRequest, schema *Schema, data APIObject, create bool) error - -type Formatter func(request *APIRequest, resource *RawResource) - -type CollectionFormatter func(request *APIRequest, collection *GenericCollection) - -type ErrorHandler func(request *APIRequest, err error) - -type ResponseWriter interface { - Write(apiOp *APIRequest, code int, obj interface{}) -} - -type AccessControl interface { - CanCreate(apiOp *APIRequest, schema *Schema) error - CanList(apiOp *APIRequest, schema *Schema) error - CanGet(apiOp *APIRequest, schema *Schema) error - CanUpdate(apiOp *APIRequest, obj APIObject, schema *Schema) error - CanDelete(apiOp *APIRequest, obj APIObject, schema *Schema) error - CanWatch(apiOp *APIRequest, schema *Schema) error -} - -type APIRequest struct { - Action string - Name string - Type string - Link string - Method string - Namespaces []string - Schema *Schema - Schemas *Schemas - Query url.Values - ResponseFormat string - ReferenceValidator ReferenceValidator - ResponseWriter ResponseWriter - QueryFilter QueryFilter - URLPrefix string - URLBuilder URLBuilder - AccessControl AccessControl - Pagination *Pagination - - Request *http.Request - Response http.ResponseWriter -} - -func (r *APIRequest) WithContext(ctx context.Context) *APIRequest { - result := *r - result.Request = result.Request.WithContext(ctx) - return &result -} - -func (r *APIRequest) Context() context.Context { - return r.Request.Context() -} - -func (r *APIRequest) GetUser() string { - user, ok := request.UserFrom(r.Request.Context()) - if ok { - return user.GetName() - } - return "" -} - -func (r *APIRequest) GetUserInfo() (user.Info, bool) { - return request.UserFrom(r.Request.Context()) -} - -func (r *APIRequest) Option(key string) string { - return r.Query.Get("_" + key) -} - -func (r *APIRequest) WriteResponse(code int, obj interface{}) { - r.ResponseWriter.Write(r, code, obj) -} - -func (r *APIRequest) FilterList(opts *QueryOptions, schema *Schema, obj APIObject) APIObject { - return r.QueryFilter(opts, schema, obj) -} - -func (r *APIRequest) FilterObject(opts *QueryOptions, schema *Schema, obj APIObject) APIObject { - if opts != nil { - opts.Pagination = nil - } - result := r.QueryFilter(opts, schema, obj) - return result.First() -} - -func (r *APIRequest) Filter(opts *QueryOptions, schema *Schema, obj APIObject) APIObject { - if obj.IsList() { - return r.FilterList(opts, schema, obj) - } - return r.FilterObject(opts, schema, obj) -} - -var ( - ASC = SortOrder("asc") - DESC = SortOrder("desc") -) - -type QueryOptions struct { - Sort Sort - Pagination *Pagination - Conditions []*QueryCondition - Options map[string]string -} - -type ReferenceValidator interface { - Validate(resourceType, resourceID string) bool - Lookup(resourceType, resourceID string) *RawResource -} - -type URLBuilder interface { - Current() string - - Collection(schema *Schema) string - CollectionAction(schema *Schema, action string) string - ResourceLink(schema *Schema, id string) string - Link(schema *Schema, id string, linkName string) string - FilterLink(schema *Schema, fieldName string, value string) string - Action(schema *Schema, id string, action string) string - - RelativeToRoot(path string) string - Marker(marker string) string - ReverseSort(order SortOrder) string - Sort(field string) string -} - -type Store interface { - ByID(apiOp *APIRequest, schema *Schema, id string) (APIObject, error) - List(apiOp *APIRequest, schema *Schema, opt *QueryOptions) (APIObject, error) - Create(apiOp *APIRequest, schema *Schema, data APIObject) (APIObject, error) - Update(apiOp *APIRequest, schema *Schema, data APIObject, id string) (APIObject, error) - Delete(apiOp *APIRequest, schema *Schema, id string) (APIObject, error) - Watch(apiOp *APIRequest, schema *Schema, w WatchRequest) (chan APIEvent, error) -} - -type WatchRequest struct { - Revision string -} - -type APIEvent struct { - Name string `json:"name,omitempty"` - ResourceType string `json:"resourceType,omitempty"` - Revision string `json:"revision,omitempty"` - Object APIObject `json:"-"` - Error error `json:"-"` - // Data should be used - Data interface{} `json:"data,omitempty"` -} - -type APIObject struct { - ListRevision string `json:"-"` - Object interface{} `json:",inline"` -} - -func ToAPI(data interface{}) APIObject { - result := APIObject{ - Object: data, - } - return result -} - -func (a *APIObject) Raw() interface{} { - if a == nil { - return nil - } - return a.Object -} - -func (a *APIObject) Map() data.Object { - if a == nil || a.IsNil() { - return nil - } - data, err := convert.EncodeToMap(a.Object) - if err != nil { - return convert.ToMapInterface(a.Object) - } - return data -} - -func (a APIObject) IsNil() bool { - if a.Object == nil { - return true - } - val := reflect.ValueOf(a.Object) - switch val.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: - return val.IsNil() - } - return false -} - -func (a *APIObject) List() data.List { - result, ok := a.ListCheck() - if !ok { - if a == nil || a.IsNil() { - return nil - } else { - return data.List{a.Map()} - } - } - return result -} - -func (a *APIObject) IsList() bool { - _, ret := a.listCheck(false) - return ret -} - -func (a *APIObject) ListCheck() (data.List, bool) { - return a.listCheck(true) -} - -func (a *APIObject) listCheck(doConvert bool) (data.List, bool) { - if a == nil { - return nil, false - } - if result, ok := a.Object.(data.List); ok { - return result, true - } - if result, ok := a.Object.([]map[string]interface{}); ok { - return result, true - } - if result, ok := a.Object.([]interface{}); ok { - if !doConvert { - return nil, true - } - mapResult := make(data.List, 0, len(result)) - for _, obj := range result { - asMap, err := convert.EncodeToMap(obj) - if err != nil { - return nil, false - } - mapResult = append(mapResult, asMap) - } - return mapResult, true - } - return nil, false -} - -func (a *APIObject) First() APIObject { - if a == nil { - return ToAPI(nil) - } - - if list, ok := a.ListCheck(); ok { - if len(list) == 0 { - return ToAPI(([]interface{})(nil)) - } - return ToAPI(list[0]) - } - return ToAPI(nil) -} - -func (a *APIObject) Name() string { - return Name(a.Map()) -} - -func (a *APIObject) Namespace() string { - return Namespace(a.Map()) -} - -func Name(data map[string]interface{}) string { - return convert.ToString(values.GetValueN(data, "metadata", "name")) -} - -func Namespace(data map[string]interface{}) string { - return convert.ToString(values.GetValueN(data, "metadata", "namespace")) -} - -func APIChan(c <-chan APIEvent, f func(APIEvent) APIEvent) chan APIEvent { - if c == nil { - return nil - } - result := make(chan APIEvent) - go func() { - for data := range c { - modified := f(data) - result <- modified - } - close(result) - }() - return result -} - -func FormatterChain(formatter Formatter, next Formatter) Formatter { - return func(request *APIRequest, resource *RawResource) { - formatter(request, resource) - next(request, resource) - } -} diff --git a/vendor/github.com/rancher/norman/pkg/types/slice/contains.go b/vendor/github.com/rancher/norman/pkg/types/slice/contains.go deleted file mode 100644 index 10cbac0a1..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/slice/contains.go +++ /dev/null @@ -1,22 +0,0 @@ -package slice - -func ContainsString(slice []string, item string) bool { - for _, j := range slice { - if j == item { - return true - } - } - return false -} - -func StringsEqual(left, right []string) bool { - if len(left) != len(right) { - return false - } - for i := 0; i < len(left); i++ { - if left[i] != right[i] { - return false - } - } - return true -} diff --git a/vendor/github.com/rancher/norman/pkg/types/types.go b/vendor/github.com/rancher/norman/pkg/types/types.go deleted file mode 100644 index 1c28463e0..000000000 --- a/vendor/github.com/rancher/norman/pkg/types/types.go +++ /dev/null @@ -1,212 +0,0 @@ -package types - -const ( - ResourceFieldID = "id" -) - -type Collection struct { - Type string `json:"type,omitempty"` - Links map[string]string `json:"links"` - CreateTypes map[string]string `json:"createTypes,omitempty"` - Actions map[string]string `json:"actions"` - Pagination *Pagination `json:"pagination,omitempty"` - Sort *Sort `json:"sort,omitempty"` - Filters map[string][]Condition `json:"filters,omitempty"` - ResourceType string `json:"resourceType"` - Revision string `json:"revision,omitempty"` -} - -type GenericCollection struct { - Collection - Data []interface{} `json:"data"` -} - -type ResourceCollection struct { - Collection - Data []Resource `json:"data,omitempty"` -} - -type SortOrder string - -type Sort struct { - Name string `json:"name,omitempty"` - Order SortOrder `json:"order,omitempty"` - Reverse string `json:"reverse,omitempty"` - Links map[string]string `json:"links,omitempty"` -} - -var ( - ModifierEQ ModifierType = "eq" - ModifierNE ModifierType = "ne" - ModifierNull ModifierType = "null" - ModifierNotNull ModifierType = "notnull" - ModifierIn ModifierType = "in" - ModifierNotIn ModifierType = "notin" -) - -type ModifierType string - -type Condition struct { - Modifier ModifierType `json:"modifier,omitempty"` - Value interface{} `json:"value,omitempty"` -} - -type Pagination struct { - Marker string `json:"marker,omitempty"` - First string `json:"first,omitempty"` - Previous string `json:"previous,omitempty"` - Next string `json:"next,omitempty"` - Last string `json:"last,omitempty"` - Limit *int64 `json:"limit,omitempty"` - Total *int64 `json:"total,omitempty"` - Partial bool `json:"partial,omitempty"` -} - -type Resource struct { - ID string `json:"id,omitempty"` - Type string `json:"type,omitempty"` - Links map[string]string `json:"links"` - Actions map[string]string `json:"actions"` -} - -type NamedResource struct { - Resource - Name string `json:"name"` - Description string `json:"description"` -} - -type NamedResourceCollection struct { - Collection - Data []NamedResource `json:"data,omitempty"` -} - -type Schema struct { - ID string `json:"id,omitempty"` - Description string `json:"description,omitempty"` - CodeName string `json:"-"` - CodeNamePlural string `json:"-"` - PkgName string `json:"-"` - Type string `json:"type,omitempty"` - Links map[string]string `json:"links"` - PluralName string `json:"pluralName,omitempty"` - ResourceMethods []string `json:"resourceMethods,omitempty"` - ResourceFields map[string]Field `json:"resourceFields"` - ResourceActions map[string]Action `json:"resourceActions,omitempty"` - CollectionMethods []string `json:"collectionMethods,omitempty"` - CollectionFields map[string]Field `json:"collectionFields,omitempty"` - CollectionActions map[string]Action `json:"collectionActions,omitempty"` - CollectionFilters map[string]Filter `json:"collectionFilters,omitempty"` - Attributes map[string]interface{} `json:"attributes,omitempty"` - Dynamic bool `json:"dynamic,omitempty"` - - InternalSchema *Schema `json:"-"` - Mapper Mapper `json:"-"` - ActionHandler ActionHandler `json:"-"` - LinkHandler RequestHandler `json:"-"` - ListHandler RequestHandler `json:"-"` - CreateHandler RequestHandler `json:"-"` - DeleteHandler RequestHandler `json:"-"` - UpdateHandler RequestHandler `json:"-"` - InputFormatter InputFormatter `json:"-"` - Formatter Formatter `json:"-"` - CollectionFormatter CollectionFormatter `json:"-"` - ErrorHandler ErrorHandler `json:"-"` - Validator Validator `json:"-"` - Store Store `json:"-"` -} - -func (s *Schema) DeepCopy() *Schema { - r := *s - - if s.Links != nil { - r.Links = map[string]string{} - for k, v := range s.Links { - r.Links[k] = v - } - } - - if s.ResourceFields != nil { - r.ResourceFields = map[string]Field{} - for k, v := range s.ResourceFields { - r.ResourceFields[k] = v - } - } - - if s.ResourceActions != nil { - r.ResourceActions = map[string]Action{} - for k, v := range s.ResourceActions { - r.ResourceActions[k] = v - } - } - - if s.CollectionFields != nil { - r.CollectionFields = map[string]Field{} - for k, v := range s.CollectionFields { - r.CollectionFields[k] = v - } - } - - if s.CollectionActions != nil { - r.CollectionActions = map[string]Action{} - for k, v := range s.CollectionActions { - r.CollectionActions[k] = v - } - } - - if s.CollectionFilters != nil { - r.CollectionFilters = map[string]Filter{} - for k, v := range s.CollectionFilters { - r.CollectionFilters[k] = v - } - } - - if s.Attributes != nil { - r.Attributes = map[string]interface{}{} - for k, v := range s.Attributes { - r.Attributes[k] = v - } - } - - if s.InternalSchema != nil { - r.InternalSchema = r.InternalSchema.DeepCopy() - } - - return &r -} - -type Field struct { - Type string `json:"type,omitempty"` - Default interface{} `json:"default,omitempty"` - Nullable bool `json:"nullable,omitempty"` - Create bool `json:"create"` - WriteOnly bool `json:"writeOnly,omitempty"` - Required bool `json:"required,omitempty"` - Update bool `json:"update"` - MinLength *int64 `json:"minLength,omitempty"` - MaxLength *int64 `json:"maxLength,omitempty"` - Min *int64 `json:"min,omitempty"` - Max *int64 `json:"max,omitempty"` - Options []string `json:"options,omitempty"` - ValidChars string `json:"validChars,omitempty"` - InvalidChars string `json:"invalidChars,omitempty"` - Description string `json:"description,omitempty"` - Dynamic bool `json:"dynamic,omitempty"` - CodeName string `json:"-"` -} - -type Action struct { - Input string `json:"input,omitempty"` - Output string `json:"output,omitempty"` -} - -type Filter struct { - Modifiers []ModifierType `json:"modifiers,omitempty"` -} - -type ListOpts struct { - Filters map[string]interface{} -} - -func (c *Collection) AddAction(apiOp *APIRequest, name string) { - c.Actions[name] = apiOp.URLBuilder.CollectionAction(apiOp.Schema, name) -} diff --git a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go index af96efc39..7d3948851 100644 --- a/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go +++ b/vendor/github.com/rancher/wrangler/pkg/controller-gen/generators/type_go.go @@ -343,14 +343,15 @@ func (a *{{.lowerName}}StatusHandler) sync(key string, obj *{{.version}}.{{.type return obj, nil } - status := obj.Status + origStatus := obj.Status obj = obj.DeepCopy() newStatus, err := a.handler(obj, obj.Status) if err != nil { // Revert to old status on error - newStatus = *status.DeepCopy() + newStatus = *origStatus.DeepCopy() } + obj.Status = newStatus if a.condition != "" { if errors.IsConflict(err) { a.condition.SetError(obj, "", nil) @@ -358,9 +359,8 @@ func (a *{{.lowerName}}StatusHandler) sync(key string, obj *{{.version}}.{{.type a.condition.SetError(obj, "", err) } } - if !equality.Semantic.DeepEqual(status, newStatus) { + if !equality.Semantic.DeepEqual(origStatus, obj.Status) { var newErr error - obj.Status = newStatus obj, newErr = a.client.UpdateStatus(obj) if err == nil { err = newErr diff --git a/vendor/github.com/rancher/wrangler/pkg/crd/init.go b/vendor/github.com/rancher/wrangler/pkg/crd/init.go index cbd0d880d..8e327e786 100644 --- a/vendor/github.com/rancher/wrangler/pkg/crd/init.go +++ b/vendor/github.com/rancher/wrangler/pkg/crd/init.go @@ -34,6 +34,8 @@ type CRD struct { Columns []v1beta1.CustomResourceColumnDefinition Status bool Scale bool + Categories []string + ShortNames []string } func (c CRD) WithSchema(schema *v1beta1.JSONSchemaProps) CRD { @@ -56,6 +58,16 @@ func (c CRD) WithScale() CRD { return c } +func (c CRD) WithCategories(categories ...string) CRD { + c.Categories = categories + return c +} + +func (c CRD) WithShortNames(shortNames ...string) CRD { + c.ShortNames = shortNames + return c +} + func (c CRD) ToCustomResourceDefinition() apiext.CustomResourceDefinition { plural := c.PluralName if plural == "" { @@ -80,8 +92,10 @@ func (c CRD) ToCustomResourceDefinition() apiext.CustomResourceDefinition { }, }, Names: apiext.CustomResourceDefinitionNames{ - Plural: plural, - Kind: c.GVK.Kind, + Plural: plural, + Kind: c.GVK.Kind, + Categories: c.Categories, + ShortNames: c.ShortNames, }, }, } diff --git a/vendor/github.com/rancher/norman/pkg/types/convert/convert.go b/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go similarity index 93% rename from vendor/github.com/rancher/norman/pkg/types/convert/convert.go rename to vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go index 64e6053ef..47af9bc74 100644 --- a/vendor/github.com/rancher/norman/pkg/types/convert/convert.go +++ b/vendor/github.com/rancher/wrangler/pkg/data/convert/convert.go @@ -11,23 +11,6 @@ import ( "unicode" ) -func Chan(c <-chan map[string]interface{}, f func(map[string]interface{}) map[string]interface{}) chan map[string]interface{} { - if c == nil { - return nil - } - result := make(chan map[string]interface{}) - go func() { - for data := range c { - modified := f(data) - if modified != nil { - result <- modified - } - } - close(result) - }() - return result -} - func Singular(value interface{}) interface{} { if slice, ok := value.([]string); ok { if len(slice) == 0 { diff --git a/vendor/github.com/rancher/norman/pkg/data/data.go b/vendor/github.com/rancher/wrangler/pkg/data/data.go similarity index 73% rename from vendor/github.com/rancher/norman/pkg/data/data.go rename to vendor/github.com/rancher/wrangler/pkg/data/data.go index cef3330f0..e279a2992 100644 --- a/vendor/github.com/rancher/norman/pkg/data/data.go +++ b/vendor/github.com/rancher/wrangler/pkg/data/data.go @@ -1,8 +1,7 @@ package data import ( - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/values" + "github.com/rancher/wrangler/pkg/data/convert" ) type List []map[string]interface{} @@ -14,13 +13,13 @@ func New() Object { } func (o Object) Map(names ...string) Object { - v := values.GetValueN(o, names...) + v := GetValueN(o, names...) m := convert.ToMapInterface(v) return m } func (o Object) Slice(names ...string) (result []Object) { - v := values.GetValueN(o, names...) + v := GetValueN(o, names...) for _, item := range convert.ToInterfaceSlice(v) { result = append(result, convert.ToMapInterface(item)) } @@ -35,12 +34,12 @@ func (o Object) Values() (result []Object) { } func (o Object) String(names ...string) string { - v := values.GetValueN(o, names...) + v := GetValueN(o, names...) return convert.ToString(v) } func (o Object) StringSlice(names ...string) []string { - v := values.GetValueN(o, names...) + v := GetValueN(o, names...) return convert.ToStringSlice(v) } @@ -52,9 +51,9 @@ func (o Object) Set(key string, obj interface{}) { } func (o Object) SetNested(obj interface{}, key ...string) { - values.PutValue(o, obj, key...) + PutValue(o, obj, key...) } func (o Object) Bool(key ...string) bool { - return convert.ToBool(values.GetValueN(o, key...)) + return convert.ToBool(GetValueN(o, key...)) } diff --git a/vendor/github.com/rancher/norman/pkg/types/values/values.go b/vendor/github.com/rancher/wrangler/pkg/data/values.go similarity index 51% rename from vendor/github.com/rancher/norman/pkg/types/values/values.go rename to vendor/github.com/rancher/wrangler/pkg/data/values.go index ccc5c5e00..87ff6159f 100644 --- a/vendor/github.com/rancher/norman/pkg/types/values/values.go +++ b/vendor/github.com/rancher/wrangler/pkg/data/values.go @@ -1,8 +1,4 @@ -package values - -import ( - convert2 "github.com/rancher/norman/pkg/types/convert" -) +package data func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool) { for i, key := range keys { @@ -17,57 +13,6 @@ func RemoveValue(data map[string]interface{}, keys ...string) (interface{}, bool return nil, false } -func GetStringSlice(data map[string]interface{}, keys ...string) ([]string, bool) { - val, ok := GetValue(data, keys...) - if !ok { - return nil, ok - } - - slice, typeOk := val.([]string) - if typeOk { - return slice, typeOk - } - - sliceNext, typeOk := val.([]interface{}) - if !typeOk { - return nil, typeOk - } - - var result []string - for _, item := range sliceNext { - result = append(result, convert2.ToString(item)) - } - - return result, true -} - -func GetSlice(data map[string]interface{}, keys ...string) ([]map[string]interface{}, bool) { - val, ok := GetValue(data, keys...) - if !ok { - return nil, ok - } - - slice, typeOk := val.([]map[string]interface{}) - if typeOk { - return slice, typeOk - } - - sliceNext, typeOk := val.([]interface{}) - if !typeOk { - return nil, typeOk - } - - result := []map[string]interface{}{} - for _, val := range sliceNext { - if v, ok := val.(map[string]interface{}); ok { - result = append(result, v) - } - } - - return result, true - -} - func GetValueN(data map[string]interface{}, keys ...string) interface{} { val, _ := GetValue(data, keys...) return val diff --git a/vendor/github.com/rancher/wrangler/pkg/kv/split.go b/vendor/github.com/rancher/wrangler/pkg/kv/split.go index 357f1ae94..7368bde40 100644 --- a/vendor/github.com/rancher/wrangler/pkg/kv/split.go +++ b/vendor/github.com/rancher/wrangler/pkg/kv/split.go @@ -16,6 +16,14 @@ func Split(s, sep string) (string, string) { return strings.TrimSpace(parts[0]), strings.TrimSpace(safeIndex(parts, 1)) } +func SplitLast(s, sep string) (string, string) { + idx := strings.LastIndex(s, sep) + if idx > -1 { + return strings.TrimSpace(s[:idx]), strings.TrimSpace(s[idx+1:]) + } + return s, "" +} + func SplitMap(s, sep string) map[string]string { return SplitMapFromSlice(strings.Split(s, sep)) } diff --git a/vendor/github.com/rancher/wrangler/pkg/merr/error.go b/vendor/github.com/rancher/wrangler/pkg/merr/error.go index df57b6b40..23b3c2e02 100644 --- a/vendor/github.com/rancher/wrangler/pkg/merr/error.go +++ b/vendor/github.com/rancher/wrangler/pkg/merr/error.go @@ -2,7 +2,6 @@ package merr import "bytes" - type Errors []error func (e Errors) Err() error { diff --git a/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go b/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go index 62c8dfa4c..8bb1e214e 100644 --- a/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go +++ b/vendor/github.com/rancher/wrangler/pkg/relatedresource/changeset.go @@ -28,12 +28,20 @@ type ControllerWrapper interface { AddGenericHandler(ctx context.Context, name string, handler generic.Handler) } +type ClusterScopedEnqueuer interface { + Enqueue(name string) +} + type Enqueuer interface { Enqueue(namespace, name string) } type Resolver func(namespace, name string, obj runtime.Object) ([]Key, error) +func WatchClusterScoped(ctx context.Context, name string, resolve Resolver, enq ClusterScopedEnqueuer, watching ...ControllerWrapper) { + Watch(ctx, name, resolve, &wrapper{ClusterScopedEnqueuer: enq}, watching...) +} + func Watch(ctx context.Context, name string, resolve Resolver, enq Enqueuer, watching ...ControllerWrapper) { for _, c := range watching { watch(ctx, name, enq, resolve, c) @@ -77,3 +85,11 @@ func watch(ctx context.Context, name string, enq Enqueuer, resolve Resolver, con return obj, runResolve(ns, name, obj) }) } + +type wrapper struct { + ClusterScopedEnqueuer +} + +func (w *wrapper) Enqueue(namespace, name string) { + w.ClusterScopedEnqueuer.Enqueue(name) +} diff --git a/vendor/github.com/rancher/norman/pkg/types/definition/definition.go b/vendor/github.com/rancher/wrangler/pkg/schemas/definition/definition.go similarity index 74% rename from vendor/github.com/rancher/norman/pkg/types/definition/definition.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/definition/definition.go index 9f332a51f..c3fe964c2 100644 --- a/vendor/github.com/rancher/norman/pkg/types/definition/definition.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/definition/definition.go @@ -3,7 +3,7 @@ package definition import ( "strings" - "github.com/rancher/norman/pkg/types/convert" + "github.com/rancher/wrangler/pkg/data/convert" ) func IsMapType(fieldType string) bool { @@ -32,14 +32,5 @@ func SubType(fieldType string) string { } func GetType(data map[string]interface{}) string { - return GetShortTypeFromFull(GetFullType(data)) -} - -func GetShortTypeFromFull(fullType string) string { - parts := strings.Split(fullType, "/") - return parts[len(parts)-1] -} - -func GetFullType(data map[string]interface{}) string { return convert.ToString(data["type"]) } diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mapper.go similarity index 80% rename from vendor/github.com/rancher/norman/pkg/types/mapper.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mapper.go index 5766d3a8b..4d051b74b 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mapper.go @@ -1,9 +1,10 @@ -package types +package schemas import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/definition" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + "github.com/rancher/wrangler/pkg/merr" + "github.com/rancher/wrangler/pkg/schemas/definition" ) type Mapper interface { @@ -12,20 +13,6 @@ type Mapper interface { ModifySchema(schema *Schema, schemas *Schemas) error } -type EmptyMapper struct { -} - -func (e *EmptyMapper) FromInternal(data data.Object) { -} - -func (e *EmptyMapper) ToInternal(data data.Object) error { - return nil -} - -func (e *EmptyMapper) ModifySchema(schema *Schema, schemas *Schemas) error { - return nil -} - type Mappers []Mapper func (m Mappers) FromInternal(data data.Object) { @@ -39,7 +26,7 @@ func (m Mappers) ToInternal(data data.Object) error { for i := len(m) - 1; i >= 0; i-- { errors = append(errors, m[i].ToInternal(data)) } - return NewErrors(errors...) + return merr.NewErrors(errors...) } func (m Mappers) ModifySchema(schema *Schema, schemas *Schemas) error { @@ -89,16 +76,23 @@ func (t *typeMapper) FromInternal(data data.Object) { Mappers(t.Mappers).FromInternal(data) } +func addError(errors []error, err error) []error { + if err == nil { + return errors + } + return append(errors, err) +} + func (t *typeMapper) ToInternal(data data.Object) error { - errors := Errors{} - errors.Add(Mappers(t.Mappers).ToInternal(data)) + var errors []error + errors = addError(errors, Mappers(t.Mappers).ToInternal(data)) for fieldName, schema := range t.subArraySchemas { if schema.Mapper == nil { continue } for _, fieldData := range data.Slice(fieldName) { - errors.Add(schema.Mapper.ToInternal(fieldData)) + errors = addError(errors, schema.Mapper.ToInternal(fieldData)) } } @@ -107,7 +101,7 @@ func (t *typeMapper) ToInternal(data data.Object) error { continue } for _, fieldData := range data.Map(fieldName) { - errors.Add(schema.Mapper.ToInternal(convert.ToMapInterface(fieldData))) + errors = addError(errors, schema.Mapper.ToInternal(convert.ToMapInterface(fieldData))) } } @@ -115,10 +109,10 @@ func (t *typeMapper) ToInternal(data data.Object) error { if schema.Mapper == nil { continue } - errors.Add(schema.Mapper.ToInternal(data.Map(fieldName))) + errors = addError(errors, schema.Mapper.ToInternal(data.Map(fieldName))) } - return errors.Err() + return merr.NewErrors(errors...) } func (t *typeMapper) ModifySchema(schema *Schema, schemas *Schemas) error { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/access.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/access.go similarity index 86% rename from vendor/github.com/rancher/norman/pkg/types/mapper/access.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/access.go index 4a8d55623..6d55a53b8 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/access.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/access.go @@ -1,10 +1,10 @@ -package mapper +package mappers import ( "strings" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type Access struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/alias.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/alias.go similarity index 85% rename from vendor/github.com/rancher/norman/pkg/types/mapper/alias.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/alias.go index 25320ea85..d3f1d21db 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/alias.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/alias.go @@ -1,8 +1,8 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type AliasField struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/check.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/check.go similarity index 77% rename from vendor/github.com/rancher/norman/pkg/types/mapper/check.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/check.go index 60166cd11..d693bf790 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/check.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/check.go @@ -1,9 +1,9 @@ -package mapper +package mappers import ( "fmt" - "github.com/rancher/norman/pkg/types" + types "github.com/rancher/wrangler/pkg/schemas" ) func ValidateField(field string, schema *types.Schema) error { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/condition.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/condition.go similarity index 88% rename from vendor/github.com/rancher/norman/pkg/types/mapper/condition.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/condition.go index cdbef539c..ad9273805 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/condition.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/condition.go @@ -1,7 +1,7 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/types" + types "github.com/rancher/wrangler/pkg/schemas" ) type Condition struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/copy.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/copy.go similarity index 90% rename from vendor/github.com/rancher/norman/pkg/types/mapper/copy.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/copy.go index a2de65b24..75b661ad1 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/copy.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/copy.go @@ -1,9 +1,9 @@ -package mapper +package mappers import ( "fmt" - "github.com/rancher/norman/pkg/types" + types "github.com/rancher/wrangler/pkg/schemas" ) type Copy struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/default.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/default.go similarity index 77% rename from vendor/github.com/rancher/norman/pkg/types/mapper/default.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/default.go index b1c08d09d..6ec6e1212 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/default.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/default.go @@ -1,8 +1,8 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type DefaultMapper struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/drop.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/drop.go similarity index 82% rename from vendor/github.com/rancher/norman/pkg/types/mapper/drop.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/drop.go index 90a842546..1781b9b5f 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/drop.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/drop.go @@ -1,10 +1,10 @@ -package mapper +package mappers import ( "fmt" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type Drop struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/embed.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/embed.go similarity index 94% rename from vendor/github.com/rancher/norman/pkg/types/mapper/embed.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/embed.go index 1b23f70dd..03afd5b1b 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/embed.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/embed.go @@ -1,10 +1,10 @@ -package mapper +package mappers import ( "fmt" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type Embed struct { diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/empty.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/empty.go new file mode 100644 index 000000000..0bc562b7a --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/empty.go @@ -0,0 +1,20 @@ +package mappers + +import ( + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/schemas" +) + +type EmptyMapper struct { +} + +func (e *EmptyMapper) FromInternal(data data.Object) { +} + +func (e *EmptyMapper) ToInternal(data data.Object) error { + return nil +} + +func (e *EmptyMapper) ModifySchema(schema *schemas.Schema, schemas *schemas.Schemas) error { + return nil +} diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/enum.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/enum.go similarity index 80% rename from vendor/github.com/rancher/norman/pkg/types/mapper/enum.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/enum.go index e1d7cfbaf..d5e2b01ea 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/enum.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/enum.go @@ -1,13 +1,13 @@ -package mapper +package mappers import ( "fmt" "strings" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" "github.com/rancher/wrangler/pkg/kv" + "github.com/rancher/wrangler/pkg/schemas" ) type Enum struct { @@ -16,7 +16,7 @@ type Enum struct { vals map[string]string } -func NewEnum(field string, vals ...string) types.Mapper { +func NewEnum(field string, vals ...string) schemas.Mapper { f := &Enum{ DefaultMapper: DefaultMapper{ Field: field, diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/exists.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/exists.go similarity index 83% rename from vendor/github.com/rancher/norman/pkg/types/mapper/exists.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/exists.go index f7786e0e2..4a1f39d7c 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/exists.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/exists.go @@ -1,8 +1,8 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type Exists struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/json_keys.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/json_keys.go similarity index 72% rename from vendor/github.com/rancher/norman/pkg/types/mapper/json_keys.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/json_keys.go index f35e488fd..476beb1a4 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/json_keys.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/json_keys.go @@ -1,9 +1,9 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + types "github.com/rancher/wrangler/pkg/schemas" ) type JSONKeys struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/metadata.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/metadata.go similarity index 90% rename from vendor/github.com/rancher/norman/pkg/types/mapper/metadata.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/metadata.go index 7bcb2c078..2e0ce4dba 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/metadata.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/metadata.go @@ -1,6 +1,8 @@ -package mapper +package mappers -import "github.com/rancher/norman/pkg/types" +import ( + types "github.com/rancher/wrangler/pkg/schemas" +) func NewMetadataMapper() types.Mapper { return types.Mappers{ diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/move.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go similarity index 74% rename from vendor/github.com/rancher/norman/pkg/types/mapper/move.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go index eaa1e635e..06f1e88b4 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/move.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/move.go @@ -1,14 +1,13 @@ -package mapper +package mappers import ( "fmt" "strings" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/definition" - "github.com/rancher/norman/pkg/types/values" + "github.com/rancher/wrangler/pkg/data" + "github.com/rancher/wrangler/pkg/data/convert" + types "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/definition" ) type Move struct { @@ -18,15 +17,15 @@ type Move struct { NoDeleteFromField bool } -func (m Move) FromInternal(data data.Object) { - if v, ok := values.RemoveValue(data, strings.Split(m.From, "/")...); ok { - values.PutValue(data, v, strings.Split(m.To, "/")...) +func (m Move) FromInternal(d data.Object) { + if v, ok := data.RemoveValue(d, strings.Split(m.From, "/")...); ok { + data.PutValue(d, v, strings.Split(m.To, "/")...) } } -func (m Move) ToInternal(data data.Object) error { - if v, ok := values.RemoveValue(data, strings.Split(m.To, "/")...); ok { - values.PutValue(data, v, strings.Split(m.From, "/")...) +func (m Move) ToInternal(d data.Object) error { + if v, ok := data.RemoveValue(d, strings.Split(m.To, "/")...); ok { + data.PutValue(d, v, strings.Split(m.From, "/")...) } return nil } diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/set_value.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/set_value.go similarity index 83% rename from vendor/github.com/rancher/norman/pkg/types/mapper/set_value.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/set_value.go index 1cc3800c5..82157ab8f 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/set_value.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/set_value.go @@ -1,8 +1,8 @@ -package mapper +package mappers import ( - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" ) type SetValue struct { diff --git a/vendor/github.com/rancher/norman/pkg/types/mapper/slice_to_map.go b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/slice_to_map.go similarity index 83% rename from vendor/github.com/rancher/norman/pkg/types/mapper/slice_to_map.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/mappers/slice_to_map.go index 6a4eae4c6..152f05f7a 100644 --- a/vendor/github.com/rancher/norman/pkg/types/mapper/slice_to_map.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/mappers/slice_to_map.go @@ -1,11 +1,11 @@ -package mapper +package mappers import ( "fmt" - "github.com/rancher/norman/pkg/data" - "github.com/rancher/norman/pkg/types" - definition2 "github.com/rancher/norman/pkg/types/definition" + "github.com/rancher/wrangler/pkg/data" + types "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/definition" ) type SliceToMap struct { @@ -61,11 +61,11 @@ func (s SliceToMap) ModifySchema(schema *types.Schema, schemas *types.Schemas) e } field := schema.ResourceFields[s.Field] - if !definition2.IsArrayType(field.Type) { + if !definition.IsArrayType(field.Type) { return fmt.Errorf("field %s on %s is not an array", s.Field, schema.ID) } - field.Type = "map[" + definition2.SubType(field.Type) + "]" + field.Type = "map[" + definition.SubType(field.Type) + "]" schema.ResourceFields[s.Field] = field delete(subSchema.ResourceFields, subFieldName) diff --git a/vendor/github.com/rancher/norman/pkg/openapi/generate.go b/vendor/github.com/rancher/wrangler/pkg/schemas/openapi/generate.go similarity index 88% rename from vendor/github.com/rancher/norman/pkg/openapi/generate.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/openapi/generate.go index dadec40b9..ff5af90ad 100644 --- a/vendor/github.com/rancher/norman/pkg/openapi/generate.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/openapi/generate.go @@ -3,11 +3,22 @@ package openapi import ( "fmt" - "github.com/rancher/norman/pkg/types" - "github.com/rancher/norman/pkg/types/definition" + types "github.com/rancher/wrangler/pkg/schemas" + "github.com/rancher/wrangler/pkg/schemas/definition" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" ) +func MustGenerate(obj interface{}) *v1beta1.JSONSchemaProps { + if obj == nil { + return nil + } + result, err := ToOpenAPIFromStruct(obj) + if err != nil { + panic(err) + } + return result +} + func ToOpenAPIFromStruct(obj interface{}) (*v1beta1.JSONSchemaProps, error) { schemas := types.EmptySchemas() schema, err := schemas.Import(obj) @@ -177,12 +188,26 @@ func typeAndSchema(typeName string, schemas *types.Schemas) (string, *types.Sche return "string", nil, nil case "date": return "string", nil, nil + case "enum": + return "string", nil, nil + case "password": + return "string", nil, nil + case "hostname": + return "string", nil, nil case "boolean": return "boolean", nil, nil case "json": return "object", nil, nil } + if definition.IsReferenceType(typeName) { + return "string", nil, nil + } + + if definition.IsArrayType(typeName) { + return "array", nil, nil + } + schema := schemas.Schema(typeName) if schema == nil { return "", nil, fmt.Errorf("failed to find schema %s", typeName) diff --git a/vendor/github.com/rancher/norman/pkg/types/reflection.go b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go similarity index 87% rename from vendor/github.com/rancher/norman/pkg/types/reflection.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go index a0018e7e8..4acfbe29e 100644 --- a/vendor/github.com/rancher/norman/pkg/types/reflection.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/reflection.go @@ -1,20 +1,17 @@ -package types +package schemas import ( "fmt" - "net/http" "reflect" "strconv" "strings" - "github.com/rancher/norman/pkg/types/convert" - "github.com/rancher/norman/pkg/types/definition" - "github.com/rancher/norman/pkg/types/slice" + "github.com/rancher/wrangler/pkg/data/convert" + "github.com/rancher/wrangler/pkg/slice" "github.com/sirupsen/logrus" ) var ( - resourceType = reflect.TypeOf(Resource{}) blacklistNames = map[string]bool{ "links": true, "actions": true, @@ -97,44 +94,6 @@ func (s *Schemas) newSchemaFromType(t reflect.Type, typeName string) (*Schema, e return schema, nil } -func (s *Schemas) setupFilters(schema *Schema) { - if !slice.ContainsString(schema.CollectionMethods, http.MethodGet) { - return - } - for fieldName, field := range schema.ResourceFields { - var mods []ModifierType - switch field.Type { - case "enum": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "date": - fallthrough - case "dnsLabel": - fallthrough - case "hostname": - fallthrough - case "string": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "int": - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - case "boolean": - mods = []ModifierType{ModifierEQ, ModifierNE} - default: - if definition.IsReferenceType(field.Type) { - mods = []ModifierType{ModifierEQ, ModifierNE, ModifierIn, ModifierNotIn} - } - } - - if len(mods) > 0 { - if schema.CollectionFilters == nil { - schema.CollectionFilters = map[string]Filter{} - } - schema.CollectionFilters[fieldName] = Filter{ - Modifiers: mods, - } - } - } -} - func (s *Schemas) MustCustomizeType(obj interface{}, f func(*Schema)) *Schemas { name := s.getTypeName(reflect.TypeOf(obj)) schema := s.Schema(name) @@ -153,7 +112,7 @@ func (s *Schemas) assignMappers(schema *Schema) error { } mappers := s.mapper(schema.ID) - if schema.CanList(nil) == nil { + if canList(schema) { if s.DefaultMapper != nil { mappers = append([]Mapper{s.DefaultMapper()}, mappers...) } @@ -168,7 +127,7 @@ func (s *Schemas) assignMappers(schema *Schema) error { mapper := &typeMapper{ Mappers: mappers, - root: schema.CanList(nil) == nil, + root: canList(schema), } if err := mapper.ModifySchema(schema, s); err != nil { @@ -179,6 +138,10 @@ func (s *Schemas) assignMappers(schema *Schema) error { return nil } +func canList(schema *Schema) bool { + return slice.ContainsString(schema.CollectionMethods, "GET") +} + func (s *Schemas) importType(t reflect.Type, overrides ...reflect.Type) (*Schema, error) { typeName := s.getTypeName(t) @@ -205,8 +168,6 @@ func (s *Schemas) importType(t reflect.Type, overrides ...reflect.Type) (*Schema } } - s.setupFilters(schema) - if err := s.assignMappers(schema); err != nil { return nil, err } @@ -230,11 +191,6 @@ func k8sObject(field reflect.StructField) bool { } func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { - if t == resourceType { - schema.CollectionMethods = []string{"GET", "POST"} - schema.ResourceMethods = []string{"GET", "PUT", "DELETE"} - } - hasType := false hasMeta := false @@ -314,11 +270,11 @@ func (s *Schemas) readFields(schema *Schema, t reflect.Type) error { } if schemaField.Type == "" { - inferedType, err := s.determineSchemaType(fieldType) + inferredType, err := s.determineSchemaType(fieldType) if err != nil { return fmt.Errorf("failed inspecting type %s, field %s: %v", t, fieldName, err) } - schemaField.Type = inferedType + schemaField.Type = inferredType } if schemaField.Default != nil { @@ -405,14 +361,20 @@ func applyTag(structField *reflect.StructField, field *Field) error { field.Default = value case "nullable": field.Nullable = true + case "notnullable": + field.Nullable = false case "create": field.Create = true + case "nocreate": + field.Create = false case "writeOnly": field.WriteOnly = true case "required": field.Required = true case "update": field.Update = true + case "noupdate": + field.Update = false case "minLength": field.MinLength, err = toInt(value, structField) case "maxLength": @@ -451,7 +413,7 @@ func toInt(value string, structField *reflect.StructField) (*int64, error) { } func split(input string) []string { - result := []string{} + var result []string for _, i := range strings.Split(input, "|") { for _, part := range strings.Split(i, " ") { part = strings.TrimSpace(part) diff --git a/vendor/github.com/rancher/norman/pkg/types/schemas.go b/vendor/github.com/rancher/wrangler/pkg/schemas/schemas.go similarity index 81% rename from vendor/github.com/rancher/norman/pkg/types/schemas.go rename to vendor/github.com/rancher/wrangler/pkg/schemas/schemas.go index c1ef22ad3..444276eef 100644 --- a/vendor/github.com/rancher/norman/pkg/types/schemas.go +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/schemas.go @@ -1,21 +1,16 @@ -package types +package schemas import ( - "bytes" "fmt" "reflect" "strings" "sync" - "github.com/rancher/norman/pkg/types/convert" + "github.com/rancher/wrangler/pkg/data/convert" "github.com/rancher/wrangler/pkg/merr" "github.com/rancher/wrangler/pkg/name" ) -type SchemaCollection struct { - Data []Schema -} - type SchemasInitFunc func(*Schemas) *Schemas type MapperFactory func() Mapper @@ -66,6 +61,14 @@ func (s *Schemas) Init(initFunc SchemasInitFunc) *Schemas { return initFunc(s) } +func (s *Schemas) MustAddSchemas(schema *Schemas) *Schemas { + s, err := s.AddSchemas(schema) + if err != nil { + panic(err) + } + return s +} + func (s *Schemas) AddSchemas(schema *Schemas) (*Schemas, error) { var errs []error for _, schema := range schema.Schemas() { @@ -118,7 +121,6 @@ func (s *Schemas) doAddSchema(schema Schema) error { } func (s *Schemas) setupDefaults(schema *Schema) (err error) { - schema.Type = "schema" if schema.ID == "" { return fmt.Errorf("ID is not set on schema: %v", schema) } @@ -188,50 +190,11 @@ func (s *Schemas) doSchema(name string, lock bool) *Schema { return nil } -type MultiErrors struct { - Errors []error -} - -type Errors struct { - errors []error -} - -func (e *Errors) Add(err error) { - if err != nil { - e.errors = append(e.errors, err) - } -} - -func (e *Errors) Err() error { - return NewErrors(e.errors...) -} - -func NewErrors(inErrors ...error) error { - var errors []error - for _, err := range inErrors { - if err != nil { - errors = append(errors, err) - } - } - - if len(errors) == 0 { - return nil - } else if len(errors) == 1 { - return errors[0] - } - return &MultiErrors{ - Errors: errors, - } -} - -func (m *MultiErrors) Error() string { - buf := bytes.NewBuffer(nil) - for _, err := range m.Errors { - if buf.Len() > 0 { - buf.WriteString(", ") - } - buf.WriteString(err.Error()) +func (s *Schema) MustCustomizeField(name string, f func(f Field) Field) *Schema { + field, ok := s.ResourceFields[name] + if !ok { + panic("Failed to find field " + name + " on schema " + s.ID) } - - return buf.String() + s.ResourceFields[name] = f(field) + return s } diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/types.go b/vendor/github.com/rancher/wrangler/pkg/schemas/types.go new file mode 100644 index 000000000..ed934fd5e --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/types.go @@ -0,0 +1,89 @@ +package schemas + +type Schema struct { + ID string `json:"-"` + Description string `json:"description,omitempty"` + CodeName string `json:"-"` + CodeNamePlural string `json:"-"` + PkgName string `json:"-"` + PluralName string `json:"pluralName,omitempty"` + ResourceMethods []string `json:"resourceMethods,omitempty"` + ResourceFields map[string]Field `json:"resourceFields"` + ResourceActions map[string]Action `json:"resourceActions,omitempty"` + CollectionMethods []string `json:"collectionMethods,omitempty"` + CollectionFields map[string]Field `json:"collectionFields,omitempty"` + CollectionActions map[string]Action `json:"collectionActions,omitempty"` + Attributes map[string]interface{} `json:"attributes,omitempty"` + + InternalSchema *Schema `json:"-"` + Mapper Mapper `json:"-"` +} + +func (s *Schema) DeepCopy() *Schema { + r := *s + + if s.ResourceFields != nil { + r.ResourceFields = map[string]Field{} + for k, v := range s.ResourceFields { + r.ResourceFields[k] = v + } + } + + if s.ResourceActions != nil { + r.ResourceActions = map[string]Action{} + for k, v := range s.ResourceActions { + r.ResourceActions[k] = v + } + } + + if s.CollectionFields != nil { + r.CollectionFields = map[string]Field{} + for k, v := range s.CollectionFields { + r.CollectionFields[k] = v + } + } + + if s.CollectionActions != nil { + r.CollectionActions = map[string]Action{} + for k, v := range s.CollectionActions { + r.CollectionActions[k] = v + } + } + + if s.Attributes != nil { + r.Attributes = map[string]interface{}{} + for k, v := range s.Attributes { + r.Attributes[k] = v + } + } + + if s.InternalSchema != nil { + r.InternalSchema = r.InternalSchema.DeepCopy() + } + + return &r +} + +type Field struct { + Type string `json:"type,omitempty"` + Default interface{} `json:"default,omitempty"` + Nullable bool `json:"nullable,omitempty"` + Create bool `json:"create"` + WriteOnly bool `json:"writeOnly,omitempty"` + Required bool `json:"required,omitempty"` + Update bool `json:"update"` + MinLength *int64 `json:"minLength,omitempty"` + MaxLength *int64 `json:"maxLength,omitempty"` + Min *int64 `json:"min,omitempty"` + Max *int64 `json:"max,omitempty"` + Options []string `json:"options,omitempty"` + ValidChars string `json:"validChars,omitempty"` + InvalidChars string `json:"invalidChars,omitempty"` + Description string `json:"description,omitempty"` + CodeName string `json:"-"` +} + +type Action struct { + Input string `json:"input,omitempty"` + Output string `json:"output,omitempty"` +} diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/validation/error.go b/vendor/github.com/rancher/wrangler/pkg/schemas/validation/error.go new file mode 100644 index 000000000..e18b52f5e --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/validation/error.go @@ -0,0 +1,47 @@ +package validation + +import ( + "errors" + "fmt" +) + +var ( + Unauthorized = ErrorCode{"Unauthorized", 401} + PermissionDenied = ErrorCode{"PermissionDenied", 403} + NotFound = ErrorCode{"NotFound", 404} + MethodNotAllowed = ErrorCode{"MethodNotAllowed", 405} + Conflict = ErrorCode{"Conflict", 409} + + InvalidDateFormat = ErrorCode{"InvalidDateFormat", 422} + InvalidFormat = ErrorCode{"InvalidFormat", 422} + InvalidReference = ErrorCode{"InvalidReference", 422} + NotNullable = ErrorCode{"NotNullable", 422} + NotUnique = ErrorCode{"NotUnique", 422} + MinLimitExceeded = ErrorCode{"MinLimitExceeded", 422} + MaxLimitExceeded = ErrorCode{"MaxLimitExceeded", 422} + MinLengthExceeded = ErrorCode{"MinLengthExceeded", 422} + MaxLengthExceeded = ErrorCode{"MaxLengthExceeded", 422} + InvalidOption = ErrorCode{"InvalidOption", 422} + InvalidCharacters = ErrorCode{"InvalidCharacters", 422} + MissingRequired = ErrorCode{"MissingRequired", 422} + InvalidCSRFToken = ErrorCode{"InvalidCSRFToken", 422} + InvalidAction = ErrorCode{"InvalidAction", 422} + InvalidBodyContent = ErrorCode{"InvalidBodyContent", 422} + InvalidType = ErrorCode{"InvalidType", 422} + ActionNotAvailable = ErrorCode{"ActionNotAvailable", 404} + InvalidState = ErrorCode{"InvalidState", 422} + + ServerError = ErrorCode{"ServerError", 500} + ClusterUnavailable = ErrorCode{"ClusterUnavailable", 503} + + ErrComplete = errors.New("request completed") +) + +type ErrorCode struct { + Code string + Status int +} + +func (e ErrorCode) Error() string { + return fmt.Sprintf("%s %d", e.Code, e.Status) +} diff --git a/vendor/github.com/rancher/wrangler/pkg/schemas/validation/validation.go b/vendor/github.com/rancher/wrangler/pkg/schemas/validation/validation.go new file mode 100644 index 000000000..a7d27724b --- /dev/null +++ b/vendor/github.com/rancher/wrangler/pkg/schemas/validation/validation.go @@ -0,0 +1,155 @@ +package validation + +import ( + "errors" + "fmt" + "strings" + + "github.com/rancher/wrangler/pkg/data/convert" + "github.com/rancher/wrangler/pkg/schemas" + "k8s.io/apimachinery/pkg/util/validation" +) + +var ( + ErrComplexType = errors.New("complex type") +) + +func CheckFieldCriteria(fieldName string, field schemas.Field, value interface{}) error { + numVal, isNum := value.(int64) + strVal := "" + hasStrVal := false + + if value == nil && field.Default != nil { + value = field.Default + } + + if value != nil && value != "" { + hasStrVal = true + strVal = fmt.Sprint(value) + } + + if (value == nil || value == "") && !field.Nullable { + if field.Default == nil { + return NotNullable + } + } + + if isNum { + if field.Min != nil && numVal < *field.Min { + return MinLimitExceeded + } + if field.Max != nil && numVal > *field.Max { + return MaxLimitExceeded + } + } + + if hasStrVal || value == "" { + if field.MinLength != nil && int64(len(strVal)) < *field.MinLength { + return MinLengthExceeded + } + if field.MaxLength != nil && int64(len(strVal)) > *field.MaxLength { + return MaxLengthExceeded + } + } + + if len(field.Options) > 0 { + if hasStrVal || !field.Nullable { + found := false + for _, option := range field.Options { + if strVal == option { + found = true + break + } + } + + if !found { + return InvalidOption + } + } + } + + if len(field.ValidChars) > 0 && hasStrVal { + for _, c := range strVal { + if !strings.ContainsRune(field.ValidChars, c) { + return InvalidCharacters + } + + } + } + + if len(field.InvalidChars) > 0 && hasStrVal { + if strings.ContainsAny(strVal, field.InvalidChars) { + return InvalidCharacters + } + } + + return nil +} + +func ConvertSimple(fieldType string, value interface{}) (interface{}, error) { + if value == nil { + return value, nil + } + + switch fieldType { + case "json": + return value, nil + case "date": + v := convert.ToString(value) + if v == "" { + return nil, nil + } + return v, nil + case "boolean": + return convert.ToBool(value), nil + case "enum": + return convert.ToString(value), nil + case "int": + return convert.ToNumber(value) + case "float": + return convert.ToFloat(value) + case "password": + return convert.ToString(value), nil + case "string": + return convert.ToString(value), nil + case "dnsLabel": + str := convert.ToString(value) + if str == "" { + return "", nil + } + if errs := validation.IsDNS1123Label(str); len(errs) != 0 { + return nil, InvalidFormat + } + return str, nil + case "dnsLabelRestricted": + str := convert.ToString(value) + if str == "" { + return "", nil + } + if errs := validation.IsDNS1035Label(str); len(errs) != 0 { + return value, InvalidFormat + } + return str, nil + case "hostname": + str := convert.ToString(value) + if str == "" { + return "", nil + } + if errs := validation.IsDNS1123Subdomain(str); len(errs) != 0 { + return value, InvalidFormat + } + return str, nil + case "intOrString": + num, err := convert.ToNumber(value) + if err == nil { + return num, nil + } + return convert.ToString(value), nil + case "base64": + return convert.ToString(value), nil + case "reference": + return convert.ToString(value), nil + } + + return nil, ErrComplexType +} diff --git a/vendor/github.com/urfave/cli/v2/.flake8 b/vendor/github.com/urfave/cli/v2/.flake8 new file mode 100644 index 000000000..6deafc261 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/vendor/github.com/urfave/cli/v2/.gitignore b/vendor/github.com/urfave/cli/v2/.gitignore new file mode 100644 index 000000000..b013e4ac6 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.gitignore @@ -0,0 +1,5 @@ +*.coverprofile +*.orig +node_modules/ +vendor +.idea diff --git a/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..41ba294f6 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, race, +religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be +reviewed and investigated and will result in a response that is deemed necessary +and appropriate to the circumstances. The project team is obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of +specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + diff --git a/vendor/github.com/urfave/cli/v2/LICENSE b/vendor/github.com/urfave/cli/v2/LICENSE new file mode 100644 index 000000000..42a597e29 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Jeremy Saenz & Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/urfave/cli/v2/README.md b/vendor/github.com/urfave/cli/v2/README.md new file mode 100644 index 000000000..e7fb3d755 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/README.md @@ -0,0 +1,68 @@ +cli +=== + +[![Windows Build Status](https://ci.appveyor.com/api/projects/status/rtgk5xufi932pb2v?svg=true)](https://ci.appveyor.com/project/urfave/cli) + +[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) +[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) +[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) +[![codecov](https://codecov.io/gh/urfave/cli/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/cli) + +cli is a simple, fast, and fun package for building command line apps in Go. The +goal is to enable developers to write fast and distributable command line +applications in an expressive way. + +## Usage Documentation + +Usage documentation exists for each major version. Don't know what version you're on? You're probably using the version from the `master` branch, which is currently `v2`. + +- `v2` - [./docs/v2/manual.md](./docs/v2/manual.md) +- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md) + +## Installation + +Make sure you have a working Go environment. Go version 1.11+ is supported. [See the install instructions for Go](http://golang.org/doc/install.html). + +Go Modules are strongly recommended when using this package. [See the go blog guide on using Go Modules](https://blog.golang.org/using-go-modules). + +### Using `v2` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli/v2 +``` + +```go +... +import ( + "github.com/urfave/cli/v2" // imports as package "cli" +) +... +``` + +### Using `v1` releases + +``` +$ GO111MODULE=on go get github.com/urfave/cli +``` + +```go +... +import ( + "github.com/urfave/cli" +) +... +``` + +### GOPATH + +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: +``` +export PATH=$PATH:$GOPATH/bin +``` + +### Supported platforms + +cli is tested against multiple versions of Go on Linux, and against the latest +released version of Go on OS X and Windows. This project uses Github Actions for +builds. For more build info, please look at the [./.github/workflows/cli.yml](https://github.com/urfave/cli/blob/master/.github/workflows/cli.yml). diff --git a/vendor/github.com/urfave/cli/v2/app.go b/vendor/github.com/urfave/cli/v2/app.go new file mode 100644 index 000000000..c04e9afda --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/app.go @@ -0,0 +1,558 @@ +package cli + +import ( + "context" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "reflect" + "sort" + "time" +) + +var ( + changeLogURL = "https://github.com/urfave/cli/blob/master/docs/CHANGELOG.md" + appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL) + contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." + errInvalidActionType = NewExitError("ERROR invalid Action type. "+ + fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ + fmt.Sprintf("See %s", appActionDeprecationURL), 2) +) + +// App is the main structure of a cli application. It is recommended that +// an app be created with the cli.NewApp() function +type App struct { + // The name of the program. Defaults to path.Base(os.Args[0]) + Name string + // Full name of command for help, defaults to Name + HelpName string + // Description of the program. + Usage string + // Text to override the USAGE section of help + UsageText string + // Description of the program argument format. + ArgsUsage string + // Version of the program + Version string + // Description of the program + Description string + // List of commands to execute + Commands []*Command + // List of flags to parse + Flags []Flag + // Boolean to enable bash completion commands + EnableBashCompletion bool + // Boolean to hide built-in help command + HideHelp bool + // Boolean to hide built-in version flag and the VERSION section of help + HideVersion bool + // categories contains the categorized commands and is populated on app startup + categories CommandCategories + // An action to execute when the shell completion flag is set + BashComplete BashCompleteFunc + // An action to execute before any subcommands are run, but after the context is ready + // If a non-nil error is returned, no subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The action to execute when no subcommands are specified + Action ActionFunc + // Execute this function if the proper command cannot be found + CommandNotFound CommandNotFoundFunc + // Execute this function if an usage error occurs + OnUsageError OnUsageErrorFunc + // Compilation date + Compiled time.Time + // List of all authors who contributed + Authors []*Author + // Copyright of the binary if any + Copyright string + // Writer writer to write output to + Writer io.Writer + // ErrWriter writes error output + ErrWriter io.Writer + // Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to + // function as a default, so this is optional. + ExitErrHandler ExitErrHandlerFunc + // Other custom info + Metadata map[string]interface{} + // Carries a function which returns app specific info. + ExtraInfo func() map[string]string + // CustomAppHelpTemplate the text template for app help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomAppHelpTemplate string + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + didSetup bool +} + +// Tries to find out when this binary was compiled. +// Returns the current time if it fails to find it. +func compileTime() time.Time { + info, err := os.Stat(os.Args[0]) + if err != nil { + return time.Now() + } + return info.ModTime() +} + +// NewApp creates a new cli Application with some reasonable defaults for Name, +// Usage, Version and Action. +func NewApp() *App { + return &App{ + Name: filepath.Base(os.Args[0]), + HelpName: filepath.Base(os.Args[0]), + Usage: "A new cli application", + UsageText: "", + BashComplete: DefaultAppComplete, + Action: helpCommand.Action, + Compiled: compileTime(), + Writer: os.Stdout, + } +} + +// Setup runs initialization code to ensure all data structures are ready for +// `Run` or inspection prior to `Run`. It is internally called by `Run`, but +// will return early if setup has already happened. +func (a *App) Setup() { + if a.didSetup { + return + } + + a.didSetup = true + + if a.Name == "" { + a.Name = filepath.Base(os.Args[0]) + } + + if a.HelpName == "" { + a.HelpName = filepath.Base(os.Args[0]) + } + + if a.Usage == "" { + a.Usage = "A new cli application" + } + + if a.Version == "" { + a.HideVersion = true + } + + if a.BashComplete == nil { + a.BashComplete = DefaultAppComplete + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + if a.Compiled == (time.Time{}) { + a.Compiled = compileTime() + } + + if a.Writer == nil { + a.Writer = os.Stdout + } + + var newCommands []*Command + + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCommands = append(newCommands, c) + } + a.Commands = newCommands + + if a.Command(helpCommand.Name) == nil && !a.HideHelp { + a.appendCommand(helpCommand) + + if HelpFlag != nil { + a.appendFlag(HelpFlag) + } + } + + if !a.HideVersion { + a.appendFlag(VersionFlag) + } + + a.categories = newCommandCategories() + for _, command := range a.Commands { + a.categories.AddCommand(command.Category, command) + } + sort.Sort(a.categories.(*commandCategories)) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } + + if a.Writer == nil { + a.Writer = os.Stdout + } +} + +func (a *App) newFlagSet() (*flag.FlagSet, error) { + return flagSet(a.Name, a.Flags) +} + +func (a *App) useShortOptionHandling() bool { + return a.UseShortOptionHandling +} + +// Run is the entry point to the cli app. Parses the arguments slice and routes +// to the proper flag/args combination +func (a *App) Run(arguments []string) (err error) { + return a.RunContext(context.Background(), arguments) +} + +// RunContext is like Run except it takes a Context that will be +// passed to its commands and sub-commands. Through this, you can +// propagate timeouts and cancellation requests +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) { + a.Setup() + + // handle the completion flag separately from the flagset since + // completion could be attempted after a flag, but before its value was put + // on the command line. this causes the flagset to interpret the completion + // flag name as the value of the flag before it which is undesirable + // note that we can only do this because the shell autocomplete function + // always appends the completion flag at the end of the command + shellComplete, arguments := checkShellCompleteFlag(a, arguments) + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, arguments[1:], shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, &Context{Context: ctx}) + if nerr != nil { + _, _ = fmt.Fprintln(a.Writer, nerr) + _ = ShowAppHelp(context) + return nerr + } + context.shellComplete = shellComplete + + if checkCompletions(context) { + return nil + } + + if err != nil { + if a.OnUsageError != nil { + err := a.OnUsageError(context, err, false) + a.handleExitCoder(context, err) + return err + } + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowAppHelp(context) + return err + } + + if !a.HideHelp && checkHelp(context) { + _ = ShowAppHelp(context) + return nil + } + + if !a.HideVersion && checkVersion(context) { + ShowVersion(context) + return nil + } + + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + _ = ShowAppHelp(context) + return cerr + } + + if a.After != nil { + defer func() { + if afterErr := a.After(context); afterErr != nil { + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + beforeErr := a.Before(context) + if beforeErr != nil { + _, _ = fmt.Fprintf(a.Writer, "%v\n\n", beforeErr) + _ = ShowAppHelp(context) + a.handleExitCoder(context, beforeErr) + err = beforeErr + return err + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +// RunAndExitOnError calls .Run() and exits non-zero if an error was returned +// +// Deprecated: instead you should return an error that fulfills cli.ExitCoder +// to cli.App.Run. This will cause the application to exit with the given eror +// code in the cli.ExitCoder +func (a *App) RunAndExitOnError() { + if err := a.Run(os.Args); err != nil { + _, _ = fmt.Fprintln(a.errWriter(), err) + OsExiter(1) + } +} + +// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to +// generate command-specific flags +func (a *App) RunAsSubcommand(ctx *Context) (err error) { + a.Setup() + + // append help to commands + if len(a.Commands) > 0 { + if a.Command(helpCommand.Name) == nil && !a.HideHelp { + a.appendCommand(helpCommand) + + if HelpFlag != nil { + a.appendFlag(HelpFlag) + } + } + } + + var newCmds []*Command + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCmds = append(newCmds, c) + } + a.Commands = newCmds + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, ctx) + + if nerr != nil { + _, _ = fmt.Fprintln(a.Writer, nerr) + _, _ = fmt.Fprintln(a.Writer) + if len(a.Commands) > 0 { + _ = ShowSubcommandHelp(context) + } else { + _ = ShowCommandHelp(ctx, context.Args().First()) + } + return nerr + } + + if checkCompletions(context) { + return nil + } + + if err != nil { + if a.OnUsageError != nil { + err = a.OnUsageError(context, err, true) + a.handleExitCoder(context, err) + return err + } + _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) + _ = ShowSubcommandHelp(context) + return err + } + + if len(a.Commands) > 0 { + if checkSubcommandHelp(context) { + return nil + } + } else { + if checkCommandHelp(ctx, context.Args().First()) { + return nil + } + } + + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + _ = ShowSubcommandHelp(context) + return cerr + } + + if a.After != nil { + defer func() { + afterErr := a.After(context) + if afterErr != nil { + a.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + beforeErr := a.Before(context) + if beforeErr != nil { + a.handleExitCoder(context, beforeErr) + err = beforeErr + return err + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +// Command returns the named command on App. Returns nil if the command does not exist +func (a *App) Command(name string) *Command { + for _, c := range a.Commands { + if c.HasName(name) { + return c + } + } + + return nil +} + +// VisibleCategories returns a slice of categories and commands that are +// Hidden=false +func (a *App) VisibleCategories() []CommandCategory { + ret := []CommandCategory{} + for _, category := range a.categories.Categories() { + if visible := func() CommandCategory { + if len(category.VisibleCommands()) > 0 { + return category + } + return nil + }(); visible != nil { + ret = append(ret, visible) + } + } + return ret +} + +// VisibleCommands returns a slice of the Commands with Hidden=false +func (a *App) VisibleCommands() []*Command { + var ret []*Command + for _, command := range a.Commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (a *App) VisibleFlags() []Flag { + return visibleFlags(a.Flags) +} + +func (a *App) hasFlag(flag Flag) bool { + for _, f := range a.Flags { + if reflect.DeepEqual(flag, f) { + return true + } + } + + return false +} + +func (a *App) errWriter() io.Writer { + // When the app ErrWriter is nil use the package level one. + if a.ErrWriter == nil { + return ErrWriter + } + + return a.ErrWriter +} + +func (a *App) appendFlag(fl Flag) { + if !hasFlag(a.Flags, fl) { + a.Flags = append(a.Flags, fl) + } +} + +func (a *App) appendCommand(c *Command) { + if !hasCommand(a.Commands, c) { + a.Commands = append(a.Commands, c) + } +} + +func (a *App) handleExitCoder(context *Context, err error) { + if a.ExitErrHandler != nil { + a.ExitErrHandler(context, err) + } else { + HandleExitCoder(err) + } +} + +// Author represents someone who has contributed to a cli project. +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + +// String makes Author comply to the Stringer interface, to allow an easy print in the templating process +func (a *Author) String() string { + e := "" + if a.Email != "" { + e = " <" + a.Email + ">" + } + + return fmt.Sprintf("%v%v", a.Name, e) +} + +// HandleAction attempts to figure out which Action signature was used. If +// it's an ActionFunc or a func with the legacy signature for Action, the func +// is run! +func HandleAction(action interface{}, context *Context) (err error) { + switch a := action.(type) { + case ActionFunc: + return a(context) + case func(*Context) error: + return a(context) + case func(*Context): // deprecated function signature + a(context) + return nil + } + + return errInvalidActionType +} diff --git a/vendor/github.com/urfave/cli/v2/appveyor.yml b/vendor/github.com/urfave/cli/v2/appveyor.yml new file mode 100644 index 000000000..f1cae90b5 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/appveyor.yml @@ -0,0 +1,28 @@ +version: "{build}" + +os: Windows Server 2016 + +image: Visual Studio 2017 + +clone_folder: c:\gopath\src\github.com\urfave\cli + +cache: + - node_modules + +environment: + GOPATH: C:\gopath + GOVERSION: 1.11.x + GO111MODULE: on + GOPROXY: https://proxy.golang.org + +install: + - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% + - go version + - go env + - go get github.com/urfave/gfmrun/cmd/gfmrun + - go mod tidy + +build_script: + - go run build.go vet + - go run build.go test + - go run build.go gfmrun docs/v1/manual.md diff --git a/vendor/github.com/urfave/cli/v2/args.go b/vendor/github.com/urfave/cli/v2/args.go new file mode 100644 index 000000000..bd65c17bd --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/args.go @@ -0,0 +1,54 @@ +package cli + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type args []string + +func (a *args) Get(n int) string { + if len(*a) > n { + return (*a)[n] + } + return "" +} + +func (a *args) First() string { + return a.Get(0) +} + +func (a *args) Tail() []string { + if a.Len() >= 2 { + tail := []string((*a)[1:]) + ret := make([]string, len(tail)) + copy(ret, tail) + return ret + } + return []string{} +} + +func (a *args) Len() int { + return len(*a) +} + +func (a *args) Present() bool { + return a.Len() != 0 +} + +func (a *args) Slice() []string { + ret := make([]string, len(*a)) + copy(ret, *a) + return ret +} diff --git a/vendor/github.com/urfave/cli/v2/category.go b/vendor/github.com/urfave/cli/v2/category.go new file mode 100644 index 000000000..867e3908c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/category.go @@ -0,0 +1,79 @@ +package cli + +// CommandCategories interface allows for category manipulation +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // categories returns a copy of the category slice + Categories() []CommandCategory +} + +type commandCategories []*commandCategory + +func newCommandCategories() CommandCategories { + ret := commandCategories([]*commandCategory{}) + return &ret +} + +func (c *commandCategories) Less(i, j int) bool { + return lexicographicLess((*c)[i].Name(), (*c)[j].Name()) +} + +func (c *commandCategories) Len() int { + return len(*c) +} + +func (c *commandCategories) Swap(i, j int) { + (*c)[i], (*c)[j] = (*c)[j], (*c)[i] +} + +func (c *commandCategories) AddCommand(category string, command *Command) { + for _, commandCategory := range []*commandCategory(*c) { + if commandCategory.name == category { + commandCategory.commands = append(commandCategory.commands, command) + return + } + } + newVal := append(*c, + &commandCategory{name: category, commands: []*Command{command}}) + *c = newVal +} + +func (c *commandCategories) Categories() []CommandCategory { + ret := make([]CommandCategory, len(*c)) + for i, cat := range *c { + ret[i] = cat + } + return ret +} + +// CommandCategory is a category containing commands. +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + +type commandCategory struct { + name string + commands []*Command +} + +func (c *commandCategory) Name() string { + return c.name +} + +func (c *commandCategory) VisibleCommands() []*Command { + if c.commands == nil { + c.commands = []*Command{} + } + + var ret []*Command + for _, command := range c.commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} diff --git a/vendor/github.com/urfave/cli/v2/cli.go b/vendor/github.com/urfave/cli/v2/cli.go new file mode 100644 index 000000000..62a5bc22d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/cli.go @@ -0,0 +1,23 @@ +// Package cli provides a minimal framework for creating and organizing command line +// Go applications. cli is designed to be easy to understand and write, the most simple +// cli application can be written as follows: +// func main() { +// (&cli.App{}).Run(os.Args) +// } +// +// Of course this application does not do much, so let's make this an actual application: +// func main() { +// app := &cli.App{ +// Name: "greet", +// Usage: "say a greeting", +// Action: func(c *cli.Context) error { +// fmt.Println("Greetings") +// return nil +// }, +// } +// +// app.Run(os.Args) +// } +package cli + +//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go diff --git a/vendor/github.com/urfave/cli/v2/command.go b/vendor/github.com/urfave/cli/v2/command.go new file mode 100644 index 000000000..db6c8024b --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/command.go @@ -0,0 +1,297 @@ +package cli + +import ( + "flag" + "fmt" + "sort" + "strings" +) + +// Command is a subcommand for a cli.App. +type Command struct { + // The name of the command + Name string + // A list of aliases for the command + Aliases []string + // A short description of the usage of this command + Usage string + // Custom text to show on USAGE section of help + UsageText string + // A longer explanation of how the command works + Description string + // A short description of the arguments of this command + ArgsUsage string + // The category the command is part of + Category string + // The function to call when checking for bash command completions + BashComplete BashCompleteFunc + // An action to execute before any sub-subcommands are run, but after the context is ready + // If a non-nil error is returned, no sub-subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The function to call when this command is invoked + Action ActionFunc + // Execute this function if a usage error occurs. + OnUsageError OnUsageErrorFunc + // List of child commands + Subcommands []*Command + // List of flags to parse + Flags []Flag + // Treat all flags as normal arguments if true + SkipFlagParsing bool + // Boolean to hide built-in help command + HideHelp bool + // Boolean to hide this command from help or completion + Hidden bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + commandNamePath []string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string +} + +type Commands []*Command + +type CommandsByName []*Command + +func (c CommandsByName) Len() int { + return len(c) +} + +func (c CommandsByName) Less(i, j int) bool { + return lexicographicLess(c[i].Name, c[j].Name) +} + +func (c CommandsByName) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +// FullName returns the full name of the command. +// For subcommands this ensures that parent commands are part of the command path +func (c *Command) FullName() string { + if c.commandNamePath == nil { + return c.Name + } + return strings.Join(c.commandNamePath, " ") +} + +// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags +func (c *Command) Run(ctx *Context) (err error) { + if len(c.Subcommands) > 0 { + return c.startApp(ctx) + } + + if !c.HideHelp && HelpFlag != nil { + // append help to flags + c.appendFlag(HelpFlag) + } + + if ctx.App.UseShortOptionHandling { + c.UseShortOptionHandling = true + } + + set, err := c.parseFlags(ctx.Args(), ctx.shellComplete) + + context := NewContext(ctx.App, set, ctx) + context.Command = c + if checkCommandCompletions(context, c.Name) { + return nil + } + + if err != nil { + if c.OnUsageError != nil { + err = c.OnUsageError(context, err, false) + context.App.handleExitCoder(context, err) + return err + } + _, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) + _, _ = fmt.Fprintln(context.App.Writer) + _ = ShowCommandHelp(context, c.Name) + return err + } + + if checkCommandHelp(context, c.Name) { + return nil + } + + cerr := checkRequiredFlags(c.Flags, context) + if cerr != nil { + _ = ShowCommandHelp(context, c.Name) + return cerr + } + + if c.After != nil { + defer func() { + afterErr := c.After(context) + if afterErr != nil { + context.App.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if c.Before != nil { + err = c.Before(context) + if err != nil { + _ = ShowCommandHelp(context, c.Name) + context.App.handleExitCoder(context, err) + return err + } + } + + if c.Action == nil { + c.Action = helpSubcommand.Action + } + + context.Command = c + err = c.Action(context) + + if err != nil { + context.App.handleExitCoder(context, err) + } + return err +} + +func (c *Command) newFlagSet() (*flag.FlagSet, error) { + return flagSet(c.Name, c.Flags) +} + +func (c *Command) useShortOptionHandling() bool { + return c.UseShortOptionHandling +} + +func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { + set, err := c.newFlagSet() + if err != nil { + return nil, err + } + + if c.SkipFlagParsing { + return set, set.Parse(append([]string{"--"}, args.Tail()...)) + } + + err = parseIter(set, c, args.Tail(), shellComplete) + if err != nil { + return nil, err + } + + err = normalizeFlags(c.Flags, set) + if err != nil { + return nil, err + } + + return set, nil +} + +// Names returns the names including short names and aliases. +func (c *Command) Names() []string { + return append([]string{c.Name}, c.Aliases...) +} + +// HasName returns true if Command.Name matches given name +func (c *Command) HasName(name string) bool { + for _, n := range c.Names() { + if n == name { + return true + } + } + return false +} + +func (c *Command) startApp(ctx *Context) error { + app := &App{ + Metadata: ctx.App.Metadata, + Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name), + } + + if c.HelpName == "" { + app.HelpName = c.HelpName + } else { + app.HelpName = app.Name + } + + app.Usage = c.Usage + app.Description = c.Description + app.ArgsUsage = c.ArgsUsage + + // set CommandNotFound + app.CommandNotFound = ctx.App.CommandNotFound + app.CustomAppHelpTemplate = c.CustomHelpTemplate + + // set the flags and commands + app.Commands = c.Subcommands + app.Flags = c.Flags + app.HideHelp = c.HideHelp + + app.Version = ctx.App.Version + app.HideVersion = ctx.App.HideVersion + app.Compiled = ctx.App.Compiled + app.Writer = ctx.App.Writer + app.ErrWriter = ctx.App.ErrWriter + app.ExitErrHandler = ctx.App.ExitErrHandler + app.UseShortOptionHandling = ctx.App.UseShortOptionHandling + + app.categories = newCommandCategories() + for _, command := range c.Subcommands { + app.categories.AddCommand(command.Category, command) + } + + sort.Sort(app.categories.(*commandCategories)) + + // bash completion + app.EnableBashCompletion = ctx.App.EnableBashCompletion + if c.BashComplete != nil { + app.BashComplete = c.BashComplete + } + + // set the actions + app.Before = c.Before + app.After = c.After + if c.Action != nil { + app.Action = c.Action + } else { + app.Action = helpSubcommand.Action + } + app.OnUsageError = c.OnUsageError + + for index, cc := range app.Commands { + app.Commands[index].commandNamePath = []string{c.Name, cc.Name} + } + + return app.RunAsSubcommand(ctx) +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (c *Command) VisibleFlags() []Flag { + return visibleFlags(c.Flags) +} + +func (c *Command) appendFlag(fl Flag) { + if !hasFlag(c.Flags, fl) { + c.Flags = append(c.Flags, fl) + } +} + +func hasCommand(commands []*Command, command *Command) bool { + for _, existing := range commands { + if command == existing { + return true + } + } + + return false +} diff --git a/vendor/github.com/urfave/cli/v2/context.go b/vendor/github.com/urfave/cli/v2/context.go new file mode 100644 index 000000000..c0c526f41 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/context.go @@ -0,0 +1,274 @@ +package cli + +import ( + "context" + "errors" + "flag" + "fmt" + "strings" +) + +// Context is a type that is passed through to +// each Handler action in a cli application. Context +// can be used to retrieve context-specific args and +// parsed command-line options. +type Context struct { + context.Context + App *App + Command *Command + shellComplete bool + setFlags map[string]bool + flagSet *flag.FlagSet + parentContext *Context +} + +// NewContext creates a new context. For use in when invoking an App or Command action. +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { + c := &Context{App: app, flagSet: set, parentContext: parentCtx} + if parentCtx != nil { + c.Context = parentCtx.Context + c.shellComplete = parentCtx.shellComplete + if parentCtx.flagSet == nil { + parentCtx.flagSet = &flag.FlagSet{} + } + } + + c.Command = &Command{} + + if c.Context == nil { + c.Context = context.Background() + } + + return c +} + +// NumFlags returns the number of flags set +func (c *Context) NumFlags() int { + return c.flagSet.NFlag() +} + +// Set sets a context flag to a value. +func (c *Context) Set(name, value string) error { + return c.flagSet.Set(name, value) +} + +// IsSet determines if the flag was actually set +func (c *Context) IsSet(name string) bool { + if fs := lookupFlagSet(name, c); fs != nil { + if fs := lookupFlagSet(name, c); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true + } + }) + if isSet { + return true + } + } + + f := lookupFlag(name, c) + if f == nil { + return false + } + + return f.IsSet() + } + + return false +} + +// LocalFlagNames returns a slice of flag names used in this context. +func (c *Context) LocalFlagNames() []string { + var names []string + c.flagSet.Visit(makeFlagNameVisitor(&names)) + return names +} + +// FlagNames returns a slice of flag names used by the this context and all of +// its parent contexts. +func (c *Context) FlagNames() []string { + var names []string + for _, ctx := range c.Lineage() { + ctx.flagSet.Visit(makeFlagNameVisitor(&names)) + } + return names +} + +// Lineage returns *this* context and all of its ancestor contexts in order from +// child to parent +func (c *Context) Lineage() []*Context { + var lineage []*Context + + for cur := c; cur != nil; cur = cur.parentContext { + lineage = append(lineage, cur) + } + + return lineage +} + +// Value returns the value of the flag corresponding to `name` +func (c *Context) Value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + +// Args returns the command line arguments associated with the context. +func (c *Context) Args() Args { + ret := args(c.flagSet.Args()) + return &ret +} + +// NArg returns the number of the command line arguments. +func (c *Context) NArg() int { + return c.Args().Len() +} + +func lookupFlag(name string, ctx *Context) Flag { + for _, c := range ctx.Lineage() { + if c.Command == nil { + continue + } + + for _, f := range c.Command.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + if ctx.App != nil { + for _, f := range ctx.App.Flags { + for _, n := range f.Names() { + if n == name { + return f + } + } + } + } + + return nil +} + +func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { + for _, c := range ctx.Lineage() { + if f := c.flagSet.Lookup(name); f != nil { + return c.flagSet + } + } + + return nil +} + +func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { + switch ff.Value.(type) { + case Serializer: + _ = set.Set(name, ff.Value.(Serializer).Serialize()) + default: + _ = set.Set(name, ff.Value.String()) + } +} + +func normalizeFlags(flags []Flag, set *flag.FlagSet) error { + visited := make(map[string]bool) + set.Visit(func(f *flag.Flag) { + visited[f.Name] = true + }) + for _, f := range flags { + parts := f.Names() + if len(parts) == 1 { + continue + } + var ff *flag.Flag + for _, name := range parts { + name = strings.Trim(name, " ") + if visited[name] { + if ff != nil { + return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) + } + ff = set.Lookup(name) + } + } + if ff == nil { + continue + } + for _, name := range parts { + name = strings.Trim(name, " ") + if !visited[name] { + copyFlag(name, ff, set) + } + } + } + return nil +} + +func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { + return func(f *flag.Flag) { + nameParts := strings.Split(f.Name, ",") + name := strings.TrimSpace(nameParts[0]) + + for _, part := range nameParts { + part = strings.TrimSpace(part) + if len(part) > len(name) { + name = part + } + } + + if name != "" { + *names = append(*names, name) + } + } +} + +type requiredFlagsErr interface { + error + getMissingFlags() []string +} + +type errRequiredFlags struct { + missingFlags []string +} + +func (e *errRequiredFlags) Error() string { + numberOfMissingFlags := len(e.missingFlags) + if numberOfMissingFlags == 1 { + return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) + } + joinedMissingFlags := strings.Join(e.missingFlags, ", ") + return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) +} + +func (e *errRequiredFlags) getMissingFlags() []string { + return e.missingFlags +} + +func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { + var missingFlags []string + for _, f := range flags { + if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { + var flagPresent bool + var flagName string + + for _, key := range f.Names() { + if len(key) > 1 { + flagName = key + } + + if context.IsSet(strings.TrimSpace(key)) { + flagPresent = true + } + } + + if !flagPresent && flagName != "" { + missingFlags = append(missingFlags, flagName) + } + } + } + + if len(missingFlags) != 0 { + return &errRequiredFlags{missingFlags: missingFlags} + } + + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/docs.go b/vendor/github.com/urfave/cli/v2/docs.go new file mode 100644 index 000000000..dc16fc82d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/docs.go @@ -0,0 +1,148 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "sort" + "strings" + "text/template" + + "github.com/cpuguy83/go-md2man/v2/md2man" +) + +// ToMarkdown creates a markdown string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMarkdown() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +// ToMan creates a man page string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMan() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + man := md2man.Render(w.Bytes()) + return string(man), nil +} + +type cliTemplate struct { + App *App + Commands []string + GlobalArgs []string + SynopsisArgs []string +} + +func (a *App) writeDocTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(MarkdownDocTemplate) + if err != nil { + return err + } + return t.ExecuteTemplate(w, name, &cliTemplate{ + App: a, + Commands: prepareCommands(a.Commands, 0), + GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), + SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), + }) +} + +func prepareCommands(commands []*Command, level int) []string { + var coms []string + for _, command := range commands { + if command.Hidden { + continue + } + usage := "" + if command.Usage != "" { + usage = command.Usage + } + + prepared := fmt.Sprintf("%s %s\n\n%s\n", + strings.Repeat("#", level+2), + strings.Join(command.Names(), ", "), + usage, + ) + + flags := prepareArgsWithValues(command.Flags) + if len(flags) > 0 { + prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) + } + + coms = append(coms, prepared) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + coms = append( + coms, + prepareCommands(command.Subcommands, level+1)..., + ) + } + } + + return coms +} + +func prepareArgsWithValues(flags []Flag) []string { + return prepareFlags(flags, ", ", "**", "**", `""`, true) +} + +func prepareArgsSynopsis(flags []Flag) []string { + return prepareFlags(flags, "|", "[", "]", "[value]", false) +} + +func prepareFlags( + flags []Flag, + sep, opener, closer, value string, + addDetails bool, +) []string { + args := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + modifiedArg := opener + + for _, s := range flag.Names() { + trimmed := strings.TrimSpace(s) + if len(modifiedArg) > len(opener) { + modifiedArg += sep + } + if len(trimmed) > 1 { + modifiedArg += fmt.Sprintf("--%s", trimmed) + } else { + modifiedArg += fmt.Sprintf("-%s", trimmed) + } + } + modifiedArg += closer + if flag.TakesValue() { + modifiedArg += fmt.Sprintf("=%s", value) + } + + if addDetails { + modifiedArg += flagDetails(flag) + } + + args = append(args, modifiedArg+"\n") + + } + sort.Strings(args) + return args +} + +// flagDetails returns a string containing the flags metadata +func flagDetails(flag DocGenerationFlag) string { + description := flag.GetUsage() + value := flag.GetValue() + if value != "" { + description += " (default: " + value + ")" + } + return ": " + description +} diff --git a/vendor/github.com/urfave/cli/v2/errors.go b/vendor/github.com/urfave/cli/v2/errors.go new file mode 100644 index 000000000..344b4361e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/errors.go @@ -0,0 +1,131 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" +) + +// OsExiter is the function used when the app exits. If not set defaults to os.Exit. +var OsExiter = os.Exit + +// ErrWriter is used to write errors to the user. This can be anything +// implementing the io.Writer interface and defaults to os.Stderr. +var ErrWriter io.Writer = os.Stderr + +// MultiError is an error that wraps multiple errors. +type MultiError interface { + error + // Errors returns a copy of the errors slice + Errors() []error +} + +// NewMultiError creates a new MultiError. Pass in one or more errors. +func newMultiError(err ...error) MultiError { + ret := multiError(err) + return &ret +} + +type multiError []error + +// Error implements the error interface. +func (m *multiError) Error() string { + errs := make([]string, len(*m)) + for i, err := range *m { + errs[i] = err.Error() + } + + return strings.Join(errs, "\n") +} + +// Errors returns a copy of the errors slice +func (m *multiError) Errors() []error { + errs := make([]error, len(*m)) + for _, err := range *m { + errs = append(errs, err) + } + return errs +} + +// ErrorFormatter is the interface that will suitably format the error output +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + +// ExitCoder is the interface checked by `App` and `Command` for a custom exit +// code +type ExitCoder interface { + error + ExitCode() int +} + +type exitError struct { + exitCode int + message interface{} +} + +// NewExitError makes a new *exitError +func NewExitError(message interface{}, exitCode int) ExitCoder { + return Exit(message, exitCode) +} + +// Exit wraps a message and exit code into an ExitCoder suitable for handling by +// HandleExitCoder +func Exit(message interface{}, exitCode int) ExitCoder { + return &exitError{ + message: message, + exitCode: exitCode, + } +} + +func (ee *exitError) Error() string { + return fmt.Sprintf("%v", ee.message) +} + +func (ee *exitError) ExitCode() int { + return ee.exitCode +} + +// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if +// so prints the error to stderr (if it is non-empty) and calls OsExiter with the +// given exit code. If the given error is a MultiError, then this func is +// called on all members of the Errors slice and calls OsExiter with the last exit code. +func HandleExitCoder(err error) { + if err == nil { + return + } + + if exitErr, ok := err.(ExitCoder); ok { + if err.Error() != "" { + if _, ok := exitErr.(ErrorFormatter); ok { + _, _ = fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + _, _ = fmt.Fprintln(ErrWriter, err) + } + } + OsExiter(exitErr.ExitCode()) + return + } + + if multiErr, ok := err.(MultiError); ok { + code := handleMultiError(multiErr) + OsExiter(code) + return + } +} + +func handleMultiError(multiErr MultiError) int { + code := 1 + for _, merr := range multiErr.Errors() { + if multiErr2, ok := merr.(MultiError); ok { + code = handleMultiError(multiErr2) + } else if merr != nil { + fmt.Fprintln(ErrWriter, merr) + if exitErr, ok := merr.(ExitCoder); ok { + code = exitErr.ExitCode() + } + } + } + return code +} diff --git a/vendor/github.com/urfave/cli/v2/fish.go b/vendor/github.com/urfave/cli/v2/fish.go new file mode 100644 index 000000000..67122c9fe --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/fish.go @@ -0,0 +1,192 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "strings" + "text/template" +) + +// ToFishCompletion creates a fish completion string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToFishCompletion() (string, error) { + var w bytes.Buffer + if err := a.writeFishCompletionTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +type fishCompletionTemplate struct { + App *App + Completions []string + AllCommands []string +} + +func (a *App) writeFishCompletionTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(FishCompletionTemplate) + if err != nil { + return err + } + allCommands := []string{} + + // Add global flags + completions := a.prepareFishFlags(a.VisibleFlags(), allCommands) + + // Add help flag + if !a.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, allCommands)..., + ) + } + + // Add version flag + if !a.HideVersion { + completions = append( + completions, + a.prepareFishFlags([]Flag{VersionFlag}, allCommands)..., + ) + } + + // Add commands and their flags + completions = append( + completions, + a.prepareFishCommands(a.VisibleCommands(), &allCommands, []string{})..., + ) + + return t.ExecuteTemplate(w, name, &fishCompletionTemplate{ + App: a, + Completions: completions, + AllCommands: allCommands, + }) +} + +func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { + completions := []string{} + for _, command := range commands { + if command.Hidden { + continue + } + + var completion strings.Builder + completion.WriteString(fmt.Sprintf( + "complete -r -c %s -n '%s' -a '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + strings.Join(command.Names(), " "), + )) + + if command.Usage != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(command.Usage))) + } + + if !command.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, command.Names())..., + ) + } + + *allCommands = append(*allCommands, command.Names()...) + completions = append(completions, completion.String()) + completions = append( + completions, + a.prepareFishFlags(command.Flags, command.Names())..., + ) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + completions = append( + completions, + a.prepareFishCommands( + command.Subcommands, allCommands, command.Names(), + )..., + ) + } + } + + return completions +} + +func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { + completions := []string{} + for _, f := range flags { + flag, ok := f.(DocGenerationFlag) + if !ok { + continue + } + + completion := &strings.Builder{} + completion.WriteString(fmt.Sprintf( + "complete -c %s -n '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + )) + + fishAddFileFlag(f, completion) + + for idx, opt := range flag.Names() { + if idx == 0 { + completion.WriteString(fmt.Sprintf( + " -l %s", strings.TrimSpace(opt), + )) + } else { + completion.WriteString(fmt.Sprintf( + " -s %s", strings.TrimSpace(opt), + )) + + } + } + + if flag.TakesValue() { + completion.WriteString(" -r") + } + + if flag.GetUsage() != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(flag.GetUsage()))) + } + + completions = append(completions, completion.String()) + } + + return completions +} + +func fishAddFileFlag(flag Flag, completion *strings.Builder) { + switch f := flag.(type) { + case *GenericFlag: + if f.TakesFile { + return + } + case *StringFlag: + if f.TakesFile { + return + } + case *StringSliceFlag: + if f.TakesFile { + return + } + } + completion.WriteString(" -f") +} + +func (a *App) fishSubcommandHelper(allCommands []string) string { + fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name) + if len(allCommands) > 0 { + fishHelper = fmt.Sprintf( + "__fish_seen_subcommand_from %s", + strings.Join(allCommands, " "), + ) + } + return fishHelper + +} + +func escapeSingleQuotes(input string) string { + return strings.Replace(input, `'`, `\'`, -1) +} diff --git a/vendor/github.com/urfave/cli/v2/flag.go b/vendor/github.com/urfave/cli/v2/flag.go new file mode 100644 index 000000000..ec128fd44 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag.go @@ -0,0 +1,398 @@ +package cli + +import ( + "flag" + "fmt" + "io/ioutil" + "reflect" + "regexp" + "runtime" + "strconv" + "strings" + "syscall" + "time" +) + +const defaultPlaceholder = "value" + +var ( + slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano()) + + commaWhitespace = regexp.MustCompile("[, ]+.*") +) + +// BashCompletionFlag enables bash-completion for all commands and subcommands +var BashCompletionFlag Flag = &BoolFlag{ + Name: "generate-bash-completion", + Hidden: true, +} + +// VersionFlag prints the version for the application +var VersionFlag Flag = &BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", +} + +// HelpFlag prints the help for all commands and subcommands. +// Set to nil to disable the flag. The subcommand +// will still be added unless HideHelp is set to true. +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", +} + +// FlagStringer converts a flag definition to a string. This is used by help +// to display a flag. +var FlagStringer FlagStringFunc = stringifyFlag + +// Serializer is used to circumvent the limitations of flag.FlagSet.Set +type Serializer interface { + Serialize() string +} + +// FlagNamePrefixer converts a full flag name and its placeholder into the help +// message flag prefix. This is used by the default FlagStringer. +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + +// FlagEnvHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + +// FlagFileHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagFileHinter FlagFileHintFunc = withFileHint + +// FlagsByName is a slice of Flag. +type FlagsByName []Flag + +func (f FlagsByName) Len() int { + return len(f) +} + +func (f FlagsByName) Less(i, j int) bool { + if len(f[j].Names()) == 0 { + return false + } else if len(f[i].Names()) == 0 { + return true + } + return lexicographicLess(f[i].Names()[0], f[j].Names()[0]) +} + +func (f FlagsByName) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + +// Flag is a common interface related to parsing flags in cli. +// For more advanced flag parsing techniques, it is recommended that +// this interface be implemented. +type Flag interface { + fmt.Stringer + // Apply Flag settings to the given flag set + Apply(*flag.FlagSet) error + Names() []string + IsSet() bool +} + +// RequiredFlag is an interface that allows us to mark flags as required +// it allows flags required flags to be backwards compatible with the Flag interface +type RequiredFlag interface { + Flag + + IsRequired() bool +} + +// DocGenerationFlag is an interface that allows documentation generation for the flag +type DocGenerationFlag interface { + Flag + + // TakesValue returns true if the flag takes a value, otherwise false + TakesValue() bool + + // GetUsage returns the usage string for the flag + GetUsage() string + + // GetValue returns the flags value as string representation and an empty + // string if the flag takes no value at all. + GetValue() string +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { + set := flag.NewFlagSet(name, flag.ContinueOnError) + + for _, f := range flags { + if err := f.Apply(set); err != nil { + return nil, err + } + } + set.SetOutput(ioutil.Discard) + return set, nil +} + +func visibleFlags(fl []Flag) []Flag { + var visible []Flag + for _, f := range fl { + field := flagValue(f).FieldByName("Hidden") + if !field.IsValid() || !field.Bool() { + visible = append(visible, f) + } + } + return visible +} + +func prefixFor(name string) (prefix string) { + if len(name) == 1 { + prefix = "-" + } else { + prefix = "--" + } + + return +} + +// Returns the placeholder, if any, and the unquoted usage string. +func unquoteUsage(usage string) (string, string) { + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name := usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break + } + } + return "", usage +} + +func prefixedNames(names []string, placeholder string) string { + var prefixed string + for i, name := range names { + if name == "" { + continue + } + + prefixed += prefixFor(name) + name + if placeholder != "" { + prefixed += " " + placeholder + } + if i < len(names)-1 { + prefixed += ", " + } + } + return prefixed +} + +func withEnvHint(envVars []string, str string) string { + envText := "" + if envVars != nil && len(envVars) > 0 { + prefix := "$" + suffix := "" + sep := ", $" + if runtime.GOOS == "windows" { + prefix = "%" + suffix = "%" + sep = "%, %" + } + + envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + } + return str + envText +} + +func flagNames(f Flag) []string { + var ret []string + + name := flagStringField(f, "Name") + aliases := flagStringSliceField(f, "Aliases") + + for _, part := range append([]string{name}, aliases...) { + // v1 -> v2 migration warning zone: + // Strip off anything after the first found comma or space, which + // *hopefully* makes it a tiny bit more obvious that unexpected behavior is + // caused by using the v1 form of stringly typed "Name". + ret = append(ret, commaWhitespace.ReplaceAllString(part, "")) + } + + return ret +} + +func flagStringSliceField(f Flag, name string) []string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.Interface().([]string) + } + + return []string{} +} + +func flagStringField(f Flag, name string) string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.String() + } + + return "" +} + +func withFileHint(filePath, str string) string { + fileText := "" + if filePath != "" { + fileText = fmt.Sprintf(" [%s]", filePath) + } + return str + fileText +} + +func flagValue(f Flag) reflect.Value { + fv := reflect.ValueOf(f) + for fv.Kind() == reflect.Ptr { + fv = reflect.Indirect(fv) + } + return fv +} + +func stringifyFlag(f Flag) string { + fv := flagValue(f) + + switch f.(type) { + case *IntSliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyIntSliceFlag(f.(*IntSliceFlag))) + case *Int64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyInt64SliceFlag(f.(*Int64SliceFlag))) + case *Float64SliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyFloat64SliceFlag(f.(*Float64SliceFlag))) + case *StringSliceFlag: + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifyStringSliceFlag(f.(*StringSliceFlag))) + } + + placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) + + needsPlaceholder := false + defaultValueString := "" + val := fv.FieldByName("Value") + if val.IsValid() { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface()) + + if val.Kind() == reflect.String && val.String() != "" { + defaultValueString = fmt.Sprintf(" (default: %q)", val.String()) + } + } + + helpText := fv.FieldByName("DefaultText") + if helpText.IsValid() && helpText.String() != "" { + needsPlaceholder = val.Kind() != reflect.Bool + defaultValueString = fmt.Sprintf(" (default: %s)", helpText.String()) + } + + if defaultValueString == " (default: )" { + defaultValueString = "" + } + + if needsPlaceholder && placeholder == "" { + placeholder = defaultPlaceholder + } + + usageWithDefault := strings.TrimSpace(usage + defaultValueString) + + return withEnvHint(flagStringSliceField(f, "EnvVars"), + fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault)) +} + +func stringifyIntSliceFlag(f *IntSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.Itoa(i)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyInt64SliceFlag(f *Int64SliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyFloat64SliceFlag(f *Float64SliceFlag) string { + var defaultVals []string + + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifyStringSliceFlag(f *StringSliceFlag) string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, s := range f.Value.Value() { + if len(s) > 0 { + defaultVals = append(defaultVals, strconv.Quote(s)) + } + } + } + + return stringifySliceFlag(f.Usage, f.Names(), defaultVals) +} + +func stringifySliceFlag(usage string, names, defaultVals []string) string { + placeholder, usage := unquoteUsage(usage) + if placeholder == "" { + placeholder = defaultPlaceholder + } + + defaultVal := "" + if len(defaultVals) > 0 { + defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", ")) + } + + usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) + return fmt.Sprintf("%s\t%s", prefixedNames(names, placeholder), usageWithDefault) +} + +func hasFlag(flags []Flag, fl Flag) bool { + for _, existing := range flags { + if fl == existing { + return true + } + } + + return false +} + +func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) { + for _, envVar := range envVars { + envVar = strings.TrimSpace(envVar) + if val, ok := syscall.Getenv(envVar); ok { + return val, true + } + } + for _, fileVar := range strings.Split(filePath, ",") { + if data, err := ioutil.ReadFile(fileVar); err == nil { + return string(data), true + } + } + return "", false +} diff --git a/vendor/github.com/urfave/cli/v2/flag_bool.go b/vendor/github.com/urfave/cli/v2/flag_bool.go new file mode 100644 index 000000000..6a1da61ef --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_bool.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value bool + DefaultText string + Destination *bool + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *BoolFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *BoolFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *BoolFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *BoolFlag) TakesValue() bool { + return false +} + +// GetUsage returns the usage string for the flag +func (f *BoolFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *BoolFlag) GetValue() string { + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *BoolFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valBool, err := strconv.ParseBool(val) + + if err != nil { + return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, f.Name, err) + } + + f.Value = valBool + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.BoolVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Bool(name, f.Value, f.Usage) + } + + return nil +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupBool(name, fs) + } + return false +} + +func lookupBool(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} diff --git a/vendor/github.com/urfave/cli/v2/flag_duration.go b/vendor/github.com/urfave/cli/v2/flag_duration.go new file mode 100644 index 000000000..2c34944a4 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_duration.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) +type DurationFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value time.Duration + DefaultText string + Destination *time.Duration + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *DurationFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *DurationFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *DurationFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *DurationFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *DurationFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *DurationFlag) GetValue() string { + return f.Value.String() +} + +// Apply populates the flag given the flag set and environment +func (f *DurationFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valDuration, err := time.ParseDuration(val) + + if err != nil { + return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, f.Name, err) + } + + f.Value = valDuration + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.DurationVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Duration(name, f.Value, f.Usage) + } + return nil +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupDuration(name, fs) + } + return 0 +} + +func lookupDuration(name string, set *flag.FlagSet) time.Duration { + f := set.Lookup(name) + if f != nil { + parsed, err := time.ParseDuration(f.Value.String()) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64.go b/vendor/github.com/urfave/cli/v2/flag_float64.go new file mode 100644 index 000000000..31f06f35e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value float64 + DefaultText string + Destination *float64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Float64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64Flag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64Flag) GetValue() string { + return fmt.Sprintf("%f", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *Float64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valFloat, err := strconv.ParseFloat(val, 10) + + if err != nil { + return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, f.Name, err) + } + + f.Value = valFloat + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Float64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Float64(name, f.Value, f.Usage) + } + + return nil +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupFloat64(name, fs) + } + return 0 +} + +func lookupFloat64(name string, set *flag.FlagSet) float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseFloat(f.Value.String(), 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64_slice.go b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go new file mode 100644 index 000000000..91d2e9d10 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go @@ -0,0 +1,165 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Float64Slice wraps []float64 to satisfy flag.Value +type Float64Slice struct { + slice []float64 + hasBeenSet bool +} + +// NewFloat64Slice makes a *Float64Slice with default values +func NewFloat64Slice(defaults ...float64) *Float64Slice { + return &Float64Slice{slice: append([]float64{}, defaults...)} +} + +// Set parses the value into a float64 and appends it to the list of values +func (f *Float64Slice) Set(value string) error { + if !f.hasBeenSet { + f.slice = []float64{} + f.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &f.slice) + f.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseFloat(value, 64) + if err != nil { + return err + } + + f.slice = append(f.slice, tmp) + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Float64Slice) String() string { + return fmt.Sprintf("%#v", f.slice) +} + +// Serialize allows Float64Slice to fulfill Serializer +func (f *Float64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(f.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of float64s set by this flag +func (f *Float64Slice) Value() []float64 { + return f.slice +} + +// Get returns the slice of float64s set by this flag +func (f *Float64Slice) Get() interface{} { + return *f +} + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Float64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Float64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Float64SliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64SliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true if the flag takes a value, otherwise false +func (f *Float64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Float64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Float64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + f.Value = &Float64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err) + } + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &Float64Slice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// nil if not found +func (c *Context) Float64Slice(name string) []float64 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupFloat64Slice(name, fs) + } + return nil +} + +func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Float64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_generic.go b/vendor/github.com/urfave/cli/v2/flag_generic.go new file mode 100644 index 000000000..2d9baa78d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_generic.go @@ -0,0 +1,108 @@ +package cli + +import ( + "flag" + "fmt" +) + +// Generic is a generic parseable type identified by a specific flag +type Generic interface { + Set(value string) error + String() string +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value Generic + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *GenericFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *GenericFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *GenericFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *GenericFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *GenericFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *GenericFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply takes the flagset and calls Set on the generic flag with the value +// provided by the user for parsing by the flag +func (f GenericFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err) + } + + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (c *Context) Generic(name string) interface{} { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupGeneric(name, fs) + } + return nil +} + +func lookupGeneric(name string, set *flag.FlagSet) interface{} { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value, error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int.go b/vendor/github.com/urfave/cli/v2/flag_int.go new file mode 100644 index 000000000..be961bf5f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int.go @@ -0,0 +1,106 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int + DefaultText string + Destination *int + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *IntFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *IntFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *IntFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + } + + f.Value = int(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.IntVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int(name, f.Value, f.Usage) + } + + return nil +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupInt(name, fs) + } + return 0 +} + +func lookupInt(name string, set *flag.FlagSet) int { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return int(parsed) + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64.go b/vendor/github.com/urfave/cli/v2/flag_int64.go new file mode 100644 index 000000000..c979119f8 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value int64 + DefaultText string + Destination *int64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Int64Flag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Apply populates the flag given the flag set and environment +func (f *Int64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseInt(val, 0, 64) + + if err != nil { + return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Int64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Int64(name, f.Value, f.Usage) + } + return nil +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupInt64(name, fs) + } + return 0 +} + +func lookupInt64(name string, set *flag.FlagSet) int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int64_slice.go b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go new file mode 100644 index 000000000..41aa0667e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go @@ -0,0 +1,161 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Int64Slice wraps []int64 to satisfy flag.Value +type Int64Slice struct { + slice []int64 + hasBeenSet bool +} + +// NewInt64Slice makes an *Int64Slice with default values +func NewInt64Slice(defaults ...int64) *Int64Slice { + return &Int64Slice{slice: append([]int64{}, defaults...)} +} + +// Set parses the value into an integer and appends it to the list of values +func (i *Int64Slice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int64{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseInt(value, 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, tmp) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *Int64Slice) String() string { + return fmt.Sprintf("%#v", i.slice) +} + +// Serialize allows Int64Slice to fulfill Serializer +func (i *Int64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *Int64Slice) Value() []int64 { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *Int64Slice) Get() interface{} { + return *i +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *Int64Slice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Int64SliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64SliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Int64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f Int64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Int64SliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &Int64Slice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &Int64Slice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (c *Context) Int64Slice(name string) []int64 { + return lookupInt64Slice(name, c.flagSet) +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_int_slice.go b/vendor/github.com/urfave/cli/v2/flag_int_slice.go new file mode 100644 index 000000000..938897842 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_int_slice.go @@ -0,0 +1,175 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// IntSlice wraps []int to satisfy flag.Value +type IntSlice struct { + slice []int + hasBeenSet bool +} + +// NewIntSlice makes an *IntSlice with default values +func NewIntSlice(defaults ...int) *IntSlice { + return &IntSlice{slice: append([]int{}, defaults...)} +} + +// TODO: Consistently have specific Set function for Int64 and Float64 ? +// SetInt directly adds an integer to the list of values +func (i *IntSlice) SetInt(value int) { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + i.slice = append(i.slice, value) +} + +// Set parses the value into an integer and appends it to the list of values +func (i *IntSlice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []int{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + tmp, err := strconv.ParseInt(value, 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, int(tmp)) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (i *IntSlice) String() string { + return fmt.Sprintf("%#v", i.slice) +} + +// Serialize allows IntSlice to fulfill Serializer +func (i *IntSlice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *IntSlice) Value() []int { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *IntSlice) Get() interface{} { + return *i +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value *IntSlice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *IntSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *IntSliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *IntSliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *IntSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f IntSliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *IntSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &IntSlice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &IntSlice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (c *Context) IntSlice(name string) []int { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupIntSlice(name, c.flagSet) + } + return nil +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_path.go b/vendor/github.com/urfave/cli/v2/flag_path.go new file mode 100644 index 000000000..a32285739 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_path.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +type PathFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *PathFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *PathFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *PathFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *PathFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *PathFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *PathFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *PathFlag) GetValue() string { + return f.Value +} + +// Apply populates the flag given the flag set and environment +func (f *PathFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// Path looks up the value of a local PathFlag, returns +// "" if not found +func (c *Context) Path(name string) string { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupPath(name, fs) + } + + return "" +} + +func lookupPath(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string.go b/vendor/github.com/urfave/cli/v2/flag_string.go new file mode 100644 index 000000000..bcd82530c --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string.go @@ -0,0 +1,95 @@ +package cli + +import "flag" + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value string + DefaultText string + Destination *string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *StringFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringFlag) GetValue() string { + return f.Value +} + +// Apply populates the flag given the flag set and environment +func (f *StringFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = val + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.StringVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.String(name, f.Value, f.Usage) + } + + return nil +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupString(name, fs) + } + return "" +} + +func lookupString(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} diff --git a/vendor/github.com/urfave/cli/v2/flag_string_slice.go b/vendor/github.com/urfave/cli/v2/flag_string_slice.go new file mode 100644 index 000000000..a114a495e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_string_slice.go @@ -0,0 +1,159 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strings" +) + +// StringSlice wraps a []string to satisfy flag.Value +type StringSlice struct { + slice []string + hasBeenSet bool +} + +// NewStringSlice creates a *StringSlice with default values +func NewStringSlice(defaults ...string) *StringSlice { + return &StringSlice{slice: append([]string{}, defaults...)} +} + +// Set appends the string value to the list of values +func (s *StringSlice) Set(value string) error { + if !s.hasBeenSet { + s.slice = []string{} + s.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &s.slice) + s.hasBeenSet = true + return nil + } + + s.slice = append(s.slice, value) + + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (s *StringSlice) String() string { + return fmt.Sprintf("%s", s.slice) +} + +// Serialize allows StringSlice to fulfill Serializer +func (s *StringSlice) Serialize() string { + jsonBytes, _ := json.Marshal(s.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of strings set by this flag +func (s *StringSlice) Value() []string { + return s.slice +} + +// Get returns the slice of strings set by this flag +func (s *StringSlice) Get() interface{} { + return *s +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + TakesFile bool + Value *StringSlice + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *StringSliceFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *StringSliceFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *StringSliceFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *StringSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *StringSliceFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *StringSliceFlag) GetValue() string { + if f.Value != nil { + return f.Value.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.Value = &StringSlice{} + + for _, s := range strings.Split(val, ",") { + if err := f.Value.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err) + } + } + + f.HasBeenSet = true + } + + for _, name := range f.Names() { + if f.Value == nil { + f.Value = &StringSlice{} + } + set.Var(f.Value, name, f.Usage) + } + + return nil +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (c *Context) StringSlice(name string) []string { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupStringSlice(name, fs) + } + return nil +} + +func lookupStringSlice(name string, set *flag.FlagSet) []string { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_timestamp.go b/vendor/github.com/urfave/cli/v2/flag_timestamp.go new file mode 100644 index 000000000..d24edcd7f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_timestamp.go @@ -0,0 +1,152 @@ +package cli + +import ( + "flag" + "fmt" + "time" +) + +// Timestamp wrap to satisfy golang's flag interface. +type Timestamp struct { + timestamp *time.Time + hasBeenSet bool + layout string +} + +// Timestamp constructor +func NewTimestamp(timestamp time.Time) *Timestamp { + return &Timestamp{timestamp: ×tamp} +} + +// Set the timestamp value directly +func (t *Timestamp) SetTimestamp(value time.Time) { + if !t.hasBeenSet { + t.timestamp = &value + t.hasBeenSet = true + } +} + +// Set the timestamp string layout for future parsing +func (t *Timestamp) SetLayout(layout string) { + t.layout = layout +} + +// Parses the string value to timestamp +func (t *Timestamp) Set(value string) error { + timestamp, err := time.Parse(t.layout, value) + if err != nil { + return err + } + + t.timestamp = ×tamp + t.hasBeenSet = true + return nil +} + +// String returns a readable representation of this value (for usage defaults) +func (t *Timestamp) String() string { + return fmt.Sprintf("%#v", t.timestamp) +} + +// Value returns the timestamp value stored in the flag +func (t *Timestamp) Value() *time.Time { + return t.timestamp +} + +// Get returns the flag structure +func (t *Timestamp) Get() interface{} { + return *t +} + +// TimestampFlag is a flag with type time +type TimestampFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Layout string + Value *Timestamp + DefaultText string + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *TimestampFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *TimestampFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *TimestampFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *TimestampFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *TimestampFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *TimestampFlag) GetUsage() string { + return f.Usage +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *TimestampFlag) GetValue() string { + if f.Value != nil { + return f.Value.timestamp.String() + } + return "" +} + +// Apply populates the flag given the flag set and environment +func (f *TimestampFlag) Apply(set *flag.FlagSet) error { + if f.Layout == "" { + return fmt.Errorf("timestamp Layout is required") + } + f.Value = &Timestamp{} + f.Value.SetLayout(f.Layout) + + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if err := f.Value.Set(val); err != nil { + return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err) + } + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(f.Value, name, f.Usage) + } + return nil +} + +// Timestamp gets the timestamp from a flag name +func (c *Context) Timestamp(name string) *time.Time { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupTimestamp(name, fs) + } + return nil +} + +// Fetches the timestamp value from the local timestampWrap +func lookupTimestamp(name string, set *flag.FlagSet) *time.Time { + f := set.Lookup(name) + if f != nil { + return (f.Value.(*Timestamp)).Value() + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint.go b/vendor/github.com/urfave/cli/v2/flag_uint.go new file mode 100644 index 000000000..9f592388f --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint + DefaultText string + Destination *uint + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintFlag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *UintFlag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *UintFlag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *UintFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *UintFlag) GetUsage() string { + return f.Usage +} + +// Apply populates the flag given the flag set and environment +func (f *UintFlag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, f.Name, err) + } + + f.Value = uint(valInt) + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.UintVar(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *UintFlag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupUint(name, fs) + } + return 0 +} + +func lookupUint(name string, set *flag.FlagSet) uint { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return uint(parsed) + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint64.go b/vendor/github.com/urfave/cli/v2/flag_uint64.go new file mode 100644 index 000000000..5bbd1fa4b --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint64.go @@ -0,0 +1,105 @@ +package cli + +import ( + "flag" + "fmt" + "strconv" +) + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Aliases []string + Usage string + EnvVars []string + FilePath string + Required bool + Hidden bool + Value uint64 + DefaultText string + Destination *uint64 + HasBeenSet bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64Flag) IsSet() bool { + return f.HasBeenSet +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// Names returns the names of the flag +func (f *Uint64Flag) Names() []string { + return flagNames(f) +} + +// IsRequired returns whether or not the flag is required +func (f *Uint64Flag) IsRequired() bool { + return f.Required +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Uint64Flag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Uint64Flag) GetUsage() string { + return f.Usage +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64Flag) Apply(set *flag.FlagSet) error { + if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + if val != "" { + valInt, err := strconv.ParseUint(val, 0, 64) + if err != nil { + return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, f.Name, err) + } + + f.Value = valInt + f.HasBeenSet = true + } + } + + for _, name := range f.Names() { + if f.Destination != nil { + set.Uint64Var(f.Destination, name, f.Value, f.Usage) + continue + } + set.Uint64(name, f.Value, f.Usage) + } + + return nil +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Uint64Flag) GetValue() string { + return fmt.Sprintf("%d", f.Value) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + if fs := lookupFlagSet(name, c); fs != nil { + return lookupUint64(name, fs) + } + return 0 +} + +func lookupUint64(name string, set *flag.FlagSet) uint64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} diff --git a/vendor/github.com/urfave/cli/v2/funcs.go b/vendor/github.com/urfave/cli/v2/funcs.go new file mode 100644 index 000000000..474c48faf --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/funcs.go @@ -0,0 +1,44 @@ +package cli + +// BashCompleteFunc is an action to execute when the shell completion flag is set +type BashCompleteFunc func(*Context) + +// BeforeFunc is an action to execute before any subcommands are run, but after +// the context is ready if a non-nil error is returned, no subcommands are run +type BeforeFunc func(*Context) error + +// AfterFunc is an action to execute after any subcommands are run, but after the +// subcommand has finished it is run even if Action() panics +type AfterFunc func(*Context) error + +// ActionFunc is the action to execute when no subcommands are specified +type ActionFunc func(*Context) error + +// CommandNotFoundFunc is executed if the proper command cannot be found +type CommandNotFoundFunc func(*Context, string) + +// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying +// customized usage error messages. This function is able to replace the +// original error messages. If this function is not set, the "Incorrect usage" +// is displayed and the execution is interrupted. +type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error + +// ExitErrHandlerFunc is executed if provided in order to handle exitError values +// returned by Actions and Before/After functions. +type ExitErrHandlerFunc func(context *Context, err error) + +// FlagStringFunc is used by the help generation to display a flag, which is +// expected to be a single line. +type FlagStringFunc func(Flag) string + +// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix +// text for a flag's full name. +type FlagNamePrefixFunc func(fullName []string, placeholder string) string + +// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help +// with the environment variable details. +type FlagEnvHintFunc func(envVars []string, str string) string + +// FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help +// with the file path details. +type FlagFileHintFunc func(filePath, str string) string diff --git a/vendor/github.com/urfave/cli/v2/go.mod b/vendor/github.com/urfave/cli/v2/go.mod new file mode 100644 index 000000000..c38d41c14 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.mod @@ -0,0 +1,9 @@ +module github.com/urfave/cli/v2 + +go 1.11 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d + gopkg.in/yaml.v2 v2.2.2 +) diff --git a/vendor/github.com/urfave/cli/v2/go.sum b/vendor/github.com/urfave/cli/v2/go.sum new file mode 100644 index 000000000..ef121ff5d --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/go.sum @@ -0,0 +1,14 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/urfave/cli/v2/help.go b/vendor/github.com/urfave/cli/v2/help.go new file mode 100644 index 000000000..c1e974a48 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/help.go @@ -0,0 +1,368 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" + "text/tabwriter" + "text/template" + "unicode/utf8" +) + +var helpCommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + _ = ShowAppHelp(c) + return nil + }, +} + +var helpSubcommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + return ShowSubcommandHelp(c) + }, +} + +// Prints help for the App or Command +type helpPrinter func(w io.Writer, templ string, data interface{}) + +// Prints help for the App or Command with custom template function. +type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{}) + +// HelpPrinter is a function that writes the help output. If not set explicitly, +// this calls HelpPrinterCustom using only the default template functions. +// +// If custom logic for printing help is required, this function can be +// overridden. If the ExtraInfo field is defined on an App, this function +// should not be modified, as HelpPrinterCustom will be used directly in order +// to capture the extra information. +var HelpPrinter helpPrinter = printHelp + +// HelpPrinterCustom is a function that writes the help output. It is used as +// the default implementation of HelpPrinter, and may be called directly if +// the ExtraInfo field is set on an App. +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + +// VersionPrinter prints the version for the App +var VersionPrinter = printVersion + +// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code. +func ShowAppHelpAndExit(c *Context, exitCode int) { + _ = ShowAppHelp(c) + os.Exit(exitCode) +} + +// ShowAppHelp is an action that displays the help. +func ShowAppHelp(c *Context) error { + template := c.App.CustomAppHelpTemplate + if template == "" { + template = AppHelpTemplate + } + + if c.App.ExtraInfo == nil { + HelpPrinter(c.App.Writer, template, c.App) + return nil + } + + customAppData := func() map[string]interface{} { + return map[string]interface{}{ + "ExtraInfo": c.App.ExtraInfo, + } + } + HelpPrinterCustom(c.App.Writer, template, c.App, customAppData()) + + return nil +} + +// DefaultAppComplete prints the list of subcommands as the default app completion method +func DefaultAppComplete(c *Context) { + DefaultCompleteWithFlags(nil)(c) +} + +func printCommandSuggestions(commands []*Command, writer io.Writer) { + for _, command := range commands { + if command.Hidden { + continue + } + if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) + } + } else { + for _, name := range command.Names() { + _, _ = fmt.Fprintf(writer, "%s\n", name) + } + } + } +} + +func cliArgContains(flagName string) bool { + for _, name := range strings.Split(flagName, ",") { + name = strings.TrimSpace(name) + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 + } + flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + for _, a := range os.Args { + if a == flag { + return true + } + } + } + return false +} + +func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { + cur := strings.TrimPrefix(lastArg, "-") + cur = strings.TrimPrefix(cur, "-") + for _, flag := range flags { + if bflag, ok := flag.(*BoolFlag); ok && bflag.Hidden { + continue + } + for _, name := range flag.Names() { + name = strings.TrimSpace(name) + // this will get total count utf8 letters in flag name + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 // resuse this count to generate single - or -- in flag completion + } + // if flag name has more than one utf8 letter and last argument in cli has -- prefix then + // skip flag completion for short flags example -v or -x + if strings.HasPrefix(lastArg, "--") && count == 1 { + continue + } + // match if last argument matches this flag and it is not repeated + if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) { + flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + _, _ = fmt.Fprintln(writer, flagCompletion) + } + } + } +} + +func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { + return func(c *Context) { + if len(os.Args) > 2 { + lastArg := os.Args[len(os.Args)-2] + if strings.HasPrefix(lastArg, "-") { + printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer) + if cmd != nil { + printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer) + } + return + } + } + if cmd != nil { + printCommandSuggestions(cmd.Subcommands, c.App.Writer) + } else { + printCommandSuggestions(c.App.Commands, c.App.Writer) + } + } +} + +// ShowCommandHelpAndExit - exits with code after showing help +func ShowCommandHelpAndExit(c *Context, command string, code int) { + _ = ShowCommandHelp(c, command) + os.Exit(code) +} + +// ShowCommandHelp prints help for the given command +func ShowCommandHelp(ctx *Context, command string) error { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) + return nil + } + + for _, c := range ctx.App.Commands { + if c.HasName(command) { + templ := c.CustomHelpTemplate + if templ == "" { + templ = CommandHelpTemplate + } + + HelpPrinter(ctx.App.Writer, templ, c) + + return nil + } + } + + if ctx.App.CommandNotFound == nil { + return Exit(fmt.Sprintf("No help topic for '%v'", command), 3) + } + + ctx.App.CommandNotFound(ctx, command) + return nil +} + +// ShowSubcommandHelp prints help for the given subcommand +func ShowSubcommandHelp(c *Context) error { + if c == nil { + return nil + } + + if c.Command != nil { + return ShowCommandHelp(c, c.Command.Name) + } + + return ShowCommandHelp(c, "") +} + +// ShowVersion prints the version number of the App +func ShowVersion(c *Context) { + VersionPrinter(c) +} + +func printVersion(c *Context) { + _, _ = fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) +} + +// ShowCompletions prints the lists of commands within a given context +func ShowCompletions(c *Context) { + a := c.App + if a != nil && a.BashComplete != nil { + a.BashComplete(c) + } +} + +// ShowCommandCompletions prints the custom completions for a given command +func ShowCommandCompletions(ctx *Context, command string) { + c := ctx.App.Command(command) + if c != nil { + if c.BashComplete != nil { + c.BashComplete(ctx) + } else { + DefaultCompleteWithFlags(c)(ctx) + } + } + +} + +// printHelpCustom is the default implementation of HelpPrinterCustom. +// +// The customFuncs map will be combined with a default template.FuncMap to +// allow using arbitrary functions in template rendering. +func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { + funcMap := template.FuncMap{ + "join": strings.Join, + } + for key, value := range customFuncs { + funcMap[key] = value + } + + w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) + t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + + err := t.Execute(w, data) + if err != nil { + // If the writer is closed, t.Execute will fail, and there's nothing + // we can do to recover. + if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" { + _, _ = fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) + } + return + } + _ = w.Flush() +} + +func printHelp(out io.Writer, templ string, data interface{}) { + HelpPrinterCustom(out, templ, data, nil) +} + +func checkVersion(c *Context) bool { + found := false + for _, name := range VersionFlag.Names() { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkHelp(c *Context) bool { + found := false + for _, name := range HelpFlag.Names() { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkCommandHelp(c *Context, name string) bool { + if c.Bool("h") || c.Bool("help") { + _ = ShowCommandHelp(c, name) + return true + } + + return false +} + +func checkSubcommandHelp(c *Context) bool { + if c.Bool("h") || c.Bool("help") { + _ = ShowSubcommandHelp(c) + return true + } + + return false +} + +func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { + if !a.EnableBashCompletion { + return false, arguments + } + + pos := len(arguments) - 1 + lastArg := arguments[pos] + + if lastArg != "--generate-bash-completion" { + return false, arguments + } + + return true, arguments[:pos] +} + +func checkCompletions(c *Context) bool { + if !c.shellComplete { + return false + } + + if args := c.Args(); args.Present() { + name := args.First() + if cmd := c.App.Command(name); cmd != nil { + // let the command handle the completion + return false + } + } + + ShowCompletions(c) + return true +} + +func checkCommandCompletions(c *Context, name string) bool { + if !c.shellComplete { + return false + } + + ShowCommandCompletions(c, name) + return true +} diff --git a/vendor/github.com/urfave/cli/v2/parse.go b/vendor/github.com/urfave/cli/v2/parse.go new file mode 100644 index 000000000..7df17296a --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/parse.go @@ -0,0 +1,94 @@ +package cli + +import ( + "flag" + "strings" +) + +type iterativeParser interface { + newFlagSet() (*flag.FlagSet, error) + useShortOptionHandling() bool +} + +// To enable short-option handling (e.g., "-it" vs "-i -t") we have to +// iteratively catch parsing errors. This way we achieve LR parsing without +// transforming any arguments. Otherwise, there is no way we can discriminate +// combined short options from common arguments that should be left untouched. +// Pass `shellComplete` to continue parsing options on failure during shell +// completion when, the user-supplied options may be incomplete. +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error { + for { + err := set.Parse(args) + if !ip.useShortOptionHandling() || err == nil { + if shellComplete { + return nil + } + return err + } + + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") + if errStr == trimmed { + return err + } + + // regenerate the initial args with the split short opts + argsWereSplit := false + for i, arg := range args { + // skip args that are not part of the error message + if name := strings.TrimLeft(arg, "-"); name != trimmed { + continue + } + + // if we can't split, the error was accurate + shortOpts := splitShortOptions(set, arg) + if len(shortOpts) == 1 { + return err + } + + // swap current argument with the split version + args = append(args[:i], append(shortOpts, args[i+1:]...)...) + argsWereSplit = true + break + } + + // This should be an impossible to reach code path, but in case the arg + // splitting failed to happen, this will prevent infinite loops + if !argsWereSplit { + return err + } + + // Since custom parsing failed, replace the flag set before retrying + newSet, err := ip.newFlagSet() + if err != nil { + return err + } + *set = *newSet + } +} + +func splitShortOptions(set *flag.FlagSet, arg string) []string { + shortFlagsExist := func(s string) bool { + for _, c := range s[1:] { + if f := set.Lookup(string(c)); f == nil { + return false + } + } + return true + } + + if !isSplittable(arg) || !shortFlagsExist(arg) { + return []string{arg} + } + + separated := make([]string, 0, len(arg)-1) + for _, flagChar := range arg[1:] { + separated = append(separated, "-"+string(flagChar)) + } + + return separated +} + +func isSplittable(flagArg string) bool { + return strings.HasPrefix(flagArg, "-") && !strings.HasPrefix(flagArg, "--") && len(flagArg) > 2 +} diff --git a/vendor/github.com/urfave/cli/v2/sort.go b/vendor/github.com/urfave/cli/v2/sort.go new file mode 100644 index 000000000..23d1c2f77 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sort.go @@ -0,0 +1,29 @@ +package cli + +import "unicode" + +// lexicographicLess compares strings alphabetically considering case. +func lexicographicLess(i, j string) bool { + iRunes := []rune(i) + jRunes := []rune(j) + + lenShared := len(iRunes) + if lenShared > len(jRunes) { + lenShared = len(jRunes) + } + + for index := 0; index < lenShared; index++ { + ir := iRunes[index] + jr := jRunes[index] + + if lir, ljr := unicode.ToLower(ir), unicode.ToLower(jr); lir != ljr { + return lir < ljr + } + + if ir != jr { + return ir < jr + } + } + + return i < j +} diff --git a/vendor/github.com/urfave/cli/v2/template.go b/vendor/github.com/urfave/cli/v2/template.go new file mode 100644 index 000000000..1cc4bd624 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/template.go @@ -0,0 +1,119 @@ +package cli + +// AppHelpTemplate is the text template for the Default help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var AppHelpTemplate = `NAME: + {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if len .Authors}} + +AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +GLOBAL OPTIONS: + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} + +COPYRIGHT: + {{.Copyright}}{{end}} +` + +// CommandHelpTemplate is the text template for the command help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var CommandHelpTemplate = `NAME: + {{.HelpName}} - {{.Usage}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + +CATEGORY: + {{.Category}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + +// SubcommandHelpTemplate is the text template for the subcommand help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var SubcommandHelpTemplate = `NAME: + {{.HelpName}} - {{if .Description}}{{.Description}}{{else}}{{.Usage}}{{end}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{.}} + {{end}}{{end}} +` + +var MarkdownDocTemplate = `% {{ .App.Name }}(8){{ if .App.Description }} {{ .App.Description }}{{ end }} +{{ range $a := .App.Authors }} +% {{ $a }}{{ end }} + +# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.UsageText }} +# DESCRIPTION + +{{ .App.UsageText }} +{{ end }} +**Usage**: + +` + "```" + ` +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` + +var FishCompletionTemplate = `# {{ .App.Name }} fish shell completion + +function __fish_{{ .App.Name }}_no_subcommand --description 'Test if there has been any subcommand yet' + for i in (commandline -opc) + if contains -- $i{{ range $v := .AllCommands }} {{ $v }}{{ end }} + return 1 + end + end + return 0 +end + +{{ range $v := .Completions }}{{ $v }} +{{ end }}` diff --git a/vendor/k8s.io/gengo/args/args.go b/vendor/k8s.io/gengo/args/args.go index 7401098c5..26c790e65 100644 --- a/vendor/k8s.io/gengo/args/args.go +++ b/vendor/k8s.io/gengo/args/args.go @@ -159,6 +159,9 @@ func (g *GeneratorArgs) InputIncludes(p *types.Package) bool { if strings.HasSuffix(d, "...") { d = strings.TrimSuffix(d, "...") } + if strings.HasPrefix(d, "./vendor/") { + d = strings.TrimPrefix(d, "./vendor/") + } if strings.HasPrefix(p.Path, d) { return true } diff --git a/vendor/k8s.io/gengo/generator/default_package.go b/vendor/k8s.io/gengo/generator/default_package.go index 11517fc6a..dcf088323 100644 --- a/vendor/k8s.io/gengo/generator/default_package.go +++ b/vendor/k8s.io/gengo/generator/default_package.go @@ -26,6 +26,8 @@ type DefaultPackage struct { PackageName string // Import path of the package, and the location on disk of the package. PackagePath string + // The location of the package on disk. + Source string // Emitted at the top of every file. HeaderText []byte @@ -43,8 +45,9 @@ type DefaultPackage struct { FilterFunc func(*Context, *types.Type) bool } -func (d *DefaultPackage) Name() string { return d.PackageName } -func (d *DefaultPackage) Path() string { return d.PackagePath } +func (d *DefaultPackage) Name() string { return d.PackageName } +func (d *DefaultPackage) Path() string { return d.PackagePath } +func (d *DefaultPackage) SourcePath() string { return d.Source } func (d *DefaultPackage) Filter(c *Context, t *types.Type) bool { if d.FilterFunc != nil { diff --git a/vendor/k8s.io/gengo/generator/execute.go b/vendor/k8s.io/gengo/generator/execute.go index b5f5aaeb4..d1b12258c 100644 --- a/vendor/k8s.io/gengo/generator/execute.go +++ b/vendor/k8s.io/gengo/generator/execute.go @@ -233,11 +233,13 @@ func (c *Context) ExecutePackage(outDir string, p Package) error { if f == nil { // This is the first generator to reference this file, so start it. f = &File{ - Name: g.Filename(), - FileType: fileType, - PackageName: p.Name(), - Header: p.Header(g.Filename()), - Imports: map[string]struct{}{}, + Name: g.Filename(), + FileType: fileType, + PackageName: p.Name(), + PackagePath: p.Path(), + PackageSourcePath: p.SourcePath(), + Header: p.Header(g.Filename()), + Imports: map[string]struct{}{}, } files[f.Name] = f } else { diff --git a/vendor/k8s.io/gengo/generator/generator.go b/vendor/k8s.io/gengo/generator/generator.go index 05a3f65fe..4b48f503c 100644 --- a/vendor/k8s.io/gengo/generator/generator.go +++ b/vendor/k8s.io/gengo/generator/generator.go @@ -31,6 +31,8 @@ type Package interface { Name() string // Path returns the package import path. Path() string + // SourcePath returns the location of the package on disk. + SourcePath() string // Filter should return true if this package cares about this type. // Otherwise, this type will be omitted from the type ordering for @@ -50,14 +52,16 @@ type Package interface { } type File struct { - Name string - FileType string - PackageName string - Header []byte - Imports map[string]struct{} - Vars bytes.Buffer - Consts bytes.Buffer - Body bytes.Buffer + Name string + FileType string + PackageName string + Header []byte + PackagePath string + PackageSourcePath string + Imports map[string]struct{} + Vars bytes.Buffer + Consts bytes.Buffer + Body bytes.Buffer } type FileType interface { @@ -156,6 +160,12 @@ type Context struct { // All the types, in case you want to look up something. Universe types.Universe + // Incoming imports, i.e. packages importing the given package. + incomingImports map[string][]string + + // Incoming transitive imports, i.e. the transitive closure of IncomingImports + incomingTransitiveImports map[string][]string + // All the user-specified packages. This is after recursive expansion. Inputs []string @@ -203,11 +213,36 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder return c, nil } +// IncomingImports returns the incoming imports for each package. The map is lazily computed. +func (ctxt *Context) IncomingImports() map[string][]string { + if ctxt.incomingImports == nil { + incoming := map[string][]string{} + for _, pkg := range ctxt.Universe { + for imp := range pkg.Imports { + incoming[imp] = append(incoming[imp], pkg.Path) + } + } + ctxt.incomingImports = incoming + } + return ctxt.incomingImports +} + +// TransitiveIncomingImports returns the transitive closure of the incoming imports for each package. +// The map is lazily computed. +func (ctxt *Context) TransitiveIncomingImports() map[string][]string { + if ctxt.incomingTransitiveImports == nil { + ctxt.incomingTransitiveImports = transitiveClosure(ctxt.IncomingImports()) + } + return ctxt.incomingTransitiveImports +} + // AddDir adds a Go package to the context. The specified path must be a single // go package import path. GOPATH, GOROOT, and the location of your go binary // (`which go`) will all be searched, in the normal Go fashion. // Deprecated. Please use AddDirectory. func (ctxt *Context) AddDir(path string) error { + ctxt.incomingImports = nil + ctxt.incomingTransitiveImports = nil return ctxt.builder.AddDirTo(path, &ctxt.Universe) } @@ -215,5 +250,7 @@ func (ctxt *Context) AddDir(path string) error { // single go package import path. GOPATH, GOROOT, and the location of your go // binary (`which go`) will all be searched, in the normal Go fashion. func (ctxt *Context) AddDirectory(path string) (*types.Package, error) { + ctxt.incomingImports = nil + ctxt.incomingTransitiveImports = nil return ctxt.builder.AddDirectoryTo(path, &ctxt.Universe) } diff --git a/vendor/k8s.io/gengo/generator/import_tracker.go b/vendor/k8s.io/gengo/generator/import_tracker.go index 5d058410a..5d87de4ff 100644 --- a/vendor/k8s.io/gengo/generator/import_tracker.go +++ b/vendor/k8s.io/gengo/generator/import_tracker.go @@ -17,6 +17,7 @@ limitations under the License. package generator import ( + "go/token" "strings" "k8s.io/klog" @@ -58,6 +59,11 @@ func golangTrackerLocalName(tracker namer.ImportTracker, t types.Name) string { // This name collides with some other package continue } + + // If the import name is a Go keyword, prefix with an underscore. + if token.Lookup(name).IsKeyword() { + name = "_" + name + } return name } panic("can't find import for " + path) diff --git a/vendor/k8s.io/gengo/generator/transitive_closure.go b/vendor/k8s.io/gengo/generator/transitive_closure.go new file mode 100644 index 000000000..385a49fce --- /dev/null +++ b/vendor/k8s.io/gengo/generator/transitive_closure.go @@ -0,0 +1,65 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package generator + +import "sort" + +type edge struct { + from string + to string +} + +func transitiveClosure(in map[string][]string) map[string][]string { + adj := make(map[edge]bool) + imports := make(map[string]struct{}) + for from, tos := range in { + for _, to := range tos { + adj[edge{from, to}] = true + imports[to] = struct{}{} + } + } + + // Warshal's algorithm + for k := range in { + for i := range in { + if !adj[edge{i, k}] { + continue + } + for j := range imports { + if adj[edge{i, j}] { + continue + } + if adj[edge{k, j}] { + adj[edge{i, j}] = true + } + } + } + } + + out := make(map[string][]string, len(in)) + for i := range in { + for j := range imports { + if adj[edge{i, j}] { + out[i] = append(out[i], j) + } + } + + sort.Strings(out[i]) + } + + return out +} diff --git a/vendor/k8s.io/gengo/namer/order.go b/vendor/k8s.io/gengo/namer/order.go index f86282b9b..fd89be9b0 100644 --- a/vendor/k8s.io/gengo/namer/order.go +++ b/vendor/k8s.io/gengo/namer/order.go @@ -43,6 +43,9 @@ func (o *Orderer) OrderUniverse(u types.Universe) []*types.Type { for _, v := range p.Variables { list.types = append(list.types, v) } + for _, v := range p.Constants { + list.types = append(list.types, v) + } } sort.Sort(list) return list.types diff --git a/vendor/k8s.io/gengo/parser/parse.go b/vendor/k8s.io/gengo/parser/parse.go index 6a3d53b25..2bceaee47 100644 --- a/vendor/k8s.io/gengo/parser/parse.go +++ b/vendor/k8s.io/gengo/parser/parse.go @@ -227,12 +227,16 @@ func (b *Builder) AddDirRecursive(dir string) error { klog.Warningf("Ignoring directory %v: %v", dir, err) } - // filepath.Walk includes the root dir, but we already did that, so we'll - // remove that prefix and rebuild a package import path. - prefix := b.buildPackages[dir].Dir + // filepath.Walk does not follow symlinks. We therefore evaluate symlinks and use that with + // filepath.Walk. + realPath, err := filepath.EvalSymlinks(b.buildPackages[dir].Dir) + if err != nil { + return err + } + fn := func(filePath string, info os.FileInfo, err error) error { if info != nil && info.IsDir() { - rel := filepath.ToSlash(strings.TrimPrefix(filePath, prefix)) + rel := filepath.ToSlash(strings.TrimPrefix(filePath, realPath)) if rel != "" { // Make a pkg path. pkg := path.Join(string(canonicalizeImportPath(b.buildPackages[dir].ImportPath)), rel) @@ -245,7 +249,7 @@ func (b *Builder) AddDirRecursive(dir string) error { } return nil } - if err := filepath.Walk(b.buildPackages[dir].Dir, fn); err != nil { + if err := filepath.Walk(realPath, fn); err != nil { return err } return nil @@ -544,6 +548,10 @@ func (b *Builder) findTypesIn(pkgPath importPathString, u *types.Universe) error if ok && !tv.IsField() { b.addVariable(*u, nil, tv) } + tconst, ok := obj.(*tc.Const) + if ok { + b.addConstant(*u, nil, tconst) + } } importedPkgs := []string{} @@ -774,7 +782,10 @@ func (b *Builder) walkType(u types.Universe, useName *types.Name, in tc.Type) *t if out.Methods == nil { out.Methods = map[string]*types.Type{} } - out.Methods[t.Method(i).Name()] = b.walkType(u, nil, t.Method(i).Type()) + method := t.Method(i) + mt := b.walkType(u, nil, method.Type()) + mt.CommentLines = splitLines(b.priorCommentLines(method.Pos(), 1).Text()) + out.Methods[method.Name()] = mt } } return out @@ -811,6 +822,17 @@ func (b *Builder) addVariable(u types.Universe, useName *types.Name, in *tc.Var) return out } +func (b *Builder) addConstant(u types.Universe, useName *types.Name, in *tc.Const) *types.Type { + name := tcVarNameToName(in.String()) + if useName != nil { + name = *useName + } + out := u.Constant(name) + out.Kind = types.DeclarationOf + out.Underlying = b.walkType(u, nil, in.Type()) + return out +} + // canonicalizeImportPath takes an import path and returns the actual package. // It doesn't support nested vendoring. func canonicalizeImportPath(importPath string) importPathString { diff --git a/vendor/k8s.io/gengo/types/types.go b/vendor/k8s.io/gengo/types/types.go index ec25248e7..78357bcce 100644 --- a/vendor/k8s.io/gengo/types/types.go +++ b/vendor/k8s.io/gengo/types/types.go @@ -135,6 +135,10 @@ type Package struct { // package name). Variables map[string]*Type + // Global constants within this package, indexed by their name (*not* including + // package name). + Constants map[string]*Type + // Packages imported by this package, indexed by (canonicalized) // package path. Imports map[string]*Package @@ -193,6 +197,20 @@ func (p *Package) Variable(varName string) *Type { return t } +// Constant gets the given constant Type in this Package. If the constant is +// not already defined, this will add it. If a constant is added, it's the caller's +// responsibility to finish construction of the constant by setting Underlying +// to the correct type. +func (p *Package) Constant(constName string) *Type { + if t, ok := p.Constants[constName]; ok { + return t + } + t := &Type{Name: Name{Package: p.Path, Name: constName}} + t.Kind = DeclarationOf + p.Constants[constName] = t + return t +} + // HasImport returns true if p imports packageName. Package names include the // package directory. func (p *Package) HasImport(packageName string) bool { @@ -229,6 +247,14 @@ func (u Universe) Variable(n Name) *Type { return u.Package(n.Package).Variable(n.Name) } +// Constant returns the canonical constant for the given fully-qualified name. +// If a non-existing constant is requested, this will create (a marker for) it. +// If a marker is created, it's the caller's responsibility to finish +// construction of the constant by setting Underlying to the correct type. +func (u Universe) Constant(n Name) *Type { + return u.Package(n.Package).Constant(n.Name) +} + // AddImports registers import lines for packageName. May be called multiple times. // You are responsible for canonicalizing all package paths. func (u Universe) AddImports(packagePath string, importPaths ...string) { @@ -251,6 +277,7 @@ func (u Universe) Package(packagePath string) *Package { Types: map[string]*Type{}, Functions: map[string]*Type{}, Variables: map[string]*Type{}, + Constants: map[string]*Type{}, Imports: map[string]*Package{}, } u[packagePath] = p diff --git a/vendor/modules.txt b/vendor/modules.txt index b0b07a901..535107829 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -499,22 +499,10 @@ github.com/rancher/gitwatcher/pkg/generated/informers/externalversions/gitwatche github.com/rancher/gitwatcher/pkg/generated/informers/externalversions/gitwatcher.cattle.io/v1 github.com/rancher/gitwatcher/pkg/generated/informers/externalversions/internalinterfaces github.com/rancher/gitwatcher/pkg/generated/listers/gitwatcher.cattle.io/v1 -# github.com/rancher/norman v0.0.0-20191114233102-966e8db9e670 -github.com/rancher/norman/pkg/data -github.com/rancher/norman/pkg/debug -github.com/rancher/norman/pkg/httperror -github.com/rancher/norman/pkg/openapi -github.com/rancher/norman/pkg/parse/builder -github.com/rancher/norman/pkg/types -github.com/rancher/norman/pkg/types/convert -github.com/rancher/norman/pkg/types/definition -github.com/rancher/norman/pkg/types/mapper -github.com/rancher/norman/pkg/types/slice -github.com/rancher/norman/pkg/types/values # github.com/rancher/rdns-server v0.5.7-0.20190927164127-7128efe7d065 github.com/rancher/rdns-server/client github.com/rancher/rdns-server/model -# github.com/rancher/wrangler v0.2.1-0.20191109002915-2a833f7e410d +# github.com/rancher/wrangler v0.4.1 github.com/rancher/wrangler/pkg/apply github.com/rancher/wrangler/pkg/apply/injectors github.com/rancher/wrangler/pkg/cleanup @@ -523,6 +511,8 @@ github.com/rancher/wrangler/pkg/controller-gen github.com/rancher/wrangler/pkg/controller-gen/args github.com/rancher/wrangler/pkg/controller-gen/generators github.com/rancher/wrangler/pkg/crd +github.com/rancher/wrangler/pkg/data +github.com/rancher/wrangler/pkg/data/convert github.com/rancher/wrangler/pkg/generic github.com/rancher/wrangler/pkg/genericcondition github.com/rancher/wrangler/pkg/gvk @@ -533,6 +523,11 @@ github.com/rancher/wrangler/pkg/merr github.com/rancher/wrangler/pkg/name github.com/rancher/wrangler/pkg/objectset github.com/rancher/wrangler/pkg/relatedresource +github.com/rancher/wrangler/pkg/schemas +github.com/rancher/wrangler/pkg/schemas/definition +github.com/rancher/wrangler/pkg/schemas/mappers +github.com/rancher/wrangler/pkg/schemas/openapi +github.com/rancher/wrangler/pkg/schemas/validation github.com/rancher/wrangler/pkg/schemes github.com/rancher/wrangler/pkg/signals github.com/rancher/wrangler/pkg/slice @@ -721,6 +716,8 @@ github.com/tonistiigi/fsutil/types github.com/tonistiigi/units # github.com/urfave/cli v1.22.2 github.com/urfave/cli +# github.com/urfave/cli/v2 v2.1.1 +github.com/urfave/cli/v2 # github.com/wercker/stern v1.11.0 => github.com/rancher/stern v0.0.0-20191213223518-59c2bf84f705 github.com/wercker/stern/kubernetes github.com/wercker/stern/stern @@ -873,7 +870,7 @@ gotest.tools/assert/cmp gotest.tools/internal/difflib gotest.tools/internal/format gotest.tools/internal/source -# k8s.io/api v0.0.0 => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.2-k3s.1 +# k8s.io/api v0.17.0 => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.16.2-k3s.1 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 k8s.io/api/admissionregistration/v1 @@ -915,7 +912,7 @@ k8s.io/api/settings/v1alpha1 k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 -# k8s.io/apiextensions-apiserver v0.0.0 => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.2-k3s.1 +# k8s.io/apiextensions-apiserver v0.17.0 => github.com/rancher/kubernetes/staging/src/k8s.io/apiextensions-apiserver v1.16.2-k3s.1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1 @@ -933,7 +930,7 @@ k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensio k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1 k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1 -# k8s.io/apimachinery v0.0.0 => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.2-k3s.1 +# k8s.io/apimachinery v0.17.0 => github.com/rancher/kubernetes/staging/src/k8s.io/apimachinery v1.16.2-k3s.1 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/api/meta @@ -1228,7 +1225,7 @@ k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/code-generator v0.0.0 => github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.2-k3s.1 +# k8s.io/code-generator v0.17.0 => github.com/rancher/kubernetes/staging/src/k8s.io/code-generator v1.16.2-k3s.1 k8s.io/code-generator/cmd/client-gen/args k8s.io/code-generator/cmd/client-gen/generators k8s.io/code-generator/cmd/client-gen/generators/fake @@ -1243,7 +1240,7 @@ k8s.io/code-generator/cmd/lister-gen/args k8s.io/code-generator/cmd/lister-gen/generators k8s.io/code-generator/pkg/namer k8s.io/code-generator/pkg/util -# k8s.io/gengo v0.0.0-20190822140433-26a664648505 +# k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e k8s.io/gengo/args k8s.io/gengo/examples/deepcopy-gen/generators k8s.io/gengo/examples/set-gen/sets