m/cli/metroctl: transition node platform

Add a platform transition to the node binary data dependencies of
metroctl. These binaries always need to be built for linux.
Additionally, the user may want to build them for a different
architecture than metroctl, which is possible with the new node_arch
flag. If the flag is not set, the architecture is inherited.

Change-Id: If4a15146392dfbc48c8e13db3bfb131f32176559
Reviewed-on: https://review.monogon.dev/c/monogon/+/4190
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/metropolis/cli/metroctl/BUILD.bazel b/metropolis/cli/metroctl/BUILD.bazel
index 65b8e8a..f300f44 100644
--- a/metropolis/cli/metroctl/BUILD.bazel
+++ b/metropolis/cli/metroctl/BUILD.bazel
@@ -1,3 +1,5 @@
+load("@aspect_bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
+load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
 load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
 load(":defs.bzl", "buildkind")
 
@@ -14,6 +16,42 @@
     },
 )
 
+# By default, the architecture for node binaries is inherited from the metroctl
+# binary, but it can be changed with this flag.
+# Example: --//metropolis/cli/metroctl:node_arch=x86_64
+string_flag(
+    name = "node_arch",
+    build_setting_default = "",
+    values = [
+        "",
+        "x86_64",
+        "aarch64",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+config_setting(
+    name = "node_arch_x86_64",
+    flag_values = {":node_arch": "x86_64"},
+)
+
+config_setting(
+    name = "node_arch_aarch64",
+    flag_values = {":node_arch": "aarch64"},
+)
+
+config_setting(
+    name = "node_arch_inherit_x86_64",
+    constraint_values = ["@platforms//cpu:x86_64"],
+    flag_values = {":node_arch": ""},
+)
+
+config_setting(
+    name = "node_arch_inherit_aarch64",
+    constraint_values = ["@platforms//cpu:aarch64"],
+    flag_values = {":node_arch": ""},
+)
+
 go_library(
     name = "metroctl_lib",
     srcs = [
@@ -73,15 +111,32 @@
     ],
 )
 
+platform_transition_filegroup(
+    name = "node_arch_deps",
+    srcs = [
+        "//metropolis/cli/takeover",
+        "//metropolis/installer:kernel",
+        "//metropolis/node:oci_image",
+    ],
+    target_platform = select(
+        {
+            ":node_arch_x86_64": "//build/platforms:linux_x86_64",
+            ":node_arch_aarch64": "//build/platforms:linux_aarch64",
+            ":node_arch_inherit_x86_64": "//build/platforms:linux_x86_64",
+            ":node_arch_inherit_aarch64": "//build/platforms:linux_aarch64",
+        },
+        no_match_error = """
+        Metropolis Node does not support this architecture.
+        Specify a supported architecture with the node_arch flag.""",
+    ),
+    visibility = ["//visibility:private"],
+)
+
 go_binary(
     name = "metroctl",
     data = select({
         ":buildkind_lite": [],
-        "//conditions:default": [
-            "//metropolis/cli/takeover",
-            "//metropolis/installer:kernel",
-            "//metropolis/node:oci_image",
-        ],
+        "//conditions:default": [":node_arch_deps"],
     }),
     embed = [":metroctl_lib"],
     visibility = ["//visibility:public"],