Publish AMI artifact IDs to SSM
This commit is contained in:
@@ -58,6 +58,14 @@ The final AMI is tagged with:
|
||||
- `NixSnapshotId`
|
||||
- `NixosSystemClosure`
|
||||
|
||||
The publisher also writes SSM parameters that point to the AMI ID:
|
||||
|
||||
- `/quixos/amis/<name>/<architecture>/recommended`
|
||||
- `/quixos/amis/<name>/<architecture>/by-builder-rev/<rev>`
|
||||
- `/quixos/amis/<name>/<architecture>/by-input-hash/<hash>`
|
||||
|
||||
Central services read the `recommended` parameter by default.
|
||||
|
||||
Do not deregister the AMI or delete either snapshot while runtime deployments
|
||||
use it.
|
||||
|
||||
@@ -69,6 +77,13 @@ List published AMIs and cross-reference qx-deploy runtime registry records:
|
||||
nix run ./tofu/ami-builder#ami-artifacts -- list
|
||||
```
|
||||
|
||||
Publish SSM parameters for an existing AMI, useful for AMIs created before SSM
|
||||
publication was added:
|
||||
|
||||
```bash
|
||||
nix run ./tofu/ami-builder#ami-artifacts -- publish-ssm --ami-id ami-...
|
||||
```
|
||||
|
||||
Delete an unused AMI and its root and `/nix` snapshots:
|
||||
|
||||
```bash
|
||||
|
||||
+74
-3
@@ -10,14 +10,15 @@ const repoRoot = process.env.QUIXOS_REPO_ROOT ?? path.resolve(sourceScriptDir, "
|
||||
const amiBuilderDir = process.env.QUIXOS_AMI_BUILDER_DIR ?? path.resolve(repoRoot, "tofu/ami-builder");
|
||||
const centralDir = path.resolve(amiBuilderDir, "../central");
|
||||
|
||||
const usage = `Usage: nix run ./tofu/ami-builder#ami-artifacts -- <list|delete> [options]
|
||||
const usage = `Usage: nix run ./tofu/ami-builder#ami-artifacts -- <list|delete|publish-ssm> [options]
|
||||
|
||||
Commands:
|
||||
list List published AMI artifacts and deployment references
|
||||
delete --ami-id <ami> Deregister an AMI and delete its root and /nix snapshots
|
||||
publish-ssm --ami-id <ami> Publish an existing AMI into the SSM artifact registry
|
||||
|
||||
Options:
|
||||
--ami-id <ami> AMI to delete
|
||||
--ami-id <ami> AMI to operate on
|
||||
--aws-region <region> AWS region (default: AWS_REGION or us-west-2)
|
||||
--name <name> AMI project tag (default: nixos-zfs-ec2)
|
||||
--architecture <arm64|x86_64> Filter by architecture
|
||||
@@ -62,7 +63,7 @@ const parseArgs = (argv) => {
|
||||
console.error(usage.trimEnd());
|
||||
process.exit(command ? 0 : 1);
|
||||
}
|
||||
if (command !== "list" && command !== "delete") {
|
||||
if (command !== "list" && command !== "delete" && command !== "publish-ssm") {
|
||||
throw new Error(`Unknown command: ${command}\n\n${usage}`);
|
||||
}
|
||||
|
||||
@@ -287,6 +288,72 @@ const deleteArtifact = (state) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getImage = (state) => {
|
||||
const result = awsJson([
|
||||
"ec2",
|
||||
"describe-images",
|
||||
"--region",
|
||||
state.awsRegion,
|
||||
"--owners",
|
||||
"self",
|
||||
"--image-ids",
|
||||
state.amiId,
|
||||
]);
|
||||
const image = result?.Images?.[0];
|
||||
if (!image) {
|
||||
throw new Error(`AMI not found: ${state.amiId}`);
|
||||
}
|
||||
return image;
|
||||
};
|
||||
|
||||
const putSsmParameter = (state, name, value) => {
|
||||
run("aws", [
|
||||
"ssm",
|
||||
"put-parameter",
|
||||
"--region",
|
||||
state.awsRegion,
|
||||
"--name",
|
||||
name,
|
||||
"--type",
|
||||
"String",
|
||||
"--value",
|
||||
value,
|
||||
"--overwrite",
|
||||
]);
|
||||
};
|
||||
|
||||
const publishSsmArtifact = (state) => {
|
||||
if (!state.amiId) {
|
||||
throw new Error("Missing --ami-id");
|
||||
}
|
||||
|
||||
const image = getImage(state);
|
||||
const tags = amiTags(image);
|
||||
const architecture = tags.Architecture ?? image.Architecture ?? "";
|
||||
const builderGitRev = tags.BuilderGitRev ?? "";
|
||||
const inputHash = tags.InputHash ?? "";
|
||||
if (!architecture) {
|
||||
throw new Error(`AMI ${state.amiId} is missing Architecture metadata`);
|
||||
}
|
||||
if (!builderGitRev) {
|
||||
throw new Error(`AMI ${state.amiId} is missing BuilderGitRev tag`);
|
||||
}
|
||||
if (!inputHash) {
|
||||
throw new Error(`AMI ${state.amiId} is missing InputHash tag`);
|
||||
}
|
||||
|
||||
const prefix = `/quixos/amis/${state.name}/${architecture}`;
|
||||
const parameters = [
|
||||
`${prefix}/recommended`,
|
||||
`${prefix}/by-builder-rev/${builderGitRev}`,
|
||||
`${prefix}/by-input-hash/${inputHash}`,
|
||||
];
|
||||
for (const parameter of parameters) {
|
||||
console.error(`Writing ${parameter} = ${state.amiId}`);
|
||||
putSsmParameter(state, parameter, state.amiId);
|
||||
}
|
||||
};
|
||||
|
||||
const main = () => {
|
||||
const state = parseArgs(process.argv.slice(2));
|
||||
requireCommand("aws");
|
||||
@@ -296,6 +363,10 @@ const main = () => {
|
||||
listArtifacts(state);
|
||||
return;
|
||||
}
|
||||
if (state.command === "publish-ssm") {
|
||||
publishSsmArtifact(state);
|
||||
return;
|
||||
}
|
||||
deleteArtifact(state);
|
||||
};
|
||||
|
||||
|
||||
+18
-1
@@ -271,6 +271,20 @@ aws ec2 create-tags \
|
||||
"Key=RootSnapshotId,Value=${root_snapshot_id}" \
|
||||
"Key=NixSnapshotId,Value=${nix_snapshot_id}"
|
||||
|
||||
ssm_ami_prefix="/quixos/amis/${name}/${architecture}"
|
||||
for ssm_ami_parameter_name in \
|
||||
"${ssm_ami_prefix}/recommended" \
|
||||
"${ssm_ami_prefix}/by-builder-rev/${builder_git_rev}" \
|
||||
"${ssm_ami_prefix}/by-input-hash/${input_hash}"
|
||||
do
|
||||
aws ssm put-parameter \
|
||||
--region "$aws_region" \
|
||||
--name "$ssm_ami_parameter_name" \
|
||||
--type String \
|
||||
--value "$image_id" \
|
||||
--overwrite >/dev/null
|
||||
done
|
||||
|
||||
aws ec2 deregister-image --region "$aws_region" --image-id "$capture_image_id" >/dev/null
|
||||
|
||||
jq -n \
|
||||
@@ -285,6 +299,7 @@ jq -n \
|
||||
--arg rootDeviceName "$root_device_name" \
|
||||
--arg nixDeviceName "$nix_device_name" \
|
||||
--arg nixPool "$nix_pool" \
|
||||
--arg ssmRecommendedParameter "${ssm_ami_prefix}/recommended" \
|
||||
'{
|
||||
architecture: $architecture,
|
||||
system: $system,
|
||||
@@ -296,7 +311,8 @@ jq -n \
|
||||
nixSnapshotId: $nixSnapshotId,
|
||||
rootDeviceName: $rootDeviceName,
|
||||
nixDeviceName: $nixDeviceName,
|
||||
nixPool: $nixPool
|
||||
nixPool: $nixPool,
|
||||
ssmRecommendedParameter: $ssmRecommendedParameter
|
||||
}' > artifact.json
|
||||
|
||||
if [ "$keep_builder" = false ]; then
|
||||
@@ -313,3 +329,4 @@ if [ "$keep_builder" = false ]; then
|
||||
fi
|
||||
|
||||
echo "Published AMI: $image_id"
|
||||
echo "Published SSM parameter: ${ssm_ami_prefix}/recommended"
|
||||
|
||||
Reference in New Issue
Block a user