Skip to content

Commit

Permalink
feat: helm ref in envvar
Browse files Browse the repository at this point in the history
  • Loading branch information
adityathebe authored and moshloop committed Dec 12, 2023
1 parent 65b6c29 commit da1ffe6
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 19 deletions.
94 changes: 85 additions & 9 deletions context/envvar.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package context

import (
"context"
"bytes"
"compress/gzip"
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"time"

"github.com/RaveNoX/go-jsonmerge"
"github.com/ohler55/ojg/jp"

"github.com/flanksource/duty/types"
"github.com/patrickmn/go-cache"
authenticationv1 "k8s.io/api/authentication/v1"
Expand All @@ -16,6 +22,8 @@ import (
// purges expired items every 10 minutes
var envCache = cache.New(5*time.Minute, 10*time.Minute)

const helmSecretType = "helm.sh/release.v1"

func GetEnvValueFromCache(ctx Context, input types.EnvVar, namespace string) (string, error) {
if namespace == "" {
namespace = ctx.GetNamespace()
Expand All @@ -24,16 +32,16 @@ func GetEnvValueFromCache(ctx Context, input types.EnvVar, namespace string) (st
return input.ValueStatic, nil
}
if input.ValueFrom.SecretKeyRef != nil {
value, err := GetSecretFromCache(ctx, namespace, input.ValueFrom.SecretKeyRef.Name, input.ValueFrom.SecretKeyRef.Key)
return value, err
return GetSecretFromCache(ctx, namespace, input.ValueFrom.SecretKeyRef.Name, input.ValueFrom.SecretKeyRef.Key)
}
if input.ValueFrom.ConfigMapKeyRef != nil {
value, err := GetConfigMapFromCache(ctx, namespace, input.ValueFrom.ConfigMapKeyRef.Name, input.ValueFrom.ConfigMapKeyRef.Key)
return value, err
return GetConfigMapFromCache(ctx, namespace, input.ValueFrom.ConfigMapKeyRef.Name, input.ValueFrom.ConfigMapKeyRef.Key)
}
if input.ValueFrom.HelmRef != nil {
return GetHelmValueFromCache(ctx, namespace, input.ValueFrom.HelmRef.Name, input.ValueFrom.HelmRef.Key)
}
if input.ValueFrom.ServiceAccount != nil {
value, err := GetServiceAccountTokenFromCache(ctx, namespace, *input.ValueFrom.ServiceAccount)
return value, err
return GetServiceAccountTokenFromCache(ctx, namespace, *input.ValueFrom.ServiceAccount)
}

return "", nil
Expand All @@ -47,13 +55,81 @@ func GetEnvStringFromCache(ctx Context, env string, namespace string) (string, e
return GetEnvValueFromCache(ctx, envvar, namespace)
}

func GetHelmValueFromCache(ctx Context, namespace, releaseName, key string) (string, error) {
id := fmt.Sprintf("helm/%s/%s/%s", namespace, releaseName, key)
if value, found := envCache.Get(id); found {
return value.(string), nil
}

keyJPExpr, err := jp.ParseString(key)
if err != nil {
return "", fmt.Errorf("could not parse key:%s. must be a valid jsonpath expression. %w", key, err)
}

secretList, err := ctx.Kubernetes().CoreV1().Secrets(namespace).List(ctx, metav1.ListOptions{
FieldSelector: fmt.Sprintf("type=%s", helmSecretType),
LabelSelector: fmt.Sprintf("status=deployed,name=%s", releaseName),
Limit: 1,
})
if err != nil {
return "", fmt.Errorf("could not get secrets in namespace: %s: %w", namespace, err)
}

if len(secretList.Items) == 0 {
return "", fmt.Errorf("a deployed helm secret was not found %s/%s", namespace, releaseName)
}
secret := secretList.Items[0]

if secret.Name == "" {
return "", fmt.Errorf("could not find helm secret %s/%s", namespace, releaseName)
}

release, err := base64.StdEncoding.DecodeString(string(secret.Data["release"]))
if err != nil {
return "", fmt.Errorf("could not base64 decode helm secret %s/%s: %w", namespace, secret.Name, err)
}

gzipReader, err := gzip.NewReader(bytes.NewReader(release))
if err != nil {
return "", fmt.Errorf("could not unzip helm secret %s/%s: %w", namespace, secret.Name, err)
}

var rawJson map[string]any
if err := json.NewDecoder(gzipReader).Decode(&rawJson); err != nil {
return "", fmt.Errorf("could not decode unzipped helm secret %s/%s: %w", namespace, secret.Name, err)
}

var chartValues any = map[string]any{}
if chart, ok := rawJson["chart"].(map[string]any); ok {
chartValues = chart["values"]
}

merged, info := jsonmerge.Merge(rawJson["config"], chartValues)
if len(info.Errors) != 0 {
return "", fmt.Errorf("could not merge helm config and values of helm secret %s/%s: %v", namespace, secret.Name, info.Errors)
}

results := keyJPExpr.Get(merged)
if len(results) == 0 {
return "", fmt.Errorf("could not find key %s in merged helm secret %s/%s: %w", key, namespace, secret.Name, err)
}

output, err := json.Marshal(results[0])
if err != nil {
return "", fmt.Errorf("could not marshal merged helm secret %s/%s: %w", namespace, secret.Name, err)
}

envCache.Set(id, string(output), 5*time.Minute)
return string(output), nil
}

func GetSecretFromCache(ctx Context, namespace, name, key string) (string, error) {
id := fmt.Sprintf("secret/%s/%s/%s", namespace, name, key)

if value, found := envCache.Get(id); found {
return value.(string), nil
}
secret, err := ctx.Kubernetes().CoreV1().Secrets(namespace).Get(context.Background(), name, metav1.GetOptions{})
secret, err := ctx.Kubernetes().CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{})
if secret == nil {
return "", fmt.Errorf("could not get contents of secret %s/%s: %w", namespace, name, err)
}
Expand All @@ -76,7 +152,7 @@ func GetConfigMapFromCache(ctx Context, namespace, name, key string) (string, er
if value, found := envCache.Get(id); found {
return value.(string), nil
}
configMap, err := ctx.Kubernetes().CoreV1().ConfigMaps(namespace).Get(context.Background(), name, metav1.GetOptions{})
configMap, err := ctx.Kubernetes().CoreV1().ConfigMaps(namespace).Get(ctx, name, metav1.GetOptions{})
if configMap == nil {
return "", fmt.Errorf("could not get contents of configmap %s/%s: %w", namespace, name, err)
}
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ go 1.20
require (
ariga.io/atlas v0.14.2
cloud.google.com/go/cloudsqlconn v1.5.1
github.com/RaveNoX/go-jsonmerge v1.0.0
github.com/fergusstrange/embedded-postgres v1.21.0
github.com/flanksource/commons v1.17.1
github.com/flanksource/gomplate/v3 v3.20.16
github.com/flanksource/kommons v0.31.4
github.com/flanksource/postq v0.1.1
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.4.0
github.com/hashicorp/hcl/v2 v2.18.1
github.com/hexops/gotextdiff v1.0.3
Expand All @@ -18,6 +20,7 @@ require (
github.com/json-iterator/go v1.1.12
github.com/liamylian/jsontime/v2 v2.0.0
github.com/lib/pq v1.10.9
github.com/ohler55/ojg v1.20.3
github.com/onsi/ginkgo/v2 v2.9.4
github.com/onsi/gomega v1.27.6
github.com/patrickmn/go-cache v2.1.0+incompatible
Expand Down Expand Up @@ -75,7 +78,6 @@ require (
github.com/google/btree v1.0.1 // indirect
github.com/google/cel-go v0.18.1 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect
github.com/google/s2a-go v0.1.7 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/RaveNoX/go-jsonmerge v1.0.0 h1:2e0nqnadoGUP8rAvcA0hkQelZreVO5X3BHomT2XMrAk=
github.com/RaveNoX/go-jsonmerge v1.0.0/go.mod h1:qYM/NA77LhO4h51JJM7Z+xBU3ovqrNIACZe+SkSNVFo=
github.com/TomOnTime/utfutil v0.0.0-20210710122150-437f72b26edf h1:+GdVyvpzTy3UFAS1+hbTqm9Mk0U1Xrocm28s/E2GWz0=
github.com/TomOnTime/utfutil v0.0.0-20210710122150-437f72b26edf/go.mod h1:FiuynIwe98RFhWI8nZ0dnsldPVsBy9rHH1hn2WYwme4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
Expand Down Expand Up @@ -675,6 +678,7 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -1072,6 +1076,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
Expand Down Expand Up @@ -1169,6 +1174,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/ohler55/ojg v1.20.3 h1:Z+fnElsA/GbI5oiT726qJaG4Ca9q5l7UO68Qd0PtkD4=
github.com/ohler55/ojg v1.20.3/go.mod h1:uHcD1ErbErC27Zhb5Df2jUjbseLLcmOCo6oxSr3jZxo=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down Expand Up @@ -1286,6 +1293,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
Expand Down
2 changes: 2 additions & 0 deletions hack/migrate/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/AlekSi/pointer v1.1.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/RaveNoX/go-jsonmerge v1.0.0 // indirect
github.com/TomOnTime/utfutil v0.0.0-20210710122150-437f72b26edf // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
Expand Down Expand Up @@ -94,6 +95,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ohler55/ojg v1.20.3 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
8 changes: 8 additions & 0 deletions hack/migrate/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/RaveNoX/go-jsonmerge v1.0.0 h1:2e0nqnadoGUP8rAvcA0hkQelZreVO5X3BHomT2XMrAk=
github.com/RaveNoX/go-jsonmerge v1.0.0/go.mod h1:qYM/NA77LhO4h51JJM7Z+xBU3ovqrNIACZe+SkSNVFo=
github.com/TomOnTime/utfutil v0.0.0-20210710122150-437f72b26edf h1:+GdVyvpzTy3UFAS1+hbTqm9Mk0U1Xrocm28s/E2GWz0=
github.com/TomOnTime/utfutil v0.0.0-20210710122150-437f72b26edf/go.mod h1:FiuynIwe98RFhWI8nZ0dnsldPVsBy9rHH1hn2WYwme4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
Expand Down Expand Up @@ -675,6 +678,7 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down Expand Up @@ -1063,6 +1067,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
Expand Down Expand Up @@ -1159,6 +1164,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/ohler55/ojg v1.20.3 h1:Z+fnElsA/GbI5oiT726qJaG4Ca9q5l7UO68Qd0PtkD4=
github.com/ohler55/ojg v1.20.3/go.mod h1:uHcD1ErbErC27Zhb5Df2jUjbseLLcmOCo6oxSr3jZxo=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down Expand Up @@ -1275,6 +1282,7 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
Expand Down
35 changes: 33 additions & 2 deletions types/envvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ func (e EnvVar) IsEmpty() bool {
type EnvVarSource struct {
// ServiceAccount specifies the service account whose token should be fetched
ServiceAccount *string `json:"serviceAccount,omitempty" yaml:"serviceAccount,omitempty" protobuf:"bytes,1,opt,name=serviceAccount"`
ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty" yaml:"configMapKeyRef,omitempty" protobuf:"bytes,1,opt,name=configMapKeyRef"`
SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty" yaml:"secretKeyRef,omitempty" protobuf:"bytes,2,opt,name=secretKeyRef"`
HelmRef *HelmRefKeySelector `json:"helmRef,omitempty" yaml:"helmRef,omitempty" protobuf:"bytes,2,opt,name=helmRef"`
ConfigMapKeyRef *ConfigMapKeySelector `json:"configMapKeyRef,omitempty" yaml:"configMapKeyRef,omitempty" protobuf:"bytes,3,opt,name=configMapKeyRef"`
SecretKeyRef *SecretKeySelector `json:"secretKeyRef,omitempty" yaml:"secretKeyRef,omitempty" protobuf:"bytes,4,opt,name=secretKeyRef"`
}

func (e EnvVarSource) String() string {
Expand All @@ -71,9 +72,23 @@ func (e EnvVarSource) String() string {
if e.ServiceAccount != nil {
return "serviceaccount://" + *e.ServiceAccount
}
if e.HelmRef != nil {
return "helm://" + e.HelmRef.String()
}
return ""
}

// +kubebuilder:object:generate=true
type HelmRefKeySelector struct {
LocalObjectReference `json:",inline" yaml:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
// Key is a JSONPath expression used to fetch the key from the merged JSON.
Key string `json:"key" yaml:"key" protobuf:"bytes,2,opt,name=key"`
}

func (c HelmRefKeySelector) String() string {
return c.Name + "/" + c.Key
}

// +kubebuilder:object:generate=true
type ConfigMapKeySelector struct {
LocalObjectReference `json:",inline" yaml:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
Expand Down Expand Up @@ -162,6 +177,22 @@ func (e *EnvVar) Scan(value any) error {
return nil
}

if strings.HasPrefix(v, "helm://") {
if len(strings.Split(v, "/")) != 4 {
return fmt.Errorf("invalid helm reference: %s", v)
}
*e = EnvVar{
ValueFrom: &EnvVarSource{
HelmRef: &HelmRefKeySelector{
LocalObjectReference: LocalObjectReference{
Name: strings.Split(v, "/")[2],
},
Key: strings.Split(v, "/")[3],
},
}}
return nil
}

if strings.HasPrefix(v, "serviceaccount://") {
segments := strings.Split(v, "/")
if len(segments) != 3 || segments[2] == "" {
Expand Down
30 changes: 24 additions & 6 deletions types/envvar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/flanksource/commons/utils"
"github.com/google/go-cmp/cmp"
)

// test EnvVar implements the sql.Scanner interface correctly
Expand Down Expand Up @@ -79,6 +80,27 @@ func TestEnvVar_Scan(t *testing.T) {
expected: nil,
errorExpected: true,
},
{
name: "valid helm reference",
input: "helm://canary-checker/the-key",
expected: &EnvVar{
ValueFrom: &EnvVarSource{
HelmRef: &HelmRefKeySelector{
LocalObjectReference: LocalObjectReference{
Name: "canary-checker",
},
Key: "the-key",
},
},
},
errorExpected: false,
},
{
name: "invalid helm reference",
input: "helm:///canary-checker/the-key",
expected: nil,
errorExpected: true,
},
}

for _, tc := range tests {
Expand All @@ -98,12 +120,8 @@ func TestEnvVar_Scan(t *testing.T) {
return
}

if e.ValueStatic != "" {
t.Errorf("Expected service account reference, but got static value: %s", e.ValueStatic)
}

if e.ValueFrom == nil || e.ValueFrom.ServiceAccount == nil || *e.ValueFrom.ServiceAccount != *tc.expected.ValueFrom.ServiceAccount {
t.Errorf("Expected service account reference: %v, got: %v", tc.expected.ValueFrom.ServiceAccount, e.ValueFrom.ServiceAccount)
if diff := cmp.Diff(&e, tc.expected); diff != "" {
t.Errorf("EnvVar mismatch (-want +got):\n%s", diff)
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func GenericStructScan[T any](t *T, val any) error {
case string:
ba = []byte(v)
default:
return fmt.Errorf("Failed to unmarshal JSONB value: %v", val)
return fmt.Errorf("failed to unmarshal JSONB value: %v", val)
}
err := json.Unmarshal(ba, &t)
return err
Expand Down
Loading

0 comments on commit da1ffe6

Please sign in to comment.