Skip to content

Commit

Permalink
- improve documentation
Browse files Browse the repository at this point in the history
- set templateBody instead of spec
- add basic tests to controller
  • Loading branch information
ericogr committed Oct 15, 2020
1 parent 6d4fea4 commit c542008
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 154 deletions.
47 changes: 18 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This operator can be used to create any kubernetes object dynamically. Build your templates and set parameters to create new k8s objects.

## Use case
Many kubernetes clusters are shared among many applications and teams. Sometimes services are available within the cluster scope and teams can use it to create or configure services using kubernetes spec (such as PrometheusRule, ExternalDNS, etc.). Some of these specs are too complex or contains some configurations that we do not want to expose. You can automate it's creation using templates.
Many kubernetes clusters are shared among many applications and teams. Sometimes services are available within the cluster scope and teams can use it to create or configure services using kubernetes spec (such as ConfigMap, Secret, PrometheusRule, ExternalDNS, etc.). Some of these specs are too complex or contains some configurations that we do not want to expose. You can automate it's creation using templates.

This operator can create kubernete objects based on templates and simple namespaced parameters. You can give permissions to user create parameters but hide templates and created objects from developers or users using the Kubernetes RBAC system.

Expand All @@ -16,7 +16,7 @@ kubectl apply -f https://raw.githubusercontent.com/ericogr/k8s-object-template-o
## Additionals Kubernetes Roles
This operator should be allowed to create objects defined in templates. With default permission, it can create any object, but it can be a bit tricky. The ClusterRole ```k8s-ot-manager-role``` can be used to set permissions as needed.

See this example to add PrometheusRules permission to this operator:
See this example to add ConfigMap permission to this operator:

```yaml
---
Expand All @@ -27,9 +27,9 @@ metadata:
name: k8s-ot-manager-role
rules:
- apiGroups:
- monitoring.coreos.com
- ""
resources:
- prometheusrules
- configmaps
verbs:
- create
- get
Expand Down Expand Up @@ -94,39 +94,28 @@ Use templates as a base to create kubernetes objects. Users can define your own
apiVersion: template.ericogr.github.com/v1
kind: ObjectTemplate
metadata:
name: objecttemplate-prometheus-rules-default
name: objecttemplate-configmap-test
spec:
description: Default prometheus rule
description: ConfigMap test
objects:
- kind: PrometheusRule
apiVersion: monitoring.coreos.com/v1
- kind: ConfigMap
apiVersion: v1
metadata:
labels:
chave1: valor1
chave2: valor2
annotations:
chave1a: valor1a
chave2a: valor2a
name: prometheus-rule-default
spec: |-
groups:
- name: pods
rules:
- alert: pod_not_ready
annotations:
description: 'Pod not ready : {{"{{ $labels.pod }}"}}'
summary: 'Pod not ready: {{"{{ $labels.pod }}"}}'
expr: sum by(pod) (kube_pod_status_ready{namespace="{{ .__namespace }}"} == 0) != 0
for: 10m
labels:
app_name: {{ .app_name }}
app_route: slack
app_severity: critical
app_slack_channel: '{{ .app_slack_channel }}'
name: configmap-test
templateBody: |-
data:
name: '{{ .name }}'
age: '{{ .age }}'
```
## Basic Template Substitution System
You can use sintax like ```{{ .variable }}``` to replace parameters. Let's say you create ```app_name: myapp```. You can use ```{{ .app_name }}``` inside spec template to be replaced in runtime by this controller. If you need to scape braces, use ```{{"{{anything}}"}}```
You can use sintax like ```{{ .variable }}``` to replace parameters. Let's say you create ```name: foo```. You can use ```{{ .name }}``` inside spec template to be replaced in runtime by this controller. If you need to scape braces, use ```{{"{{anything}}"}}```

### System Runtime Variables

