Caddy: v2: Support CUE language as config file format

Created on 30 Nov 2019  路  7Comments  路  Source: caddyserver/caddy

1. What would you like to have changed?

Right now caddy2 has two config adapters: Caddyfile and JSON.
I have to admit, that I am not a big fan of json, because it's not possible to insert comments and it's difficult to write manual.

JSON is a format that should be used only from one computer to another.

I know that there is caddyfile config support, but the documentation says that the caddyfile support is not complete (there are certain options that will be only configurable via JSON).

So how to resolve this problem?

The answer for this could be the CUE language. CUE is a superset of JSON, can be transformed into JSON, and brings certain other benefits like validation with schemes (could be very useful for config files).

2. Why is this feature a useful, necessary, and/or important addition to this project?

CUE would make the configuration a lot easier. People would be able to use all features in the json config adapter and the config file would still be readable + it would be possible to insert comments.

The project would benefit of CUE in other parts as well (validation with schemes and fixed datatypes could be a lot more easier with CUE).

I really recommend this short CUE tutorial:

https://cuelang.org/docs/tutorials/tour/

I can imagine this as third-party config adapter package. CUE is a superset of json, therefore somebody could just parse CUE and pipe all the output into the caddy2 JSON config adapter and this should be fine. (Although the best part is the validation via schemes in CUE etc).

Here is a short example from YAML to CUE with a kubernetes deployment file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-kubernetes
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-kubernetes
  template:
    metadata:
      labels:
        app: hello-kubernetes
    spec:
      containers:
      - name: hello-kubernetes
        image: paulbouwer/hello-kubernetes:1.5
        ports:
        - containerPort: 8080

Same in JSON:

{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "hello-kubernetes"
  },
  "spec": {
    "replicas": 3,
    "selector": {
      "matchLabels": {
        "app": "hello-kubernetes"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "hello-kubernetes"
        }
      },
      "spec": {
        "containers": [
          {
            "name": "hello-kubernetes",
            "image": "paulbouwer/hello-kubernetes:1.5",
            "ports": [
              {
                "containerPort": 8080
              }
            ]
          }
        ]
      }
    }
  }
}

Here is the equivalent in CUE:

// This is a comment
apiVersion: "apps/v1"
kind:       "Deployment"
metadata name: "hello-kubernetes"
spec: {
  replicas: 3
  selector matchLabels app: "hello-kubernetes"
  template: {
    metadata labels app: "hello-kubernetes"
    spec containers: [{
      name:  "hello-kubernetes"
      image: "paulbouwer/hello-kubernetes:1.5"
      ports: [{
        containerPort: 8080
      }]
    }]
  }
}
feature request good first issue plugin

Most helpful comment

@shibumi FYI json5 and jsonc are also supported, which address some of the complaints you have about json. See here in the codebase: https://github.com/caddyserver/caddy/tree/v2/caddyconfig

All 7 comments

A CUE config adapter would certainly be welcome, but probably not as a standard module, like you said (also see https://github.com/caddyserver/caddy/issues/2780).

If you or somebody builds a CUE adapter for Caddy, please link to it here and when our new website is up we'll be sure to add it! Shouldn't be too hard to build this, I figure.

@shibumi FYI json5 and jsonc are also supported, which address some of the complaints you have about json. See here in the codebase: https://github.com/caddyserver/caddy/tree/v2/caddyconfig

I could see a couple of different approaches:

  1. Cue is a superset of json so any raw json object can be dumped into a cue file and it works swell so existing json config would accepted without breaking anything.
  2. A much less heavy handed approach that would let you dip your toes in cue without having to mess with the internals of caddy would be to use a cue tool script. Using this approach your existing json data model could be defined via cue, user can write a minimal config in JSON (or YAML cue supports import of either), and execution of the cue tool script spits out a json config. This would make adoption more of an opt-in give you a chance to see if users like Cue (I bet they will, but no-one likes having something forced on them)

Thanks for the input @rudolph9 !

Cue is a superset of json so any raw json object can be dumped into a cue file and it works swell so existing json config would accepted without breaking anything.

That's really cool. Just to be sure it's clear, though, users would write a cue file and then we'd have to convert it to JSON which Caddy accepts as input.

A much less heavy handed approach that would let you dip your toes in cue without having to mess with the internals of caddy would be to use a cue tool script. Using this approach your existing json data model could be defined via cue, user can write a minimal config in JSON (or YAML cue supports import of either), and execution of the cue tool script spits out a json config.

Ah this sounds much more like what we need. I commented on the linked issue in the cue repo, maybe evaluating a cue file and then calling Value() and then Marshal() is what we need.

@mholt Glad I was able to help. Check out the cue slack channel if you have any more questions it's pretty active :+1: https://github.com/cuelang/cue#contact

Well that was easy:

var rt cue.Runtime
inst, err := rt.Compile("testing.cue", body)
if err != nil {
    return nil, nil, err
}
jsonResult, err := inst.Value().MarshalJSON()
if err != nil {
    return nil, nil, err
}
return jsonResult, nil, nil

It's spikey (needs some polish) but it works.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

billop picture billop  路  3Comments

klaasel picture klaasel  路  3Comments

mschneider82 picture mschneider82  路  3Comments

jgsqware picture jgsqware  路  3Comments

whs picture whs  路  3Comments