Documentation
¶
Index ¶
- Constants
- Variables
- func AvailableSprigFunctions() []string
- func HasTemplate(template []byte, startDelim string, checkForEncrypted bool) bool
- func JSONToYAML(j []byte) ([]byte, error)
- func UsesEncryption(template []byte, startDelim string, stopDelim string) bool
- type CachingQueryAPI
- type ClusterScopedLookupRestrictedError
- type ClusterScopedObjectIdentifier
- type Config
- type EncryptionConfig
- type ResolveOptions
- type TemplateContext
- type TemplateResolver
- func NewResolver(kubeConfig *rest.Config, config Config) (*TemplateResolver, error)
- func NewResolverWithCaching(ctx context.Context, kubeConfig *rest.Config, config Config) (*TemplateResolver, source.TypedSource[reconcile.Request], error)
- func NewResolverWithClients(dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface, ...) (*TemplateResolver, error)
- func NewResolverWithDynamicWatcher(dynWatcher client.DynamicWatcher, config Config) (*TemplateResolver, error)
- func (t *TemplateResolver) EndQueryBatch(watcher client.ObjectIdentifier) error
- func (t *TemplateResolver) GetFromCache(gvk schema.GroupVersionKind, namespace string, name string) (*unstructured.Unstructured, error)
- func (t *TemplateResolver) GetUsedResources() []unstructured.Unstructured
- func (t *TemplateResolver) GetWatchCount() uint
- func (t *TemplateResolver) ListWatchedFromCache(watcher client.ObjectIdentifier) ([]unstructured.Unstructured, error)
- func (t *TemplateResolver) ResolveTemplate(tmplRaw []byte, context interface{}, options *ResolveOptions) (TemplateResult, error)
- func (t *TemplateResolver) StartQueryBatch(watcher client.ObjectIdentifier) error
- func (t *TemplateResolver) UncacheWatcher(watcher client.ObjectIdentifier) error
- type TemplateResult
Examples ¶
Constants ¶
const (
IVSize = 16 // Size in bytes
)
Variables ¶
var ( ErrAESKeyNotSet = errors.New("AESKey must be set to use this encryption mode") ErrInvalidAESKey = errors.New("the AES key is invalid") ErrInvalidB64OfEncrypted = errors.New("the encrypted string is invalid base64") ErrIVNotSet = errors.New("initialization vector must be set to use this encryption mode") ErrInvalidIV = errors.New("initialization vector must be 128 bits") ErrInvalidPKCS7Padding = errors.New("invalid PCKS7 padding") ErrMissingAPIResource = errors.New("one or more API resources are not installed on the API server") ErrProtectNotEnabled = errors.New("the protect template function is not enabled in this mode") ErrNewLinesNotAllowed = errors.New("new lines are not allowed in the string passed to the toLiteral function") ErrInvalidContextType = errors.New( "the input context must be a struct with fields (recursively) of type string, map[string]string, " + "map[string]interface{}, or struct", ) ErrMissingNamespace = errors.New( "the lookup of a single namespaced resource must have a namespace specified", ) ErrRestrictedNamespace = errors.New("the namespace argument is restricted") ErrInvalidInput = errors.New("the input is invalid") ErrCacheDisabled = client.ErrCacheDisabled ErrNoCacheEntry = client.ErrNoCacheEntry ErrContextTransformerFailed = errors.New("the context transformer failed") )
Functions ¶
func AvailableSprigFunctions ¶ added in v6.2.0
func AvailableSprigFunctions() []string
AvailableSprigFunctions returns a copy of the list of functions that this library makes available from the Sprig library.
func HasTemplate ¶
HasTemplate performs a simple check for the template start delimiter or the "$ocm_encrypted" prefix (checkForEncrypted must be set to true) to indicate if the input byte slice has a template. If the startDelim argument is an empty string, the default start delimiter of "{{" will be used.
func JSONToYAML ¶
JSONToYAML converts JSON to YAML using yaml.v3. This is important since line wrapping is disabled in v3.
Types ¶
type CachingQueryAPI ¶
type CachingQueryAPI interface { // Get will add an additional watch and return the watched object. Get( gvk schema.GroupVersionKind, namespace string, name string, ) (*unstructured.Unstructured, error) // List will add an additional list watch and return the watched objects. List( gvk schema.GroupVersionKind, namespace string, selector labels.Selector, ) ([]unstructured.Unstructured, error) }
CachingQueryAPI is a limited query API that will cache results. This is used with ContextTransformers.
type ClusterScopedLookupRestrictedError ¶
type ClusterScopedLookupRestrictedError struct {
// contains filtered or unexported fields
}
func (ClusterScopedLookupRestrictedError) Error ¶
func (e ClusterScopedLookupRestrictedError) Error() string
type Config ¶
type Config struct { AdditionalIndentation uint32 DisabledFunctions []string StartDelim string StopDelim string MissingAPIResourceCacheTTL time.Duration SkipBatchManagement bool }
Config is a struct containing configuration for the API.
- AdditionalIndentation sets the number of additional spaces to be added to the input number to the indent method. This is useful in situations when the indentation should be relative to a logical starting point in a YAML file.
- DisabledFunctions is a slice of default template function names that should be disabled.
- StartDelim customizes the start delimiter used to distinguish a template action. This defaults to "{{". If StopDelim is set, this must also be set.
- StopDelim customizes the stop delimiter used to distinguish a template action. This defaults to "}}". If StartDelim is set, this must also be set.
- MissingAPIResourceCacheTTL can be set if you want to temporarily cache an API resource is missing to avoid duplicate API queries when a CRD is missing. By default, this will not be cached. Note that this only affects when caching is enabled.
- SkipBatchManagement can be set if multiple calls to ResolveTemplate are needed for one watcher before API watches and cache entries are cleaned up. The manual control is done with the StartQueryBatch and EndQueryBatch methods. This has no effect if caching is not enabled.
type EncryptionConfig ¶
type EncryptionConfig struct { AESKey []byte AESKeyFallback []byte DecryptionConcurrency uint8 DecryptionEnabled bool EncryptionEnabled bool InitializationVector []byte }
EncryptionConfig is a struct containing configuration for template encryption/decryption functionality.
- AESKey is an AES key (e.g. AES-256) to use for the "protect" template function and decrypting such values.
- AESKeyFallback is an AES key to try if the decryption fails using AESKey.
- DecryptionConcurrency is the concurrency (i.e. number of Goroutines) limit when decrypting encrypted strings. Not setting this value is the equivalent of setting this to 1, which means no concurrency.
- DecryptionEnabled enables automatic decrypting of encrypted strings. AESKey and InitializationVector must also be set if this is enabled.
- EncryptionEnabled enables the "protect" template function and "fromSecret" returns encrypted content. AESKey and InitializationVector must also be set if this is enabled.
- InitializationVector is the initialization vector (IV) used in the AES-CBC encryption/decryption. Note that it must be equal to the AES block size which is always 128 bits (16 bytes). This value must be random but does not need to be private. Its purpose is to make the same plaintext value, when encrypted with the same AES key, appear unique. When performing decryption, the IV must be the same as it was for the encryption of the data. Note that all values encrypted in the template will use this same IV, which means that duplicate plaintext values that are encrypted will yield the same encrypted value in the template.
type ResolveOptions ¶
type ResolveOptions struct { ContextTransformers []func( queryAPI CachingQueryAPI, context interface{}, ) (transformedContext interface{}, err error) ClusterScopedAllowList []ClusterScopedObjectIdentifier CustomFunctions template.FuncMap EncryptionConfig InputIsYAML bool LookupNamespace string Watcher *client.ObjectIdentifier }
ResolveOptions is a struct containing configuration for calling ResolveTemplate.
- ContextTransformers is a list of functions that can modify the input context to ResolveTemplate using the caching query API. This is useful if you want to add information about a Kubernetes object in the context and be notified when the object changes.
- ClusterScopedAllowList is a list of cluster-scoped object identifiers (group, kind, name) which are allowed to be used in "lookup" calls even when LookupNamespace is set. A wildcard value `*` may be used in any or all of the fields. The default behavior when LookupNamespace is set is to deny all cluster-scoped lookups.
- CustomFunctions is an optional map of custom functions available during template resolution.
- EncryptionConfig is the configuration for template encryption/decryption functionality.
- InputIsYAML can be set to true to indicate that the input to the template is already in YAML format and thus does not need to be converted from JSON to YAML before template processing occurs. This should be set to true when passing raw YAML directly to the template resolver.
- LookupNamespace is the namespace to restrict "lookup" template functions (e.g. fromConfigMap) to. If this is not set (i.e. an empty string), then all namespaces can be used.
- Watcher is the Kubernetes object that includes the templates. This is only used when caching is enabled.
type TemplateContext ¶ added in v6.5.0
type TemplateResolver ¶
type TemplateResolver struct {
// contains filtered or unexported fields
}
TemplateResolver is the API for processing templates. It's better to use the NewResolver function instead of instantiating this directly so that configuration defaults and validation are applied.
func NewResolver ¶
func NewResolver(kubeConfig *rest.Config, config Config) (*TemplateResolver, error)
NewResolver creates a new (non-caching) TemplateResolver instance, which is the API for processing templates.
- kubeConfig is the rest.Config instance used to create Kubernetes clients for template processing.
- config is the Config instance for configuring optional values for template processing.
func NewResolverWithCaching ¶
func NewResolverWithCaching( ctx context.Context, kubeConfig *rest.Config, config Config, ) ( *TemplateResolver, source.TypedSource[reconcile.Request], error, )
NewResolverWithCaching creates a new caching TemplateResolver instance, which is the API for processing templates.
The caching works by adding watches to the objects and list queries used in the templates. A controller-runtime Channel is also returned to trigger reconciles on the watched object provided in ResolveTemplate when a watched object is added, updated, or removed.
ctx should be a cancelable context that should be canceled when you want the background goroutines involving caching to be stopped.
kubeConfig is the rest.Config instance used to create Kubernetes clients for template processing.
config is the Config instance for configuring optional values for template processing.
func NewResolverWithClients ¶ added in v6.3.0
func NewResolverWithClients( dynamicClient dynamic.Interface, discoveryClient discovery.DiscoveryInterface, config Config, ) (*TemplateResolver, error)
NewResolverWithClients creates a new (non-caching) TemplateResolver instance, which is the API for processing templates.
func NewResolverWithDynamicWatcher ¶
func NewResolverWithDynamicWatcher(dynWatcher client.DynamicWatcher, config Config) (*TemplateResolver, error)
NewResolverWithDynamicWatcher creates a new caching TemplateResolver instance, using the provided dependency-watcher. The caller is responsible for managing the given DynamicWatcher, including starting and stopping it. The caller must start a query batch on the DynamicWatcher for the "watcher" object before calling ResolveTemplate.
- dynWatcher is an already running DynamicWatcher from kubernetes-dependency-watches.
- config is the Config instance for configuring optional values for template processing.
func (*TemplateResolver) EndQueryBatch ¶
func (t *TemplateResolver) EndQueryBatch(watcher client.ObjectIdentifier) error
EndQueryBatch will stop a query batch transaction for the watcher. This will clean up the non-applicable preexisting watches made from before this query batch.
func (*TemplateResolver) GetFromCache ¶
func (t *TemplateResolver) GetFromCache( gvk schema.GroupVersionKind, namespace string, name string, ) (*unstructured.Unstructured, error)
GetFromCache will return the object from the cache. The ErrNoCacheEntry error is returned if no template function has caused an entry to be cached.
func (*TemplateResolver) GetUsedResources ¶ added in v6.5.0
func (t *TemplateResolver) GetUsedResources() []unstructured.Unstructured
func (*TemplateResolver) GetWatchCount ¶
func (t *TemplateResolver) GetWatchCount() uint
GetWatchCount returns the total number of active API watch requests which can be used for metrics.
func (*TemplateResolver) ListWatchedFromCache ¶
func (t *TemplateResolver) ListWatchedFromCache(watcher client.ObjectIdentifier) ([]unstructured.Unstructured, error)
ListWatchedFromCache will return all watched objects by the watcher in the cache. The ErrNoCacheEntry error is returned if no template function has caused an entry to be cached.
func (*TemplateResolver) ResolveTemplate ¶
func (t *TemplateResolver) ResolveTemplate( tmplRaw []byte, context interface{}, options *ResolveOptions, ) (TemplateResult, error)
ResolveTemplate accepts a map marshaled as JSON or YAML. It also accepts a combination of structs and maps that ultimately end in a string value to be made available when the template is processed. For example, if the argument is `struct{ClusterName string}{"cluster1"}`, the value `cluster1` would be available with `{{ .ClusterName }}`. This can also be `nil` if no fields should be made available.
ResolveTemplate will process any template strings in the map and return the processed map. The ErrMissingAPIResource is returned when one or more "lookup" calls referenced an API resource which isn't installed on the Kubernetes API server.
The input options contains options for template resolution. The options.Watcher field is an ObjectIdentifier that is used in caching mode and the controller-runtime integration. Set this to nil when not in caching mode. When in caching mode, watches are automatically garbage collected when a new call to ResolveTemplate no longer specifies an object or list query it used to.
This method is only concurrency safe when caching is enabled. When caching is disabled, a local cache of objects is stored just for the ResolveTemplate execution to avoid duplicate API queries. If running this method concurrently with caching disabled, you may get some items from the temporary cache while others will be from API queries.
Example ¶
policyYAML := ` --- apiVersion: policy.open-cluster-management.io/v1 kind: ConfigurationPolicy metadata: name: demo-sampleapp-config namespace: sampleapp spec: remediationAction: enforce namespaceSelector: exclude: - kube-* include: - default object-templates: - complianceType: musthave objectDefinition: kind: ConfigMap apiVersion: v1 metadata: name: demo-sampleapp-config namespace: test data: message: '{{ "VGVtcGxhdGVzIHJvY2sh" | base64dec }}' b64-cluster-name: '{{ .ClusterName | base64enc }}' severity: high ` policyJSON, err := yamlToJSON([]byte(policyYAML)) if err != nil { fmt.Fprintf(os.Stderr, "Failed to convert the policy YAML to JSON: %v\n", err) panic(err) } resolver, err := NewResolver(k8sConfig, Config{}) if err != nil { fmt.Fprintf(os.Stderr, "Failed to instantiate the templatesResolver struct: %v\n", err) panic(err) } templateContext := struct{ ClusterName string }{ClusterName: "cluster0001"} tmplResult, err := resolver.ResolveTemplate(policyJSON, templateContext, nil) policyResolvedJSON := tmplResult.ResolvedJSON if err != nil { fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err) panic(err) } var policyResolved interface{} err = yaml.Unmarshal(policyResolvedJSON, &policyResolved) objTmpls := policyResolved.(map[string]interface{})["spec"].(map[string]interface{})["object-templates"] objDef := objTmpls.([]interface{})[0].(map[string]interface{})["objectDefinition"] data, ok := objDef.(map[string]interface{})["data"].(map[string]interface{}) if !ok { fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err) panic(err) } message, ok := data["message"].(string) if !ok { fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err) panic(err) } b64ClusterName, ok := data["b64-cluster-name"].(string) if !ok { fmt.Fprintf(os.Stderr, "Failed to process the policy YAML: %v\n", err) panic(err) } fmt.Println(message) fmt.Println(b64ClusterName)
Output: Templates rock! Y2x1c3RlcjAwMDE=
func (*TemplateResolver) StartQueryBatch ¶
func (t *TemplateResolver) StartQueryBatch(watcher client.ObjectIdentifier) error
StartQueryBatch will start a query batch transaction for the watcher. After template resolution is complete for a watcher, calling EndQueryBatch will clean up the non-applicable preexisting watches made from before this query batch.
func (*TemplateResolver) UncacheWatcher ¶
func (t *TemplateResolver) UncacheWatcher(watcher client.ObjectIdentifier) error
UncacheWatcher will clear the watcher from the cache and remove all associated API watches.