Skip to content
This repository was archived by the owner on Apr 18, 2024. It is now read-only.

Commit 0de22a6

Browse files
author
Saul
committed
feat: add js file output
1 parent 5c3489d commit 0de22a6

File tree

7 files changed

+115
-6
lines changed

7 files changed

+115
-6
lines changed

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and Cust
103103
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
104104
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
105105

106+
.PHONY:
107+
gen-manifests: generate manifests
108+
106109
##@ Build
107110

108111
run: manifests generate fmt vet ## Run a controller from your host.

api/v1/konfig_types.go

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Output struct {
2727
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
2828
Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
2929
Type string `yaml:"type,omitempty" json:"type,omitempty"`
30+
FileType string `yaml:"filetype,omitempty" json:"filetype,omitempty"`
3031
Key string `yaml:"key,omitempty" json:"key,omitempty"`
3132
}
3233

config/crd/bases/konfigmanager.flanksource.com_konfigs.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ spec:
6262
description: Output defines where and how properties file need to
6363
be created
6464
properties:
65+
filetype:
66+
type: string
6567
key:
6668
type: string
6769
kind:
@@ -105,6 +107,8 @@ spec:
105107
description: Output defines where and how properties file need to
106108
be created
107109
properties:
110+
filetype:
111+
type: string
108112
key:
109113
type: string
110114
kind:

controllers/output.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package controllers
22

