oc plugins to simplify reproducers
Kubernetes provides a nice and handsome feature to simplify reproducing or annoying tasks through cli.
As example we'll take a look at reproducers, GitOps dumps or showing CRD's to others. Most of the time when querying objects in the Kubernetes API, we get attributes or sections returned that are of no use or even just scrambling the whole screen.
Attributes and sections that are necessary for debugging or Operator tracking but not for sharing or showing necessary information to others.
As example, here's the metadata section of a simple deployment
$ oc -n demo get deployment test -o yaml | yq -r .metadata
annotations:
deployment.kubernetes.io/revision: "5"
creationTimestamp: "2024-04-19T08:21:54Z"
generation: 13
name: test
namespace: demo
resourceVersion: "165131330"
uid: b10acbc2-eb8d-40f1-b5e2-78ce205fdad5
We can identify some attributes which are not of importance and can be removed as they do not harm functionality of re-applying the CRD like
Right now, each of you comfortable with `yq` will be able to remove those attributes by piping it to `yq` and calling the `del` method like
$ oc -n demo get deployment test -o yaml | yq -r '.metadata| del(.annotations."deployment.kubernetes.io/revision") | del(.creationTimestamp) | del(.generation) | del(.resourceVersion) | del(.uid)'
annotations: {}
name: test
namespace: demo
Let's now take a look at oc plugins. oc plugins will provide a different way of doing so and even streamline that without the need to remember the piping syntax on even more complicated use-cases (like iterating over multiple items)
Therefor we are going to create a small bash script in /usr/local/bin or any user specific executeable searchpath ${PATH}
I'll call mine now `clean` so that my oc syntax will be `oc clean ...`
Recommended by LinkedIn
milang@tikibar:~$ cat <<EOF > /usr/local/bin/kubectl-clean
#!/bin/bash
cmd=$@
oc $@ -o yaml | yq -r '.metadata| del(.annotations."deployment.kubernetes.io/revision") | del(.creationTimestamp) | del(.generation) | del(.resourceVersion) | del(.uid)'
EOF
milang@tikibar:~$ chmod +x /usr/local/bin/kubectl-clean
with that done, we can now switch the piping to an more read-able and remember able command as follows
milang@tikibar:~$ oc clean -n demo get deployment test | yq -r .metadata
annotations: {}
name: test
namespace: demo
As mentioned before, that's a verif specific use-case focused on one particular resource so let's adjust the `kubectl-clean` script to a more generic version
#!/bin/bash
cmd=$@
oc $@ -o yaml | yq -r '
del(.items[]|.status) |
del(.status) |
del(.items[]|.metadata.resourceVersion) |
del(.metadata.resourceVersion) |
del(.items[]|.metadata.uid) |
del(.metadata.uid) |
del(.items[]|.metadata.generation) |
del(.metadata.generation) |
del(.items[]|.metadata.creationTimestamp) |
del(.metadata.creationTimestamp) |
del(.items[]|.metadata.ownerReferences) |
del(.metadata.ownerReferences) |
del(.items[]|
.metadata.annotations."kubectl.kubernetes.io/last-applied-configuration") |
del(.metadata.annotations."kubectl.kubernetes.io/last-applied-configuration") |
del(.items[]|.metadata.annotations."deployment.kubernetes.io/revision") |
del(.metadata.annotations."deployment.kubernetes.io/revision") |
del(.items[]|.spec.clusterIP) |
del(.spec.clusterIP) |
del(.items[]|.spec.clusterIPs) |
del(.spec.clusterIPs) ' | \
sed -e " s#${BASEDOMAIN:-.local}#example.com#g; "
Let me explain what will happen here. With the requirement to obfuscate sensitive data (and yes, domain names are considere sensitive) the `clean` plugin will remove unwanted annotations, not re-use able specs like clusterIP(s) and change any domain names identified through the bash environment variable `${BASEDOMAIN}` with `example.com`.
As example I will now dump and clean all ServiceMesh related resources and replace a Lab domain with `example.com`.
$ BASEDOMAIN=lab.io oc clean -n demo get \
destinationrules.networking.istio.io,serviceentries.networking.istio.io,virtualservices.networking.istio.io
apiVersion: v1
items:
- apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: egressgateway-for-mockbin-c1-ns1
namespace: demo
spec:
...
- apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
annotations: {}
name: se-mockbin-external
namespace: demo
spec:
hosts:
- mockbin-ns1.apps.example.com
- mockbin-ns2.apps.example.com
- mockbin-ns3.apps.example.com
- mockbin-ns4.apps.example.com
- mockbin-ns5.apps.example.com
....
spec:
gateways:
- oauth-gateway
hosts:
- oauth2.apps.example.com
tls:
- match:
- port: 443
sniHosts:
- oauth2.apps.example.com
route:
- destination:
host: oauth2
port:
number: 8080
kind: List
metadata: {}
Sure I could have piped it through the same `yq` as before manually but you need to admit, that this is a really nice way of cleaning up stuff and sharing it without sensitive data leakage to others.
Feel free to adjust or extend the list and functionality and ping me if you have a great idea on how to extend the use-case
Happy plugin writing