Skip to content

Commit

Permalink
✨ Allowing generators
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinemartin committed Jan 22, 2023
1 parent fe221e9 commit 677f052
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 56 deletions.
113 changes: 60 additions & 53 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@ import (
"fmt"
"os"

"github.com/kaweezle/krmfnbuiltin/pkg/transformers"
"github.com/kaweezle/krmfnbuiltin/pkg/plugins"

"sigs.k8s.io/kustomize/api/konfig"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/filesys"
"sigs.k8s.io/kustomize/kyaml/fn/framework"
"sigs.k8s.io/kustomize/kyaml/fn/framework/command"
"sigs.k8s.io/kustomize/kyaml/kio/filters"
"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
"sigs.k8s.io/kustomize/kyaml/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
Expand Down Expand Up @@ -43,34 +41,6 @@ var BuildAnnotations = []string{
BuildAnnotationsGenAddHashSuffix,
}

func makeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
bpt := transformers.GetBuiltinPluginType(r.Kind)
if f, ok := transformers.TransformerFactories[bpt]; ok {
return f(), nil
}
return nil, errors.Errorf("unable to load builtin %s", r)
}

func NewPluginHelpers() (*resmap.PluginHelpers, error) {
depProvider := provider.NewDepProvider()

fSys := filesys.MakeFsOnDisk()
path, err := os.Getwd()
if err != nil {
return nil, err
}
resmapFactory := resmap.NewFactory(depProvider.GetResourceFactory())

lr := fLdr.RestrictionNone

ldr, err := fLdr.NewLoader(lr, path, fSys)
if err != nil {
return nil, err
}

return resmap.NewPluginHelpers(ldr, depProvider.GetFieldValidator(), resmapFactory, types.DisabledPluginConfig()), nil
}

