<p>I'm trying to use a ytt overlay to replace the <code>objectName</code> in my secret class following <a href="https://carvel.dev/ytt/#gist:https://gist.github.com/cppforlife/7633c2ed0560e5c8005e05c8448a74d2" rel="nofollow noreferrer">this gist example replacing only part of a multi-line string</a>, but it ends up appending a new item instead of replacing the existing one. How can I get it to work for this case?</p>
<h4>Input Files</h4>
<p>db_secret.yaml</p>
<pre><code>kind: SecretProviderClass
metadata:
  namespace: default
  name: db_credentials
spec:
  provider: aws
  parameters:
    objects: |
      - objectName: TO_BE_REPLACED_BY_YTT
        objectType: &quot;secretsmanager&quot;
        jmesPath: 
          - path: username
            objectAlias: dbusername
          - path: password
            objectAlias: dbpassword
</code></pre>
<p>overlay.yaml</p>
<pre><code>#@ load(&quot;@ytt:overlay&quot;, &quot;overlay&quot;)
#@ load(&quot;@ytt:yaml&quot;, &quot;yaml&quot;)
#@ load(&quot;@ytt:data&quot;, &quot;data&quot;)

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

#@overlay/match by=overlay.subset({&quot;kind&quot;: &quot;SecretProviderClass&quot;, &quot;metadata&quot;: {&quot;name&quot;: &quot;db_credentials&quot;}})
---
spec:
  provider: aws
  parameters:
    #@overlay/replace via=lambda a,_: yaml.encode(overlay.apply(yaml.decode(a), updates()))
    objects:
</code></pre>
<p>values-staging.yaml</p>
<pre><code>db_secret_name: db-secret-staging
</code></pre>
<h4>ytt output:</h4>
<pre><code>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
</code></pre>

Mai Lubega
<p>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.</p>
<p>In order to reach the map that has the <code>objectName</code> map item, you need to first match its parent: that containing array item.</p>
<p>The most durable way to do that is by selecting for the array item that has a map that contains the <code>objectName</code> key. You can say that like this:</p>
<pre><code>  #@ def updates():
+ #@overlay/match by=lambda idx,left,right: &quot;objectName&quot; in left
  - objectName: #@ data.values.db_secret_name
  #@ end
</code></pre>
<p>can be read: &quot;in the array value being overlay'ed (aka 'left'), find the array item whose value has a map whose keys include the string &quot;objectName&quot;... merge the value of <em>this</em> array item (i.e. the map in the array item within this overlay) into <em>that</em> matched map.&quot;</p>
<p><em>(Playground: <a href="https://carvel.dev/ytt/#gist:https://gist.github.com/pivotaljohn/9593f971ac5962055ff38c5eeaf1df11" rel="nofollow noreferrer">https://carvel.dev/ytt/#gist:https://gist.github.com/pivotaljohn/9593f971ac5962055ff38c5eeaf1df11</a>)</em></p>
<p>When working with overlays, it can be helpful to visualize the tree of values. There are some nice examples in the docs: <a href="https://carvel.dev/ytt/docs/v0.40.0/yaml-primer/" rel="nofollow noreferrer">https://carvel.dev/ytt/docs/v0.40.0/yaml-primer/</a></p>
<p>Also, there was a recent-ish vlog post that has been reported to help folks level up using <code>ytt</code> overlays: <a href="https://carvel.dev/blog/primer-on-ytt-overlays/" rel="nofollow noreferrer">https://carvel.dev/blog/primer-on-ytt-overlays/</a></p>
