oc plugins to simplify reproducers

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 ...`

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

To view or add a comment, sign in

Others also viewed

Explore content categories