m/c/metroctl: add prototext node-params option
This adds the node-params flag to metroctl install, which allows
advanced users to specify customized NodeParameters in a prototext file.
The cluster field gets overwritten by the existing logic. As of now,
this is only useful for specifying network_config.
Change-Id: Ieccf208177bb49635a634e484c67e99e80792bda
Reviewed-on: https://review.monogon.dev/c/monogon/+/3700
Vouch-Run-CI: Lorenz Brun <lorenz@monogon.tech>
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/BUILD.bazel b/metropolis/cli/metroctl/BUILD.bazel
index 43805df..024b96c 100644
--- a/metropolis/cli/metroctl/BUILD.bazel
+++ b/metropolis/cli/metroctl/BUILD.bazel
@@ -61,6 +61,7 @@
"@io_k8s_client_go//pkg/apis/clientauthentication/v1:clientauthentication",
"@io_k8s_utils//ptr",
"@org_golang_google_grpc//:grpc",
+ "@org_golang_google_protobuf//encoding/prototext",
"@org_golang_google_protobuf//proto",
"@org_golang_google_protobuf//types/known/fieldmaskpb",
"@org_golang_x_crypto//ssh",
diff --git a/metropolis/cli/metroctl/cmd_install.go b/metropolis/cli/metroctl/cmd_install.go
index c40c9ed..9a996b2 100644
--- a/metropolis/cli/metroctl/cmd_install.go
+++ b/metropolis/cli/metroctl/cmd_install.go
@@ -11,6 +11,7 @@
"github.com/bazelbuild/rules_go/go/runfiles"
"github.com/spf13/cobra"
+ "google.golang.org/protobuf/encoding/prototext"
"source.monogon.dev/metropolis/proto/api"
cpb "source.monogon.dev/metropolis/proto/common"
@@ -35,6 +36,7 @@
var bootstrapTPMMode = flagdefs.TPMModePflag(installCmd.PersistentFlags(), "bootstrap-tpm-mode", cpb.ClusterConfiguration_TPM_MODE_REQUIRED, "TPM mode to set on cluster")
var bootstrapStorageSecurityPolicy = flagdefs.StorageSecurityPolicyPflag(installCmd.PersistentFlags(), "bootstrap-storage-security", cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION_AND_AUTHENTICATION, "Storage security policy to set on cluster")
var bundlePath = installCmd.PersistentFlags().StringP("bundle", "b", "", "Path to the Metropolis bundle to be installed")
+var nodeParamPath = installCmd.PersistentFlags().String("node-params", "", "Path to the metropolis.proto.api.NodeParameters prototext file (advanced usage only)")
func makeNodeParams() (*api.NodeParameters, error) {
ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
@@ -44,6 +46,18 @@
}
var params *api.NodeParameters
+ if *nodeParamPath != "" {
+ nodeParamsRaw, err := os.ReadFile(*nodeParamPath)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read node-params file: %w", err)
+ }
+ if err := prototext.Unmarshal(nodeParamsRaw, params); err != nil {
+ return nil, fmt.Errorf("failed to parse node-params: %w", err)
+ }
+ } else {
+ params = &api.NodeParameters{}
+ }
+
if *bootstrap {
if flags.cluster == "" {
return nil, fmt.Errorf("when bootstrapping a cluster, the --cluster parameter is required")
@@ -58,15 +72,13 @@
return nil, fmt.Errorf("failed to generate or get owner key: %w", err)
}
pub := priv.Public().(ed25519.PublicKey)
- params = &api.NodeParameters{
- Cluster: &api.NodeParameters_ClusterBootstrap_{
- ClusterBootstrap: &api.NodeParameters_ClusterBootstrap{
- OwnerPublicKey: pub,
- InitialClusterConfiguration: &cpb.ClusterConfiguration{
- ClusterDomain: flags.cluster,
- StorageSecurityPolicy: *bootstrapStorageSecurityPolicy,
- TpmMode: *bootstrapTPMMode,
- },
+ params.Cluster = &api.NodeParameters_ClusterBootstrap_{
+ ClusterBootstrap: &api.NodeParameters_ClusterBootstrap{
+ OwnerPublicKey: pub,
+ InitialClusterConfiguration: &cpb.ClusterConfiguration{
+ ClusterDomain: flags.cluster,
+ StorageSecurityPolicy: *bootstrapStorageSecurityPolicy,
+ TpmMode: *bootstrapTPMMode,
},
},
}
@@ -85,13 +97,11 @@
return nil, fmt.Errorf("while receiving cluster directory: %w", err)
}
- params = &api.NodeParameters{
- Cluster: &api.NodeParameters_ClusterRegister_{
- ClusterRegister: &api.NodeParameters_ClusterRegister{
- RegisterTicket: resT.Ticket,
- ClusterDirectory: resI.ClusterDirectory,
- CaCertificate: resI.CaCertificate,
- },
+ params.Cluster = &api.NodeParameters_ClusterRegister_{
+ ClusterRegister: &api.NodeParameters_ClusterRegister{
+ RegisterTicket: resT.Ticket,
+ ClusterDirectory: resI.ClusterDirectory,
+ CaCertificate: resI.CaCertificate,
},
}
}