func RemoveBuildAnnotations(r *resource.Resource) {
annotations := r.GetAnnotations()
if len(annotations) == 0 {
Expand All @@ -92,46 +62,83 @@ func main() {

res := resource.Resource{RNode: *config}

plugin, err := makeBuiltinPlugin(resid.GvkFromNode(config))
plugin, err := plugins.MakeBuiltinPlugin(resid.GvkFromNode(config))
if err != nil {
return errors.WrapPrefixf(err, "creating plugin")
}

yamlNode := config.YNode()
yaml, err := yaml.Marshal(yamlNode)
yamlBytes, err := yaml.Marshal(yamlNode)

if err != nil {
return errors.WrapPrefixf(err, "marshalling yaml from res %s", res.OrgId())
}
helpers, err := NewPluginHelpers()
helpers, err := plugins.NewPluginHelpers()
if err != nil {
return errors.WrapPrefixf(err, "Cannot build Plugin helpers")
}
err = plugin.Config(helpers, yaml)
err = plugin.Config(helpers, yamlBytes)
if err != nil {
return errors.WrapPrefixf(
err, "plugin %s fails configuration", res.OrgId())
}

transformer, ok := plugin.(resmap.Transformer)
if !ok {
return fmt.Errorf("plugin %s not a transformer", res.OrgId())
}
if ok {
rm, err := helpers.ResmapFactory().NewResMapFromRNodeSlice(rl.Items)
if err != nil {
return errors.WrapPrefixf(err, "getting resource maps")
}
err = transformer.Transform(rm)
if err != nil {
return errors.WrapPrefixf(err, "Transforming resources")
}

for _, r := range rm.Resources() {
RemoveBuildAnnotations(r)
}

rl.Items = rm.ToRNodeSlice()

// kustomize fn don't remove config.kubernetes.io/local-config resources upon completion.
// As it always add a filename by default, the local resources keep saved.
// To avoid this, an annotation `config.kubernetes.io/prune-local` present in a
// transformer makes all the local resources disappear.
if _, ok := config.GetAnnotations()["config.kubernetes.io/prune-local"]; ok {
filter := &filters.IsLocalConfig{IncludeLocalConfig: false, ExcludeNonLocalConfig: false}
err = rl.Filter(filter)
if err != nil {
return errors.WrapPrefixf(err, "filtering local configs")
}
}

} else {
generator, ok := plugin.(resmap.Generator)

if !ok {
return fmt.Errorf("plugin %s is neither a generator nor a transformer", res.OrgId())
}

rm, err := generator.Generate()
if err != nil {
return errors.WrapPrefixf(err, "generating resource(s)")
}

for _, r := range rm.Resources() {
r.RemoveBuildAnnotations()
// We add the annotation config.kubernetes.io/local-config to be able to delete
// The generated resource at the end of the process. Unfortunately, kustomize doesn't
// do that on functions. So we have added a special annotation
// `config.kubernetes.io/prune-local` to add on the last transformer.
// We set the filename of the generated resource in case it is forgotten.
r.Pipe(yaml.SetAnnotation(filters.LocalConfigAnnotation, "true"))
r.Pipe(yaml.SetAnnotation(kioutil.PathAnnotation, ".generated.yaml"))
r.Pipe(yaml.SetAnnotation(kioutil.LegacyPathAnnotation, ".generated.yaml"))
}

rl.Items = append(rl.Items, rm.ToRNodeSlice()...)

rm, err := helpers.ResmapFactory().NewResMapFromRNodeSlice(rl.Items)
if err != nil {
return errors.WrapPrefixf(err, "getting resource maps")
}
err = transformer.Transform(rm)
if err != nil {
return errors.WrapPrefixf(err, "Transforming resources")
}

for _, r := range rm.Resources() {
RemoveBuildAnnotations(r)
}

rl.Items = rm.ToRNodeSlice()

return nil

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 51 additions & 1 deletion pkg/transformers/tranformers.go → pkg/plugins/factories.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package transformers
package plugins

import (
"os"

"sigs.k8s.io/kustomize/api/builtins"
"sigs.k8s.io/kustomize/api/filesys"
fLdr "sigs.k8s.io/kustomize/api/loader"
"sigs.k8s.io/kustomize/api/provider"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/kustomize/kyaml/resid"
)

//go:generate go run golang.org/x/tools/cmd/stringer -type=BuiltinPluginType
Expand Down Expand Up @@ -41,6 +49,9 @@ func makeStringToBuiltinPluginTypeMap() (result map[string]BuiltinPluginType) {
for k := range TransformerFactories {
result[k.String()] = k
}
for k := range GeneratorFactories {
result[k.String()] = k
}
return
}

Expand Down Expand Up @@ -100,3 +111,42 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
// We only want it to be available in the top-level kustomization.
// See: https://github.com/kubernetes-sigs/kustomize/issues/3913
}

var GeneratorFactories = map[BuiltinPluginType]func() resmap.GeneratorPlugin{
ConfigMapGenerator: builtins.NewConfigMapGeneratorPlugin,
IAMPolicyGenerator: builtins.NewIAMPolicyGeneratorPlugin,
SecretGenerator: builtins.NewSecretGeneratorPlugin,
HelmChartInflationGenerator: builtins.NewHelmChartInflationGeneratorPlugin,
}

func MakeBuiltinPlugin(r resid.Gvk) (resmap.Configurable, error) {
bpt := GetBuiltinPluginType(r.Kind)
if f, ok := TransformerFactories[bpt]; ok {
return f(), nil
}
if f, ok := GeneratorFactories[bpt]; ok {
return f(), nil
}
return nil, errors.Errorf("unable to load builtin %s", r)
}

func NewPluginHelpers() (*resmap.PluginHelpers, error) {
depProvider := provider.NewDepProvider()

fSys := filesys.MakeFsOnDisk()
path, err := os.Getwd()
if err != nil {
return nil, err
}
resmapFactory := resmap.NewFactory(depProvider.GetResourceFactory())
resmapFactory.RF().IncludeLocalConfigs = true

lr := fLdr.RestrictionNone

ldr, err := fLdr.NewLoader(lr, path, fSys)
if err != nil {
return nil, err
}

return resmap.NewPluginHelpers(ldr, depProvider.GetFieldValidator(), resmapFactory, types.DisabledPluginConfig()), nil
}
12 changes: 12 additions & 0 deletions tests/functions2/01_configmap-generator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: builtin
kind: ConfigMapGenerator
metadata:
name: configuration-map
namespace: argocd
annotations:
config.kubernetes.io/function: |
exec:
path: ../krmfnbuiltin
literals:
- repoURL=https://github.com/antoinemartin/autocloud.git
- targetRevision=deploy/citest
29 changes: 29 additions & 0 deletions tests/functions2/02_replacement-transformer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: replacement-transformer
namespace: argocd
annotations:
config.kubernetes.io/prune-local: "true"
config.kubernetes.io/function: |
exec:
path: ../krmfnbuiltin
replacements:
- source:
kind: ConfigMap
fieldPath: data.repoURL
targets:
- select:
kind: Application
annotationSelector: "autocloud/local=true"
fieldPaths:
- spec.source.repoURL
- source:
kind: ConfigMap
fieldPath: data.targetRevision
targets:
- select:
kind: Application
annotationSelector: "autocloud/local=true"
fieldPaths:
- spec.source.targetRevision
6 changes: 5 additions & 1 deletion tests/test_krmfnbuiltin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ set -e pipefail

trap "cp compare/argocd.original.yaml applications/argocd.yaml" EXIT

echo "Running kustomize with transformer..."
echo "Running kustomize with patch transformer..."
kustomize fn run --enable-exec --fn-path functions applications
diff <(yq eval -P compare/argocd.expected.yaml) <(yq eval -P applications/argocd.yaml)
cp compare/argocd.original.yaml applications/argocd.yaml
echo "Running kustomize with replacement transformer..."
kustomize fn run --enable-exec --fn-path functions2 applications
diff <(yq eval -P compare/argocd.expected.yaml) <(yq eval -P applications/argocd.yaml)
echo "Done ok 🎉"

0 comments on commit 677f052

Please sign in to comment.