Skip to content
Permalink
Browse files

New Kuberentes client package

- move various existing helpers
- enhanced raw REST client with `RawClient` & `RawResource`
  • Loading branch information
errordeveloper committed Mar 12, 2019
1 parent ede4c5a commit 12a51e5f7499b3a491c46a9cbe3d7dce7d418c6c
@@ -10,6 +10,7 @@
"\/src\/(crypto|internal|net|os|runtime|syscall)\/",
"^pkg\/nodebootstrap\/assets.go",
"^pkg\/testutils\/ginkgo.go",
"^pkg\/testutils\/client.go",
"^pkg\/drain"
],
"Deadline": "5m"
@@ -1,86 +1,21 @@
package defaultaddons

import (
"bytes"
"io"
"strings"

"github.com/pkg/errors"
"github.com/weaveworks/eksctl/pkg/kubernetes"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes/scheme"

apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
)

func init() {
apiextensionsv1beta1.AddToScheme(scheme.Scheme)
}

// LoadAsset return embedded manifest as a runtime.Object
func LoadAsset(name, ext string) (*metav1.List, error) {
data, err := Asset(name + "." + ext)
if err != nil {
return nil, errors.Wrapf(err, "decoding embedded manifest for %q", name)
}
list, err := NewList(data)
list, err := kubernetes.NewList(data)
if err != nil {
return nil, errors.Wrapf(err, "loading individual resources from manifest for %q", name)
}
return list, nil
}

// NewList parses data into a list of Kubernetes resources
func NewList(data []byte) (*metav1.List, error) {
list := metav1.List{}
decoder := yaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(data), 4096)

for {
obj := new(runtime.RawExtension)
err := decoder.Decode(obj)
if err != nil {
if err == io.EOF {
return &list, nil
}
return nil, err
}
// obj.Object, err = runtime.Decode(scheme.Codecs.UniversalDeserializer(), obj.Raw)
// if err != nil {
// return nil, errors.Wrapf(err, "converting object")
// }
// list.Items = append(list.Items, *obj)
if err := listAppendFlattened(&list, *obj); err != nil {
return nil, err
}
}
}

// this was copied from kubegen
func listAppendFlattened(components *metav1.List, component runtime.RawExtension) error {
if component.Object != nil {
if strings.HasSuffix(component.Object.GetObjectKind().GroupVersionKind().Kind, "List") {
// must use corev1, as it panics on obj.(*metav1.List) with
// an amusing error message saying that *v1.List is not *v1.List
// TODO: test this to find out if the conversion is still required
list := component.Object.(*corev1.List)
for _, item := range (*list).Items {
// we attempt to recurse here, but most likely
// we will have to try decoding component.Raw
if err := listAppendFlattened(components, item); err != nil {
return err
}
}
return nil
}
components.Items = append(components.Items, component)
return nil
}
obj, err := runtime.Decode(scheme.Codecs.UniversalDeserializer(), component.Raw)
if err != nil {
return errors.Wrapf(err, "converting object")
}
return listAppendFlattened(components, runtime.RawExtension{Object: obj})
}
@@ -5,6 +5,7 @@ import (
. "github.com/onsi/gomega"

. "github.com/weaveworks/eksctl/pkg/addons/default"
"github.com/weaveworks/eksctl/pkg/testutils"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
@@ -29,7 +30,7 @@ var _ = Describe("default addons - kube-proxy", func() {
}

BeforeEach(func() {
clientSet = clientSetWithSample("testdata/sample-1.10.json")
clientSet, _ = testutils.NewFakeClientSetWithSamples("testdata/sample-1.10.json")
})

It("can load sample addons into a clientset", func() {
@@ -1,18 +1,10 @@
package eks

import (
"github.com/kris-nova/logger"
"github.com/pkg/errors"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"

@@ -21,6 +13,7 @@ import (
"github.com/kubernetes-sigs/aws-iam-authenticator/pkg/token"

api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha4"
kubewrapper "github.com/weaveworks/eksctl/pkg/kubernetes"
"github.com/weaveworks/eksctl/pkg/utils"
"github.com/weaveworks/eksctl/pkg/utils/kubeconfig"
)
@@ -33,13 +26,6 @@ type Client struct {
rawConfig *restclient.Config
}

// RawClient stores information about the client config
type RawClient struct {
mapper meta.RESTMapper
config *restclient.Config
ClientSet kubernetes.Interface
}

// NewClient creates a new client config, if withEmbeddedToken is true
// it will embed the STS token, otherwise it will use authenticator exec plugin
// and ensures that AWS_PROFILE environment variable gets set also
@@ -121,63 +107,11 @@ func (c *ClusterProvider) newClientSetWithEmbeddedToken(spec *api.ClusterConfig)
}

// NewRawClient creates a new raw REST client in one go with an embedded STS token
func (c *ClusterProvider) NewRawClient(spec *api.ClusterConfig) (*RawClient, error) {
func (c *ClusterProvider) NewRawClient(spec *api.ClusterConfig) (*kubewrapper.RawClient, error) {
client, clientSet, err := c.newClientSetWithEmbeddedToken(spec)
if err != nil {
return nil, err
}
rawClient := &RawClient{
config: client.rawConfig,
ClientSet: clientSet,
}
return rawClient.new()
}

func (c *RawClient) new() (*RawClient, error) {
apiGroupResources, err := restmapper.GetAPIGroupResources(c.ClientSet.Discovery())
if err != nil {
return nil, errors.Wrap(err, "getting list of API resources for raw REST client")
}

for i, r := range apiGroupResources {
logger.Debug("apiGroupResources[%d] = %#v", i, *r)
}

c.mapper = restmapper.NewDiscoveryRESTMapper(apiGroupResources)

if c.config.APIPath == "" {
c.config.APIPath = "/api"
}
if c.config.NegotiatedSerializer == nil {
c.config.NegotiatedSerializer = &serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
}
if err := restclient.SetKubernetesDefaults(c.config); err != nil {
return nil, errors.Wrap(err, "applying defaults for REST client")
}
return c, nil
}

// NewFor construct a resource type-specific client for a give gvk
// (it's based on k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go)
func (c *RawClient) NewFor(gvk schema.GroupVersionKind) (*resource.Helper, error) {
mapping, err := c.mapper.RESTMapping(gvk.GroupKind(), gvk.GroupVersion().Version, "")
if err != nil {
return nil, errors.Wrapf(err, "constructing REST client mapping for %s", gvk.String())
}

switch gvk.Group {
case corev1.GroupName:
c.config.APIPath = "/api"
default:
c.config.APIPath = "/apis"
}
gv := gvk.GroupVersion()
c.config.GroupVersion = &gv

client, err := restclient.RESTClientFor(c.config)
if err != nil {
return nil, errors.Wrapf(err, "constructing REST client for %s", gvk.String())
}

return resource.NewHelper(client, mapping), nil
return kubewrapper.NewRawClient(clientSet, client.rawConfig)
}

0 comments on commit 12a51e5

Please sign in to comment.
You can’t perform that action at this time.