Expand All @@ -151,8 +140,8 @@ metadata:
namespace: default
spec:
templates:
- name: objecttemplate-prometheus-rules-default
- name: objecttemplate-configmap-test
values:
app_name: myapp
app_slack_channel: '#slack-channel'
```
name: foo
age: '64'
```
10 changes: 5 additions & 5 deletions apis/template.ericogr.github.com/v1/objecttemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ type Metadata struct {

// Object defines a single object to be created
type Object struct {
Kind string `json:"kind"`
APIVersion string `json:"apiVersion"`
Metadata Metadata `json:"metadata,omitempty"`
Name string `json:"name"`
Spec string `json:"spec"`
Kind string `json:"kind"`
APIVersion string `json:"apiVersion"`
Metadata Metadata `json:"metadata,omitempty"`
Name string `json:"name"`
TemplateBody string `json:"templateBody"`
}

// ObjectTemplateSpec defines the desired state of ObjectTemplate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ spec:
type: object
name:
type: string
spec:
templateBody:
type: string
required:
- apiVersion
- kind
- name
- spec
- templateBody
type: object
type: array
required:
Expand Down
29 changes: 9 additions & 20 deletions config/samples/template.ericogr.github.com_v1_objecttemplate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,21 @@
apiVersion: template.ericogr.github.com/v1
kind: ObjectTemplate
metadata:
name: objecttemplate-prometheus-rules-default
name: objecttemplate-configmap-test
spec:
description: Default prometheus rule
description: ConfigMap test
objects:
- kind: PrometheusRule
apiVersion: monitoring.coreos.com/v1
- kind: ConfigMap
apiVersion: v1
metadata:
labels:
chave1: valor1
chave2: valor2
annotations:
chave1a: valor1a
chave2a: valor2a
name: prometheus-rule-default
spec: |-
groups:
- name: pods
rules:
- alert: pod_not_ready
annotations:
description: 'Pod not ready : {{"{{ $labels.pod }}"}}'
summary: 'Pod not ready: {{"{{ $labels.pod }}"}}'
expr: sum by(pod) (kube_pod_status_ready{namespace="{{ .__namespace }}"} == 0) != 0
for: 10m
labels:
app_name: {{ .app_name }}
app_route: slack
app_severity: critical
app_slack_channel: '{{ .app_slack_channel }}'
name: configmap-test
templateBody: |-
data:
name: '{{ .name }}'
age: '{{ .age }}'
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
namespace: default
spec:
templates:
- name: objecttemplate-prometheus-rules-default
- name: objecttemplate-configmap-test
values:
app_name: myapp
app_slack_channel: '#slack-channel'
name: foo
age: '64'
2 changes: 1 addition & 1 deletion controllers/template.ericogr.github.com/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (c *Common) GetObjectSimplified(groupversion string, kind string, namespace
// ToObject process object from template
func (c *Common) ToObject(obj otv1.Object, owners []metav1.OwnerReference, values map[string]string, namespaceName string) (unstructured.Unstructured, *schema.GroupVersionKind, error) {
templateValues := c.addRuntimeVariablesToMap(values, obj, namespaceName)
templateYAML := getStringObject(obj.APIVersion, obj.Kind, obj.Spec)
templateYAML := getStringObject(obj.APIVersion, obj.Kind, obj.TemplateBody)
templateYAMLExecuted, err := executeTemplate(templateYAML, templateValues)

if err != nil {
Expand Down
10 changes: 2 additions & 8 deletions controllers/template.ericogr.github.com/object_utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"text/template"
)

func getStringObject(apiVersion string, kind string, spec string) string {
func getStringObject(apiVersion string, kind string, templateBody string) string {
sb := strings.Builder{}

sb.WriteString("---\n")
Expand All @@ -31,17 +31,11 @@ func getStringObject(apiVersion string, kind string, spec string) string {
sb.WriteString("kind: ")
sb.WriteString(kind)
sb.WriteRune('\n')
sb.WriteString("spec:\n")
sb.WriteString(addIdentation(spec))
sb.WriteString(templateBody)

return sb.String()
}

func addIdentation(str string) string {
str = " " + str
return strings.ReplaceAll(str, "\n", "\n ")
}

func executeTemplate(templateYAML string, values map[string]string) (string, error) {
template, err := template.New("template").Parse(templateYAML)

Expand Down
71 changes: 0 additions & 71 deletions controllers/template.ericogr.github.com/object_utilities_test.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (
"context"
"reflect"

//metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/go-logr/logr"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down
Loading

0 comments on commit c542008

Please sign in to comment.