From bf377c5ad5c05f0966ec5671b77ef8105c3c04dc Mon Sep 17 00:00:00 2001 From: Morten Torkildsen <mortent@google.com> Date: Wed, 24 Apr 2019 20:07:22 -0700 Subject: [PATCH] fix(helm): Only validate new manifests Signed-off-by: Morten Torkildsen <mortent@google.com> --- pkg/kube/client.go | 17 +++++++++++++++-- pkg/tiller/environment/environment.go | 17 +++++++++++++++++ pkg/tiller/environment/environment_test.go | 3 +++ pkg/tiller/release_server.go | 3 +-- pkg/tiller/release_server_test.go | 3 +++ 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index aa025eb0a..36467fad5 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -141,7 +141,7 @@ func (c *Client) validator() validation.Schema { return schema } -// BuildUnstructured validates for Kubernetes objects and returns unstructured infos. +// BuildUnstructured reads Kubernetes objects and returns unstructured infos. func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result, error) { var result Result @@ -150,13 +150,26 @@ func (c *Client) BuildUnstructured(namespace string, reader io.Reader) (Result, ContinueOnError(). NamespaceParam(namespace). DefaultNamespace(). - Schema(c.validator()). Stream(reader, ""). Flatten(). Do().Infos() return result, scrubValidationError(err) } +// Validate reads Kubernetes manifests and validates the content. +func (c *Client) Validate(namespace string, reader io.Reader) error { + _, err := c.NewBuilder(). + Unstructured(). + ContinueOnError(). + NamespaceParam(namespace). + DefaultNamespace(). + Schema(c.validator()). + Stream(reader, ""). + Flatten(). + Do().Infos() + return 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 diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index 21c23d421..24b93bfb3 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -147,8 +147,20 @@ type KubeClient interface { UpdateWithOptions(namespace string, originalReader, modifiedReader io.Reader, opts kube.UpdateOptions) error Build(namespace string, reader io.Reader) (kube.Result, error) + + // BuildUnstructured reads a stream of manifests from a reader and turns them into + // info objects. Manifests are not validated against the schema, but it will fail if + // any resoures types are not known by the apiserver. + // + // reader must contain a YAML stream (one or more YAML documents separated by "\n---\n"). BuildUnstructured(namespace string, reader io.Reader) (kube.Result, error) + // Validate reads a stream of manifests from a reader and validates them against + // the schema from the apiserver. It returns an error if any of the manifests does not validate. + // + // reader must contain a YAML stream (one or more YAML documents separated by "\n---\n"). + Validate(namespace string, reader io.Reader) error + // WaitAndGetCompletedPodPhase waits up to a timeout until a pod enters a completed phase // and returns said phase (PodSucceeded or PodFailed qualify). WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (v1.PodPhase, error) @@ -214,6 +226,11 @@ func (p *PrintingKubeClient) BuildUnstructured(ns string, reader io.Reader) (kub return []*resource.Info{}, nil } +// Validate implements KubeClient Validate +func (p *PrintingKubeClient) Validate(ns string, reader io.Reader) error { + return nil +} + // WaitAndGetCompletedPodPhase implements KubeClient WaitAndGetCompletedPodPhase. func (p *PrintingKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (v1.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 24ff8b88d..1c2d5343f 100644 --- a/pkg/tiller/environment/environment_test.go +++ b/pkg/tiller/environment/environment_test.go @@ -64,6 +64,9 @@ func (k *mockKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) func (k *mockKubeClient) BuildUnstructured(ns string, reader io.Reader) (kube.Result, error) { return []*resource.Info{}, nil } +func (k *mockKubeClient) Validate(ns string, reader io.Reader) error { + return nil +} func (k *mockKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (v1.PodPhase, error) { return v1.PodUnknown, nil } diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 6733035f7..c5638d20d 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -436,8 +436,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin func validateManifest(c environment.KubeClient, ns string, manifest []byte) error { r := bytes.NewReader(manifest) - _, err := c.BuildUnstructured(ns, r) - return err + return c.Validate(ns, r) } func validateReleaseName(releaseName string) error { diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 05b41be20..d70221ed1 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -650,6 +650,9 @@ func (kc *mockHooksKubeClient) Build(ns string, reader io.Reader) (kube.Result, func (kc *mockHooksKubeClient) BuildUnstructured(ns string, reader io.Reader) (kube.Result, error) { return []*resource.Info{}, nil } +func (kc *mockHooksKubeClient) Validate(ns string, reader io.Reader) error { + return nil +} func (kc *mockHooksKubeClient) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, timeout time.Duration) (v1.PodPhase, error) { return v1.PodUnknown, nil } -- GitLab