diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e24e44e --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +generate: + GO111MODULE=on go generate + +run: + GO111MODULE=on go run . + +build: + GO111MODULE=on go build . + +check: + GO111MODULE=on ./scripts/check-everything.sh diff --git a/go.mod b/go.mod index 2fc18cf..29e9f54 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect - github.com/google/wire v0.2.1 + github.com/google/wire v0.2.2-0.20190423202733-d079521b6f51 github.com/googleapis/gnostic v0.2.0 // indirect github.com/gophercloud/gophercloud v0.0.0-20190328150603-33e54f40ffcf // indirect github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect @@ -37,7 +37,6 @@ require ( go.uber.org/atomic v1.3.2 // indirect go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.9.1 // indirect - golang.org/x/net v0.0.0-20190328230028-74de082e2cca // indirect golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914 // indirect golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 37607d9..aea979b 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,8 @@ github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeq github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/wire v0.2.1 h1:TYj4Z2qjqxa2ufb34UJqVeO9aznL+i0fLO6TqThKZ7Y= github.com/google/wire v0.2.1/go.mod h1:ptBl5bWD3nzmJHVNwYHV3v4wdtKzBMlU2YbtKQCG9GI= +github.com/google/wire v0.2.2-0.20190423202733-d079521b6f51 h1:oah2osnQk2JwZUU9BasNK201Ea2oNDY/3is4GYtnR7k= +github.com/google/wire v0.2.2-0.20190423202733-d079521b6f51/go.mod h1:7FHVg6mFpFQrjeUZrm+BaD50N5jnDKm50uVPTpyYOmU= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/gophercloud/gophercloud v0.0.0-20190328150603-33e54f40ffcf h1:Cadz8DdkvBq1XLIk6aDDLsYHfXFr9sjlHE0RmaZpY9Q= @@ -201,6 +203,8 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -220,6 +224,9 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190328230028-74de082e2cca h1:hyA6yiAgbUwuWqtscNvWAI7U1CtlaD1KilQ6iudt1aI= golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 h1:HdqqaWmYAUI7/dmByKKEw+yxDksGSo+9GjkUc9Zp34E= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -243,6 +250,9 @@ golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= @@ -254,6 +264,7 @@ golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.2.0 h1:B5VXkdjt7K2Gm6fGBC9C9a1OAKJDT95cTqwet+2zib0= google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU= diff --git a/internal/pkg/client/client.go b/internal/pkg/client/client.go new file mode 100644 index 0000000..391e0a3 --- /dev/null +++ b/internal/pkg/client/client.go @@ -0,0 +1,200 @@ +/* +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 client + +import ( + "context" + "fmt" + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/dynamic" +) + +// NewForConfig returns a new Client using the provided config and Options. +// The returned client reads *and* writes directly from the server +// (it doesn't use object caches). It understands how to work with +// normal types (both custom resources and aggregated/built-in resources), +// as well as unstructured types. +// +// In the case of normal types, the scheme will be used to look up the +// corresponding group, version, and kind for the given type. In the +// case of unstrctured types, the group, version, and kind will be extracted +// from the corresponding fields on the object. +func NewForConfig(dynamicClient dynamic.Interface, mapper meta.RESTMapper) (Client, error) { + c := &client{ + client: dynamicClient, + restMapper: mapper, + } + + return c, nil +} + +var _ Client = &client{} + +// client is a client.Client that reads and writes directly from/to an API server. It lazily initializes +// new clients at the time they are used, and caches the client. +type client struct { + client dynamic.Interface + restMapper meta.RESTMapper +} + +// Create implements client.Client +func (uc *client) Create(_ context.Context, obj runtime.Object, options metav1.CreateOptions) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + i, err := r.Create(u, options) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +// Update implements client.Client +func (uc *client) Update(_ context.Context, obj runtime.Object, options metav1.UpdateOptions) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + i, err := r.Update(u, options) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +// Delete implements client.Client +func (uc *client) Delete(_ context.Context, obj runtime.Object, options *metav1.DeleteOptions) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + err = r.Delete(u.GetName(), options) + return err +} + +// Patch implements client.Client +func (uc *client) Patch(_ context.Context, obj runtime.Object, patch Patch, options metav1.PatchOptions) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + + data, err := patch.Data(obj) + if err != nil { + return err + } + + i, err := r.Patch(u.GetName(), patch.Type(), data, options) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +// Get implements client.Client +func (uc *client) Get(_ context.Context, key types.NamespacedName, obj runtime.Object) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), key.Namespace) + if err != nil { + return err + } + i, err := r.Get(key.Name, metav1.GetOptions{}) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +// List implements client.Client +func (uc *client) List(_ context.Context, obj runtime.Object, namespace string, options metav1.ListOptions) error { + u, ok := obj.(*unstructured.UnstructuredList) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + gvk := u.GroupVersionKind() + if strings.HasSuffix(gvk.Kind, "List") { + gvk.Kind = gvk.Kind[:len(gvk.Kind)-4] + } + r, err := uc.getResourceInterface(gvk, namespace) + if err != nil { + return err + } + + i, err := r.List(options) + if err != nil { + return err + } + u.Items = i.Items + u.Object = i.Object + return nil +} + +func (uc *client) UpdateStatus(_ context.Context, obj runtime.Object) error { + u, ok := obj.(*unstructured.Unstructured) + if !ok { + return fmt.Errorf("unstructured client did not understand object: %T", obj) + } + r, err := uc.getResourceInterface(u.GroupVersionKind(), u.GetNamespace()) + if err != nil { + return err + } + i, err := r.UpdateStatus(u, metav1.UpdateOptions{}) + if err != nil { + return err + } + u.Object = i.Object + return nil +} + +func (uc *client) getResourceInterface(gvk schema.GroupVersionKind, ns string) (dynamic.ResourceInterface, error) { + mapping, err := uc.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version) + if err != nil { + return nil, err + } + if mapping.Scope.Name() == meta.RESTScopeNameRoot { + return uc.client.Resource(mapping.Resource), nil + } + return uc.client.Resource(mapping.Resource).Namespace(ns), nil +} diff --git a/internal/pkg/client/interface.go b/internal/pkg/client/interface.go new file mode 100644 index 0000000..23c3c70 --- /dev/null +++ b/internal/pkg/client/interface.go @@ -0,0 +1,75 @@ +/* +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 client + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" +) + +// Patch is a patch that can be applied to a Kubernetes object. +type Patch interface { + // Type is the PatchType of the patch. + Type() types.PatchType + // Data is the raw data representing the patch. + Data(obj runtime.Object) ([]byte, error) +} + +// Reader knows how to read and list Kubernetes objects. +type Reader interface { + // Get retrieves an obj for the given object key from the Kubernetes Cluster. + // obj must be a struct pointer so that obj can be updated with the response + // returned by the Server. + Get(ctx context.Context, key types.NamespacedName, obj runtime.Object) error + + // List retrieves list of objects for a given namespace and list options. On a + // successful call, Items field in the list will be populated with the + // result returned from the server. + List(ctx context.Context, list runtime.Object, namespace string, options metav1.ListOptions) error +} + +// Writer knows how to create, delete, and update Kubernetes objects. +type Writer interface { + // Create saves the object obj in the Kubernetes cluster. + Create(ctx context.Context, obj runtime.Object, options metav1.CreateOptions) error + + // Delete deletes the given obj from Kubernetes cluster. + Delete(ctx context.Context, obj runtime.Object, options *metav1.DeleteOptions) error + + // Update updates the given obj in the Kubernetes cluster. obj must be a + // struct pointer so that obj can be updated with the content returned by the Server. + Update(ctx context.Context, obj runtime.Object, options metav1.UpdateOptions) error + + // Patch patches the given obj in the Kubernetes cluster. obj must be a + // struct pointer so that obj can be updated with the content returned by the Server. + Patch(ctx context.Context, obj runtime.Object, patch Patch, options metav1.PatchOptions) error +} + +// StatusWriter knows how to update status subresource of a Kubernetes object. +type StatusWriter interface { + // UpdateStatus updates the fields corresponding to the status subresource for the + // given obj. obj must be a struct pointer so that obj can be updated + // with the content returned by the Server. + UpdateStatus(ctx context.Context, obj runtime.Object) error +} + +// Client knows how to perform CRUD operations on Kubernetes objects. +type Client interface { + Reader + Writer + StatusWriter +} diff --git a/internal/pkg/dy/dy.go b/internal/pkg/dy/dy.go index f067173..0f4da80 100644 --- a/internal/pkg/dy/dy.go +++ b/internal/pkg/dy/dy.go @@ -29,9 +29,11 @@ import ( ) // ProviderSet provides wiring for initializing types. -var ProviderSet = wire.NewSet( - output.CommandOutputWriter{}, list.CommandLister{}, parse.CommandParser{}, dispatch.Dispatcher{}, - CommandBuilder{}) +var ProviderSet = wire.NewSet(wire.Struct(new(output.CommandOutputWriter), "*"), + wire.Struct(new(list.CommandLister), "*"), + wire.Struct(new(parse.CommandParser), "*"), + wire.Struct(new(dispatch.Dispatcher), "*"), + wire.Struct(new(CommandBuilder), "*")) // CommandBuilder creates dynamically generated commands from annotations on CRDs. type CommandBuilder struct { diff --git a/internal/pkg/wirecli/wire.go b/internal/pkg/wirecli/wire.go index 2e4a709..380cd36 100644 --- a/internal/pkg/wirecli/wire.go +++ b/internal/pkg/wirecli/wire.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/cli-experimental/internal/pkg/status" ) -// InitializeApplyStatus creates a new *status.Status object +// InitializeStatus creates a new *status.Status object func InitializeStatus(clik8s.ResourceConfigPath, io.Writer, util.Args) (*status.Status, error) { panic(wire.Build(ProviderSet)) } diff --git a/internal/pkg/wirecli/wirecli.go b/internal/pkg/wirecli/wirecli.go index 96d5df1..7e2f957 100644 --- a/internal/pkg/wirecli/wirecli.go +++ b/internal/pkg/wirecli/wirecli.go @@ -25,7 +25,7 @@ import ( // ProviderSet defines dependencies for initializing objects var ProviderSet = wire.NewSet(wirek8s.ProviderSet, wiregit.OptionalProviderSet, - status.Status{}, apply.Apply{}, NewStatusCommandResult, NewApplyCommandResult) + wire.Struct(new(status.Status), "*"), wire.Struct(new(apply.Apply), "*"), NewStatusCommandResult, NewApplyCommandResult) // NewStatusCommandResult returns a new status.Result func NewStatusCommandResult(s *status.Status, out io.Writer) (status.Result, error) { diff --git a/internal/pkg/wirecli/wirek8s/wirek8s.go b/internal/pkg/wirecli/wirek8s/wirek8s.go index 16752ef..76f1f42 100644 --- a/internal/pkg/wirecli/wirek8s/wirek8s.go +++ b/internal/pkg/wirecli/wirek8s/wirek8s.go @@ -24,14 +24,17 @@ import ( "github.com/google/wire" "github.com/spf13/pflag" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/kustomize" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "sigs.k8s.io/cli-experimental/internal/pkg/client" "sigs.k8s.io/cli-experimental/internal/pkg/clik8s" "sigs.k8s.io/cli-experimental/internal/pkg/util" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/kustomize/pkg/fs" "sigs.k8s.io/yaml" @@ -40,8 +43,8 @@ import ( ) // ProviderSet defines dependencies for initializing Kubernetes objects -var ProviderSet = wire.NewSet(NewKubernetesClientSet, NewExtensionsClientSet, NewConfigFlags, NewRestConfig, - NewResourceConfig, NewFileSystem, NewDynamicClient) +var ProviderSet = wire.NewSet(NewKubernetesClientSet, NewExtensionsClientSet, NewConfigFlags, NewRestConfig, NewDynamicClient, NewRestMapper, + NewResourceConfig, NewFileSystem, NewClient) // Flags registers flags for talkig to a Kubernetes cluster func Flags(fs *pflag.FlagSet) { @@ -130,6 +133,16 @@ func NewDynamicClient(c *rest.Config) (dynamic.Interface, error) { return dynamic.NewForConfig(c) } +// NewRestMapper provides a dynamic.Interface +func NewRestMapper(c *rest.Config) (meta.RESTMapper, error) { + return apiutil.NewDiscoveryRESTMapper(c) +} + +// NewClient provides a dynamic.Interface +func NewClient(d dynamic.Interface, m meta.RESTMapper) (client.Client, error) { + return client.NewForConfig(d, m) +} + // NewFileSystem provides a real FileSystem func NewFileSystem() fs.FileSystem { return fs.MakeRealFS() diff --git a/internal/pkg/wirecli/wiretest/wiretest.go b/internal/pkg/wirecli/wiretest/wiretest.go index d6605df..b0c122b 100644 --- a/internal/pkg/wirecli/wiretest/wiretest.go +++ b/internal/pkg/wirecli/wiretest/wiretest.go @@ -26,7 +26,7 @@ import ( // ProviderSet defines dependencies for initializing objects var ProviderSet = wire.NewSet( dy.ProviderSet, wirek8s.NewKubernetesClientSet, wirek8s.NewExtensionsClientSet, wirek8s.NewDynamicClient, - NewRestConfig, status.Status{}, apply.Apply{}) + NewRestConfig, wire.Struct(new(status.Status), "*"), wire.Struct(new(apply.Apply), "*")) // NewRestConfig provides a rest.Config for a testing environment func NewRestConfig() (*rest.Config, func(), error) { diff --git a/scripts/check-everything.sh b/scripts/check-everything.sh index db901bb..58aeb84 100755 --- a/scripts/check-everything.sh +++ b/scripts/check-everything.sh @@ -63,9 +63,22 @@ function fetch_kb_tools { tar -zvxf "$kb_tools_archive_path" -C "$tmp_root/" } +# Install metalinter +function install_metalinter { + which gometalinter.v2 || go get -v -u gopkg.in/alecthomas/gometalinter.v2 +} + + +# Install wire +function install_wire { + which wire|| go get -v -u github.com/google/wire/cmd/wire +} + header_text "using tools" -which gometalinter.v2 +install_wire +install_metalinter + fetch_kb_tools setup_envs diff --git a/scripts/verify.sh b/scripts/verify.sh index 3ee480d..989cf47 100755 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -18,14 +18,13 @@ set -e source $(dirname ${BASH_SOURCE})/common.sh +header_text "populating vendor for gometalinter.v2" +go mod vendor + header_text "running go vet" go vet ./internal/... ./pkg/... ./cmd/... ./util/... -header_text "populating vendor for gometalinter.v2" - -go mod vendor - header_text "running gometalinter.v2" gometalinter.v2 -e $(go env GOROOT) -e vendor/ -e _gen.go --disable-all \