The other day I came across this post about bash. If you are a pro bash user, you may already know all these tricks, but if you are a newbie or not such a pro user, it is very likely that the post made your day.

I thought it would be useful to create something similar for the oc command. The oc command is dope, everyone should know that. It’s well designed, consistent, flexible, and, as you will see, there are many hidden features worth trying.

If you are an OpenShift pro, you may already know most of what I’ll reveal here; otherwise, if you are just starting to work with OpenShift, or you are not an experienced user, this is gonna save you some precious time and pain.

1. First things first: debugging

When I don't know what is going on or I get an unfriendly error message, I always use the flag --loglevel. It writes log level info to the stderr. Depending on the loglevel, you will get curl API Rest calls, API Rest body answers, or even more detailed info.
more detailed info

$ oc --loglevel 7 get pod
...
I0216 21:24:12.027793 973 cached_discovery.go:72] returning cached discovery info from /home/jtudelag/.kube/192.168.42.77_8443/v1/serverresources.json
I0216 21:24:12.028046 973 round_trippers.go:383] GET https://192.168.42.77:8443/api/v1/namespaces/myproject/pods
I0216 21:24:12.028052 973 round_trippers.go:390] Request Headers:
I0216 21:24:12.028057 973 round_trippers.go:393] Accept: application/json
I0216 21:24:12.028061 973 round_trippers.go:393] User-Agent: oc/v1.7.6+a08f5eeb62 (linux/amd64) kubernetes/c84beff
I0216 21:24:12.053230 973 round_trippers.go:408] Response Status: 200 OK in 25 milliseconds
I0216 21:24:12.055143 973 cached_discovery.go:119] returning cached discovery info from /home/jtudelag/.kube/192.168.42.77_8443/servergroups.json
I0216 21:24:12.055228 973 cached_discovery.go:72] returning cached discovery info from /home/jtudelag/.kube/192.168.42.77_8443/authentication.k8s.io/v1/serverresources.json
I0216 21:24:12.055288 973 cached_discovery.go:72]
...

loglevel 9 is pretty handy if you want to patch an OCP object, as it shows the patch (API request body) you would need to apply.
Let's say you want to change the label of a service object, in this case, the label "app: hello-jorge".

$ oc --loglevel 9 edit svc hello-openshift
...
I0216 21:33:15.786463 1389 request.go:994] Request Body: {"metadata":{"labels":{"app":"hello-jorge"}}}
I0216 21:33:15.786590 1389 round_trippers.go:386] curl -k -v -XPATCH -H "Accept: application/json" -H "Content-Type: application/strategic-merge-patch+json" -H "User-Agent: oc/v1.7.6+a08f5eeb62 (linux/amd64) kubernetes/c84beff" https://192.168.42.77:8443/api/v1/namespaces/myproject/services/hello-openshift
I0216 21:33:15.797185 1389 round_trippers.go:405] PATCH https://192.168.42.77:8443/api/v1/namespaces/myproject/services/hello-openshift 200 OK in 10 milliseconds
...

Note: In moments of despair you can always add as many 9s as you want, the result would be the same as just one 9, but you might feel relieved.

$ oc --loglevel 9999 get pod

2. su -

Yes, you are reading right. You can substitute the user who is running the oc command, or in OCP jargon, you can impersonate a user. If you have enough permissions to impersonate, obviously. You only need to use the flag --as.

For example:

# run the command as jorge user
$ oc --as=jorge get pods

Also, a group impersonation can be done, instead of a user impersonation:

# run the command as the developers group
$ oc --as-group=developers get pods

It’s very handy and quick in many situations, for example, to check if a user can perform a specific action or to check the output a user would receive when running oc. It’s also useful when messing with roles and permissions.

3. Whoami ?

oc whoami is widely known, especially the -t flag used to get the bearer token of your current user/session. But what happens when you have a token and you don't who is the owner?

One thing you can do is log into OpenShift with the token, and then do an oc whoami...but wait a second. oc whoami gives you this information! Just pass the token in the command line as the 3rd arg, no flags needed.

Give it a try:

# save the token
$ token=$(oc whoami -t)

# get the owner of the token
$ oc whoami $token
jorge

4. oc debug

You can run a pod and get a shell. Sometimes it's useful to get an exact copy of a running pod configuration and troubleshoot it with a shell. This is the default behaviour.

Have a look at the oc debug options, you can run the container as root, or any other user id, force it to run in a specific node or run a command different to a shell.

You have to run the command against a valid dc, for example:

# get a shell inside a pod for dc/jorge
$ oc debug dc/jorge

# same but as root user
$ oc debug --as-root=true dc/jorge

5. oc explain

OpenShift/k8s objects are sometimes complex, with many fields. Many times I end up looking for object definition examples in OCP docs or other sources. You can consider oc explain the source of truth when it comes to OCP/k8s object definitions.

oc explain gives you the documentation of a resource and its fields. It’s incredibly useful when declaring new OCP objects, or when you just don’t have access to the official OCP docs.

For example, you can get pod documentation and pod spec affinity field description:

# get pod explanation
$ oc explain pod
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.

FIELDS:
metadata <Object>
Standard object's metadata. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata

spec <Object>
Specification of the desired behavior of the pod. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status

status <Object>
Most recently observed status of the pod. This data may not be up to date.
Populated by the system. Read-only. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status

apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources

kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds

# get pod spec affinity field
$ oc explain pod.spec.affinity
RESOURCE: affinity <Object>

DESCRIPTION:
If specified, the pod's scheduling constraints

Affinity is a group of affinity scheduling rules.

FIELDS:
nodeAffinity <Object>
Describes node affinity scheduling rules for the pod.

podAffinity <Object>
Describes pod affinity scheduling rules (e.g. co-locate this pod in the
same node, zone, etc. as some other pod(s)).

podAntiAffinity <Object>
Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
in the same node, zone, etc. as some other pod(s)).

6. Forget about grep, awk, cut, etc.

One really cool thing about oc command is that it has built-in features to format the output. We all know about -o json or -o yaml, but the -o flag gives you many other possibilities.

From all of these output options I find go-template and jsonpath the most powerful:

json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...

For example, let's say you want to get the service that is being exposed by a specific route (docker registry route):

# get the service being exposed by a route, only if the hostname matches my-docker-registry.example.com
$ oc get routes -o=go-template='{{range .items}}{{if eq .spec.host "my-docker-registry.example.com"}}{{.metadata.name}}{{end}}{{end}}'
docker-registry

Or that you want to know the deployment strategy for the router dc:

# get router deployment strategy
$ oc get dc router -o=go-template='{{ .spec.strategy.type }}'
Rolling

As you can see, the oc command is awesome. I encourage you to keep playing with it, because is one of the coolest things about OpenShift.

Author

Jorge Tudela Gonzalez de Riancho works for Red Hat Spain as a Cloud Consultant specialising in OpenShift and container-related technologies.