Skip to content

Commit

Permalink
Merge pull request #5 from kaweezle/feature/kpt-compatible
Browse files Browse the repository at this point in the history
♻️ make function kpt compatible
  • Loading branch information
antoinemartin committed Jan 26, 2023
2 parents 0c02181 + 150a080 commit 31a2a21
Show file tree
Hide file tree
Showing 13 changed files with 240 additions and 88 deletions.
98 changes: 74 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ transformation in your kustomize projects.
<li><a href="#keeping-or-deleting-generated-resources">Keeping or deleting generated resources</a></li>
<li><a href="#extensions">Extensions</a>
<ul>
<li><a href="#heredoc-generator">Heredoc generator</a></li>
<li><a href="#remove-transformer">Remove Transformer</a></li>
<li><a href="#configmap-generator-with-git-properties">ConfigMap generator with git properties</a></li>
<li><a href="#heredoc-generator">Heredoc generator</a></li>
<li><a href="#extended-replacement-in-structured-content">Extended replacement in structured content</a></li>
</ul>
</li>
Expand Down Expand Up @@ -133,7 +134,7 @@ metadata:
path: krmfnbuiltin
# Can also be:
# container:
# image: ghcr.io/kaweezle/krmfnbuiltin:v0.2.0
# image: ghcr.io/kaweezle/krmfnbuiltin:v0.3.0
patch: |-
- op: replace
path: /spec/source/repoURL
Expand Down Expand Up @@ -171,7 +172,7 @@ applications.

## Use of generators

