mirror of https://github.com/fluxcd/cli-utils.git
Adding dynamic-client interface
This commit is contained in:
parent
2aa93f9c3c
commit
dd28dd9c37
|
@ -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
|
3
go.mod
3
go.mod
|
@ -17,7 +17,7 @@ require (
|
||||||
github.com/google/go-github v17.0.0+incompatible // indirect
|
github.com/google/go-github v17.0.0+incompatible // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.0.0 // indirect
|
||||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // 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/googleapis/gnostic v0.2.0 // indirect
|
||||||
github.com/gophercloud/gophercloud v0.0.0-20190328150603-33e54f40ffcf // indirect
|
github.com/gophercloud/gophercloud v0.0.0-20190328150603-33e54f40ffcf // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // 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/atomic v1.3.2 // indirect
|
||||||
go.uber.org/multierr v1.1.0 // indirect
|
go.uber.org/multierr v1.1.0 // indirect
|
||||||
go.uber.org/zap v1.9.1 // 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/oauth2 v0.0.0-20190319182350-c85d3e98c914 // indirect
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
|
11
go.sum
11
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/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 h1:TYj4Z2qjqxa2ufb34UJqVeO9aznL+i0fLO6TqThKZ7Y=
|
||||||
github.com/google/wire v0.2.1/go.mod h1:ptBl5bWD3nzmJHVNwYHV3v4wdtKzBMlU2YbtKQCG9GI=
|
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 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
|
||||||
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
github.com/gophercloud/gophercloud v0.0.0-20190328150603-33e54f40ffcf h1:Cadz8DdkvBq1XLIk6aDDLsYHfXFr9sjlHE0RmaZpY9Q=
|
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-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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
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/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-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/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-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 h1:hyA6yiAgbUwuWqtscNvWAI7U1CtlaD1KilQ6iudt1aI=
|
||||||
golang.org/x/net v0.0.0-20190328230028-74de082e2cca/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
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-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-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-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-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 h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
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 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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=
|
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-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-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-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.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 h1:B5VXkdjt7K2Gm6fGBC9C9a1OAKJDT95cTqwet+2zib0=
|
||||||
google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU=
|
google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU=
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -29,9 +29,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProviderSet provides wiring for initializing types.
|
// ProviderSet provides wiring for initializing types.
|
||||||
var ProviderSet = wire.NewSet(
|
var ProviderSet = wire.NewSet(wire.Struct(new(output.CommandOutputWriter), "*"),
|
||||||
output.CommandOutputWriter{}, list.CommandLister{}, parse.CommandParser{}, dispatch.Dispatcher{},
|
wire.Struct(new(list.CommandLister), "*"),
|
||||||
CommandBuilder{})
|
wire.Struct(new(parse.CommandParser), "*"),
|
||||||
|
wire.Struct(new(dispatch.Dispatcher), "*"),
|
||||||
|
wire.Struct(new(CommandBuilder), "*"))
|
||||||
|
|
||||||
// CommandBuilder creates dynamically generated commands from annotations on CRDs.
|
// CommandBuilder creates dynamically generated commands from annotations on CRDs.
|
||||||
type CommandBuilder struct {
|
type CommandBuilder struct {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"sigs.k8s.io/cli-experimental/internal/pkg/status"
|
"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) {
|
func InitializeStatus(clik8s.ResourceConfigPath, io.Writer, util.Args) (*status.Status, error) {
|
||||||
panic(wire.Build(ProviderSet))
|
panic(wire.Build(ProviderSet))
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
// ProviderSet defines dependencies for initializing objects
|
// ProviderSet defines dependencies for initializing objects
|
||||||
var ProviderSet = wire.NewSet(wirek8s.ProviderSet, wiregit.OptionalProviderSet,
|
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
|
// NewStatusCommandResult returns a new status.Result
|
||||||
func NewStatusCommandResult(s *status.Status, out io.Writer) (status.Result, error) {
|
func NewStatusCommandResult(s *status.Status, out io.Writer) (status.Result, error) {
|
||||||
|
|
|
@ -24,14 +24,17 @@ import (
|
||||||
"github.com/google/wire"
|
"github.com/google/wire"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/kustomize"
|
"k8s.io/cli-runtime/pkg/kustomize"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"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/clik8s"
|
||||||
"sigs.k8s.io/cli-experimental/internal/pkg/util"
|
"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/kustomize/pkg/fs"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
@ -40,8 +43,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProviderSet defines dependencies for initializing Kubernetes objects
|
// ProviderSet defines dependencies for initializing Kubernetes objects
|
||||||
var ProviderSet = wire.NewSet(NewKubernetesClientSet, NewExtensionsClientSet, NewConfigFlags, NewRestConfig,
|
var ProviderSet = wire.NewSet(NewKubernetesClientSet, NewExtensionsClientSet, NewConfigFlags, NewRestConfig, NewDynamicClient, NewRestMapper,
|
||||||
NewResourceConfig, NewFileSystem, NewDynamicClient)
|
NewResourceConfig, NewFileSystem, NewClient)
|
||||||
|
|
||||||
// Flags registers flags for talkig to a Kubernetes cluster
|
// Flags registers flags for talkig to a Kubernetes cluster
|
||||||
func Flags(fs *pflag.FlagSet) {
|
func Flags(fs *pflag.FlagSet) {
|
||||||
|
@ -130,6 +133,16 @@ func NewDynamicClient(c *rest.Config) (dynamic.Interface, error) {
|
||||||
return dynamic.NewForConfig(c)
|
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
|
// NewFileSystem provides a real FileSystem
|
||||||
func NewFileSystem() fs.FileSystem {
|
func NewFileSystem() fs.FileSystem {
|
||||||
return fs.MakeRealFS()
|
return fs.MakeRealFS()
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
// ProviderSet defines dependencies for initializing objects
|
// ProviderSet defines dependencies for initializing objects
|
||||||
var ProviderSet = wire.NewSet(
|
var ProviderSet = wire.NewSet(
|
||||||
dy.ProviderSet, wirek8s.NewKubernetesClientSet, wirek8s.NewExtensionsClientSet, wirek8s.NewDynamicClient,
|
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
|
// NewRestConfig provides a rest.Config for a testing environment
|
||||||
func NewRestConfig() (*rest.Config, func(), error) {
|
func NewRestConfig() (*rest.Config, func(), error) {
|
||||||
|
|
|
@ -63,9 +63,22 @@ function fetch_kb_tools {
|
||||||
tar -zvxf "$kb_tools_archive_path" -C "$tmp_root/"
|
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"
|
header_text "using tools"
|
||||||
|
|
||||||
which gometalinter.v2
|
install_wire
|
||||||
|
install_metalinter
|
||||||
|
|
||||||
fetch_kb_tools
|
fetch_kb_tools
|
||||||
setup_envs
|
setup_envs
|
||||||
|
|
||||||
|
|
|
@ -18,14 +18,13 @@ set -e
|
||||||
|
|
||||||
source $(dirname ${BASH_SOURCE})/common.sh
|
source $(dirname ${BASH_SOURCE})/common.sh
|
||||||
|
|
||||||
|
header_text "populating vendor for gometalinter.v2"
|
||||||
|
go mod vendor
|
||||||
|
|
||||||
header_text "running go vet"
|
header_text "running go vet"
|
||||||
|
|
||||||
go vet ./internal/... ./pkg/... ./cmd/... ./util/...
|
go vet ./internal/... ./pkg/... ./cmd/... ./util/...
|
||||||
|
|
||||||
header_text "populating vendor for gometalinter.v2"
|
|
||||||
|
|
||||||
go mod vendor
|
|
||||||
|
|
||||||
header_text "running gometalinter.v2"
|
header_text "running gometalinter.v2"
|
||||||
|
|
||||||
gometalinter.v2 -e $(go env GOROOT) -e vendor/ -e _gen.go --disable-all \
|
gometalinter.v2 -e $(go env GOROOT) -e vendor/ -e _gen.go --disable-all \
|
||||||
|
|
Loading…
Reference in New Issue