Skip to content

Commit

Permalink
Merge pull request #474 from jnummelin/fix-helm-values-parsing
Browse files Browse the repository at this point in the history
Fix Helm values parsing
  • Loading branch information
jnummelin authored Dec 1, 2020
2 parents 44f94f4 + 1b232cf commit 8122c5c
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ bindata
*.tfstate*
aws_private.pem
out.json
.vscode
50 changes: 46 additions & 4 deletions inttest/addons/addons_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,19 @@ func (as *AddonsSuite) TestHelmBasedAddons() {
as.Require().NoError(as.InitMainController("/tmp/k0s.yaml", ""))
as.waitForPrometheusRelease(addonName, 1)

as.doPrometheusUpdate(addonName, map[string]interface{}{"key": "value"})
chartName := as.waitForPrometheusRelease(addonName, 2)
values := map[string]interface{}{
"server": map[string]interface{}{
"env": []interface{}{
map[string]interface{}{
"name": "FOO",
"value": "foobar",
},
},
},
}
as.doPrometheusUpdate(addonName, values)
chartName, releaseName := as.waitForPrometheusRelease(addonName, 2)
as.Require().NoError(as.waitForPrometheusServerEnvs(releaseName))
as.doPrometheusDelete(chartName)
}

Expand All @@ -73,12 +84,13 @@ func (as *AddonsSuite) doPrometheusDelete(chartName string) {
}))
}

func (as *AddonsSuite) waitForPrometheusRelease(addonName string, rev int64) string {
func (as *AddonsSuite) waitForPrometheusRelease(addonName string, rev int64) (string, string) {
as.T().Logf("waiting to see prometheus release ready in kube API, generation %d", rev)
cfg := as.getKubeConfig("controller0")
chartClient, err := clientset.New(cfg)
as.Require().NoError(err)
var chartName string
var releaseName string
as.Require().NoError(wait.PollImmediate(time.Second, 5*time.Minute, func() (done bool, err error) {
charts, err := chartClient.Charts("kube-system").List(context.Background())
if err != nil {
Expand Down Expand Up @@ -110,14 +122,44 @@ func (as *AddonsSuite) waitForPrometheusRelease(addonName string, rev int64) str
as.Require().Equal("2.21.0", testAddonItem.Status.AppVersion)
as.Require().Equal("default", testAddonItem.Status.Namespace)
as.Require().NotEmpty(testAddonItem.Status.ReleaseName)
releaseName = testAddonItem.Status.ReleaseName
as.Require().Empty(testAddonItem.Status.Error)
as.Require().Equal(rev, testAddonItem.Status.Revision)
as.T().Logf("found test addon release: %s\n", testAddonItem.Name)
as.Require().Equal(rev, testAddonItem.Generation)
chartName = testAddonItem.Name
return true, nil
}))
return chartName
return chartName, releaseName
}

func (as *AddonsSuite) waitForPrometheusServerEnvs(releaseName string) error {
as.T().Logf("waiting to see prometheus release to have envs set from values yaml")
kc, err := as.KubeClient("controller0", "")
if err != nil {
return err
}

return wait.PollImmediate(time.Second, 2*time.Minute, func() (done bool, err error) {
serverDeployment := fmt.Sprintf("%s-server", releaseName)
d, err := kc.AppsV1().Deployments("default").Get(context.TODO(), serverDeployment, v1.GetOptions{})
if err != nil {
return false, nil
}

for _, c := range d.Spec.Template.Spec.Containers {
if c.Name == "prometheus-server" {
for _, e := range c.Env {
if e.Name == "FOO" && e.Value == "foobar" {
return true, nil
}
}
} else {
continue
}
}
return false, nil
})
}

func (as *AddonsSuite) doPrometheusUpdate(addonName string, values map[string]interface{}) {
Expand Down
4 changes: 3 additions & 1 deletion pkg/apis/helm.k0sproject.io/v1beta1/chart_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ func (cs ChartSpec) YamlValues() map[string]interface{} {
if err := yaml.Unmarshal([]byte(cs.Values), &res); err != nil {
logrus.WithField("values", cs.Values).Warn("broken yaml values")
}
return res
// We need to clean the map to have nested maps as map[string]interface{} types
// otherwise Helm will fail to merge default values and create the release object
return CleanUpGenericMap(res)
}

// ChartStatus defines the observed state of Chart
Expand Down
66 changes: 66 additions & 0 deletions pkg/apis/helm.k0sproject.io/v1beta1/generic_hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright 2020 Mirantis, Inc.
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 v1beta1

import "fmt"

// Cleans up a slice of interfaces into slice of actual values
func cleanUpInterfaceArray(in []interface{}) []interface{} {
result := make([]interface{}, len(in))
for i, v := range in {
result[i] = cleanUpMapValue(v)
}
return result
}

// Cleans up the map keys to be strings
func cleanUpInterfaceMap(in map[interface{}]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range in {
result[fmt.Sprintf("%v", k)] = cleanUpMapValue(v)
}
return result
}

// Cleans up the value in the map, recurses in case of arrays and maps
func cleanUpMapValue(v interface{}) interface{} {
switch v := v.(type) {
case []interface{}:
return cleanUpInterfaceArray(v)
case map[interface{}]interface{}:
return cleanUpInterfaceMap(v)
case string:
return v
case int:
return v
case bool:
return v
case float64:
return v
default:
return fmt.Sprintf("%v", v)
}
}

// CleanUpGenericMap is a helper to "cleanup" generic yaml parsing where nested maps
// are unmarshalled with type map[interface{}]interface{}
func CleanUpGenericMap(in map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
for k, v := range in {
result[fmt.Sprintf("%v", k)] = cleanUpMapValue(v)
}
return result
}

0 comments on commit 8122c5c

Please sign in to comment.