`krmfnbuiltin` provides all the
`krmfnbuiltin` provides all the Kustomize
[builtin generators](https://kubectl.docs.kubernetes.io/references/kustomize/builtins/).

Let's imagine that one or more of your applications use an Helm chart that in
Expand Down Expand Up @@ -221,6 +222,8 @@ kind: ConfigMapGenerator
metadata:
name: configuration-map
annotations:
# This annotation will be transferred to the generated ConfigMap
config.kaweezle.com/local-config: "true"
config.kubernetes.io/function: |
exec:
path: krmfnbuiltin
Expand All @@ -240,7 +243,7 @@ metadata:
name: replacement-transformer
namespace: argocd
annotations:
# Put this annotation in the last transformation to remove generated resources
# Put this annotation in the last transformation to remove the generated resource
config.kaweezle.com/prune-local: "true"
config.kubernetes.io/function: |
exec:
Expand Down Expand Up @@ -278,40 +281,57 @@ Some remarks:
survive reordering.
- ✔️ The functions file names are prefixed with a number prefix (`01_`, `02_`)
in order to ensure that the functions are executed in the right order. Note
that you can group the two functions in one file separated by `---`.
that you can group the two functions in one file separated by `---` (this
would make it unusable from [kpt] though).
- ✔️ The generators contains the annotation:

```yaml
config.kaweezle.com/local-config: "true"
```

that is injected in the generated resource.

- ✔️ In the last transformation, we add the following annotation:

```yaml
config.kaweezle.com/prune-local: "true"
```

In order to avoid saving the generated resources. This is due to an issue in
kustomize that doesn't filter out resources annotated with
`config.kubernetes.io/local-config` in the case you are using
`kustomize fn run` (although it works with `kustomize build`).
In order to avoid saving the generated resources. In the presence of this
annotation, `krmfnbuiltin` will remove all the resource having the
`config.kaweezle.com/local-config` annotation.

## Keeping or deleting generated resources

As said above, generated resources are saved by default beside being marked with
the `config.kubernetes.io/local-config` annotation. To prevent that, adding:
As said above, generated resources are saved by default. To prevent that,
adding:

```yaml
config.kaweezle.com/local-config: "true"
```

on the generators and:

```yaml
config.kaweezle.com/prune-local: "true"
```

On the last transformation will remove those resources. If the annotation is not
present, all the generated resources will be saved in a file named
`.generated.yaml` located in the configuration directory. You may want to add
On the last transformation will remove those resources. If the absence of these
annotations, the generated resources will be saved in a file named
`.krmfnbuiltin.yaml` located in the configuration directory. You may want to add
this file name to your `.gitignore` file in order to avoid committing it.

In some cases however, we want to _inject_ new resources in the configuration.
This can be done by adding the following annotations to the generator:
This can be done by just omitting the `config.kaweezle.com/local-config`
annotation.

The name of the file containing the generated resources can be set with the
following annotations:

- `config.kaweezle.com/keep-local` prevents the deletion of the resource when
reaching the transformation annotated with `config.kaweezle.com/prune-local`.
- `config.kaweezle.com/path` allows specifying the filename of the saved file.
- `config.kaweezle.com/index` allows specifying the position of the resource in
the file.
- `config.kaweezle.com/path` for the filename. If it contains directories, they
will be created.
- `config.kaweezle.com/index` For the starting index of the resources in the
file.

Example:

Expand All @@ -321,7 +341,7 @@ kind: ConfigMapGenerator
metadata:
name: configuration-map
annotations:
config.kaweezle.com/keep-local: "true"
# config.kaweezle.com/local-config: "true"
config.kaweezle.com/path: local-config.yaml
config.kubernetes.io/function: |
exec:
Expand All @@ -333,6 +353,33 @@ With these annotations, the generated config map will be saved in the

## Extensions

### Remove Transformer

In the case the transformation(s) involves other transformers than
`krmfnbuiltin`, the `config.kaweezle.com/prune-local` may not be available to
remove resources injected in the transformation pipeline. For this use case,
`krmfnbuiltin` provides `RemoveTransformer`:

```yaml
apiVersion: builtin
kind: RemoveTransformer
metadata:
name: replacement-transformer
annotations:
config.kubernetes.io/function: |
exec:
path: ../../krmfnbuiltin
targets:
- annotationSelector: config.kaweezle.com/local-config
```

Each target specified in the `targets` field follows the
[patches target convention](https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#field-name-patches).

Note that you can use the Kustomize recommended method with a
`PatchStrategicMergeTransformer` and a `$patch: delete` field. The above
transformation is however more explicit.

### ConfigMap generator with git properties

`GitConfigMapGenerator` work identically to `ConfigMapGenerator` except it adds
Expand Down Expand Up @@ -533,6 +580,7 @@ metadata:
# This will inject this resource. like a ConfigMapGenerator, but with hierarchical
# properties
config.kaweezle.com/inject-local: "true"
config.kaweezle.com/local-config: "true"
config.kubernetes.io/function: |
exec:
path: krmfnbuiltin
Expand Down Expand Up @@ -684,6 +732,7 @@ metadata:
name: configuration-map
annotations:
config.kaweezle.com/inject-local: "true"
config.kaweezle.com/local-config: "true"
config.kubernetes.io/function: |
exec:
path: ../../krmfnbuiltin
Expand Down Expand Up @@ -775,7 +824,7 @@ curl -sLS https://raw.githubusercontent.com/kaweezle/krmfnbuiltin/main/get.sh |
If you don't want to pipe into shell, you can do:

```console
> KRMFNBUILTIN_VERSION="v0.2.0"
> KRMFNBUILTIN_VERSION="v0.3.0"
> curl -sLo /usr/local/bin/krmfnbuiltin https://github.com/kaweezle/krmfnbuiltin/releases/download/${KRMFNBUILTIN_VERSION}/krmfnbuiltin_${KRMFNBUILTIN_VERSION}_linux_amd64
```

Expand Down Expand Up @@ -804,7 +853,7 @@ summarize:
```Dockerfile
FROM argoproj/argocd:latest

ARG KRMFNBUILTIN_VERSION=v0.2.0
ARG KRMFNBUILTIN_VERSION=v0.3.0

# Switch to root for the ability to perform install
USER root
Expand Down Expand Up @@ -842,7 +891,8 @@ this model, a generator or a transformer along its parameters in much like a
line in a dockerfile. It takes a current configuration as source and generates a
new configuration after transformation.

While it has not been tested, krmfnbuiltin should work with [kpt].
krmfnbuiltin works with [kpt]. The `tests/test_krmfnbuiltin_kpt.sh` script
perform the basic tests with kpt.

[knot8] lenses have provided the idea of extended paths.

Expand Down
29 changes: 8 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"sigs.k8s.io/kustomize/kyaml/errors"
"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/resid"
"sigs.k8s.io/kustomize/kyaml/yaml"
)
Expand All @@ -31,7 +30,7 @@ func main() {
if _, ok := config.GetAnnotations()[utils.FunctionAnnotationInjectLocal]; ok {
injected := config.Copy()

err := utils.MakeResourceLocal(injected)
err := utils.TransferAnnotations([]*yaml.RNode{injected}, config)
if err != nil {
return errors.WrapPrefixf(
err, "Error while mangling annotations on %s fails configuration", res.OrgId())
Expand Down Expand Up @@ -76,19 +75,12 @@ func main() {

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.kaweezle.com/prune-local` present in a
// If the annotation `config.kaweezle.com/prune-local` is present in a
// transformer makes all the local resources disappear.
if _, ok := config.GetAnnotations()[utils.FunctionAnnotationPruneLocal]; ok {
err = rl.Filter(utils.UnLocal)
if err != nil {
return errors.WrapPrefixf(err, "Removing local from keep-local resources")
}
filter := &filters.IsLocalConfig{IncludeLocalConfig: false, ExcludeNonLocalConfig: false}
err = rl.Filter(filter)
if err != nil {
return errors.WrapPrefixf(err, "filtering local configs")
return errors.WrapPrefixf(err, "while pruning `config.kaweezle.com/local-config` resources")
}
}

Expand All @@ -104,17 +96,12 @@ func main() {
return errors.WrapPrefixf(err, "generating resource(s)")
}

for _, r := range rm.Resources() {
utils.RemoveBuildAnnotations(r)
// 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.kaweezle.com/prune-local` to add on the last transformer.
// We set the filename of the generated resource in case it is forgotten.
utils.MakeResourceLocal(&r.RNode)
rrl := rm.ToRNodeSlice()
if err := utils.TransferAnnotations(rrl, config); err != nil {
return errors.WrapPrefixf(err, "While transferring annotations")
}

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

}

Expand All @@ -124,7 +111,7 @@ func main() {

cmd := command.Build(processor, command.StandaloneDisabled, false)
command.AddGenerateDockerfile(cmd)
cmd.Version = "v0.2.0" // <---VERSION--->
cmd.Version = "v0.3.0" // <---VERSION--->

if err := cmd.Execute(); err != nil {
os.Exit(1)
Expand Down
46 changes: 46 additions & 0 deletions pkg/extras/RemoveTransformer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package extras

import (
"fmt"

"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/yaml"
)

type RemoveTransformerPlugin struct {
Targets []*types.Selector `json:"targets,omitempty" yaml:"targets,omitempty"`
}

func (p *RemoveTransformerPlugin) Config(
h *resmap.PluginHelpers, c []byte) (err error) {
err = yaml.Unmarshal(c, p)
if err != nil {
return err
}
return err
}

func (p *RemoveTransformerPlugin) Transform(m resmap.ResMap) error {
if p.Targets == nil {
return fmt.Errorf("must specify at least one target")
}
for _, t := range p.Targets {
resources, err := m.Select(*t)
if err != nil {
return errors.WrapPrefixf(err, "while selecting target %s", t.String())
}
for _, r := range resources {
err = m.Remove(r.CurId())
if err != nil {
return errors.WrapPrefixf(err, "while removing resource %s", r.CurId().String())
}
}
}
return nil
}

func NewRemoveTransformerPlugin() resmap.TransformerPlugin {
return &RemoveTransformerPlugin{}
}
5 changes: 3 additions & 2 deletions pkg/plugins/builtinplugintype_string.go

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

2 changes: 2 additions & 0 deletions pkg/plugins/factories.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
HelmChartInflationGenerator
ReplacementTransformer
GitConfigMapGenerator
RemoveTransformer
)

var stringToBuiltinPluginTypeMap map[string]BuiltinPluginType
Expand Down Expand Up @@ -109,6 +110,7 @@ var TransformerFactories = map[BuiltinPluginType]func() resmap.TransformerPlugin
ReplacementTransformer: extras.NewExtendedReplacementTransformerPlugin,
ReplicaCountTransformer: builtins.NewReplicaCountTransformerPlugin,
ValueAddTransformer: builtins.NewValueAddTransformerPlugin,
RemoveTransformer: extras.NewRemoveTransformerPlugin,
// Do not wired SortOrderTransformer as a builtin plugin.
// We only want it to be available in the top-level kustomization.
// See: https://github.com/kubernetes-sigs/kustomize/issues/3913
Expand Down
10 changes: 5 additions & 5 deletions pkg/utils/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ const (
FunctionAnnotationFunction = ConfigurationAnnotationDomain + "/function"

// true when the resource is part of the local configuration
FunctionAnnotationLocalConfig = ConfigurationAnnotationDomain + "/local-config"
FunctionAnnotationLocalConfig = LocalConfigurationAnnotationDomain + "/local-config"

// Setting to true means we want this function configuration to be injected as a
// local configuration resource (local-config)
FunctionAnnotationInjectLocal = LocalConfigurationAnnotationDomain + "/inject-local"

// if set, the transformation will remove all the resources marked as local-config
FunctionAnnotationPruneLocal = LocalConfigurationAnnotationDomain + "/prune-local"
// if set on a Generated resource, it won't be pruned
FunctionAnnotationKeepLocal = LocalConfigurationAnnotationDomain + "/keep-local"
FunctionAnnotationPath = LocalConfigurationAnnotationDomain + "/path"
FunctionAnnotationIndex = LocalConfigurationAnnotationDomain + "/index"
// Saving path for injected resource
FunctionAnnotationPath = LocalConfigurationAnnotationDomain + "/path"
// Saving index for injected resource
FunctionAnnotationIndex = LocalConfigurationAnnotationDomain + "/index"
)
Loading

0 comments on commit 31a2a21

Please sign in to comment.