1

I'm trying to use a ytt overlay to replace the objectName in my secret class following this gist example replacing only part of a multi-line string, but it ends up appending a new item instead of replacing the existing one. How can I get it to work for this case?

Input Files

db_secret.yaml

kind: SecretProviderClass
metadata:
  namespace: default
  name: db_credentials
spec:
  provider: aws
  parameters:
    objects: |
      - objectName: TO_BE_REPLACED_BY_YTT
        objectType: "secretsmanager"
        jmesPath: 
          - path: username
            objectAlias: dbusername
          - path: password
            objectAlias: dbpassword

overlay.yaml

#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:yaml", "yaml")
#@ load("@ytt:data", "data")

#@ def updates():
- objectName: #@ data.values.db_secret_name
#@ end

#@overlay/match by=overlay.subset({"kind": "SecretProviderClass", "metadata": {"name": "db_credentials"}})
---
spec:
  provider: aws
  parameters:
    #@overlay/replace via=lambda a,_: yaml.encode(overlay.apply(yaml.decode(a), updates()))
    objects:

values-staging.yaml

db_secret_name: db-secret-staging

ytt output:

apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  namespace: default
  name: db_credentials
spec:
  provider: aws
  parameters:
    objects: |
      - objectName: TO_BE_REPLACED_BY_YTT
        objectType: secretsmanager
        jmesPath:
        - path: username
          objectAlias: dbusername
        - path: password
          objectAlias: dbpassword
      - objectName: db-secret-staging
Mai Lubega
  • 13
  • 2

1 Answers1

1

It's key to notice that the YAML value being overlayed is itself an array. It's an array of one item, but an array nonetheless.

In order to reach the map that has the objectName map item, you need to first match its parent: that containing array item.

The most durable way to do that is by selecting for the array item that has a map that contains the objectName key. You can say that like this:

  #@ def updates():
+ #@overlay/match by=lambda idx,left,right: "objectName" in left
  - objectName: #@ data.values.db_secret_name
  #@ end

can be read: "in the array value being overlay'ed (aka 'left'), find the array item whose value has a map whose keys include the string "objectName"... merge the value of this array item (i.e. the map in the array item within this overlay) into that matched map."

(Playground: https://carvel.dev/ytt/#gist:https://gist.github.com/pivotaljohn/9593f971ac5962055ff38c5eeaf1df11)

When working with overlays, it can be helpful to visualize the tree of values. There are some nice examples in the docs: https://carvel.dev/ytt/docs/v0.40.0/yaml-primer/

Also, there was a recent-ish vlog post that has been reported to help folks level up using ytt overlays: https://carvel.dev/blog/primer-on-ytt-overlays/

JTigger
  • 394
  • 2
  • 10