Created
February 16, 2022 16:19
-
-
Save pj/ab580d14b3f83d8af907485faceaeed1 to your computer and use it in GitHub Desktop.
Script to stop GKE formatting local SSDs when initializing a node.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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