Hacker News new | ask | show | jobs
by q3k 2071 days ago
Three things to address:

1) This doesn't have to be a two-step process. Specialized tools like kubecfg for Jsonnet will directly take a Jsonnet top-level config and instantiate it, traverse the tree, and apply the configuration intelligently to your Kubernetes Cluster.

2) General purpose languages are at a disadvantage, because most of them are impure. Languages that limit all filesystem imports to be local to a repository and disallow any I/O ensure that you can safely instantiate configuration on CI hosts, in production programs, etc. The fact that languages like Jsonnet also ship as a single binary (or simple library) that requires no environment setup, etc. also make them super easy to integrate to any stack.

3) Configuration languages tend to be functional, lazily evaluated and declarative, vastly simplifying building abstractions that feel more in-line with your data. This allows for progressive building of abstraction, from just a raw data representation, through removal of repeated fields, to anything you could imagine makes sense for your application.

Related reading: https://landing.google.com/sre/workbook/chapters/configurati...

1 comments

I don’t think they tend to be lazily evaluated (unless you mean “lazy” in some other way than I’m familiar with), but in general I agree.
Jsonnet, Nix and CUE are lazily evaluated. Starlark is not IIRC. Dhall I don't know, but I would presume it is?

Nix as an example:

  nix-repl> { foo = 5 / 0; bar = 5; }    
  error: division by zero, at (string):1:9

  nix-repl> { foo = 5 / 0; bar = 5; }.bar 
  5
vs. Python as an obvious example of a language with eager evaluation:

  >>> { "foo": 5 / 0, "bar": 5 }.bar
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  ZeroDivisionError: division by zero
This lazy evaluation allows for a very nice construct in Jsonnet:

  local widget = {
    id:: error "id must be set",
    name: "widget-%d" % [self.id],
    url: "https://factory.com/widget/%d" % [self.id],
  };
  widgetStandard: widget { id: 42 },
  widgetSpecial: widget { name: "foo"; url: "https://foo.com" },
When the resulting code only expects a widget to have a 'name' and 'url' field, you can either have both automatically defined based on a single to-level ID, or override them, even fully skipping the ID if not needed. (a :: in jsonnet is a hidden field, ie. one that will not be evaluated automatically when generating a YAML/JSON/..., but can be evaluated by other means).