carvel-dev / ytt

YAML templating tool that works on YAML structure instead of text
https://carvel.dev/ytt
Apache License 2.0
1.66k stars 135 forks source link

Reference Data in Data Values #882

Closed antwacky closed 9 months ago

antwacky commented 10 months ago

I know there is a work around for this, however I don't think it fits my particular use case very nicely, and wondering if there's a better solution.

So consider my schema:

environment: development
domain: localhost

apps:
  - name: app1
    mountFiles:
      - name: app-config
        mountPath: /app/config.json
        content: |
          environment: #@ data.values.environment
          url: #@ "https://app1-{}".format(data.values.domain)

Then in a deployment template:

#@ for file in app.mountFiles:
- mountPath: #@ file.mountPath
   name: #@ file.name.split('.')[0]
   subPath: #@ file.name
#@ end

I can then mount files to the various application deployments with variable content as needed. Obviously, this isn't possible, as it is not possible to use data values within a data values file.

If I were to use a function, then this gets messy, quickly, as I then have to put the file content in a lib/function, and then I have to put the mountPath somewhere seperate.

For example, I then will have a lib:

#@ def getApp1Config():
environment: #@ data.values.environment
url: #@ "https://app1-{}".format(data.values.domain)
#@ end

And my deployment becomes:

#@ if app.name == "app1":
- mountPath: /app/config.json
   name: config
   subPath: config.json
#@ end

Clearly this is not nice at all, and inflexible. How is it recommended to handle this situation?

Thanks

prembhaskal commented 10 months ago

Will check today.

prembhaskal commented 9 months ago

sorry for delay. I think you can achieve what you want in 2 steps.

cat schema-values.yml. note here we are making use of https://carvel.dev/ytt/#example:example-text-template

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

---
environment: development
domain: localhost

apps:
  - name: app1
    mountFiles:
      - name: app-config
        mountPath: /app/config.json
        #@yaml/text-templated-strings
        content: |
          environment: (@= data.values.environment @)
          url: (@= "https://app1-{}".format(data.values.domain) @)
      - name: app-config
        mountPath: /app/config.json
        #@yaml/text-templated-strings
        content: |
          environment: (@= data.values.environment @)
          url: (@= "https://app2-{}".format(data.values.domain) @)

cat values.yml

#@data/values
---
domain: somedomain
environment: someenv

cat deployment.yml

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

#@ apps = data.values.apps

---
topnode:
  #@ for app in apps:
    #@ for file in app.mountFiles:
     - mountPath: #@ file.mountPath
       name: #@ file.name.split('.')[0]
       subPath: #@ file.name
    #@ end
  #@ end

and do 2 step ytt to achieve what you want. first ytt to generate the actual values and 2nd ytt to generate the final deployment

 % ytt -f values.yml -f schema-values.yml | ytt --data-values-file - -f deployment.yml
topnode:
- mountPath: /app/config.json
  name: app-config
  subPath: app-config
- mountPath: /app/config.json
  name: app-config
  subPath: app-config
antwacky commented 9 months ago

Thanks!