m/test/launch: allow specifying launch parameters
This adds flags to the launch-cluster command for specifying the size of
the cluster, tpm and storage security configuration, number of CPUs and
RAM size for all nodes, and assigning roles to specific nodes.
As an example, the following command launches a cluster with tpm
disabled, 4 nodes, 2 CPUs and 4 GiB of RAM on each node, and assigns the
Kubernetes Worker role to all except the first node:
bazel run //metropolis:launch-cluster -- -tpm-mode=disabled \
-num-nodes=4 -cpu=2 -ram=4G -kubernetes-worker=1-3
The default storage security policy was changed to insecure, as this
speeds up cluster launch.
The cluster configuration flags are defined in a new separate package to
avoid code duplication.
Fixes: https://github.com/monogon-dev/monogon/issues/315
Change-Id: Icf8b7fcbd6e609f4785b2a60ce5e7be14b641884
Reviewed-on: https://review.monogon.dev/c/monogon/+/3307
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/flagdefs/flagdefs.go b/metropolis/cli/flagdefs/flagdefs.go
new file mode 100644
index 0000000..fe2423e
--- /dev/null
+++ b/metropolis/cli/flagdefs/flagdefs.go
@@ -0,0 +1,162 @@
+// Package flagdefs contains shared flag definitions for Metropolis.
+// The usage is the same as for the standard flags in the [flag] package,
+// except that the [flag.FlagSet] needs to be passed in the first parameter.
+// Pass [flag.CommandLine] to use the default FlagSet.
+// There are also separate functions for use with the [pflag] package.
+package flagdefs
+
+import (
+ "errors"
+ "flag"
+ "strings"
+
+ "github.com/spf13/pflag"
+
+ cpb "source.monogon.dev/metropolis/proto/common"
+)
+
+// tpmModeValue implements the [flag.Value] and [pflag.Value] interfaces.
+type tpmModeValue cpb.ClusterConfiguration_TPMMode
+
+func (v *tpmModeValue) Set(val string) error {
+ var tpmMode cpb.ClusterConfiguration_TPMMode
+ switch strings.ToLower(val) {
+ case "required", "require":
+ tpmMode = cpb.ClusterConfiguration_TPM_MODE_REQUIRED
+ case "best-effort", "besteffort":
+ tpmMode = cpb.ClusterConfiguration_TPM_MODE_BEST_EFFORT
+ case "disabled", "disable":
+ tpmMode = cpb.ClusterConfiguration_TPM_MODE_DISABLED
+ default:
+ return errors.New("must be one of: required, best-effort, disabled")
+ }
+ *v = tpmModeValue(tpmMode)
+ return nil
+}
+
+func (v *tpmModeValue) String() string {
+ switch cpb.ClusterConfiguration_TPMMode(*v) {
+ case cpb.ClusterConfiguration_TPM_MODE_REQUIRED:
+ return "required"
+ case cpb.ClusterConfiguration_TPM_MODE_BEST_EFFORT:
+ return "best-effort"
+ case cpb.ClusterConfiguration_TPM_MODE_DISABLED:
+ return "disabled"
+ default:
+ return ""
+ }
+}
+
+func (*tpmModeValue) Type() string {
+ return "tpmMode"
+}
+
+// TPMModeVar defines a TPMMode flag with specified name, default value, and
+// usage string. The argument p points to a TPMMode variable in which to store
+// the value of the flag.
+func TPMModeVar(flags *flag.FlagSet, p *cpb.ClusterConfiguration_TPMMode, name string, value cpb.ClusterConfiguration_TPMMode, usage string) {
+ *p = value
+ flags.Var((*tpmModeValue)(p), name, usage+" (one of: required, best-effort, disabled)")
+}
+
+// TPMMode defines a TPMMode flag with specified name, default value, and
+// usage string. The return value is the address of a TPMMode variable that
+// stores the value of the flag.
+func TPMMode(flags *flag.FlagSet, name string, value cpb.ClusterConfiguration_TPMMode, usage string) *cpb.ClusterConfiguration_TPMMode {
+ val := new(cpb.ClusterConfiguration_TPMMode)
+ TPMModeVar(flags, val, name, value, usage)
+ return val
+}
+
+// TPMModeVarPflag defines a TPMMode flag with specified name, default value,
+// and usage string. The argument p points to a TPMMode variable in which to
+// store the value of the flag.
+func TPMModeVarPflag(flags *pflag.FlagSet, p *cpb.ClusterConfiguration_TPMMode, name string, value cpb.ClusterConfiguration_TPMMode, usage string) {
+ *p = value
+ flags.Var((*tpmModeValue)(p), name, usage+" (one of: required, best-effort, disabled)")
+}
+
+// TPMModePflag defines a TPMMode flag with specified name, default value, and
+// usage string. The return value is the address of a TPMMode variable that
+// stores the value of the flag.
+func TPMModePflag(flags *pflag.FlagSet, name string, value cpb.ClusterConfiguration_TPMMode, usage string) *cpb.ClusterConfiguration_TPMMode {
+ val := new(cpb.ClusterConfiguration_TPMMode)
+ TPMModeVarPflag(flags, val, name, value, usage)
+ return val
+}
+
+// storageSecurityPolicyValue implements the [flag.Value] and [pflag.Value]
+// interfaces.
+type storageSecurityPolicyValue cpb.ClusterConfiguration_StorageSecurityPolicy
+
+func (v *storageSecurityPolicyValue) Set(val string) error {
+ var storageSecurityPolicy cpb.ClusterConfiguration_StorageSecurityPolicy
+ switch strings.ToLower(val) {
+ case "permissive":
+ storageSecurityPolicy = cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_PERMISSIVE
+ case "needs-encryption":
+ storageSecurityPolicy = cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION
+ case "needs-encryption-and-authentication":
+ storageSecurityPolicy = cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION_AND_AUTHENTICATION
+ case "needs-insecure":
+ storageSecurityPolicy = cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_INSECURE
+ default:
+ return errors.New("must be one of: permissive, needs-encryption, needs-encryption-and-authentication, needs-insecure")
+ }
+ *v = storageSecurityPolicyValue(storageSecurityPolicy)
+ return nil
+}
+
+func (v *storageSecurityPolicyValue) String() string {
+ switch cpb.ClusterConfiguration_StorageSecurityPolicy(*v) {
+ case cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_PERMISSIVE:
+ return "permissive"
+ case cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION:
+ return "needs-encryption"
+ case cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION_AND_AUTHENTICATION:
+ return "needs-encryption-and-authentication"
+ case cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_INSECURE:
+ return "needs-insecure"
+ default:
+ return ""
+ }
+}
+
+func (*storageSecurityPolicyValue) Type() string {
+ return "storageSecurityPolicy"
+}
+
+// StorageSecurityPolicyVar defines a StorageSecurityPolicy flag with specified
+// name, default value, and usage string. The argument p points to a
+// StorageSecurityPolicy variable in which to store the value of the flag.
+func StorageSecurityPolicyVar(flags *flag.FlagSet, p *cpb.ClusterConfiguration_StorageSecurityPolicy, name string, value cpb.ClusterConfiguration_StorageSecurityPolicy, usage string) {
+ *p = value
+ flags.Var((*storageSecurityPolicyValue)(p), name, usage+" (one of: permissive, needs-encryption, needs-encryption-and-authentication, needs-insecure)")
+}
+
+// StorageSecurityPolicy defines a StorageSecurityPolicy flag with specified
+// name, default value, and usage string. The return value is the address of a
+// StorageSecurityPolicy variable that stores the value of the flag.
+func StorageSecurityPolicy(flags *flag.FlagSet, name string, value cpb.ClusterConfiguration_StorageSecurityPolicy, usage string) *cpb.ClusterConfiguration_StorageSecurityPolicy {
+ val := new(cpb.ClusterConfiguration_StorageSecurityPolicy)
+ StorageSecurityPolicyVar(flags, val, name, value, usage)
+ return val
+}
+
+// StorageSecurityPolicyVarPflag defines a StorageSecurityPolicy flag with
+// specified name, default value, and usage string. The argument p points to a
+// StorageSecurityPolicy variable in which to store the value of the flag.
+func StorageSecurityPolicyVarPflag(flags *pflag.FlagSet, p *cpb.ClusterConfiguration_StorageSecurityPolicy, name string, value cpb.ClusterConfiguration_StorageSecurityPolicy, usage string) {
+ *p = value
+ flags.Var((*storageSecurityPolicyValue)(p), name, usage+" (one of: permissive, needs-encryption, needs-encryption-and-authentication, needs-insecure)")
+}
+
+// StorageSecurityPolicyPflag defines a StorageSecurityPolicy flag with
+// specified name, default value, and usage string. The return value is the
+// address of a StorageSecurityPolicy variable that stores the value of the
+// flag.
+func StorageSecurityPolicyPflag(flags *pflag.FlagSet, name string, value cpb.ClusterConfiguration_StorageSecurityPolicy, usage string) *cpb.ClusterConfiguration_StorageSecurityPolicy {
+ val := new(cpb.ClusterConfiguration_StorageSecurityPolicy)
+ StorageSecurityPolicyVarPflag(flags, val, name, value, usage)
+ return val
+}