diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 5f284e7fc..4af5306af 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -44,11 +44,15 @@ type Engine struct { config *rest.Config } -// NewWithClient creates a new instance of client-aware Engine -func NewWithClient(config *rest.Config) *Engine { - return &Engine{ - config: config, +// New creates a new instance of Engine with the supplied options +func New(opts ...Option) (*Engine, error) { + e := &Engine{} + for _, opt := range opts { + if err := opt(e); err != nil { + return nil, err + } } + return e, nil } // Render takes a chart, optional values, and value overrides, and attempts to render the Go templates. diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index 87e84c48b..ddc10b0c6 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -22,6 +22,8 @@ import ( "sync" "testing" + "k8s.io/client-go/rest" + "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chartutil" ) @@ -738,3 +740,97 @@ func TestRenderRecursionLimit(t *testing.T) { } } + +func TestOptions(t *testing.T) { + cfg := &rest.Config{} + + tcs := []struct { + name string + opts []Option + expectError bool + validate func(t *testing.T, e *Engine) + }{ + { + name: "defaults", + opts: []Option{}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.config != nil || e.LintMode != false || e.Strict != false { + t.Errorf("Unexpected engine: %#v", e) + } + }, + }, + { + name: "explicit-defaults", + opts: []Option{WithConfig(nil), WithLintMode(false), WithStrict(false)}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.config != nil || e.LintMode != false || e.Strict != false { + t.Errorf("Unexpected engine: %#v", e) + } + }, + }, + { + name: "resetting-option", + opts: []Option{WithLintMode(true), WithLintMode(false)}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.LintMode != false { + t.Errorf("Incorrect lint mode") + } + }, + }, + { + name: "with-config", + opts: []Option{WithConfig(cfg)}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.config != cfg { + t.Errorf("Set incorrect config reference") + } + }, + }, + { + name: "with-lint-mode", + opts: []Option{WithLintMode(true)}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.LintMode != true { + t.Errorf("Did not set lint mode") + } + }, + }, + { + name: "with-strict", + opts: []Option{WithStrict(true)}, + expectError: false, + validate: func(t *testing.T, e *Engine) { + if e.Strict != true { + t.Errorf("Did not set strict") + } + }, + }, + { + name: "with-erroring-option", + opts: []Option{func(*Engine) error { return fmt.Errorf("No thank you") }}, + expectError: true, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + e, err := New(tc.opts...) + if tc.expectError { + if err == nil { + t.Error("Expected error but did not get one") + } + } else { + if err != nil { + t.Errorf("Got unexpected error: %q", err) + } else { + tc.validate(t, e) + } + } + }) + } +} diff --git a/pkg/engine/option.go b/pkg/engine/option.go new file mode 100644 index 000000000..a25d8b808 --- /dev/null +++ b/pkg/engine/option.go @@ -0,0 +1,49 @@ +/* +Copyright The Helm 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 engine + +import ( + "k8s.io/client-go/rest" +) + +// Option allows specifying various settings configurable by the user within Engine +type Option func(*Engine) error + +// WithConfig specifies a rest.Config for the Engine during rendering +func WithConfig(config *rest.Config) Option { + return func(e *Engine) error { + e.config = config + return nil + } +} + +// WithLintMode allows missing required funcs to not fail on render +func WithLintMode(lintMode bool) Option { + return func(e *Engine) error { + e.LintMode = lintMode + return nil + } +} + +// WithStrict will cause rendering to fail if a referenced value is not passed +// into the render +func WithStrict(strict bool) Option { + return func(e *Engine) error { + e.Strict = strict + return nil + } +}