`gcloud auth application-default unset-quota-project`
gcloud auth application-default includes a sub-command gcloud auth application-default set-quota-project
Unlike the similar gcloud config set and gcloud config unset pair, there’s no unset-quota-project.
However, it’s straightforward to undo set-quota-project because it’s primary side-effect is to update ${HOME}/.config/gcloud/application_default_credentials.json]
gcloud auth application-default set-quota-project ${PROJECT} \
--log-http
Request:
uri: https://cloudresourcemanager.googleapis.com/v1/projects/{PROJECT}:testIamPermissions?alt=json
method: POST
== headers start ==
b'accept': b'application/json'
b'authorization': --- Token Redacted ---
b'content-type': b'application/json'
b'x-goog-user-project': b'{PROJECT}'
== headers end ==
== body start ==
{"permissions": ["serviceusage.services.use"]}
== body end ==
Response:
Visual Studio workspace-specific settings and proto path
I use Pbkit for Protobuf support. There are other extensions available.
I’d experienced problems with the tool when (correctly) import‘ing protobufs under a proto_path and learned that there’s a solution and also learned that it’s possible to use workspace-specific settings.
With a ${workspaceFolder}/protos folder containing:
protos
└── greet
├── v1
│ └── greet.proto
└── v2
└── greet.proto
And, in which protos/greet/v2/greet.proto contains:
import "greet/v1/greet.proto";
I had been receiving import and reference errors until I read the Stack overflow answer.
Ingress contains no valid backends
Using MicroK8s with the new observability addon which uses Helm to install kube-prometheus.
This results in various Resources including several Service’s:
kubectl get services \
--namespace=observability
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP
kube-prom-stack-kube-prome-alertmanager ClusterIP 10.152.183.201 <none> 9093/TCP
kube-prom-stack-kube-prome-operator ClusterIP 10.152.183.44 <none> 443/TCP
kube-prom-stack-kube-prome-prometheus ClusterIP 10.152.183.206 <none> 9090/TCP
kube-prom-stack-kube-state-metrics ClusterIP 10.152.183.126 <none> 8080/TCP
prometheus-operated ClusterIP None <none> 9090/TCP
I’m using Tailscale Kubernetes Operator to expose MicroK8s services using Ingress to my tailnet.
Rust dependencies
I was having an issue with k8s-openapi complaining:
None of the v1_* features are enabled on the k8s-openapi crate.
The k8s-openapi crate requires a feature to be enabled to indicate which version of Kubernetes it should support.
If you’re using k8s-openapi in a binary crate, enable the feature corresponding to the minimum version of API server that you want to support. In case your binary crate does not directly depend on k8s-openapi, add a dependency on k8s-openapi and enable the corresponding feature in it.
kubectl patch'ing keys containing forward slash
I wanted to use kubectl to (JSON) patch an Ingress. The value needing patching is an annotation tailscale.com/funnel.
TL;DR The Stack overflow answer has the solution: replace
/with~1
With apologies for using YAML instead of JSON:
Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
tailscale.com/funnel: "true"
The solution becomes:
VALUE="true" # Or "false"
# Pretty-printed for clarity
PATCH="
[
{
'op':'replace',
'path':'/metadata/annotations/tailscale.com~1funnel',
'value':'${VALUE}'
}
]"
kubectl patch ingress/${INGRESS} \
--namespace=${NAMESPACE} \
--context=${CONTEXT} \
--type=json \
--patch="${PATCH}"
`kubectl` auth changes in GKE v1.25
I was prompted by a question on Stack overflow “How to remove warning in kubectl with gcp auth plugin?” to try this new mechanism for myself. It’s described by Google in the a post Here’s what to know about changes to kubectl authentciation coming in GKE v1.25.
One question I’d not considered is: how is the change manifest? Thinking about it, I realized it’s probably evident in the users section of kubectl config. A long time, I wrote a blog post Kubernetes Engine: kubectl config that explains how kubectl leverages (!) gcloud to get an access token for GKE.
Protect against accidental GCP Project Deletion
I’d forgotten about this feature but it’s a good way of protecting Google Cloud Platform (GCP) Projects against accidential (== user error) deletions.
Google documents it Protecting projects from accidental deletion
I’d forgotten that I’d applied it to a key project and then had to Google the above to recall how it works.
PROJECTs=$(gcloud projects list --format="value(projectId)")
for PROJECT in ${PROJECTS}
do
gcloud alpha resource-manager liens list \
--project=${PROJECT}
done
Simply:
`gcloud` list of results into result list
Occasionally, I want to be able to take multiline results from a gcloud command and map these onto something else. Most recently, I wanted to turn the results into a repeated list of flags.
E.g.:
From a list of Project IDs
gcloud projects list --format='value(projectId)'
Into --project=${A},--project=${B},...--project=${Z}
For posterity, one way to do this is to combine gcloud’s value (which is csv[no-headings]), replacing the default newline (\n) terminator with e.g. ,, and using gcloud’s format projection which works like (its underlying) Python format command:
`kubectl get events`
NAMESPACE=test
kubectl create namespace ${NAMESPACE}
kubectl create deployment kuard \
--image=gcr.io/kuar-demo/kuard-amd64:blue \
--port=8080 \
--namespace=${NAMESPACE}
Typically, I’d then use kubectl describe pod to check the Events section for any issues:
kubectl describe pod \
--selector=app=kuard \
--namespace=test
But, from the Pod’s name (without the pod/ prefix), you can:
NAME=$(\
kubectl get pod \
--selector=app=kuard \
--namespace=test \
--output=name) && \
NAME=${NAME#pod/} && \
echo ${NAME}
kubectl get events \
--field-selector=involvedObject.name=${NAME} \
--namespace=${NAMESPACE} \
--output=jsonpath='{range .items[*]}{.message}{"\n"}{end}'
NOTE
range‘ing over the items permits adding newlines (\n) after each entry. Using{.items[*].message}yields a less manageable result.
bash loops with multi-statement conditions
I wanted to pause a script until the status of 2 Cloud Run services became ready. In this case, I wanted to check for the status condition RoutesReady to be True.
My initial attempt is ghastly:
while [[ "True"!=$(gcloud run services describe ...) && "True"!=$(gcloud run service describe ...)]]
do
...
loop
NOTE In actuality, is was worse than that because I had
--projectand--regionflags and pumped the result throughjq
I found an interesting comment by jonathan-leffler on this Stack overflow answer suggesting that the condition in bash loops could actually be an (arbitrarily?) complex sequence of commands as long as the final statement returns true. Thanks Jonathan!