Skip to content

Commit

Permalink
Add support to accept function spec from catalogs
Browse files Browse the repository at this point in the history
This commit modifies the logic to read function specs
from catalog in addition to the annotations. This feature
is currently enabled only with transformers.

Signed-off-by: Varsha Prasad Narsing <varshaprasad96@gmail.com>
  • Loading branch information
varshaprasad96 committed Jan 26, 2024
1 parent fb6f128 commit 5a148d7
Show file tree
Hide file tree
Showing 50 changed files with 793 additions and 475 deletions.
8 changes: 4 additions & 4 deletions api/filters/namespace/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ func (ns Filter) metaNamespaceHack(obj *yaml.RNode, gvk resid.Gvk) error {
//
// kind: RoleBinding
// subjects:
// - name: "default" # this will have the namespace set
// ...
// - name: "something-else" # this will not have the namespace set
// ...
// - name: "default" # this will have the namespace set
// ...
// - name: "something-else" # this will not have the namespace set
// ...
func (ns Filter) roleBindingHack(obj *yaml.RNode) error {
var visitor filtersutil.SetFn
switch ns.SetRoleBindingSubjects {
Expand Down
28 changes: 14 additions & 14 deletions api/filters/valueadd/valueadd.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ import (
//
// - Non-existent target field.
//
// The field will be added and the value inserted.
// The field will be added and the value inserted.
//
// - Existing field, scalar or map.
//
// E.g. 'spec/template/spec/containers/[name:nginx]/image'
// E.g. 'spec/template/spec/containers/[name:nginx]/image'
//
// This behaves like an IETF RFC 6902 Replace operation would;
// the existing value is replaced without complaint, even though
// this is an Add operation. In contrast, a Replace operation
// must fail (report an error) if the field doesn't exist.
// This behaves like an IETF RFC 6902 Replace operation would;
// the existing value is replaced without complaint, even though
// this is an Add operation. In contrast, a Replace operation
// must fail (report an error) if the field doesn't exist.
//
// - Existing field, list (array)
// Not supported yet.
// TODO: Honor fields with RFC-6902-style array indices
// TODO: like 'spec/template/spec/containers/2'
// TODO: Modify kyaml/yaml/PathGetter to allow this.
// The value will be inserted into the array at the given position,
// shifting other contents. To instead replace an array entry, use
// an implementation of an IETF RFC 6902 Replace operation.
// - Existing field, list (array)
// Not supported yet.
// TODO: Honor fields with RFC-6902-style array indices
// TODO: like 'spec/template/spec/containers/2'
// TODO: Modify kyaml/yaml/PathGetter to allow this.
// The value will be inserted into the array at the given position,
// shifting other contents. To instead replace an array entry, use
// an implementation of an IETF RFC 6902 Replace operation.
//
// For the common case of a filepath in the field value, and a desire
// to add the value to the filepath (rather than replace the filepath),
Expand Down
9 changes: 5 additions & 4 deletions api/internal/accumulator/namereferencetransformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func newNameReferenceTransformer(
//
// If the Deployment's name changes, e.g. a prefix is added,
// then the HPA's reference to the Deployment must be fixed.
//
func (t *nameReferenceTransformer) Transform(m resmap.ResMap) error {
fMap := t.determineFilters(m.Resources())
debug(fMap)
Expand Down Expand Up @@ -101,8 +100,8 @@ func debug(fMap filterMap) {
//
// - kind: Deployment
// fieldSpecs:
// - kind: HorizontalPodAutoscaler
// path: spec/scaleTargetRef/name
// - kind: HorizontalPodAutoscaler
// path: spec/scaleTargetRef/name
//
// This entry says that an HPA, via its
// 'spec/scaleTargetRef/name' field, may refer to a
Expand Down Expand Up @@ -152,7 +151,9 @@ func (t *nameReferenceTransformer) determineFilters(
// how to parse fieldspec-style paths that make no distinction
// between maps and sequences. This means it cannot lookup commonly
// used "indeterminate" paths like
// spec/containers/env/valueFrom/configMapKeyRef/name
//
// spec/containers/env/valueFrom/configMapKeyRef/name
//
// ('containers' is a list, not a map).
// However, the fieldspec filter does know how to handle this;
// extract that code and call it here?
Expand Down
33 changes: 17 additions & 16 deletions api/internal/plugins/builtinconfig/namebackreferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,25 @@ import (
//
// If the name of a ConfigMap instance changed from 'alice' to 'bob',
// one must
// - visit all objects that could refer to the ConfigMap (the Referrers)
// - see if they mention 'alice',
// - if so, change the Referrer's name reference to 'bob'.
// - visit all objects that could refer to the ConfigMap (the Referrers)
// - see if they mention 'alice',
// - if so, change the Referrer's name reference to 'bob'.
//
// The NameBackReferences instance to aid in this could look like
// {
// kind: ConfigMap
// version: v1
// fieldSpecs:
// - kind: Pod
// version: v1
// path: spec/volumes/configMap/name
// - kind: Deployment
// path: spec/template/spec/volumes/configMap/name
// - kind: Job
// path: spec/template/spec/volumes/configMap/name
// (etc.)
// }
//
// {
// kind: ConfigMap
// version: v1
// fieldSpecs:
// - kind: Pod
// version: v1
// path: spec/volumes/configMap/name
// - kind: Deployment
// path: spec/template/spec/volumes/configMap/name
// - kind: Job
// path: spec/template/spec/volumes/configMap/name
// (etc.)
// }
type NameBackReferences struct {
resid.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
// TODO: rename json 'fieldSpecs' to 'referrers' for clarity.
Expand Down
87 changes: 41 additions & 46 deletions api/internal/plugins/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
// SPDX-License-Identifier: Apache-2.0

/*
Read docs/plugins.md first for an overview of kustomize plugins.
BUILTIN PLUGIN CONFIGURATION
# BUILTIN PLUGIN CONFIGURATION
There are two kinds of plugins, Go plugins (shared
object library) and exec plugins (independent binary).
Expand All @@ -18,22 +16,22 @@ follows.
The plugin config file looks like
apiVersion: builtin
kind: SecretGenerator
metadata:
name: whatever
otherField1: whatever
otherField2: whatever
...
apiVersion: builtin
kind: SecretGenerator
metadata:
name: whatever
otherField1: whatever
otherField2: whatever
...
The apiVersion must be 'builtin'.
The kind is the CamelCase name of the plugin.
The source for a builtin plugin must be at:
repo=$GOPATH/src/sigs.k8s.io/kustomize
${repo}/plugin/builtin/LOWERCASE(${kind})/${kind}
repo=$GOPATH/src/sigs.k8s.io/kustomize
${repo}/plugin/builtin/LOWERCASE(${kind})/${kind}
k8s wants 'kind' values to follow CamelCase, while
Go style doesn't like but does allow such names.
Expand All @@ -42,8 +40,7 @@ The lowercased value of kind is used as the name of the
directory holding the plugin, its test, and any
optional associated files (possibly a go.mod file).
BUILTIN PLUGIN GENERATION
# BUILTIN PLUGIN GENERATION
The `pluginator` program is a code generator that
converts kustomize generator (G) and/or
Expand All @@ -52,32 +49,32 @@ code.
It arises from following requirements:
* extension
kustomize does two things - generate or
transform k8s resources. Plugins let
users write their own G&T's without
having to fork kustomize and learn its
internals.
- extension
kustomize does two things - generate or
transform k8s resources. Plugins let
users write their own G&T's without
having to fork kustomize and learn its
internals.
* dogfooding
A G&T extension framework one can trust
should be used by its authors to deliver
builtin G&T's.
- dogfooding
A G&T extension framework one can trust
should be used by its authors to deliver
builtin G&T's.
* distribution
kustomize should be distributable via
`go get` and should run where Go
programs are expected to run.
- distribution
kustomize should be distributable via
`go get` and should run where Go
programs are expected to run.
The extension requirement led to building
a framework that accommodates writing a
G or T as either
* an 'exec' plugin (any executable file
runnable as a kustomize subprocess), or
- an 'exec' plugin (any executable file
runnable as a kustomize subprocess), or
* as a Go plugin - see
https://golang.org/pkg/plugin.
- as a Go plugin - see
https://golang.org/pkg/plugin.
The dogfooding (and an implicit performance
requirement) requires a 'builtin' G or T to
Expand All @@ -87,29 +84,27 @@ The distribution ('go get') requirement demands
conversion of Go plugins to statically linked
code, hence this program.
TO GENERATE CODE
repo=$GOPATH/src/sigs.k8s.io/kustomize
cd $repo/plugin/builtin
go generate ./...
repo=$GOPATH/src/sigs.k8s.io/kustomize
cd $repo/plugin/builtin
go generate ./...
This creates
$repo/api/plugins/builtins/SecretGenerator.go
$repo/api/plugins/builtins/SecretGenerator.go
etc.
Generated plugins are used in kustomize via
package whatever
import sigs.k8s.io/kustomize/api/plugins/builtins
...
g := builtin.NewSecretGenerator()
g.Config(h, k)
resources, err := g.Generate()
err = g.Transform(resources)
// Eventually emit resources.
package whatever
import sigs.k8s.io/kustomize/api/plugins/builtins
...
g := builtin.NewSecretGenerator()
g.Config(h, k)
resources, err := g.Generate()
err = g.Transform(resources)
// Eventually emit resources.
*/
package plugins
51 changes: 17 additions & 34 deletions api/internal/plugins/fnplugin/fnplugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ package fnplugin
import (
"bytes"
"fmt"
"os"

"sigs.k8s.io/kustomize/kyaml/errors"
k8syaml "sigs.k8s.io/yaml"

"sigs.k8s.io/kustomize/api/internal/plugins/utils"
"sigs.k8s.io/kustomize/api/resmap"
Expand Down Expand Up @@ -54,47 +52,31 @@ func resourceToRNode(res *resource.Resource) (*yaml.RNode, error) {
}

// GetFunctionSpec return function spec is there is. Otherwise return nil
func GetFunctionSpec(res *resource.Resource) (*runtimeutil.FunctionSpec, error) {
rnode, err := resourceToRNode(res)
if err != nil {
return nil, fmt.Errorf("could not convert resource to RNode: %w", err)
}
functionSpec, err := runtimeutil.GetFunctionSpec(rnode)
if err != nil {
return nil, fmt.Errorf("failed to get FunctionSpec: %w", err)
}
return functionSpec, nil
}

func GetFunctionSpecFromCatalog(res *resource.Resource) (*runtimeutil.FunctionSpec, error) {
if res.GetKind() != framework.CatalogKind || res.GetApiVersion() != framework.FunctionDefinitionGroupVersion {
return nil, fmt.Errorf("invalid resource kind: %q and apiversion: %q", res.GetKind(), res.GetApiVersion())
}
func GetFunctionSpec(res *resource.Resource, catalogs []framework.Catalog) (*runtimeutil.FunctionSpec, error) {
var (
functionSpec *runtimeutil.FunctionSpec
err error
)

rnode, err := resourceToRNode(res)
if err != nil {
return nil, fmt.Errorf("could not convert resource to RNode: %w", err)
}

n, err := rnode.Pipe(yaml.Lookup("metadata", "configFn"))
if err != nil {
return nil, fmt.Errorf("failed to look up metadata.configFn: %w", err)
}
if yaml.IsMissingOrNull(n) {
return nil, nil
if len(catalogs) > 0 {
functionSpec, err = framework.FindMatchingFunctionSpec(rnode, catalogs)
if err != nil {
return nil, fmt.Errorf("failed to get FunctionSpec from catalogs: %w", err)
}
}
var fs runtimeutil.FunctionSpec

s, err := n.String()
if err != nil {
fmt.Fprintf(os.Stderr, "configFn parse error: %v\n", err)
return nil, fmt.Errorf("configFn parse error: %w", err)
}
if err := k8syaml.UnmarshalStrict([]byte(s), &fs); err != nil {
return nil, fmt.Errorf("%s unmarshal error: %w", "configFn", err)
if functionSpec == nil {
functionSpec, err = runtimeutil.GetFunctionSpec(rnode)
if err != nil {
return nil, fmt.Errorf("failed to get FunctionSpec: %w", err)
}
}
return &fs, nil

return functionSpec, nil
}

func toStorageMounts(mounts []string) []runtimeutil.StorageMount {
Expand All @@ -117,6 +99,7 @@ func NewFnPlugin(o *types.FnPluginLoadingOptions) *FnPlugin {
Env: o.Env,
AsCurrentUser: o.AsCurrentUser,
WorkingDir: o.WorkingDir,
Catalogs: o.Catalogs,
},
}
}
Expand Down
Loading

0 comments on commit 5a148d7

Please sign in to comment.