yaml-spec icon indicating copy to clipboard operation
yaml-spec copied to clipboard

Inherit or deep merge feature for mappings

Open GoodOwl opened this issue 8 months ago • 4 comments

I would be happy to have a "deep merge" or "Inheritance" operator added to yaml.

I saw that this was previously mentioned on the issue here, but then the conversation concentrated on the first feature.

To be honest, I'm not sure if this is something that should be here or in yamlscript, let me know and I will recreate it there :)

GoodOwl avatar Apr 02 '25 07:04 GoodOwl

Have you seen the non-official <<: operator?

https://yaml.org/type/merge.html

UnePierre avatar Apr 02 '25 07:04 UnePierre

Yes, I'm familiar with the merge operator. But it is limited to merge only objects on the same level, not including the subfields. I'll copy here the example for the previous issue. I would like this source:

source: *source
 field1:
  a: 1
  b: 2
 field2:
  c: 1
dest: &source
  field1:
   <<: &&
    d: 3
 field2:
   e: 4

To result in:

dest:
  field1:
    a: 1
    b: 2
    d: 3
 field2:
   e: 4

In this example field1 performs a merge between what is passed directly in dest and what is in &source, and for field2 the field is overridden (this is default behaviour right now)

GoodOwl avatar Apr 02 '25 09:04 GoodOwl

This would be particularly helpful for files that have many deeply nested values, such as Kubernetes manifests and Helm chart values files. Take the following example:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  selector:
    matchLabels:
      app: example-deployment
  template:
    metadata:
      labels:
        app: example-deployment
    spec:
      containers:
        - &container_baseline
          name: container-1
          image: some-image
          resources: &container_baseline_resources
            limits: &container_baseline_resource_limits
              memory: "128Mi"
              cpu: "500m"
            requests:
              memory: "64Mi"
              cpu: "250m"
          ports:
            - containerPort: 1234
          # Add additional common configuration here
        - <<: *container_baseline
          name: container-2
          resources:
            <<: *container_baseline_resources
            limits:
              <<: *container_baseline_resource_limits
              memory: "256Mi"

This is pretty verbose, and it gets worse with additional nesting, and with additional values that need to be changed. Ideally users would be able to do something like this:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  selector:
    matchLabels:
      app: example-deployment
  template:
    metadata:
      labels:
        app: example-deployment
    spec:
      containers:
        - &container_baseline
          name: container-1
          image: some-image
          resources:
            limits:
              memory: "128Mi"
              cpu: "500m"
            requests:
              memory: "64Mi"
              cpu: "250m"
          ports:
            - containerPort: 1234
          env:
            - name: 
              value: "example_value"
          # Add additional common configuration here
        - <<: *container_baseline # This would probably need a new, slightly different syntax for backwards compatibility
          resources:
            limits:
              memory: "256Mi"

This cuts three anchors down to one, and reduces boilerplate significantly. It's also easier to scan over and understand what's happening.

solidDoWant avatar Apr 03 '25 20:04 solidDoWant

Have you seen the non-official <<: operator?

https://yaml.org/type/merge.html

Hasn't it been removed in 1.2.0?

art-solopov avatar Nov 02 '25 00:11 art-solopov