Siddharth Srinivasan
Siddharth Srinivasan

Reputation: 836

Parsing Kubernetes ConfigMap in Mixed Data Formats

Consider this current namespace config in JSON format:

$ kubectl get configmap config -n metallb-system -o json
{
    "apiVersion": "v1",
    "data": {
        "config": "address-pools:\n- name: default\n  protocol: layer2\n  addresses:\n  - 192.168.0.105-192.168.0.105\n  - 192.168.0.110-192.168.0.111\n"
    },
    "kind": "ConfigMap",
    "metadata": {
        "annotations": {
            "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"config\":\"address-pools:\\n- name: default\\n  protocol: layer2\\n  addresses:\\n  - 192.168.0.105-192.168.0.105\\n  - 192.168.0.110-192.168.0.111\\n\"},\"kind\":\"ConfigMap\",\"metadata\":{\"annotations\":{},\"name\":\"config\",\"namespace\":\"metallb-system\"}}\n"
        },
        "creationTimestamp": "2020-07-10T08:26:21Z",
        "managedFields": [
            {
                "apiVersion": "v1",
                "fieldsType": "FieldsV1",
                "fieldsV1": {
                    "f:data": {
                        ".": {},
                        "f:config": {}
                    },
                    "f:metadata": {
                        "f:annotations": {
                            ".": {},
                            "f:kubectl.kubernetes.io/last-applied-configuration": {}
                        }
                    }
                },
                "manager": "kubectl",
                "operation": "Update",
                "time": "2020-07-10T08:26:21Z"
            }
        ],
        "name": "config",
        "namespace": "metallb-system",
        "resourceVersion": "2086",
        "selfLink": "/api/v1/namespaces/metallb-system/configmaps/config",
        "uid": "c2cfd2d2-866c-466e-aa2a-f3f7ef4837ed"
    }
}

I am interested only in the address pools that are configured. As per the kubectl cheat sheet, I can do something like this to fetch the required address range:

$ kubectl get configmap config -n metallb-system -o jsonpath='{.data.config}'
address-pools:
- name: default
  protocol: layer2
  addresses:
  - 192.168.0.105-192.168.0.105
  - 192.168.0.110-192.168.0.111

However, my requirement is to use only a JSON parser throughout, and I cannot parse the above output since it is in YAML instead.

Since I'm not willing to accomodate the above yaml output for direct use ( or via format conversion operation ), is there any suitable way I can obtain the address range from the kubectl interface in a JSON format instead?

Upvotes: 0

Views: 1608

Answers (1)

Abdennour TOUMI
Abdennour TOUMI

Reputation: 93223

You need yq alongside kubectl ...

After inspecting your configmap, I understood the structure when I convert it to YAML :

---
apiVersion: v1
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.0.105-192.168.0.105
      - 192.168.0.110-192.168.0.111
kind: ConfigMap
metadata:
 name: config

And you can see clearly that .data.config is a multi-line string.. but it can be converted also to YAML.

  • parse the multi-line string with kubectl
  • treat this string as yaml using yq.

So This is what you are looking for :

# all addresses
kubectl -n metallb-system get cm config -o 'go-template={{index .data "config" }}' | \
    yq -r '.["address-pools"][0].addresses'

# first address only
kubectl -n metallb-system get cm config -o 'go-template={{index .data "config" }}' | \
    yq -r '.["address-pools"][0].addresses[0]'

# second address only
kubectl -n metallb-system get cm config -o 'go-template={{index .data "config" }}' | \
    yq -r '.["address-pools"][0].addresses[1]'

# so on ...

Upvotes: 2

Related Questions