-
-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate a Markdown Table from a Module Configuration #318
Conversation
I've tried to render the markdown from your example and looks like the multi-line values break into rows. Maybe we need to wrap the multi-line into code block "````"? |
Yeah, I'll try fix that shortly. I was in the process of getting it into a single line, will try the code block syntax. |
Using a code block didn't work, still split across multiple lines. But marshaling to a single line of JSON works, not very readable though... | FIELD | TYPE | DEFAULT | DESCRIPTION |
|--------------------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
| `logLevel` | `int` | `2` | |
| `rbac.enabled` | `bool` | `true` | |
| `controller.monitoring.serviceMonitor.targetPort` | `(int|string)` | `http-metrics` | |
| `controller.volumeMounts` | `list` | `[{"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount","name":"serviceaccount-token","readOnly":true}]` | |
| `controller.volumes` | `list` | `[{"name":"serviceaccount-token","projected":{"defaultMode":444,"sources":[{"serviceAccountToken":{"expirationSeconds":3607,"path":"token"}},{"configMap":{"name":"kube-root-ca.crt","items":[{"key":"ca.crt","path":"ca.crt"}]}},{"downwardAPI":{"items":[{"path":"namespace","fieldRef":{"apiVersion":"v1","fieldPath":"metadata.namespace"}}]}}]}}]` | |
| `webhook.hostNetwork` | `bool` | `false` | |
| `webhook.securePort` | `int` | `10250` | |
| `webhook.timeoutSeconds` | `int` | `10` | |
| `webhook.image.repository` | `string` | `quay.io/jetstack/cert-manager-webhook` | |
| `webhook.image.tag` | `string` | `v1.13.2` | |
| `webhook.image.digest` | `string` | `sha256:0a9470447ebf1d3ff1c172e19268be12dc26125ff83320d456f6826c677c0ed2` | |
| `webhook.image.pullPolicy` | `string` | `IfNotPresent` | |
| `webhook.networkPolicy` | `struct` | `{"ingress":[{"from":[{"ipBlock":{"cidr":"0.0.0.0/0"}}]}],"egress":[{"ports":[{"port":80,"protocol":"TCP"},{"port":443,"protocol":"TCP"},{"port":53,"protocol":"TCP"},{"port":53,"protocol":"UDP"},{"port":6443,"protocol":"TCP"}],"to":[{"ipBlock":{"cidr":"0.0.0.0/0"}}]}]}` | |
| `webhook.volumeMounts` | `list` | `[{"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount","name":"serviceaccount-token","readOnly":true}]` | |
| `webhook.volumes` | `list` | `[{"name":"serviceaccount-token","projected":{"defaultMode":444,"sources":[{"serviceAccountToken":{"expirationSeconds":3607,"path":"token"}},{"configMap":{"name":"kube-root-ca.crt","items":[{"key":"ca.crt","path":"ca.crt"}]}},{"downwardAPI":{"items":[{"path":"namespace","fieldRef":{"apiVersion":"v1","fieldPath":"metadata.namespace"}}]}}]}}]` | |
| `caInjector.automountServiceAccountToken` | `bool` | `false` | |
| `test.startupAPICheck.replicas` | `int` | `1` | |
| `test.startupAPICheck.securityContext.runAsNonRoot` | `bool` | `true` | |
| `test.startupAPICheck.securityContext.seccompProfile.type` | `string` | `RuntimeDefault` | |
| `test.startupAPICheck.serviceAccount.automountServiceAccountToken` | `bool` | `false` | |
| `test.startupAPICheck.service.type` | `string` | `ClusterIP` | |
| `test.startupAPICheck.volumeMounts` | `list` | `[{"mountPath":"/var/run/secrets/kubernetes.io/serviceaccount","name":"serviceaccount-token","readOnly":true}]` | |
| `test.startupAPICheck.volumes` | `list` | `[{"name":"serviceaccount-token","projected":{"defaultMode":444,"sources":[{"serviceAccountToken":{"expirationSeconds":3607,"path":"token"}},{"configMap":{"name":"kube-root-ca.crt","items":[{"key":"ca.crt","path":"ca.crt"}]}},{"downwardAPI":{"items":[{"path":"namespace","fieldRef":{"apiVersion":"v1","fieldPath":"metadata.namespace"}}]}}]}}]` | | In the field names do we want to have them separated by |
Figured out how to pull the comment associated with a config field:
|
Should I put |
I think we should be using |
Should this also be updated to have |
I would go for |
@Nalum can you please update the PR description and put there not in code blocks, but as markdown the cert-manager table in its latest form. |
@stefanprodan will do, just going to update the logic a bit more. |
@stefanprodan are you happy with the command structure, |
I would go with |
Add description column and format list/struct as single line of JSON Run MarshalJSON for all values Add field comment to the description column Remove +optional and +required from doc strings Format field path in cue syntax and add spaces to json defaults to allow the string to break across multiple lines Signed-off-by: Luke Mallon (Nalum) <[email protected]>
The output flag will take a file name and read the file line by line, write each line to a new temporary file. If the file is a markdown file we are looking for a table which will be replaced with the new table generated from the module configuration data. If a table is not found or the file is not markdown then the generated table is appended to the end of the file. The temporary file is then used to replace the existing file. Add logic to look for specific markdown header and only work with the table under that Better replace for json structure Fix formatting for types with pipe values Use string replace on correct variable Signed-off-by: Luke Mallon (Nalum) <[email protected]>
4a462ea
to
25a2220
Compare
25a2220
to
0845116
Compare
Test reading and writing to the output file Signed-off-by: Luke Mallon (Nalum) <[email protected]>
0845116
to
c3e8d0c
Compare
@stefanprodan I have updated this so now you can set timoni/internal/engine/module_builder.go Lines 328 to 333 in ae652b0
I've also had to update the timoni core api files and the |
d43507b
to
8142551
Compare
Signed-off-by: Luke Mallon (Nalum) <[email protected]>
6016d41
to
255cb82
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please set the copyright year to 2024 for the mod_show Go files please.
Signed-off-by: Luke Mallon (Nalum) <[email protected]>
Signed-off-by: Luke Mallon (Nalum) <[email protected]>
Signed-off-by: Luke Mallon (Nalum) <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks @Nalum awesome contribution 🏅
This adds support for creating a markdown table generated from the configuration cue structure in a module with
timoni mod show config
.Fix: #168
The command will output the table to
os.Stdout
by default, however you can provide a file name to the flag-o
or--output
where the table will be written to. If the file is markdown (i.e. has the file extention.md
or.markdown
) we look for the heading## Configuration
and then a table within this heading which will be replaced. If the file is not markdown the table will be appended to the file.The below is an example of output generated from the blueprint module and you can look at the cert-manager-module README for an example of something with more complexity.
timoni: instance: config:
struct
{"kubeVersion": "1.27.5","clusterVersion": {"major": 1,"minor": 27}, "moduleVersion": "0.0.0-devel","metadata": {"name": "module-name","namespace": "default","labels": {"app.kubernetes.io/name": "module-name","app.kubernetes.io/version": "0.0.0-devel","app.kubernetes.io/managed-by": "timoni"}}, "selector": {"labels": {"app.kubernetes.io/name": "module-name"}}, "image": {"repository": "docker.io/nginx","tag": "1-alpine","digest": "","pullPolicy": "IfNotPresent","reference": "docker.io/nginx:1-alpine"}, "pod": {"affinity": {"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "kubernetes.io/os","operator": "In","values": ["linux"]}]}]}}}}, "resources": {"requests": {"cpu": "10m","memory": "32Mi"}}, "replicas": 1,"securityContext": {"capabilities": {"drop": ["ALL"],"add": ["CHOWN","NET_BIND_SERVICE","SETGID","SETUID"]}, "privileged": false,"allowPrivilegeEscalation": false}, "service": {"port": 80}}
kubeVersion:
string
"1.27.5"
clusterVersion:
struct
{"major": 1,"minor": 27}
clusterVersion: major:
int
1
clusterVersion: minor:
int
27
moduleVersion:
string
"0.0.0-devel"
app.kubernetes.io/version
label.metadata:
struct
{"name": "module-name","namespace": "default","labels": {"app.kubernetes.io/name": "module-name","app.kubernetes.io/version": "0.0.0-devel","app.kubernetes.io/managed-by": "timoni"}}
metadata.name
andmetadata.namespace
fields are set from the user-supplied instance name and namespace.metadata: name:
string
"module-name"
metadata: namespace:
string
"default"
metadata: labels:
struct
{"app.kubernetes.io/name": "module-name","app.kubernetes.io/version": "0.0.0-devel","app.kubernetes.io/managed-by": "timoni"}
metadata.labels
to all resources. Theapp.kubernetes.io/name
andapp.kubernetes.io/version
labels are automatically generated and can't be overwritten.metadata: labels: "app.kubernetes.io/name":
string
"module-name"
metadata: labels: "app.kubernetes.io/version":
string
"0.0.0-devel"
metadata: labels: "app.kubernetes.io/managed-by":
string
"timoni"
selector:
struct
{"labels": {"app.kubernetes.io/name": "module-name"}}
app.kubernetes.io/name
label selector is automatically generated from the instance name and can't be overwritten.selector: labels:
struct
{"app.kubernetes.io/name": "module-name"}
selector: labels: "app.kubernetes.io/name":
string
"module-name"
image:
struct
{"repository": "docker.io/nginx","tag": "1-alpine","digest": "","pullPolicy": "IfNotPresent","reference": "docker.io/nginx:1-alpine"}
image: repository:
string
"docker.io/nginx"
image: tag:
string
"1-alpine"
image: digest:
string
""
image: pullPolicy:
string
"IfNotPresent"
image: reference:
string
"docker.io/nginx:1-alpine"
pod:
struct
{"affinity": {"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "kubernetes.io/os","operator": "In","values": ["linux"]}]}]}}}}
pod: affinity:
struct
{"nodeAffinity": {"requiredDuringSchedulingIgnoredDuringExecution": {"nodeSelectorTerms": [{"matchExpressions": [{"key": "kubernetes.io/os","operator": "In","values": ["linux"]}]}]}}}
resources:
struct
{"requests": {"cpu": "10m","memory": "32Mi"}}
resources: requests:
struct
{"cpu": "10m","memory": "32Mi"}
resources: requests: cpu:
string
"10m"
resources: requests: memory:
string
"32Mi"
replicas:
int
1
securityContext:
struct
{"capabilities": {"drop": ["ALL"],"add": ["CHOWN","NET_BIND_SERVICE","SETGID","SETUID"]}, "privileged": false,"allowPrivilegeEscalation": false}
securityContext: capabilities:
struct
{"drop": ["ALL"],"add": ["CHOWN","NET_BIND_SERVICE","SETGID","SETUID"]}
securityContext: capabilities: drop:
list
["ALL"]
securityContext: capabilities: add:
list
["CHOWN","NET_BIND_SERVICE","SETGID","SETUID"]
securityContext: privileged:
bool
false
securityContext: allowPrivilegeEscalation:
bool
false
service:
struct
{"port": 80}
service: port:
int
80