Overwrite a nested list element using jsonnet

2/26/2019

I have the following json

{
    "namespace": "monitoring",
    "name": "alok",
    "spec": {
        "replicas": 1,
        "template": {
            "metadata": "aaa",
            "spec": {
                "containers": [
                    {
                        "image": "practodev/test:test",
                        "env": [
                            {
                                "name":"GF_SERVER_HTTP_PORT",
                                "value":"3000"
                            },
                            {
                                "name":"GF_SERVER_HTTPS_PORT",
                                "value":"443"
                            },
                        ]
                    }
                ]
            }
        }
    }
}

How do I add deployment_env.json using jsonnet?

{
    "env": [
        {
            "name":"GF_AUTH_DISABLE_LOGIN_FORM",
            "value":"false"
        },
        {
            "name":"GF_AUTH_BASIC_ENABLED",
            "value":"false"
        },

    ]
}

I need to add it under spec.template.containers[0].env = deployment_env.json

I wrote the below jsonnet to do that. It appends a new element. But i need to change the existing 0th container element in the json. Please suggest how to do it.

local grafana_envs = (import 'custom_grafana/deployment_env.json');
local grafanaDeployment = (import 'nested.json') + {
    spec+: {
        template+: {
            spec+: {
                containers:+ [{
                    envs: grafana_envs.env,
                }]
            }
        }
    },
};
grafanaDeployment 
-- Alok Kumar Singh
json
jsonnet
kubernetes
prometheus

2 Answers

3/6/2019

Alternative implementation, not relying on the array index position, but image value instead (which makes more sense here as the env must be understood by the image implementation)

local grafana_envs = (import 'deployment_env.json');

local TARGET_CONTAINER_IMAGE = 'practodev/test:test';

local grafanaDeployment = (import 'nested.json') + {
  spec+: {
    template+: {
      spec+: {
        containers: [
          // TARGET_CONTAINER_IMAGE identifies which container to modify
          if x.image == TARGET_CONTAINER_IMAGE
          then x { env+: grafana_envs.env }
          else x
          for x in super.containers
        ],
      },
    },
  },
};
grafanaDeployment
-- jjo
Source: StackOverflow

2/26/2019

See below for an implementation that allows adding env to an existing container by its index in the containers[] array.

Do note that jsonnet is much better suited to work with objects (i.e. dictionaries / maps) rather than arrays, thus it needs contrived handling via std.mapWithIndex(), to be able to modify an entry from its matching index.

local grafana_envs = (import 'deployment_env.json');

// Add extra_env to a container by its idx passed containers array
local override_env(containers, idx, extra_env) = (
  local f(i, x) = (
    if i == idx then x {env+: extra_env} else x
  );
  std.mapWithIndex(f, containers)
);
local grafanaDeployment = (import 'nested.json') + {
    spec+: {
        template+: {
            spec+: {
                containers: override_env(super.containers, 0, grafana_envs.env)
            }
        }
    },
};
grafanaDeployment 
-- jjo
Source: StackOverflow