From 4cdb2ac538b6bf474c3d16a0fd9b4ae5f1922d00 Mon Sep 17 00:00:00 2001 From: Adam Reese Date: Thu, 9 Feb 2017 15:45:54 -0800 Subject: [PATCH] feat(kube): support thirdpartyresources --- glide.lock | 5 ++-- pkg/kube/client.go | 35 ++++++++++++++++++---- pkg/tiller/environment/environment.go | 6 ++++ pkg/tiller/environment/environment_test.go | 3 ++ pkg/tiller/release_server.go | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/glide.lock b/glide.lock index e76cb318c..dfc5e995a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: f59cd1f34ecf299aeb8ca9e16cfc181d8aeaf5a5762b89d76f18d08be35e4d67 -updated: 2016-12-21T11:19:14.731981344-07:00 +updated: 2017-02-09T11:27:34.6825226-08:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -290,7 +290,7 @@ imports: - name: gopkg.in/yaml.v2 version: a83829b6f1293c91addabc89d0571c246397bbf4 - name: k8s.io/kubernetes - version: 5f332aab13e58173f85fd204a2c77731f7a2573f + version: 08e099554f3c31f6e6f07b448ab3ed78d0520507 subpackages: - cmd/kubeadm/app/apis/kubeadm - cmd/kubeadm/app/apis/kubeadm/install @@ -482,6 +482,7 @@ imports: - pkg/util/yaml - pkg/version - pkg/watch + - pkg/watch/json - pkg/watch/versioned - plugin/pkg/client/auth - plugin/pkg/client/auth/gcp diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 850dfe1a9..b4b965f1f 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -78,7 +78,7 @@ func (c *Client) Create(namespace string, reader io.Reader, timeout int64, shoul if err := ensureNamespace(client, namespace); err != nil { return err } - infos, buildErr := c.Build(namespace, reader) + infos, buildErr := c.BuildUnstructured(namespace, reader) if buildErr != nil { return buildErr } @@ -107,6 +107,29 @@ func (c *Client) newBuilder(namespace string, reader io.Reader) *resource.Result Do() } +// BuildUnstructured validates for Kubernetes objects and returns unstructured infos. +func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result, error) { + schema, err := c.Validator(true, c.SchemaCacheDir) + if err != nil { + log.Printf("warning: failed to load schema: %s", err) + } + + mapper, typer, err := c.UnstructuredObject() + if err != nil { + log.Printf("warning: failed to load mapper: %s", err) + } + var result Result + result, err = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(c.UnstructuredClientForMapping), runtime.UnstructuredJSONScheme). + ContinueOnError(). + Schema(schema). + NamespaceParam(namespace). + DefaultNamespace(). + Stream(reader, ""). + Flatten(). + Do().Infos() + return result, scrubValidationError(err) +} + // Build validates for Kubernetes objects and returns resource Infos from a io.Reader. func (c *Client) Build(namespace string, reader io.Reader) (Result, error) { var result Result @@ -121,7 +144,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { // Since we don't know what order the objects come in, let's group them by the types, so // that when we print them, they come looking good (headers apply to subgroups, etc.) objs := make(map[string][]runtime.Object) - infos, err := c.Build(namespace, reader) + infos, err := c.BuildUnstructured(namespace, reader) if err != nil { return "", err } @@ -178,12 +201,12 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { // // Namespace will set the namespaces func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, recreate bool, timeout int64, shouldWait bool) error { - original, err := c.Build(namespace, originalReader) + original, err := c.BuildUnstructured(namespace, originalReader) if err != nil { return fmt.Errorf("failed decoding reader into objects: %s", err) } - target, err := c.Build(namespace, targetReader) + target, err := c.BuildUnstructured(namespace, targetReader) if err != nil { return fmt.Errorf("failed decoding reader into objects: %s", err) } @@ -255,7 +278,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader // // Namespace will set the namespace func (c *Client) Delete(namespace string, reader io.Reader) error { - infos, err := c.Build(namespace, reader) + infos, err := c.BuildUnstructured(namespace, reader) if err != nil { return err } @@ -585,7 +608,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error { func waitForJob(e watch.Event, name string) (bool, error) { o, ok := e.Object.(*batch.Job) if !ok { - return true, fmt.Errorf("Expected %s to be a *batch.Job, got %T", name, o) + return true, fmt.Errorf("Expected %s to be a *batch.Job, got %T", name, e.Object) } for _, c := range o.Status.Conditions { diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index fa5d1ecab..d218818e8 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -137,6 +137,7 @@ type KubeClient interface { Update(namespace string, originalReader, modifiedReader io.Reader, recreate bool, timeout int64, shouldWait bool) error Build(namespace string, reader io.Reader) (kube.Result, error) + BuildUnstructured(namespace string, reader io.Reader) (kube.Result, error) // WaitAndGetCompletedPodPhase waits up to a timeout until a pod enters a completed phase // and returns said phase (PodSucceeded or PodFailed qualify) @@ -186,6 +187,11 @@ func (p *PrintingKubeClient) Build(ns string, reader io.Reader) (kube.Result, er return []*resource.Info{}, nil } +// BuildUnstructured implements KubeClient BuildUnstructured. +func (p *PrintingKubeClient) BuildUnstructured(ns string, reader io.Reader) (kube.Result, error) { + return []*resource.Info{}, nil +} + // WaitAndGetCompletedPodPhase implements KubeClient WaitAndGetCompletedPodPhase func (p *PrintingKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (api.PodPhase, error) { _, err := io.Copy(p.Out, reader) diff --git a/pkg/tiller/environment/environment_test.go b/pkg/tiller/environment/environment_test.go index cb36de356..716836438 100644 --- a/pkg/tiller/environment/environment_test.go +++ b/pkg/tiller/environment/environment_test.go @@ -57,6 +57,9 @@ func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, func (k *mockKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) { return []*resource.Info{}, nil } +func (k *mockKubeClient) BuildUnstructured(ns string, reader io.Reader) (kube.Result, error) { + return []*resource.Info{}, nil +} func (k *mockKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (api.PodPhase, error) { return api.PodUnknown, nil } diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 29cb335b0..25150bcda 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -1047,7 +1047,7 @@ func (s *ReleaseServer) UninstallRelease(c ctx.Context, req *services.UninstallR func validateManifest(c environment.KubeClient, ns string, manifest []byte) error { r := bytes.NewReader(manifest) - _, err := c.Build(ns, r) + _, err := c.BuildUnstructured(ns, r) return err }