Skip to content

Commit

Permalink
feature(pkg/engine): introduce RenderWithClientProvider
Browse files Browse the repository at this point in the history
Signed-off-by: Marcin Owsiany <porridge@redhat.com>
  • Loading branch information
porridge committed Dec 18, 2023
1 parent e6edb15 commit bfec4ec
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 9 deletions.
26 changes: 19 additions & 7 deletions pkg/engine/engine.go
Expand Up @@ -40,16 +40,17 @@ type Engine struct {
Strict bool
// In LintMode, some 'required' template values may be missing, so don't fail
LintMode bool
// the rest config to connect to the kubernetes api
config *rest.Config
// optional provider of clients to talk to the Kubernetes API
clientProvider *ClientProvider
// EnableDNS tells the engine to allow DNS lookups when rendering templates
EnableDNS bool
}

// New creates a new instance of Engine using the passed in rest config.
func New(config *rest.Config) Engine {
var clientProvider ClientProvider = clientProviderFromConfig{config}
return Engine{
config: config,
clientProvider: &clientProvider,
}
}

Expand Down Expand Up @@ -85,10 +86,21 @@ func Render(chrt *chart.Chart, values chartutil.Values) (map[string]string, erro

// RenderWithClient takes a chart, optional values, and value overrides, and attempts to
// render the Go templates using the default options. This engine is client aware and so can have template
// functions that interact with the client
// functions that interact with the client.
func RenderWithClient(chrt *chart.Chart, values chartutil.Values, config *rest.Config) (map[string]string, error) {
var clientProvider ClientProvider = clientProviderFromConfig{config}
return Engine{
config: config,
clientProvider: &clientProvider,
}.Render(chrt, values)
}

// RenderWithClientProvider takes a chart, optional values, and value overrides, and attempts to
// render the Go templates using the default options. This engine is client aware and so can have template
// functions that interact with the client.
// This function differs from RenderWithClient in that it lets you customize the way a dynamic client is constructed.
func RenderWithClientProvider(chrt *chart.Chart, values chartutil.Values, clientProvider ClientProvider) (map[string]string, error) {
return Engine{
clientProvider: &clientProvider,
}.Render(chrt, values)
}

Expand Down Expand Up @@ -194,8 +206,8 @@ func (e Engine) initFunMap(t *template.Template, referenceTpls map[string]render

// If we are not linting and have a cluster connection, provide a Kubernetes-backed
// implementation.
if !e.LintMode && e.config != nil {
funcMap["lookup"] = NewLookupFunction(e.config)
if !e.LintMode && e.clientProvider != nil {
funcMap["lookup"] = newLookupFunction(*e.clientProvider)
}

// When DNS lookups are not enabled override the sprig function and return
Expand Down
23 changes: 21 additions & 2 deletions pkg/engine/lookup_func.go
Expand Up @@ -39,9 +39,28 @@ type lookupFunc = func(apiversion string, resource string, namespace string, nam
// This function is considered deprecated, and will be renamed in Helm 4. It will no
// longer be a public function.
func NewLookupFunction(config *rest.Config) lookupFunc {
return func(apiversion string, resource string, namespace string, name string) (map[string]interface{}, error) {
return newLookupFunction(clientProviderFromConfig{config: config})
}

type ClientProvider interface {
// GetClientFor returns a dynamic.NamespaceableResourceInterface suitable for interacting with resources
// corresponding to the provided apiVersion and kind, as well as a boolean indicating whether the resources
// are namespaced.
GetClientFor(apiVersion, kind string) (dynamic.NamespaceableResourceInterface, bool, error)
}

type clientProviderFromConfig struct {
config *rest.Config
}

func (c clientProviderFromConfig) GetClientFor(apiVersion, kind string) (dynamic.NamespaceableResourceInterface, bool, error) {
return getDynamicClientOnKind(apiVersion, kind, c.config)
}

func newLookupFunction(clientProvider ClientProvider) lookupFunc {
return func(apiversion string, kind string, namespace string, name string) (map[string]interface{}, error) {
var client dynamic.ResourceInterface
c, namespaced, err := getDynamicClientOnKind(apiversion, resource, config)
c, namespaced, err := clientProvider.GetClientFor(apiversion, kind)
if err != nil {
return map[string]interface{}{}, err
}
Expand Down

0 comments on commit bfec4ec

Please sign in to comment.