Skip to content

Commit

Permalink
Hack: Delete instances when jobs finish
Browse files Browse the repository at this point in the history
Hack because we send the request to every zone
  • Loading branch information
drakon64 committed Dec 6, 2024
1 parent c1e914b commit cc67409
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 109 deletions.
21 changes: 21 additions & 0 deletions Clients/GoogleClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,25 @@ public static async Task CreateInstance(Instance instance, string project, strin

await Console.Out.WriteLineAsync(await request.Content.ReadAsStringAsync());
}

public static async Task DeleteInstance(string instance, string project, string zone)
{
var accessToken = await GetAccessToken();

var request = await HttpClient.SendAsync(
new HttpRequestMessage
{
Method = HttpMethod.Delete,
Headers =
{
{ "Authorization", $"{accessToken!.TokenType} {accessToken.AccessToken}" },
},
RequestUri = new Uri(
$"https://compute.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances/{instance}"
),
}
);

await Console.Out.WriteLineAsync(await request.Content.ReadAsStringAsync());
}
}
239 changes: 130 additions & 109 deletions EventProcessors/GitHubWebhookEventProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,135 +29,156 @@ await Console.Out.WriteLineAsync(
return;
}

if (workflowJobEvent.Action != "queued")
{
await Console.Out.WriteLineAsync("Workflow action is not `queued`.");

return;
}

if (!workflowJobEvent.WorkflowJob.Labels.Contains("ktisis"))
{
await Console.Out.WriteLineAsync("Workflow is not set to use Ktisis.");

return;
}

var machineType = "n4-standard-4";
var disk = "14";
var architecture = "amd64";
var runnerArchitecture = "x64";
var zone = Program.Zones[Random.Next(Program.Zones.Length)];

switch (workflowJobEvent.Action)
{
var setMachineType = false;
var setDisk = false;
var setArchitecture = false;

foreach (var label in workflowJobEvent.WorkflowJob.Labels)
case "queued":
{
if (label.StartsWith("ktisis-"))
var machineType = "n4-standard-4";
var disk = "14";
var architecture = "amd64";
var runnerArchitecture = "x64";
var zone = Program.Zones[Random.Next(Program.Zones.Length)];

{
var ktisis = label.Replace("ktisis-", "");
var setMachineType = false;
var setDisk = false;
var setArchitecture = false;

if (label.EndsWith("GB"))
foreach (var label in workflowJobEvent.WorkflowJob.Labels)
{
disk = ktisis.Replace("GB", "");
setDisk = true;
}
else
{
machineType = ktisis;
setMachineType = true;
}
}
else
switch (label)
{
case "x64":
architecture = "amd64";
runnerArchitecture = "x64";
setArchitecture = true;
break;
case "ARM64":
architecture = "arm64";
runnerArchitecture = "arm64";
setArchitecture = true;
if (label.StartsWith("ktisis-"))
{
var ktisis = label.Replace("ktisis-", "");

if (label.EndsWith("GB"))
{
disk = ktisis.Replace("GB", "");
setDisk = true;
}
else
{
machineType = ktisis;
setMachineType = true;
}
}
else
switch (label)
{
case "x64":
architecture = "amd64";
runnerArchitecture = "x64";
setArchitecture = true;
break;
case "ARM64":
architecture = "arm64";
runnerArchitecture = "arm64";
setArchitecture = true;
break;
}

if (setMachineType && setDisk && setArchitecture)
{
break;
}
}

if (setMachineType && setDisk && setArchitecture)
{
break;
}
}
}

