diff --git a/integration/suites/helm/render/secret_test.go b/integration/suites/helm/render/secret_test.go index 3bf0510280..b233df8069 100644 --- a/integration/suites/helm/render/secret_test.go +++ b/integration/suites/helm/render/secret_test.go @@ -21,12 +21,8 @@ var _ = Describe("helm render with secrets", func() { for _, substr := range []string{ "int: MTc=", - `json: - web: - id: "220821453116" - redirect_uris: - - https://test.ru`, - "quoted: '''password'''", + `json: {"web": {"id": "220821453116", "redirect_uris": ["https://test.ru"]}}`, + `quoted: "'password'"`, "secret_file: TUlJSktBSUJBQUtDQWdFQXFQMEFDcHZKNmUrSFJjdndDMUlFM201TzJNQXo4ci90QU1RZldwK2w3L0g1TE1zTgpGTzJKSVJPUis1VE95R2VWc1dzekRZMTEzcFhhRTJoaDZjam16Qkhvc1h6azZSenpVd1B4TlZzUy9MN3ZkRy9iClZxTnB1UGhyRllMdVNWcFgzZC9Cc0wzUmZXVnpxS1JlYVpnb05SQnpUN044UWNFVHdCMEEzbExvYy9TcGxNY0UKOTJ5QUJJMUNwcEt4b1RWVnlGZ09vMVNhSlFBRlRwOUtLbDY4K2tkTTFhcUlhV1Y0eWxKbXB2Umo3bVR2eGlmYwp3SVdLc1FLQ0FRQmo4c05RTHl3bnJIY2pJSnpwemRKZVArTUlCN1BaUFFIVDQzWDBpZzRFaC9kS3BIVHlWb21ECituWjZLWktqRUcySmY1NnNKUysxa202cWNhYjU1MnIxTGtNcXNoRVZWb2s2K2ovanNidHROOHVCVGliMkRyUksKbFlWMmI5TTh2RnF6LzNxQmM2VkxISWNkZ29pRGlOdWl3QlhlZFdsRHBnNUN2V3BIRWx1anRKVjNMNmNpQjFRNwpqeG9lMGNtUXY5TGJYWUNCRjBBNVZVNWZqeHdJN0tQVmRCSm1rWE9RS3EvZ1ZuVGFQOG9DSlN0dk95Lzd6bm05CjgwemhRQUtJMkgzVjZMOG9ONG5vTm16TW50bkNUWUl5UWFpMlRlUVgyckswbGlpeXNjVWQxaGJGaWE5bUZMNWEKd2g2Y3EyVElNcDNpK1h2MWw4VU5pTXZOM0JGWEhKR3hBb0lCQUMrajZZY2wxRVZuMjJCOFk3bHd1Mmp1SFFuYQpiZEpTR2QrMk5mUnp3TGcxaGxDc3pmL3JPNzZkUlYyVkFnR0NTM1NUWE9iQ2s2UHR5RTJHLy9TeG5pTG1nNCtyCklkLzF6SVNFZERUdkg1TG1OejNqNmJKNXFBTUttdkYyVjRoeHhtMmYwQ2xZSjJBWFFZdGNrL2N1bzQrWUxjVkQKOTRqNXowZkd4Y0xhSVkxVVpDUXZpbHZzVmdFaEV0cEQ0enpaTGFuOXNqRVVLLzAwV2E3NG8vVzBKWmpUS3Q3RAoxaDAwbUJxcTJDN1J0OElnNitreE9QSVdCUGxTNk1CQkJuS2Q1L1VqeS9hanJERnlHVjZjNjRtRFJHR1FFKy8rCk5JcDcwZjcxaWFBQVFQSVBkaFJUdk9zaEhna2RNQTFqRlBOWUNUVlVmWk56NllCSVpzajhBTktqNnNFPQo=", } { Ω(output).Should(ContainSubstring(substr)) diff --git a/pkg/deploy/helm/extra_annotations_and_labels_post_renderer.go b/pkg/deploy/helm/extra_annotations_and_labels_post_renderer.go index 32e4bdd6c7..8cdb8144a0 100644 --- a/pkg/deploy/helm/extra_annotations_and_labels_post_renderer.go +++ b/pkg/deploy/helm/extra_annotations_and_labels_post_renderer.go @@ -4,11 +4,10 @@ import ( "bytes" "fmt" "os" - "regexp" "sort" "strings" - orig_yaml "gopkg.in/yaml.v2" + yaml_v3 "gopkg.in/yaml.v3" "helm.sh/helm/v3/pkg/releaseutil" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/yaml" @@ -35,37 +34,73 @@ type ExtraAnnotationsAndLabelsPostRenderer struct { ExtraLabels map[string]string } -func findMapByKey(mapSlice orig_yaml.MapSlice, key string) orig_yaml.MapSlice { - for _, item := range mapSlice { - if itemKey, ok := item.Key.(string); ok { - if itemKey == key { - if itemValue, ok := item.Value.(orig_yaml.MapSlice); ok { - return itemValue - } - } +func replaceNodeByKey(node *yaml_v3.Node, key string, value *yaml_v3.Node) { + content := node.Content + end := len(content) + + for pos := 0; pos < end; pos += 2 { + keyNode := content[pos] + + if keyNode.Tag != "!!str" { + continue + } + + var k string + if err := keyNode.Decode(&k); err != nil { + continue + } + + if k == key { + content[pos+1] = value + return + } + } +} + +func findNodeByKey(node *yaml_v3.Node, key string) *yaml_v3.Node { + content := node.Content + end := len(content) + + for pos := 0; pos < end; pos += 2 { + keyNode := content[pos] + valueNode := content[pos+1] + + if keyNode.Tag != "!!str" { + continue + } + + var k string + if err := keyNode.Decode(&k); err != nil { + continue + } + + if k == key { + return valueNode } } return nil } -func setMapValueByKey(mapSlice orig_yaml.MapSlice, key string, value interface{}) (res orig_yaml.MapSlice) { - var found bool - for _, item := range mapSlice { - if itemKey, ok := item.Key.(string); ok { - if itemKey == key { - res = append(res, orig_yaml.MapItem{Key: key, Value: value}) - found = true - continue +func getMapNode(docNode *yaml_v3.Node) *yaml_v3.Node { + if docNode.Kind == yaml_v3.DocumentNode { + if len(docNode.Content) > 0 { + n := docNode.Content[0] + if n.Tag == "!!map" { + return n } } - res = append(res, item) } + return nil +} - if !found { - res = append(res, orig_yaml.MapItem{Key: key, Value: value}) +func createNode(v interface{}) *yaml_v3.Node { + newNode := &yaml_v3.Node{} + if err := newNode.Encode(v); err != nil { + logboek.Warn().LogF("Unable to encode map %#v into yaml node: %s\n", v, err) + return nil } - return + return newNode } func (pr *ExtraAnnotationsAndLabelsPostRenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { @@ -95,10 +130,8 @@ func (pr *ExtraAnnotationsAndLabelsPostRenderer) Run(renderedManifests *bytes.Bu splitModifiedManifests := make([]string, 0) - manifestNameRegex := regexp.MustCompile("# Source: .*") for _, manifestKey := range manifestsKeys { manifestContent := splitManifestsByKeys[manifestKey] - manifestSource := manifestNameRegex.FindString(manifestContent) if os.Getenv("WERF_HELM_V3_EXTRA_ANNOTATIONS_AND_LABELS_DEBUG") == "1" { fmt.Printf("ExtraAnnotationsAndLabelsPostRenderer -- original manifest BEGIN\n") @@ -117,8 +150,8 @@ func (pr *ExtraAnnotationsAndLabelsPostRenderer) Run(renderedManifests *bytes.Bu continue } - var objMapSlice orig_yaml.MapSlice - if err := orig_yaml.Unmarshal([]byte(manifestContent), &objMapSlice); err != nil { + var objNode yaml_v3.Node + if err := yaml_v3.Unmarshal([]byte(manifestContent), &objNode); err != nil { logboek.Warn().LogF("Unable to decode yaml manifest as map slice: %s: will not add extra annotations and labels to this object:\n%s\n---\n", err, manifestContent) splitModifiedManifests = append(splitModifiedManifests, manifestContent) continue @@ -131,37 +164,77 @@ func (pr *ExtraAnnotationsAndLabelsPostRenderer) Run(renderedManifests *bytes.Bu if obj.IsList() && len(extraAnnotations) > 0 { logboek.Warn().LogF("werf annotations won't be applied to *List resource Kinds, including %s. We advise to replace *List resources with multiple separate resources of the same Kind\n", obj.GetKind()) } else if len(extraAnnotations) > 0 { - if metadata := findMapByKey(objMapSlice, "metadata"); metadata != nil { - annotations := findMapByKey(metadata, "annotations") - for k, v := range extraAnnotations { - annotations = append(annotations, orig_yaml.MapItem{Key: k, Value: v}) + if objMapNode := getMapNode(&objNode); objMapNode != nil { + if metadataNode := findNodeByKey(objMapNode, "metadata"); metadataNode != nil { + if annotationsNode := findNodeByKey(metadataNode, "annotations"); annotationsNode != nil { + if annotationsNode.Kind == yaml_v3.AliasNode { + if newMetadataAnnotationsNode := createNode(map[string]interface{}{"annotations": map[string]string{}}); newMetadataAnnotationsNode != nil { + if newAnnotationsNode := findNodeByKey(newMetadataAnnotationsNode, "annotations"); newAnnotationsNode != nil { + newAnnotationsNode.Content = append(newAnnotationsNode.Content, annotationsNode.Alias.Content...) + + if newExtraAnnotationsNode := createNode(extraAnnotations); newExtraAnnotationsNode != nil { + newAnnotationsNode.Content = append(newAnnotationsNode.Content, newExtraAnnotationsNode.Content...) + } + } + replaceNodeByKey(metadataNode, "annotations", newMetadataAnnotationsNode) + } + } else { + if newExtraAnnotationsNode := createNode(extraAnnotations); newExtraAnnotationsNode != nil { + annotationsNode.Content = append(annotationsNode.Content, newExtraAnnotationsNode.Content...) + } + } + } else { + if newMetadataAnnotationsNode := createNode(map[string]interface{}{"annotations": extraAnnotations}); newMetadataAnnotationsNode != nil { + metadataNode.Content = append(metadataNode.Content, newMetadataAnnotationsNode.Content...) + } + } } - metadata = setMapValueByKey(metadata, "annotations", annotations) - objMapSlice = setMapValueByKey(objMapSlice, "metadata", metadata) } } if obj.IsList() && len(extraLabels) > 0 { logboek.Warn().LogF("werf labels won't be applied to *List resource Kinds, including %s. We advise to replace *List resources with multiple separate resources of the same Kind\n", obj.GetKind()) } else if len(extraLabels) > 0 { - if metadata := findMapByKey(objMapSlice, "metadata"); metadata != nil { - labels := findMapByKey(metadata, "labels") - for k, v := range extraLabels { - labels = append(labels, orig_yaml.MapItem{Key: k, Value: v}) + if objMapNode := getMapNode(&objNode); objMapNode != nil { + if metadataNode := findNodeByKey(objMapNode, "metadata"); metadataNode != nil { + if labelsNode := findNodeByKey(metadataNode, "labels"); labelsNode != nil { + if labelsNode.Kind == yaml_v3.AliasNode { + if newMetadataLabelsNode := createNode(map[string]interface{}{"labels": map[string]string{}}); newMetadataLabelsNode != nil { + if newLabelsNode := findNodeByKey(newMetadataLabelsNode, "labels"); newLabelsNode != nil { + newLabelsNode.Content = append(newLabelsNode.Content, labelsNode.Alias.Content...) + + if newExtraLabelsNode := createNode(extraLabels); newExtraLabelsNode != nil { + newLabelsNode.Content = append(newLabelsNode.Content, newExtraLabelsNode.Content...) + } + } + replaceNodeByKey(metadataNode, "labels", newMetadataLabelsNode) + } + } else { + if newExtraLabelsNode := createNode(extraLabels); newExtraLabelsNode != nil { + labelsNode.Content = append(labelsNode.Content, newExtraLabelsNode.Content...) + } + } + } else { + if newMetadataLabelsNode := createNode(map[string]interface{}{"labels": extraLabels}); newMetadataLabelsNode != nil { + metadataNode.Content = append(metadataNode.Content, newMetadataLabelsNode.Content...) + } + } } - metadata = setMapValueByKey(metadata, "labels", labels) - objMapSlice = setMapValueByKey(objMapSlice, "metadata", metadata) } } - if modifiedManifestContent, err := orig_yaml.Marshal(objMapSlice); err != nil { + var modifiedManifestContent bytes.Buffer + yamlEncoder := yaml_v3.NewEncoder(&modifiedManifestContent) + yamlEncoder.SetIndent(2) + + if err := yamlEncoder.Encode(&objNode); err != nil { return nil, fmt.Errorf("unable to modify manifest: %w\n%s\n---\n", err, manifestContent) } else { - splitModifiedManifests = append(splitModifiedManifests, manifestSource+"\n"+string(modifiedManifestContent)) + splitModifiedManifests = append(splitModifiedManifests, modifiedManifestContent.String()) if os.Getenv("WERF_HELM_V3_EXTRA_ANNOTATIONS_AND_LABELS_DEBUG") == "1" { fmt.Printf("ExtraAnnotationsAndLabelsPostRenderer -- modified manifest BEGIN\n") - fmt.Printf("%s\n", modifiedManifestContent) + fmt.Printf("%s\n", modifiedManifestContent.String()) fmt.Printf("ExtraAnnotationsAndLabelsPostRenderer -- modified manifest END\n") } }