Home > Back-end >  Jsonnet mixin variables and functions
Jsonnet mixin variables and functions

Time:10-07

i am trying to write some wrapper logic for deployments with Tanka/Jsonnet, but seem to be running into some issue, that is probably very simple to solve.

I am trying to create some wrapper-function for a statefulSet that adds e.g. some stdLabels at multiple locations, but keep getting an error regarding Expected token OPERATOR but got "." on the stateful.new. It works without the local variable, but i have no clue as to why or how to solve this?

{
  local k = import 'github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet',
  local container = k.core.v1.container,
  local stateful = k.apps.v1.statefulSet,

  fns: {
    customStateful(name, config, c):: {

      local stdLabels = {
        realm: $._config.ingress.realm,
        app: name,
        'app.kubernetes.io/part-of': config.name,
      },
    
      stateful.new(
        name=name,
        replicas=null,
        containers=[]
      )
        stateful.metadata.withLabels(stdLabels)
        stateful.spec.template.metadata.withLabels(stdLabels)
    }
  },
  
 $.aed.customStateful('test', cfg, container.new('test', alpine:latest)),

 
}

CodePudding user response:

The main issue is that customStateful():: {...} is returning an object, thus every entry there should be { key1: value1, key2: value, ...}, you need to change it to be customStateful():: (...) instead.

Pasting below a fixed example:

main.jsonnet

For other readers, mind you need to run tk init to be able to try this code

// main.jsonnet
//
{
  local k = import 'github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet',
  local container = k.core.v1.container,
  local stateful = k.apps.v1.statefulSet,

  // plug just to make below code work when referring to $._config, as per provided example
  _config:: { ingress:: { realm:: 'bar' } },

  // cfg used by customStateful 2nd argument in the provided example, create some foo setting
  local cfg = { name: 'foo' },

  fns:: {
    // NB: returning () instead of {}, to be able to return stateful.new()   overloads,
    //     else it would need to be a named field, e.g.  { sts: stateful.new(...) }
    customStateful(name, config, c):: (

      local stdLabels = {
        realm: $._config.ingress.realm,
        app: name,
        'app.kubernetes.io/part-of': config.name,
      };

      stateful.new(
        name=name,
        replicas=null,
        containers=[]
      )
        stateful.metadata.withLabels(stdLabels)
        stateful.spec.template.metadata.withLabels(stdLabels)
    ),
  },

  foo: $.fns.customStateful('test', cfg, container.new('test', 'alpine:latest')),
}

output

$ tk init
$ tk eval main.jsonnet
{
  "foo": {
    "apiVersion": "apps/v1",
    "kind": "StatefulSet",
    "metadata": {
      "labels": {
        "app": "test",
        "app.kubernetes.io/part-of": "foo",
        "realm": "bar"
      },
      "name": "test"
    },
    "spec": {
      "replicas": null,
      "selector": {
        "matchLabels": {
          "name": "test"
        }
      },
      "template": {
        "metadata": {
          "labels": {
            "app": "test",
            "app.kubernetes.io/part-of": "foo",
            "realm": "bar"
          }
        },
        "spec": {
          "containers": []
        }
      },
      "updateStrategy": {
        "type": "RollingUpdate"
      }
    }
  }
}
  • Related