Skip to content

Instantly share code, notes, and snippets.

@hermanbanken
Last active December 12, 2021 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hermanbanken/ab3be80e3512d540b772733024c127cb to your computer and use it in GitHub Desktop.
Save hermanbanken/ab3be80e3512d540b772733024c127cb to your computer and use it in GitHub Desktop.
Cloud Function for GKE upgrade notifications

We want to receive notifications when a Kubernetes cluster upgrades. For this we can configure PubSub subscriptions:

const exec = require("child_process").execSync;

const mapping = {
  "my-dev-project": [{ name: "clusterA", region: "europe-west4" }, { name: "clusterB", region: "us-east1" }],
  "my-prod-project": [{ name: "clusterC", region: "europe-west4" }, { name: "clusterD", region: "us-east1" }],
};

for (const PROJECT in mapping) {
  exec(`gcloud pubsub topics create k8s-upgrades --project=${PROJECT}`)
  for (const { name: CLUSTERNAME, region: REGION } of mapping[project]) {
    exec(`gcloud container clusters update ${CLUSTERNAME} --notification-config=pubsub=ENABLED,pubsub-topic=projects/${PROJECT}/topics/k8s-upgrades --region=${REGION}`);
  }
}

And a Cloud Function to notify us on Slack:

printf "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX" | gcloud secrets create K8S_UPGRADES_SLACK_WEBHOOK_URL --data-file=-
gcloud functions deploy k8s-upgrades \
  --runtime=nodejs16 \
  --entryPoint=notify \
  --set-secrets 'SLACK_WEBHOOK_URL=K8S_UPGRADES_SLACK_WEBHOOK_URL:1' \
  --trigger-topic=k8s-upgrades
const https = require('https');
const url = require('url');
// Settings via environment
const slackWebhookURL = process.env.SLACK_WEBHOOK_URL; // e.g. 'https://hooks.slack.com/services/T0000/B0000/XXXXXXXXX';
/**
* Triggered from a message on a Cloud Pub/Sub topic.
* Converts event to Slack webhook.
*/
exports.notify = (event, context) => {
console.log({ event, context });
const slackRequest = https.request({
hostname: url.parse(slackWebhookURL).hostname,
method: 'POST',
path: url.parse(slackWebhookURL).path,
headers: { 'Content-Type': 'application/json' },
});
slackRequest.write(JSON.stringify(convertEvent(event, context)));
slackRequest.end();
};
/**
* Convert the PubSub event to Slack payload
* @param {!Object} event Event payload. Contains human-readable message in [data] and machine readable data in [attributes]
* @param {!Object} context Metadata for the event.
* @returns {Object} Slack message payload
*
* @docs https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-upgrade-notifications
* @docs https://github.com/shipwreckdev/gke-notification-handler/blob/main/main.py
*/
function convertEvent(event, context) {
const message = Buffer.from(event.data, "base64").toString("utf8");
const cluster = event["attributes"]["cluster_name"];
const location = event["attributes"]["cluster_location"];
const project = event["attributes"]["project"];
const payload = JSON.parse(event["attributes"]["payload"]);
// attributes.type_url = "type.googleapis.com/google.container.v1beta1.UpgradeEvent"
// attributes.type_url = "type.googleapis.com/google.container.v1beta1.UpgradeAvailableEvent"
const type_url = event["attributes"]["type_url"] || "";
const title = type_url.indexOf("UpgradeEvent") >= 0 || payload.operation
? "UpgradeEvent"
: "UpgradeAvailableEvent";
const text = `*${title}:*
${message}
*Project:* ${project}
*Cluster:* ${cluster}
*Location:* ${location}
${code("javascript", JSON.stringify(event, null, 2))}
`;
return { mrkdwn: true, text };
}
function code(lang, code) {
return "```" + lang + "\n" + code + "\n```";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment