YAML syntax - lists, dictionaries

3/30/2020

With the following YAML file:

  • why does policyTypes contain a list but metadata doesn't?

  • why does ports have 1 list item below it (i.e. protocol) whereas port doesn't?

I'm not interested in the Kubernetes side of things just the YAML syntax.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

E.g. syntactically this is valid YAML:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  - name: test-network-policy
  - namespace: default

How is it different (from a YAML standpoint) to the first example?

-- Snowcrash
kubernetes
yaml

2 Answers

3/31/2020
  • Why does policyTypes contain a list but metadata doesn't?

As written in kubernetes API Reference docs policyTypes field is a string array (in YAML data structure called a list) what means that it is a collection of values. For these particular objects only these 2 values can be specified (but standard YAML list allows to extend the values amount).

  policyTypes:
  - Ingress
  - Egress

Metadata is a map- it consists of key value pairs but can be further expanded by adding another map to it- for example labels field in metadata section:

apiVersion: v1
kind: Pod
metadata:
  name: podname
  labels:
    key: value 
[...]

All lines must be prefixed with the same amount of spaces to belong to the same map

  • why does ports have 1 list item below it (i.e. protocol) whereas port doesn't?

Similar as before- ports field is a map inside list and for NetworkPolicy object only port and protocol can be specified. Definition of port field:

The port on the given protocol. This can either be a numerical or named port on a pod. If this field is not provided, this matches all port names and numbers.

So it is key: value pair, same as protocol field.

-- KFC_
Source: StackOverflow

3/31/2020

Completely ignoring the Kubernetes context: YAML has sequences and mappings (exactly like JSON arrays and objects). Everywhere you have a - marker it's a list item; everywhere there is a key: value pair it is a mapping. You can have one inside the other.

ports:
- protocol: TCP
  port: 6379

# is equivalent to
ports: [{"protocol": "TCP", "port": 6379}]
metadata:
  name: test-network-policy
  namespace: default

# is equivalent to
metadata: {"name": "test-network-policy", "namespace": "default"}
metadata:
  - name: test-network-policy
  - namespace: default

# is equivalent to
metadata: [
  {"name": "test-network-policy"},
  {"namespace": "default"}
]

The differences between mappings and sequences matters, and if the application expects a mapping but actually gets a sequence of mappings (compare the two metadata: blocks) you'll get an application-level error.

A pattern that does appear in the Kubernetes API but can be a little confusing is to have a list of objects with some logical "kind". Volumes within a pod spec are a good example. These each have a key to say what kind they are, but you're allowed to have multiple volumes of the same kind, so a mapping isn't the right structure.

volumes:
  # This is a list of mappings
  - name: logs
    emptyDir: {}
  - name: coreDumps
    emptyDir: {}
-- David Maze
Source: StackOverflow