Skip to content

Instantly share code, notes, and snippets.

@pj
Created February 16, 2022 16:19
Show Gist options
  • Save pj/ab580d14b3f83d8af907485faceaeed1 to your computer and use it in GitHub Desktop.
Save pj/ab580d14b3f83d8af907485faceaeed1 to your computer and use it in GitHub Desktop.
Script to stop GKE formatting local SSDs when initializing a node.
import compute, { protos } from '@google-cloud/compute';
import axios from 'axios';
import util from 'util';
import * as child_process from 'child-process-promise'
import { ZoneOperationsClient } from '@google-cloud/compute/build/src/v1';
import { sleep } from '../utils';
import { hasUncaughtExceptionCaptureCallback } from 'process';
type InstanceTemplate = protos.google.cloud.compute.v1.IInstanceTemplate;
type InstanceGroupManager = protos.google.cloud.compute.v1.IInstanceGroupManager;
type Operation = protos.google.cloud.compute.v1.Operation;
async function waitForOperation(operation: any) {
const operationsClient = new compute.ZoneOperationsClient();
while (operation.status !== 'DONE') {
[operation] = await operationsClient.wait({
operation: operation.name,
project: process.env.GCP_PROJECT,
zone: operation.zone.split('/').pop(),
});
console.log("-------")
console.log(util.inspect(operation, {depth: null}))
if (operation.error) {
console.error(operation.error);
throw new Error(`Operation has errrored:\n${util.inspect(operation, {depth: null})}`)
}
}
console.log('Operation finished.');
}
async function duplicateTemplate(existingTemplate: InstanceTemplate) {
existingTemplate.name = `${existingTemplate.name}-modified`
for (const item of existingTemplate.properties.metadata.items) {
if (item.key === "kube-env") {
item.value = item.value.replace(`NODE_LOCAL_SSDS_EPHEMERAL: "true"`, `NODE_LOCAL_SSDS_EPHEMERAL: "false"`);
}
}
delete existingTemplate.creationTimestamp
delete existingTemplate.id
delete existingTemplate.kind
delete existingTemplate.selfLink
delete existingTemplate.properties["shieldedVmConfig"]
delete existingTemplate.properties.metadata.kind
existingTemplate.properties.networkInterfaces.forEach(ni => {
delete ni.name;
delete ni.kind;
ni.accessConfigs.forEach(ac => {
delete ac.kind
});
});
existingTemplate.properties.disks.forEach(d => {
delete d.index
delete d.kind
delete d.initializeParams["guestOsFeatures"]
})
const {stdout} = await child_process.exec("gcloud auth print-access-token");
await axios.post(
`https://compute.googleapis.com/compute/v1/projects/${process.env.GCP_PROJECT}/global/instanceTemplates`,
existingTemplate,
{
headers: {
"Authorization": `Bearer ${stdout.trim()}`
}
}
);
}
async function updateInstanceGroup(existingTemplate: InstanceTemplate) {
const instanceGroupClient = new compute.InstanceGroupManagersClient();
const instanceGroups = instanceGroupClient.listAsync({project: process.env.GCP_PROJECT, zone: "us-west1-a"});
let replayGroup: InstanceGroupManager;
for await (const instanceGroup of instanceGroups) {
if (instanceGroup.name.includes("replay")) {
replayGroup = instanceGroup;
if (replayGroup.instanceTemplate.includes("modified")) {
console.log(`Replay group already has template`);
return;
}
break;
}
}
if (!replayGroup) {
throw new Error("Replay group not found");
}
console.log(existingTemplate.name);
const response = await instanceGroupClient.setInstanceTemplate(
{
project: process.env.GCP_PROJECT,
instanceGroupManager: replayGroup.name,
instanceGroupManagersSetInstanceTemplateRequestResource: {
instanceTemplate: `projects/${process.env.GCP_PROJECT}/global/instanceTemplates/${existingTemplate.name}`
},
zone: "us-west1-a"
}
);
console.log(util.inspect(response, {depth: null}))
await waitForOperation(response[0].latestResponse);
}
(async() => {
const instanceTemplatesClient = new compute.InstanceTemplatesClient();
const templates = instanceTemplatesClient.listAsync({project: process.env.GCP_PROJECT});
let existingTemplate: InstanceTemplate;
let existingModified: InstanceTemplate;
for await (const template of templates) {
if (template.name.includes("modified")) {
// console.log(`Modified template exists: ${template.name}`);
// await updateInstanceGroup(template);
existingModified = template;
} else if (template.name.includes("replay")) {
existingTemplate = template;
}
}
if (!existingTemplate) {
throw new Error("Replay template not found");
}
if (existingModified && existingModified.name === `${existingTemplate.name}-modified`) {
console.log("Existing modified template already exists, updating instance group");
await updateInstanceGroup(existingModified);
return;
}
await duplicateTemplate(existingTemplate)
await updateInstanceGroup(existingTemplate);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment