Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add resourcedistribution generator #69

Merged
merged 1 commit into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions cmd/resourcedistributiongenerator/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
BINARY="resourcedistributiongenerator"

.PHONY: test fmt vet build clean

default: build

test:
go test -v ./...

fmt:
go fmt ./...

vet:
go vet ./...

build:
go build -v -o ${BINARY}

clean:
@if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
218 changes: 218 additions & 0 deletions cmd/resourcedistributiongenerator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# ResourceDistribution Generator

> To use this plug-in, you need to install Kustomize first. Please refer to the [Kustomize documentation](https://kubectl.docs.kubernetes.io/installation/kustomize/) for installation

When using Kustomize to manage applications, the generator provided with Kustomize can directly read files as data content to create Configmap or Secret, avoiding various format errors that are easy to occur during manual replication. The ResourceDistribution Generator is a third-party plug-in for Kustomize that can be used to create a ResourceDistribution by reading files as data content.

The application reads a Kubernetes object of type ResourceList, as shown below. functionConfig is a Kubernetes object used to pass build parameters to the application. Items is a list of Kubernetes objects, the content is the ResourceDistribution object generated by this application, and finally kustomize will fill this field into the output resource list.

```yaml
apiVersion: config.kubernetes.io/v1
kind: ResourceList
items:
...
functionConfig:
...
```

## Download ResourceDistribution generaotor

[This page](https://github.com/openkruise/kruise-tools/releases) provides the path to download binary files for common versions. Currently `Linux`, `Darwin` (OS X), `Windows` provide `X86_64` and `ARM64 `. If you use some other system or architecture, you must download the [source code](https://github.com/openkruise/kruise-tools/blob/master/cmd/resourcedistributiongenerator) and perform `Go Build` or `make` to build the binary

```bash
go build -o resourcedistributiongenerator main.go
```

## API Description

ResourceDistributionGenerator is the Exec KRM functions plugin of kusomize. It is mainly composed of `resource` and `targets` fields. After the build, it will generate `resource` and `targets` content corresponding to ResourceDistribution. The `name` in `metadata` is used to set the name of the generated resourceDistribution. The annotation `config.kubernetes.io/function` needs to write the path of this plugin in the file system. If a relative path is used, it needs to be relative to A kustomization file that references the configuration file.

```yaml
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistributionGenerator
metadata:
name: rdname
annotations:
config.kubernetes.io/function: |
exec:
path: ./plugins/resourcedistributiongenerator
resource:
... ...
targets:
... ...
```

## Resource Field

The contents of the `resource` field are used to generate the distributed resources. The `literals`, `files`, and `envs` fields are used in the same way as in [Configmap or Secret](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/configmapgenerator/) Generator.

- `resourceKind`: Specify the resource kind to distribute, Secret or ConfigMap;
- `resourceName`: Set the name of the distribution resource, that is, the name of the Secret or ConfigMap;
- `literals`: create data content using key/value pairs in the given literals;
- `files`: create data content with the given file name and content;
- `envs`: create data content using key/value pairs in the file;

A correctly configured resource field is as follows:

```yaml
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistributionGenerator
metadata:
... ...
resource:
resourceKind: ConfigMap
resourceName: cmname
files:
- file.properties
literals:
- JAVA_HOME=/opt/java/jdk
targets:
... ...
```

## Targets Field

The usage of the `targets` field is basically the same as that of the `targets` field in ResourceDistribution. Note that the contents of the `includedNamespaces` and `excludedNamespaces` fields are directly the names of the namespaces.

A correctly configured targets field is as follows:

```yaml
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistributionGenerator
metadata:
... ...
resource:
... ...
targets:
allNamespaces: true
excludedNamespaces:
- ns-2
includedNamespaces:
- ns-1
namespaceLabelSelector:
matchLabels:
group: "test"
```

## Options and ResourceOptions Field

The `options` and `resourceOptions` fields are used to set annotations or labels for the generated ResourceDistribution and the Resource (ie ConfigMap or Secret) in it, respectively.

A correctly configured `options` and `resourceOptions` fields is as follows:

```yaml
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistributionGenerator
metadata:
... ...
resource:
... ...
resourceOptions:
annotations:
dashboard: "1"
labels:
environment: "dev"
targets:
... ...
options:
annotations:
type: "slave"
labels:
version: "stable"
```

## A Complete Use Case

1. Create an empty directory demo. Create a configuration file named rdGenerator.yaml in the demo directory with the following content. Put the downloaded ResourceDistributionGenerator plugin into the `demo/plugins/` path.

```yaml
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistributionGenerator
metadata:
name: rdname
annotations:
config.kubernetes.io/function: |
exec:
path: ./plugins/resourcedistributiongenerator
resource:
resourceKind: ConfigMap
resourceName: cmname
files:
- application.properties
literals:
- JAVA_HOME=/opt/java/jdk
resourceOptions:
annotations:
dashboard: "1"
options:
labels:
app.kubernetes.io/name: "app1"
targets:
includedNamespaces:
- ns-1
namespaceLabelSelector:
matchLabels:
group: "test"
```

2. Create the application.properties file in the demo directory with the following contents.

```properties
FOO=Bar
```

3. Create a kustomization file in the demo directory that references the plugin configuration.

```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
... ...
generators:
- rdGenerator.yaml
```

4. Use the `kustomize build --enable-alpha-plugins --enable-exec demo` command to build your application, the effect is as follows

```yaml
...
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistribution
metadata:
labels:
app.kubernetes.io/name: app1
name: rdname
spec:
resource:
apiVersion: v1
data:
JAVA_HOME: /opt/java/jdk
application.properties: |
FOO=Bar
kind: ConfigMap
metadata:
annotations:
dashboard: "1"
name: cmname
targets:
includedNamespaces:
list:
- name: ns-1
namespaceLabelSelector:
matchLabels:
group: test
```

## Use the ResourceDistribution Generator in ArgoCD

To use the Kustomize plug-in in ArgoCD, you need to add build options for Kustomize that allow third-party plug-ins. Find the configMap named argocd-cm and add the following to the `data` field `kustomize.buildOptions : --enable-alpha-plugins --enable-exec` to add build options for third-party plugins to the default version of kustomize. See [ArgoCD](https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/#kustomize-build-optionsparameters) for more information.

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
....
data:
kustomize.buildOptions: --enable-alpha-plugins --enable-exec
```

51 changes: 51 additions & 0 deletions cmd/resourcedistributiongenerator/generator/alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2022 The Kruise Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generator

const tmpl = `
apiVersion: apps.kruise.io/v1alpha1
kind: ResourceDistribution
spec:
resource:
apiVersion: v1
`

// Field names
const (
kindField = "kind"
nameField = "name"
listField = "list"
allNamespacesField = "allNamespaces"
immutableField = "immutable"
typeField = "type"
matchExpressionsField = "matchExpressions"
keyField = "key"
operatorField = "operator"
valuesField = "values"
)

var metadataLabelsPath = []string{"metadata", "labels"}
var metadataAnnotationsPath = []string{"metadata", "annotations"}
var resourcePath = []string{"spec", "resource"}
var metadataPath = []string{"spec", "resource", "metadata"}
var resourceLabelsPath = []string{"spec", "resource", "metadata", "labels"}
var resourceAnnotationsPath = []string{"spec", "resource", "metadata", "annotations"}
var targetsPath = []string{"spec", "targets"}
var includedNamespacesPath = []string{"spec", "targets", "includedNamespaces"}
var excludedNamespacesPath = []string{"spec", "targets", "excludedNamespaces"}
var NamespaceLabelSelectorPath = []string{"spec", "targets", "namespaceLabelSelector"}
var MatchLabelsPath = []string{"spec", "targets", "namespaceLabelSelector", "matchLabels"}
Loading