Skip to content
This repository was archived by the owner on Jan 20, 2026. It is now read-only.

Commit 19d9f91

Browse files
authored
feat: support go templates in config sources (#426)
* feat: support go templates in config sources fixes #37 This allows the config sources, like ConfigMaps to be `go` templates. All the functions from sprig lib are supported, there's also a k8sLookup function to get values from k8s objects, and you can access environment variables from the template under .Env object. Signed-off-by: Luis Davim <dluis@vmware.com> * feat: allow label for k8sLookup Signed-off-by: Luis Davim <dluis@vmware.com> --------- Signed-off-by: Luis Davim <dluis@vmware.com>
1 parent fcf5975 commit 19d9f91

File tree

14 files changed

+586
-189
lines changed

14 files changed

+586
-189
lines changed

README.md

Lines changed: 202 additions & 151 deletions
Large diffs are not rendered by default.

config-reloader/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ type Config struct {
5252
MetricsPort int
5353
AllowTagExpansion bool
5454
AdminNamespace string
55+
AllowLabel string
56+
AllowLabelAnnotation string
5557
// parsed or processed/cached fields
5658
level logrus.Level
5759
ParsedMetaValues map[string]string
@@ -233,6 +235,9 @@ func (cfg *Config) ParseFlags(args []string) error {
233235
app.Flag("default-configmap", "Read the configmap by this name if namespace is not annotated. Use empty string to suppress the default.").Default(defaultConfig.DefaultConfigmapName).StringVar(&cfg.DefaultConfigmapName)
234236
app.Flag("status-annotation", "Store configuration errors in this annotation, leave empty to turn off").Default(defaultConfig.AnnotStatus).StringVar(&cfg.AnnotStatus)
235237

238+
app.Flag("allow-label", "When set only objects with this label can be fetched using go templating").Default(defaultConfig.AllowLabel).StringVar(&cfg.AllowLabel)
239+
app.Flag("allow-label-annotation", "Which annotation on the namespace stores the allow label?").Default(defaultConfig.AllowLabelAnnotation).StringVar(&cfg.AllowLabelAnnotation)
240+
236241
app.Flag("prometheus-enabled", "Prometheus metrics enabled (default: false)").BoolVar(&cfg.PrometheusEnabled)
237242
app.Flag("metrics-port", "Expose prometheus metrics on this port (also needs --prometheus-enabled)").Default(strconv.Itoa(defaultConfig.MetricsPort)).IntVar(&cfg.MetricsPort)
238243

config-reloader/datasource/fake.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/sirupsen/logrus"
1212
)
1313

14-
var template = `
14+
var logzTemplate = `
1515
<match **>
1616
@type logzio_buffered
1717
endpoint_url https://listener.logz.io:8071?token=secret
@@ -36,7 +36,7 @@ func NewFakeDatasource(ctx context.Context) Datasource {
3636
}
3737

3838
func makeFakeConfig(namespace string) string {
39-
contents := template
39+
contents := logzTemplate
4040
contents = strings.ReplaceAll(contents, "$ns$", namespace)
4141
contents = strings.ReplaceAll(contents, "$ts$", time.Now().String())
4242

config-reloader/datasource/kube_informer.go

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/vmware/kube-fluentd-operator/config-reloader/fluentd"
12+
"github.com/vmware/kube-fluentd-operator/config-reloader/template"
1213
"github.com/vmware/kube-fluentd-operator/config-reloader/util"
1314

1415
"k8s.io/apimachinery/pkg/api/errors"
@@ -107,7 +108,7 @@ func NewKubernetesInformerDatasource(ctx context.Context, cfg *config.Config, up
107108
factory.Core().V1().Pods().Informer().HasSynced,
108109
factory.Core().V1().ConfigMaps().Informer().HasSynced,
109110
kubeds.IsReady) {
110-
return nil, fmt.Errorf("Failed to sync local informer with upstream Kubernetes API")
111+
return nil, fmt.Errorf("failed to sync local informer with upstream Kubernetes API")
111112
}
112113
logrus.Infof("Synced local informer with upstream Kubernetes API")
113114

@@ -156,10 +157,25 @@ func (d *kubeInformerConnection) GetNamespaces(ctx context.Context) ([]*Namespac
156157
return nil, err
157158
}
158159

160+
if d.cfg.AllowLabel != "" {
161+
template.SetAllowLabel(d.cfg.AllowLabel)
162+
}
163+
if d.cfg.AllowLabelAnnotation != "" {
164+
if label := nsobj.GetAnnotations()[d.cfg.AllowLabelAnnotation]; label != "" {
165+
template.SetAllowLabel(label)
166+
}
167+
}
168+
159169
configdata, err := d.kubeds.GetFluentdConfig(ctx, ns)
160170
if err != nil {
161171
return nil, err
162172
}
173+
buf := new(strings.Builder)
174+
if err := template.Render(buf, configdata, map[string]string{
175+
"Namespace": ns,
176+
}); err == nil {
177+
configdata = buf.String()
178+
}
163179
if configdata == "" {
164180
logrus.Infof("Skipping namespace: %v because is empty", ns)
165181
continue
@@ -301,19 +317,19 @@ func (d *kubeInformerConnection) discoverNamespaces(ctx context.Context) ([]stri
301317
// Find the configmaps that exist on this cluster to find namespaces:
302318
confMapsList, err := d.cmlist.List(labels.NewSelector())
303319
if err != nil {
304-
return nil, fmt.Errorf("Failed to list all configmaps in cluster: %v", err)
320+
return nil, fmt.Errorf("failed to list all configmaps in cluster: %v", err)
305321
}
306322
// If default configmap name is defined get all namespaces for those configmaps:
307323
if d.cfg.DefaultConfigmapName != "" {
308324
for _, cfmap := range confMapsList {
309-
if cfmap.ObjectMeta.Name == d.cfg.DefaultConfigmapName {
310-
namespaces = append(namespaces, cfmap.ObjectMeta.Namespace)
325+
if cfmap.Name == d.cfg.DefaultConfigmapName {
326+
namespaces = append(namespaces, cfmap.Namespace)
311327
} else {
312328
// We need to find configmaps that honor the global annotation for configmaps:
313-
configMapNamespace, _ := d.nslist.Get(cfmap.ObjectMeta.Namespace)
329+
configMapNamespace, _ := d.nslist.Get(cfmap.Namespace)
314330
configMapName := configMapNamespace.Annotations[d.cfg.AnnotConfigmapName]
315331
if configMapName != "" {
316-
namespaces = append(namespaces, cfmap.ObjectMeta.Namespace)
332+
namespaces = append(namespaces, cfmap.Namespace)
317333
}
318334
}
319335
}
@@ -328,11 +344,11 @@ func (d *kubeInformerConnection) discoverNamespaces(ctx context.Context) ([]stri
328344
// get all namespaces and iterrate through them like before:
329345
nses, err := d.nslist.List(labels.NewSelector())
330346
if err != nil {
331-
return nil, fmt.Errorf("Failed to list all namespaces in cluster: %v", err)
347+
return nil, fmt.Errorf("failed to list all namespaces in cluster: %v", err)
332348
}
333349
namespaces = make([]string, 0)
334350
for _, ns := range nses {
335-
namespaces = append(namespaces, ns.ObjectMeta.Name)
351+
namespaces = append(namespaces, ns.Name)
336352
}
337353
}
338354
}
@@ -355,6 +371,12 @@ func (d *kubeInformerConnection) handlePodChange(ctx context.Context, obj interf
355371
mObj := obj.(*core.Pod)
356372
logrus.Tracef("Detected pod change %s in namespace: %s", mObj.GetName(), mObj.GetNamespace())
357373
configdata, err := d.kubeds.GetFluentdConfig(ctx, mObj.GetNamespace())
374+
buf := new(strings.Builder)
375+
if err := template.Render(buf, configdata, map[string]string{
376+
"Namespace": mObj.GetNamespace(),
377+
}); err == nil {
378+
configdata = buf.String()
379+
}
358380
nsConfigStr := fmt.Sprintf("%#v", configdata)
359381

360382
if err == nil {
@@ -386,15 +408,15 @@ func matchAny(contLabels map[string]string, mountedLabelsInNs []map[string]strin
386408

387409
func (d *kubeInformerConnection) discoverFluentdConfigNamespaces() ([]string, error) {
388410
if d.fdlist == nil {
389-
return nil, fmt.Errorf("Failed to initialize the fluentdconfig crd client, d.fclient = nil")
411+
return nil, fmt.Errorf("failed to initialize the fluentdconfig crd client, d.fclient = nil")
390412
}
391413
fcList, err := d.fdlist.List(labels.NewSelector())
392414
if err != nil {
393-
return nil, fmt.Errorf("Failed to list all fluentdconfig crds in cluster: %v", err)
415+
return nil, fmt.Errorf("failed to list all fluentdconfig crds in cluster: %v", err)
394416
}
395417
nsList := make([]string, 0)
396418
for _, crd := range fcList {
397-
nsList = append(nsList, crd.ObjectMeta.Namespace)
419+
nsList = append(nsList, crd.Namespace)
398420
}
399421
logrus.Debugf("Returned these namespaces for fluentdconfig crds: %v", nsList)
400422
return nsList, nil

config-reloader/datasource/kubedatasource/configmap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (c *ConfigMapDS) fetchConfigMaps(ctx context.Context, ns string) ([]*core.C
9797
// Get all configmaps which match a specified label, but only if we have a selector
9898
mapslist, err := nsmaps.List(c.cfg.ParsedLabelSelector.AsSelector())
9999
if err != nil {
100-
return nil, fmt.Errorf("Failed to list configmaps in namespace '%s': %v", ns, err)
100+
return nil, fmt.Errorf("failed to list configmaps in namespace '%s': %v", ns, err)
101101
}
102102
confMapByName := make(map[string]*core.ConfigMap)
103103
sortedConfMaps := make([]string, 0, len(mapslist))

config-reloader/fluentd/validator.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"context"
88
"errors"
99
"fmt"
10-
"io/ioutil"
1110
"os"
1211
"strings"
1312
"time"
@@ -54,7 +53,7 @@ func (v *validatorState) ValidateConfigExtremely(config string, namespace string
5453
return nil
5554
}
5655

57-
tmpfile, err := ioutil.TempFile("", "validate-ext-"+namespace)
56+
tmpfile, err := os.CreateTemp("", "validate-ext-"+namespace)
5857
if err != nil {
5958
logrus.Errorf("error creating temporary file for namespace %s: %s", namespace, err.Error())
6059
return err
@@ -98,7 +97,7 @@ func (v *validatorState) ValidateConfig(config string, namespace string) error {
9897
return nil
9998
}
10099

101-
tmpfile, err := ioutil.TempFile("", "validate-"+namespace)
100+
tmpfile, err := os.CreateTemp("", "validate-"+namespace)
102101
if err != nil {
103102
logrus.Errorf("error creating temporary file for namespace %s: %s", namespace, err.Error())
104103
return err

config-reloader/generator/generator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import (
1010
"path"
1111
"path/filepath"
1212
"strings"
13-
"text/template"
1413
"time"
1514

1615
"github.com/vmware/kube-fluentd-operator/config-reloader/config"
1716
"github.com/vmware/kube-fluentd-operator/config-reloader/datasource"
1817
"github.com/vmware/kube-fluentd-operator/config-reloader/fluentd"
1918
"github.com/vmware/kube-fluentd-operator/config-reloader/metrics"
2019
"github.com/vmware/kube-fluentd-operator/config-reloader/processors"
20+
"github.com/vmware/kube-fluentd-operator/config-reloader/template"
2121
"github.com/vmware/kube-fluentd-operator/config-reloader/util"
2222

2323
"github.com/sirupsen/logrus"

config-reloader/go.mod

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/vmware/kube-fluentd-operator/config-reloader
33
go 1.19
44

55
require (
6+
github.com/Masterminds/sprig/v3 v3.2.3
67
github.com/alecthomas/kingpin v2.2.6+incompatible
78
github.com/prometheus/client_golang v1.15.1
89
github.com/sirupsen/logrus v1.9.0
@@ -11,16 +12,21 @@ require (
1112
k8s.io/apiextensions-apiserver v0.27.0
1213
k8s.io/apimachinery v0.27.0
1314
k8s.io/client-go v0.27.0
15+
sigs.k8s.io/controller-runtime v0.14.2
16+
sigs.k8s.io/yaml v1.3.0
1417
)
1518

1619
require (
20+
github.com/Masterminds/goutils v1.1.1 // indirect
21+
github.com/Masterminds/semver/v3 v3.2.0 // indirect
1722
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
1823
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
1924
github.com/beorn7/perks v1.0.1 // indirect
2025
github.com/cespare/xxhash/v2 v2.2.0 // indirect
2126
github.com/davecgh/go-spew v1.1.1 // indirect
2227
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
2328
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
29+
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
2430
github.com/go-logr/logr v1.2.3 // indirect
2531
github.com/go-openapi/jsonpointer v0.19.6 // indirect
2632
github.com/go-openapi/jsonreference v0.20.1 // indirect
@@ -31,11 +37,14 @@ require (
3137
github.com/google/go-cmp v0.5.9 // indirect
3238
github.com/google/gofuzz v1.1.0 // indirect
3339
github.com/google/uuid v1.3.0 // indirect
34-
github.com/imdario/mergo v0.3.6 // indirect
40+
github.com/huandu/xstrings v1.3.3 // indirect
41+
github.com/imdario/mergo v0.3.11 // indirect
3542
github.com/josharian/intern v1.0.0 // indirect
3643
github.com/json-iterator/go v1.1.12 // indirect
3744
github.com/mailru/easyjson v0.7.7 // indirect
3845
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
46+
github.com/mitchellh/copystructure v1.0.0 // indirect
47+
github.com/mitchellh/reflectwalk v1.0.0 // indirect
3948
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4049
github.com/modern-go/reflect2 v1.0.2 // indirect
4150
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -44,13 +53,16 @@ require (
4453
github.com/prometheus/client_model v0.4.0 // indirect
4554
github.com/prometheus/common v0.44.0 // indirect
4655
github.com/prometheus/procfs v0.9.0 // indirect
56+
github.com/shopspring/decimal v1.2.0 // indirect
57+
github.com/spf13/cast v1.3.1 // indirect
4758
github.com/spf13/pflag v1.0.5 // indirect
59+
golang.org/x/crypto v0.14.0 // indirect
4860
golang.org/x/net v0.17.0 // indirect
4961
golang.org/x/oauth2 v0.8.0 // indirect
5062
golang.org/x/sys v0.13.0 // indirect
5163
golang.org/x/term v0.13.0 // indirect
5264
golang.org/x/text v0.13.0 // indirect
53-
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
65+
golang.org/x/time v0.3.0 // indirect
5466
google.golang.org/appengine v1.6.7 // indirect
5567
google.golang.org/protobuf v1.30.0 // indirect
5668
gopkg.in/inf.v0 v0.9.1 // indirect
@@ -61,5 +73,4 @@ require (
6173
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
6274
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
6375
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
64-
sigs.k8s.io/yaml v1.3.0 // indirect
6576
)

0 commit comments

Comments
 (0)