I am trying to create my Role YAML file for Kubernetes and I am getting stuck with this specific section of the needed YAML:
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
I have tried to add it as a dictionary and then a list with a dictionary inside that for the -apiGroups line, but that then causes issues with the rest of the arguments for rules. I also am having issues with the [] showing up just like that when I am using yaml.dump even though I specify default_flow_style=False
def create_role_yml(role_filename, team_name, group_user):
"""
https://kubernetes.io/docs/reference/
access-authn-authz/rbac/#role-and-clusterrole
"""
yml_file_kubernetes_data = dict(
apiVersion='rbac.authorization.k8s.io/v1',
kind='Role',
metadata=dict(
namespace=team_name,
name=group_user,
),
rules={
[{'apiGroups':""}],
'resourses': '[pods]',
'verbs':'[get, watch, list]'}
)
with open(role_filename, 'w') as outfile:
yaml.dump(yml_file_kubernetes_data, outfile,
default_flow_style=False)
I would like to open the YAML and it to look exactly like the Kubernetes reference YAML:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
but I am getting the [ ] seperated, and no - for apiGroup. This is my result:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
apiGroups:
- "" # "" indicates the core API group
resources:
- "pods"
verbs:
-"get"
-"watch"
-"list"
The rules are actually an array of maps, so you'll want to change it to look like this:
#!/usr/bin/env python
import yaml
yml_file_kubernetes_data = dict(
apiVersion='rbac.authorization.k8s.io/v1',
kind='Role',
metadata=dict(
namespace='something',
name='group',
),
rules=[
{
'apiGroups': '',
'resources': [ 'pods' ],
'verbs': [ 'get', 'watch', 'list' ],
}
],
)
with open('rbac.yml', 'w') as outfile:
yaml.dump(yml_file_kubernetes_data, outfile,
default_flow_style=False)
If you want to explicitly use the [] array notation, you'll need to use something like ruamel.yml - honestly, it's really not worth it though. This is valid YAML
What you try to do is not possible with the normal parameters you can hand to PyYAML's dump()
, which gives you only very course control using default_flow_style
True
: everything is flow style (JSON like)False
: everything is block styleNone
: leaf collections are flow style, and the rest block styleYou reference YAML has both block style leaf collections: the value for the key metadata
, as well as flow style leaf collections: the value for the key verbs
. Without hacking the representer you cannot achieve this in PyYAML.
The way more easy way to generate YAML in your particular form is by read-modify-write your expected YAML with a parser that knows how to keep the formatting. You can do that with ruamel.yaml
, which is specifically developed to preserve these kind of things (disclaimer: I am the author of that package).
If your input file is input.yaml
:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace:
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", 'list']
(the single entry under metadata
is on purpose, but you could specify both, or none if you assign instead of update)
And the following program:
import sys
from pathlib import Path
import ruamel.yaml
yaml_str = """\
"""
in_file = Path("input.yaml")
out_file = Path("output.yaml")
team_name = "default"
group_user = "pod-reader"
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(in_file)
data["metadata"].update(dict(namespace=team_name, name=group_user))
yaml.dump(data, out_file)
gives output.yaml
:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", 'list']
Please note that apart from the block/flow style, also the single/double quotes from the original and the comment are preserved. Your indentation already matches the default, so that is not explicity set (yaml.indent(mapping=2, sequence=2, offset=0)
).