await GoogleClient.CreateInstance(
new Instance
{
Name =
$"{workflowJobEvent.Repository!.FullName.Replace('/', '-')}-{workflowJobEvent.WorkflowJob.RunId}-{workflowJobEvent.WorkflowJob.Id}",
MachineType = $"projects/{Program.Project}/zones/{zone}/machineTypes/{machineType}",
Disks =
[
new Disk
await GoogleClient.CreateInstance(
new Instance
{
Boot = true,
InitializeParams = new DiskInitializeParams(zone)
Name =
$"{workflowJobEvent.Repository!.FullName.Replace('/', '-')}-{workflowJobEvent.WorkflowJob.RunId}-{workflowJobEvent.WorkflowJob.Id}",
MachineType =
$"projects/{Program.Project}/zones/{zone}/machineTypes/{machineType}",
Disks =
[
new Disk
{
Boot = true,
InitializeParams = new DiskInitializeParams(zone)
{
DiskSizeGb = disk,
SourceImage =
$"projects/ubuntu-os-cloud/global/images/ubuntu-minimal-2404-noble-{architecture}-v20241116", // TODO: Don't hardcode this
},
},
new Disk
{
DeviceName = "swap",
InitializeParams = new DiskInitializeParams(zone)
{
DiskSizeGb = "16",
},
},
],
Metadata = new Metadata
{
DiskSizeGb = disk,
SourceImage =
$"projects/ubuntu-os-cloud/global/images/ubuntu-minimal-2404-noble-{architecture}-v20241116", // TODO: Don't hardcode this
Items =
[
new MetadataItem { Key = "enable-oslogin", Value = "true" },
new MetadataItem { Key = "enable-oslogin-2fa", Value = "true" },
new MetadataItem
{
Key = "startup-script",
Value = $"""
#!/bin/sh -ex
sysctl vm.swappiness=1
mkswap /dev/disk/by-id/google-swap
swapon /dev/disk/by-id/google-swap
curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
bash add-google-cloud-ops-agent-repo.sh --also-install
rm add-google-cloud-ops-agent-repo.sh
adduser --home /runner --shell /bin/sh runner
echo '%runner ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/runner
cd /runner
wget https://github.com/actions/runner/releases/download/v2.321.0/actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
tar xf actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
rm actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
sudo -u runner ./config.sh --url https://github.com/{workflowJobEvent.Repository!.FullName} --token {(await Program.GitHubClient.CreateRunnerRegistrationToken(
workflowJobEvent.Repository!.FullName,
workflowJobEvent.Installation!.Id
)).Token} --ephemeral --labels ktisis,ktisis-{machineType},ktisis-{disk}GB
./svc.sh install runner
./svc.sh start
""",
},
],
},
},
new Disk
{
DeviceName = "swap",
InitializeParams = new DiskInitializeParams(zone) { DiskSizeGb = "16" },
},
],
Metadata = new Metadata
Program.Project,
zone
);
break;
}
case "completed":
{
var instance = workflowJobEvent.WorkflowJob.RunnerName!;

// TODO: Get the instance zone rather than brute-forcing
foreach (var zone in Program.Zones)
{
Items =
[
new MetadataItem { Key = "enable-oslogin", Value = "true" },
new MetadataItem { Key = "enable-oslogin-2fa", Value = "true" },
new MetadataItem
{
Key = "startup-script",
Value = $"""
#!/bin/sh -ex
sysctl vm.swappiness=1
mkswap /dev/disk/by-id/google-swap
swapon /dev/disk/by-id/google-swap
curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
bash add-google-cloud-ops-agent-repo.sh --also-install
rm add-google-cloud-ops-agent-repo.sh
adduser --home /runner --shell /bin/sh runner
echo '%runner ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/runner
cd /runner
wget https://github.com/actions/runner/releases/download/v2.321.0/actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
tar xf actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
rm actions-runner-linux-{runnerArchitecture}-2.321.0.tar.gz
sudo -u runner ./config.sh --url https://github.com/{workflowJobEvent.Repository!.FullName} --token {(await Program.GitHubClient.CreateRunnerRegistrationToken(
workflowJobEvent.Repository!.FullName,
workflowJobEvent.Installation!.Id
)).Token} --ephemeral --labels ktisis,ktisis-{machineType},ktisis-{disk}GB
./svc.sh install runner
./svc.sh start
""",
},
],
},
},
Program.Project,
zone
);
await GoogleClient.DeleteInstance(instance, Program.Project, zone);
}

break;
}
default:
await Console.Out.WriteLineAsync(
"Workflow action is not `queued` nor `completed`."
);
break;
}
}
}

0 comments on commit cc67409

Please sign in to comment.