33
import (
4+
"strings"
5+
46
konfigmanagerv1 "github.com/flanksource/konfig-manager/api/v1"
57
"github.com/flanksource/konfig-manager/pkg"
68
v1 "k8s.io/api/core/v1"
@@ -16,15 +18,15 @@ const (
1618

1719
func (r *KonfigReconciler) createOutputObject(output konfigmanagerv1.Output, config pkg.Config, resources []pkg.Resource) error {
1820
properties := getProperties(output, config, resources)
19-
if output.Kind == "ConfigMap" || output.Kind == "configmap" || output.Kind == "cm" {
21+
if strings.ToLower(output.Kind) == "configmap" || strings.ToLower(output.Kind) == "cm" {
2022
if err := r.Kommons.Apply(output.Namespace, getConfigMap(output.Name, output.Namespace, properties)); err != nil {
2123
r.Log.Error(err, "error creating/updating configmap", output.Name, output.Namespace)
2224
return err
2325
}
2426
r.Log.Info("created/updated configmap", output.Name, output.Namespace)
2527
return nil
2628
}
27-
if output.Kind == "Secret" || output.Kind == "secret" {
29+
if strings.ToLower(output.Kind) == "secret" {
2830
propertiesWithBytes := make(map[string][]byte)
2931
for key, value := range properties {
3032
propertiesWithBytes[key] = []byte(value)
@@ -40,11 +42,16 @@ func (r *KonfigReconciler) createOutputObject(output konfigmanagerv1.Output, con
4042

4143
func getProperties(output konfigmanagerv1.Output, config pkg.Config, resources []pkg.Resource) map[string]string {
4244
properties := make(map[string]string)
43-
if output.Type == "file" || output.Type == "File" {
45+
if strings.ToLower(output.Type) == "file" {
4446
if output.Key == "" {
4547
output.Key = "application.properties"
4648
}
47-
properties[output.Key] = config.GeneratePropertiesFile(resources)
49+
if output.FileType == "" || strings.ToLower(output.FileType) == "env" {
50+
properties[output.Key] = config.GeneratePropertiesFile(resources)
51+
}
52+
if strings.ToLower(output.FileType) == "javascript" || strings.ToLower(output.FileType) == "js" {
53+
properties[output.Key] = config.GenerateJsPropertiesFile(resources)
54+
}
4855
} else {
4956
properties = config.GetPropertiesMap(resources)
5057
}

pkg/hierarchy.go

+34-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io/ioutil"
66
"sort"
7+
"strconv"
78

89
"github.com/pkg/errors"
910

@@ -65,15 +66,20 @@ func (config Config) GetProperties(resources []Resource) map[string]Property {
6566
return propertiesMap
6667
}
6768

68-
func (config Config) GeneratePropertiesFile(resources []Resource) string {
69-
var properties string
69+
func (config Config) getPropertiesBySection(resources []Resource) map[Item]Properties {
7070
var bySection = make(map[Item]Properties)
7171
for _, v := range config.GetProperties(resources) {
7272
if _, ok := bySection[v.Resource.Hierarchy]; !ok {
7373
bySection[v.Resource.Hierarchy] = Properties{}
7474
}
7575
bySection[v.Resource.Hierarchy] = append(bySection[v.Resource.Hierarchy], v)
7676
}
77+
return bySection
78+
}
79+
80+
func (config Config) GeneratePropertiesFile(resources []Resource) string {
81+
var properties string
82+
var bySection = config.getPropertiesBySection(resources)
7783

7884
for _, item := range config.Hierarchy {
7985
list := bySection[item]
@@ -90,6 +96,32 @@ func (config Config) GeneratePropertiesFile(resources []Resource) string {
9096
return properties
9197
}
9298

99+
func (config Config) GenerateJsPropertiesFile(resources []Resource) string {
100+
var properties string
101+
var bySection = config.getPropertiesBySection(resources)
102+
for _, item := range config.Hierarchy {
103+
list := bySection[item]
104+
sort.Sort(list)
105+
if len(list) == 0 {
106+
continue
107+
}
108+
properties += fmt.Sprintf("#\n# %s\n#\n", item.String())
109+
for _, property := range list {
110+
if _, err := strconv.Atoi(property.Value); err == nil {
111+
properties += fmt.Sprintf("window['__%v__']=%v;\n", property.Key, property.Value)
112+
} else if _, err := strconv.ParseBool(property.Value); err == nil {
113+
properties += fmt.Sprintf("window['__%v__']=%v;\n", property.Key, property.Value)
114+
} else if property.Value == "null" || property.Value == "undefined" {
115+
properties += fmt.Sprintf("window['__%v__']=%v;\n", property.Key, property.Value)
116+
} else {
117+
properties += fmt.Sprintf("window['__%v__']=\"%v\";\n", property.Key, property.Value)
118+
}
119+
}
120+
}
121+
122+
return properties
123+
}
124+
93125
func (config Config) WalkHierarchy(resources []Resource) []Resource {
94126
var objs []Resource
95127
for _, item := range config.Hierarchy {

test/e2e_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package test
22

33
import (
4+
"fmt"
5+
"strconv"
46
"testing"
57

68
"github.com/flanksource/konfig-manager/pkg"
@@ -20,8 +22,14 @@ var tests = map[string]testInput{
2022
data: "fixtures/spring.yml",
2123
verifications: map[string]string{
2224
"config-key": "some-value",
25+
"config-key-quotes": "some-other-value",
2326
"spring.datasource.maxActive": "40",
27+
"null-string-key": "null",
28+
"undefined-string-key": "undefined",
29+
"bool-string-key": "true",
30+
"int-string-key": "11",
2431
},
32+
applications: []string{"spring"},
2533
},
2634
"testHierarchyMergeWithInputFile": {
2735
config: "fixtures/spring-config.yml",
@@ -30,6 +38,7 @@ var tests = map[string]testInput{
3038
"config-key": "some-value",
3139
"spring.datasource.maxActive": "40",
3240
},
41+
applications: []string{"spring"},
3342
},
3443
"testReadFromConfigMapCreatedWithFile": {
3544
config: "fixtures/fileProperties-config.yml",
@@ -39,6 +48,7 @@ var tests = map[string]testInput{
3948
"new-key": "diff-value",
4049
"logging.level.org.springframework.web": "INFO",
4150
},
51+
applications: []string{"spring"},
4252
},
4353
"testSecretValues": {
4454
config: "fixtures/secret-config.yml",
@@ -47,6 +57,7 @@ var tests = map[string]testInput{
4757
"secret-key": "some-value",
4858
"logging.level.org.springframework.web": "INFO",
4959
},
60+
applications: []string{"spring"},
5061
},
5162
"testMultipleApplications": {
5263
config: "fixtures/multi-application-config.yml",
@@ -56,9 +67,55 @@ var tests = map[string]testInput{
5667
"secret-key": "some-value",
5768
"new-key": "diff-value",
5869
},
70+
applications: []string{"spring", "quarkus"},
5971
},
6072
}
6173

74+
func TestGenerateJs(t *testing.T) {
75+
for name, test := range tests {
76+
t.Run(name, func(t *testing.T) {
77+
resources, err := pkg.ReadResources(test.data)
78+
if err != nil {
79+
t.Error(err)
80+
}
81+
82+
for _, name := range test.applications {
83+
hierarchy, err := pkg.GetHierarchy(test.config, name)
84+
if err != nil {
85+
t.Error(err)
86+
}
87+
88+
file := hierarchy.GenerateJsPropertiesFile(resources)
89+
90+
p := properties.MustLoadString(file)
91+
// check property key and values
92+
93+
for key, value := range test.verifications {
94+
var transformedValue string
95+
if _, err := strconv.Atoi(value); err == nil {
96+
transformedValue = fmt.Sprintf("%v;", value)
97+
} else if _, err := strconv.ParseBool(value); err == nil {
98+
transformedValue = fmt.Sprintf("%v;", value)
99+
} else if value == "null" || value == "undefined" {
100+
transformedValue = fmt.Sprintf("%v;", value)
101+
} else {
102+
transformedValue = fmt.Sprintf("\"%v\";", value)
103+
}
104+
105+
transformedKey := fmt.Sprintf("window['__%v__']", key)
106+
propVal, exists := p.Get(transformedKey)
107+
if !exists {
108+
t.Errorf("property not found: %s", key)
109+
}
110+
if propVal != transformedValue {
111+
t.Errorf("%s: expected %s got %s", key, propVal, transformedValue)
112+
}
113+
}
114+
}
115+
})
116+
}
117+
}
118+
62119
func TestGenerate(t *testing.T) {
63120
for name, test := range tests {
64121
t.Run(name, func(t *testing.T) {

test/fixtures/spring.yml

+5
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ metadata:
1818
namespace: default
1919
data:
2020
config-key: some-value
21+
config-key-quotes: "some-other-value"
2122
spring.main.show_banner: "true"
23+
undefined-string-key: "undefined"
2224
spring.datasource.maxActive: "40"
25+
null-string-key: "null"
26+
bool-string-key: "true"
27+
int-string-key: "11"

0 commit comments

Comments
 (0)