[Engine-1.21] Parser improvements, allow config values to be used with etcd-snapshot (#4477)

* Match to last After keyword for parser (#4383)
* Made parser able to skip over subcommands
* Fix to allow etcd-snapshot to use config file with flags that are only used with k3s server. (#4464)

Signed-off-by: Derek Nola <derek.nola@suse.com>
pull/4494/head
Derek Nola 2021-11-11 22:18:10 -08:00 committed by GitHub
parent 381d086cf0
commit d5a4147762
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 568 additions and 371 deletions

View File

@ -146,6 +146,365 @@ var (
}
)
var ServerFlags = []cli.Flag{
ConfigFlag,
DebugFlag,
VLevel,
VModule,
LogFile,
AlsoLogToStderr,
cli.StringFlag{
Name: "bind-address",
Usage: "(listener) " + version.Program + " bind address (default: 0.0.0.0)",
Destination: &ServerConfig.BindAddress,
},
cli.IntFlag{
Name: "https-listen-port",
Usage: "(listener) HTTPS listen port",
Value: 6443,
Destination: &ServerConfig.HTTPSPort,
},
cli.StringFlag{
Name: "advertise-address",
Usage: "(listener) IPv4 address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)",
Destination: &ServerConfig.AdvertiseIP,
},
cli.IntFlag{
Name: "advertise-port",
Usage: "(listener) Port that apiserver uses to advertise to members of the cluster (default: listen-port)",
Destination: &ServerConfig.AdvertisePort,
},
cli.StringSliceFlag{
Name: "tls-san",
Usage: "(listener) Add additional hostnames or IPv4/IPv6 addresses as Subject Alternative Names on the server TLS cert",
Value: &ServerConfig.TLSSan,
},
cli.StringFlag{
Name: "data-dir,d",
Usage: "(data) Folder to hold state default /var/lib/rancher/" + version.Program + " or ${HOME}/.rancher/" + version.Program + " if not root",
Destination: &ServerConfig.DataDir,
},
ClusterCIDR,
ServiceCIDR,
ServiceNodePortRange,
ClusterDNS,
ClusterDomain,
cli.StringFlag{
Name: "flannel-backend",
Usage: "(networking) One of 'none', 'vxlan', 'ipsec', 'host-gw', or 'wireguard'",
Destination: &ServerConfig.FlannelBackend,
Value: "vxlan",
},
cli.StringFlag{
Name: "token,t",
Usage: "(cluster) Shared secret used to join a server or agent to a cluster",
Destination: &ServerConfig.Token,
EnvVar: version.ProgramUpper + "_TOKEN",
},
cli.StringFlag{
Name: "token-file",
Usage: "(cluster) File containing the cluster-secret/token",
Destination: &ServerConfig.TokenFile,
EnvVar: version.ProgramUpper + "_TOKEN_FILE",
},
cli.StringFlag{
Name: "write-kubeconfig,o",
Usage: "(client) Write kubeconfig for admin client to this file",
Destination: &ServerConfig.KubeConfigOutput,
EnvVar: version.ProgramUpper + "_KUBECONFIG_OUTPUT",
},
cli.StringFlag{
Name: "write-kubeconfig-mode",
Usage: "(client) Write kubeconfig with this mode",
Destination: &ServerConfig.KubeConfigMode,
EnvVar: version.ProgramUpper + "_KUBECONFIG_MODE",
},
ExtraAPIArgs,
ExtraEtcdArgs,
ExtraControllerArgs,
ExtraSchedulerArgs,
cli.StringSliceFlag{
Name: "kube-cloud-controller-manager-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
cli.StringFlag{
Name: "datastore-endpoint",
Usage: "(db) Specify etcd, Mysql, Postgres, or Sqlite (default) data source name",
Destination: &ServerConfig.DatastoreEndpoint,
EnvVar: version.ProgramUpper + "_DATASTORE_ENDPOINT",
},
cli.StringFlag{
Name: "datastore-cafile",
Usage: "(db) TLS Certificate Authority file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCAFile,
EnvVar: version.ProgramUpper + "_DATASTORE_CAFILE",
},
cli.StringFlag{
Name: "datastore-certfile",
Usage: "(db) TLS certification file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCertFile,
EnvVar: version.ProgramUpper + "_DATASTORE_CERTFILE",
},
cli.StringFlag{
Name: "datastore-keyfile",
Usage: "(db) TLS key file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreKeyFile,
EnvVar: version.ProgramUpper + "_DATASTORE_KEYFILE",
},
&cli.BoolFlag{
Name: "etcd-expose-metrics",
Usage: "(db) Expose etcd metrics to client interface. (Default false)",
Destination: &ServerConfig.EtcdExposeMetrics,
},
&cli.BoolFlag{
Name: "etcd-disable-snapshots",
Usage: "(db) Disable automatic etcd snapshots",
Destination: &ServerConfig.EtcdDisableSnapshots,
},
&cli.StringFlag{
Name: "etcd-snapshot-name",
Usage: "(db) Set the base name of etcd snapshots. Default: etcd-snapshot-<unix-timestamp>",
Destination: &ServerConfig.EtcdSnapshotName,
Value: "etcd-snapshot",
},
&cli.StringFlag{
Name: "etcd-snapshot-schedule-cron",
Usage: "(db) Snapshot interval time in cron spec. eg. every 5 hours '* */5 * * *'",
Destination: &ServerConfig.EtcdSnapshotCron,
Value: "0 */12 * * *",
},
&cli.IntFlag{
Name: "etcd-snapshot-retention",
Usage: "(db) Number of snapshots to retain",
Destination: &ServerConfig.EtcdSnapshotRetention,
Value: defaultSnapshotRentention,
},
&cli.StringFlag{
Name: "etcd-snapshot-dir",
Usage: "(db) Directory to save db snapshots. (Default location: ${data-dir}/db/snapshots)",
Destination: &ServerConfig.EtcdSnapshotDir,
},
&cli.BoolFlag{
Name: "etcd-s3",
Usage: "(db) Enable backup to S3",
Destination: &ServerConfig.EtcdS3,
},
&cli.StringFlag{
Name: "etcd-s3-endpoint",
Usage: "(db) S3 endpoint url",
Destination: &ServerConfig.EtcdS3Endpoint,
Value: "s3.amazonaws.com",
},
&cli.StringFlag{
Name: "etcd-s3-endpoint-ca",
Usage: "(db) S3 custom CA cert to connect to S3 endpoint",
Destination: &ServerConfig.EtcdS3EndpointCA,
},
&cli.BoolFlag{
Name: "etcd-s3-skip-ssl-verify",
Usage: "(db) Disables S3 SSL certificate validation",
Destination: &ServerConfig.EtcdS3SkipSSLVerify,
},
&cli.StringFlag{
Name: "etcd-s3-access-key",
Usage: "(db) S3 access key",
EnvVar: "AWS_ACCESS_KEY_ID",
Destination: &ServerConfig.EtcdS3AccessKey,
},
&cli.StringFlag{
Name: "etcd-s3-secret-key",
Usage: "(db) S3 secret key",
EnvVar: "AWS_SECRET_ACCESS_KEY",
Destination: &ServerConfig.EtcdS3SecretKey,
},
&cli.StringFlag{
Name: "etcd-s3-bucket",
Usage: "(db) S3 bucket name",
Destination: &ServerConfig.EtcdS3BucketName,
},
&cli.StringFlag{
Name: "etcd-s3-region",
Usage: "(db) S3 region / bucket location (optional)",
Destination: &ServerConfig.EtcdS3Region,
Value: "us-east-1",
},
&cli.StringFlag{
Name: "etcd-s3-folder",
Usage: "(db) S3 folder",
Destination: &ServerConfig.EtcdS3Folder,
},
&cli.BoolFlag{
Name: "etcd-s3-insecure",
Usage: "(db) Disables S3 over HTTPS",
Destination: &ServerConfig.EtcdS3Insecure,
},
&cli.DurationFlag{
Name: "etcd-s3-timeout",
Usage: "(db) S3 timeout",
Destination: &ServerConfig.EtcdS3Timeout,
Value: 30 * time.Second,
},
cli.StringFlag{
Name: "default-local-storage-path",
Usage: "(storage) Default local storage path for local provisioner storage class",
Destination: &ServerConfig.DefaultLocalStoragePath,
},
cli.StringSliceFlag{
Name: "disable",
Usage: "(components) Do not deploy packaged components and delete any deployed components (valid items: " + DisableItems + ")",
},
cli.BoolFlag{
Name: "disable-scheduler",
Usage: "(components) Disable Kubernetes default scheduler",
Destination: &ServerConfig.DisableScheduler,
},
cli.BoolFlag{
Name: "disable-cloud-controller",
Usage: "(components) Disable " + version.Program + " default cloud controller manager",
Destination: &ServerConfig.DisableCCM,
},
cli.BoolFlag{
Name: "disable-kube-proxy",
Usage: "(components) Disable running kube-proxy",
Destination: &ServerConfig.DisableKubeProxy,
},
cli.BoolFlag{
Name: "disable-network-policy",
Usage: "(components) Disable " + version.Program + " default network policy controller",
Destination: &ServerConfig.DisableNPC,
},
cli.BoolFlag{
Name: "disable-helm-controller",
Usage: "(components) Disable Helm controller",
Destination: &ServerConfig.DisableHelmController,
},
cli.BoolFlag{
Name: "disable-apiserver",
Hidden: true,
Usage: "(experimental/components) Disable running api server",
Destination: &ServerConfig.DisableAPIServer,
},
cli.BoolFlag{
Name: "disable-controller-manager",
Hidden: true,
Usage: "(experimental/components) Disable running kube-controller-manager",
Destination: &ServerConfig.DisableControllerManager,
},
cli.BoolFlag{
Name: "disable-etcd",
Hidden: true,
Usage: "(experimental/components) Disable running etcd",
Destination: &ServerConfig.DisableETCD,
},
NodeNameFlag,
WithNodeIDFlag,
NodeLabels,
NodeTaints,
ImageCredProvBinDirFlag,
ImageCredProvConfigFlag,
DockerFlag,
CRIEndpointFlag,
PauseImageFlag,
SnapshotterFlag,
PrivateRegistryFlag,
AirgapExtraRegistryFlag,
NodeIPFlag,
NodeExternalIPFlag,
ResolvConfFlag,
FlannelIfaceFlag,
FlannelConfFlag,
ExtraKubeletArgs,
ExtraKubeProxyArgs,
ProtectKernelDefaultsFlag,
cli.BoolFlag{
Name: "rootless",
Usage: "(experimental) Run rootless",
Destination: &ServerConfig.Rootless,
},
cli.StringFlag{
Name: "agent-token",
Usage: "(cluster) Shared secret used to join agents to the cluster, but not servers",
Destination: &ServerConfig.AgentToken,
EnvVar: version.ProgramUpper + "_AGENT_TOKEN",
},
cli.StringFlag{
Name: "agent-token-file",
Usage: "(cluster) File containing the agent secret",
Destination: &ServerConfig.AgentTokenFile,
EnvVar: version.ProgramUpper + "_AGENT_TOKEN_FILE",
},
cli.StringFlag{
Name: "server,s",
Usage: "(cluster) Server to connect to, used to join a cluster",
EnvVar: version.ProgramUpper + "_URL",
Destination: &ServerConfig.ServerURL,
},
cli.BoolFlag{
Name: "cluster-init",
Usage: "(cluster) Initialize a new cluster using embedded Etcd",
EnvVar: version.ProgramUpper + "_CLUSTER_INIT",
Destination: &ServerConfig.ClusterInit,
},
cli.BoolFlag{
Name: "cluster-reset",
Usage: "(cluster) Forget all peers and become sole member of a new cluster",
EnvVar: version.ProgramUpper + "_CLUSTER_RESET",
Destination: &ServerConfig.ClusterReset,
},
&cli.StringFlag{
Name: "cluster-reset-restore-path",
Usage: "(db) Path to snapshot file to be restored",
Destination: &ServerConfig.ClusterResetRestorePath,
},
cli.BoolFlag{
Name: "secrets-encryption",
Usage: "(experimental) Enable Secret encryption at rest",
Destination: &ServerConfig.EncryptSecrets,
},
cli.StringFlag{
Name: "system-default-registry",
Usage: "(image) Private registry to be used for all system images",
EnvVar: version.ProgramUpper + "_SYSTEM_DEFAULT_REGISTRY",
Destination: &ServerConfig.SystemDefaultRegistry,
},
&SELinuxFlag,
LBServerPortFlag,
// Hidden/Deprecated flags below
&DisableSELinuxFlag,
FlannelFlag,
cli.StringSliceFlag{
Name: "no-deploy",
Usage: "(deprecated) Do not deploy packaged components (valid items: " + DisableItems + ")",
},
cli.StringFlag{
Name: "cluster-secret",
Usage: "(deprecated) use --token",
Destination: &ServerConfig.ClusterSecret,
EnvVar: version.ProgramUpper + "_CLUSTER_SECRET",
},
cli.BoolFlag{
Name: "disable-agent",
Usage: "Do not run a local agent and register a local kubelet",
Hidden: true,
Destination: &ServerConfig.DisableAgent,
},
cli.StringSliceFlag{
Hidden: true,
Name: "kube-controller-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Value: &ServerConfig.ExtraControllerArgs,
},
cli.StringSliceFlag{
Hidden: true,
Name: "kube-cloud-controller-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
}
func NewServerCommand(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "server",
@ -153,363 +512,6 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command {
UsageText: appName + " server [OPTIONS]",
Before: SetupDebug(CheckSELinuxFlags),
Action: action,
Flags: []cli.Flag{
ConfigFlag,
DebugFlag,
VLevel,
VModule,
LogFile,
AlsoLogToStderr,
cli.StringFlag{
Name: "bind-address",
Usage: "(listener) " + version.Program + " bind address (default: 0.0.0.0)",
Destination: &ServerConfig.BindAddress,
},
cli.IntFlag{
Name: "https-listen-port",
Usage: "(listener) HTTPS listen port",
Value: 6443,
Destination: &ServerConfig.HTTPSPort,
},
cli.StringFlag{
Name: "advertise-address",
Usage: "(listener) IPv4 address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)",
Destination: &ServerConfig.AdvertiseIP,
},
cli.IntFlag{
Name: "advertise-port",
Usage: "(listener) Port that apiserver uses to advertise to members of the cluster (default: listen-port)",
Destination: &ServerConfig.AdvertisePort,
},
cli.StringSliceFlag{
Name: "tls-san",
Usage: "(listener) Add additional hostnames or IPv4/IPv6 addresses as Subject Alternative Names on the server TLS cert",
Value: &ServerConfig.TLSSan,
},
cli.StringFlag{
Name: "data-dir,d",
Usage: "(data) Folder to hold state default /var/lib/rancher/" + version.Program + " or ${HOME}/.rancher/" + version.Program + " if not root",
Destination: &ServerConfig.DataDir,
},
ClusterCIDR,
ServiceCIDR,
ServiceNodePortRange,
ClusterDNS,
ClusterDomain,
cli.StringFlag{
Name: "flannel-backend",
Usage: "(networking) One of 'none', 'vxlan', 'ipsec', 'host-gw', or 'wireguard'",
Destination: &ServerConfig.FlannelBackend,
Value: "vxlan",
},
cli.StringFlag{
Name: "token,t",
Usage: "(cluster) Shared secret used to join a server or agent to a cluster",
Destination: &ServerConfig.Token,
EnvVar: version.ProgramUpper + "_TOKEN",
},
cli.StringFlag{
Name: "token-file",
Usage: "(cluster) File containing the cluster-secret/token",
Destination: &ServerConfig.TokenFile,
EnvVar: version.ProgramUpper + "_TOKEN_FILE",
},
cli.StringFlag{
Name: "write-kubeconfig,o",
Usage: "(client) Write kubeconfig for admin client to this file",
Destination: &ServerConfig.KubeConfigOutput,
EnvVar: version.ProgramUpper + "_KUBECONFIG_OUTPUT",
},
cli.StringFlag{
Name: "write-kubeconfig-mode",
Usage: "(client) Write kubeconfig with this mode",
Destination: &ServerConfig.KubeConfigMode,
EnvVar: version.ProgramUpper + "_KUBECONFIG_MODE",
},
ExtraAPIArgs,
ExtraEtcdArgs,
ExtraControllerArgs,
ExtraSchedulerArgs,
cli.StringSliceFlag{
Name: "kube-cloud-controller-manager-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
cli.StringFlag{
Name: "datastore-endpoint",
Usage: "(db) Specify etcd, Mysql, Postgres, or Sqlite (default) data source name",
Destination: &ServerConfig.DatastoreEndpoint,
EnvVar: version.ProgramUpper + "_DATASTORE_ENDPOINT",
},
cli.StringFlag{
Name: "datastore-cafile",
Usage: "(db) TLS Certificate Authority file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCAFile,
EnvVar: version.ProgramUpper + "_DATASTORE_CAFILE",
},
cli.StringFlag{
Name: "datastore-certfile",
Usage: "(db) TLS certification file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCertFile,
EnvVar: version.ProgramUpper + "_DATASTORE_CERTFILE",
},
cli.StringFlag{
Name: "datastore-keyfile",
Usage: "(db) TLS key file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreKeyFile,
EnvVar: version.ProgramUpper + "_DATASTORE_KEYFILE",
},
&cli.BoolFlag{
Name: "etcd-expose-metrics",
Usage: "(db) Expose etcd metrics to client interface. (Default false)",
Destination: &ServerConfig.EtcdExposeMetrics,
},
&cli.BoolFlag{
Name: "etcd-disable-snapshots",
Usage: "(db) Disable automatic etcd snapshots",
Destination: &ServerConfig.EtcdDisableSnapshots,
},
&cli.StringFlag{
Name: "etcd-snapshot-name",
Usage: "(db) Set the base name of etcd snapshots. Default: etcd-snapshot-<unix-timestamp>",
Destination: &ServerConfig.EtcdSnapshotName,
Value: "etcd-snapshot",
},
&cli.StringFlag{
Name: "etcd-snapshot-schedule-cron",
Usage: "(db) Snapshot interval time in cron spec. eg. every 5 hours '* */5 * * *'",
Destination: &ServerConfig.EtcdSnapshotCron,
Value: "0 */12 * * *",
},
&cli.IntFlag{
Name: "etcd-snapshot-retention",
Usage: "(db) Number of snapshots to retain",
Destination: &ServerConfig.EtcdSnapshotRetention,
Value: defaultSnapshotRentention,
},
&cli.StringFlag{
Name: "etcd-snapshot-dir",
Usage: "(db) Directory to save db snapshots. (Default location: ${data-dir}/db/snapshots)",
Destination: &ServerConfig.EtcdSnapshotDir,
},
&cli.BoolFlag{
Name: "etcd-s3",
Usage: "(db) Enable backup to S3",
Destination: &ServerConfig.EtcdS3,
},
&cli.StringFlag{
Name: "etcd-s3-endpoint",
Usage: "(db) S3 endpoint url",
Destination: &ServerConfig.EtcdS3Endpoint,
Value: "s3.amazonaws.com",
},
&cli.StringFlag{
Name: "etcd-s3-endpoint-ca",
Usage: "(db) S3 custom CA cert to connect to S3 endpoint",
Destination: &ServerConfig.EtcdS3EndpointCA,
},
&cli.BoolFlag{
Name: "etcd-s3-skip-ssl-verify",
Usage: "(db) Disables S3 SSL certificate validation",
Destination: &ServerConfig.EtcdS3SkipSSLVerify,
},
&cli.StringFlag{
Name: "etcd-s3-access-key",
Usage: "(db) S3 access key",
EnvVar: "AWS_ACCESS_KEY_ID",
Destination: &ServerConfig.EtcdS3AccessKey,
},
&cli.StringFlag{
Name: "etcd-s3-secret-key",
Usage: "(db) S3 secret key",
EnvVar: "AWS_SECRET_ACCESS_KEY",
Destination: &ServerConfig.EtcdS3SecretKey,
},
&cli.StringFlag{
Name: "etcd-s3-bucket",
Usage: "(db) S3 bucket name",
Destination: &ServerConfig.EtcdS3BucketName,
},
&cli.StringFlag{
Name: "etcd-s3-region",
Usage: "(db) S3 region / bucket location (optional)",
Destination: &ServerConfig.EtcdS3Region,
Value: "us-east-1",
},
&cli.StringFlag{
Name: "etcd-s3-folder",
Usage: "(db) S3 folder",
Destination: &ServerConfig.EtcdS3Folder,
},
&cli.BoolFlag{
Name: "etcd-s3-insecure",
Usage: "(db) Disables S3 over HTTPS",
Destination: &ServerConfig.EtcdS3Insecure,
},
&cli.DurationFlag{
Name: "etcd-s3-timeout",
Usage: "(db) S3 timeout",
Destination: &ServerConfig.EtcdS3Timeout,
Value: 30 * time.Second,
},
cli.StringFlag{
Name: "default-local-storage-path",
Usage: "(storage) Default local storage path for local provisioner storage class",
Destination: &ServerConfig.DefaultLocalStoragePath,
},
cli.StringSliceFlag{
Name: "disable",
Usage: "(components) Do not deploy packaged components and delete any deployed components (valid items: " + DisableItems + ")",
},
cli.BoolFlag{
Name: "disable-scheduler",
Usage: "(components) Disable Kubernetes default scheduler",
Destination: &ServerConfig.DisableScheduler,
},
cli.BoolFlag{
Name: "disable-cloud-controller",
Usage: "(components) Disable " + version.Program + " default cloud controller manager",
Destination: &ServerConfig.DisableCCM,
},
cli.BoolFlag{
Name: "disable-kube-proxy",
Usage: "(components) Disable running kube-proxy",
Destination: &ServerConfig.DisableKubeProxy,
},
cli.BoolFlag{
Name: "disable-network-policy",
Usage: "(components) Disable " + version.Program + " default network policy controller",
Destination: &ServerConfig.DisableNPC,
},
cli.BoolFlag{
Name: "disable-helm-controller",
Usage: "(components) Disable Helm controller",
Destination: &ServerConfig.DisableHelmController,
},
cli.BoolFlag{
Name: "disable-apiserver",
Hidden: true,
Usage: "(experimental/components) Disable running api server",
Destination: &ServerConfig.DisableAPIServer,
},
cli.BoolFlag{
Name: "disable-controller-manager",
Hidden: true,
Usage: "(experimental/components) Disable running kube-controller-manager",
Destination: &ServerConfig.DisableControllerManager,
},
cli.BoolFlag{
Name: "disable-etcd",
Hidden: true,
Usage: "(experimental/components) Disable running etcd",
Destination: &ServerConfig.DisableETCD,
},
NodeNameFlag,
WithNodeIDFlag,
NodeLabels,
NodeTaints,
ImageCredProvBinDirFlag,
ImageCredProvConfigFlag,
DockerFlag,
CRIEndpointFlag,
PauseImageFlag,
SnapshotterFlag,
PrivateRegistryFlag,
AirgapExtraRegistryFlag,
NodeIPFlag,
NodeExternalIPFlag,
ResolvConfFlag,
FlannelIfaceFlag,
FlannelConfFlag,
ExtraKubeletArgs,
ExtraKubeProxyArgs,
ProtectKernelDefaultsFlag,
cli.BoolFlag{
Name: "rootless",
Usage: "(experimental) Run rootless",
Destination: &ServerConfig.Rootless,
},
cli.StringFlag{
Name: "agent-token",
Usage: "(cluster) Shared secret used to join agents to the cluster, but not servers",
Destination: &ServerConfig.AgentToken,
EnvVar: version.ProgramUpper + "_AGENT_TOKEN",
},
cli.StringFlag{
Name: "agent-token-file",
Usage: "(cluster) File containing the agent secret",
Destination: &ServerConfig.AgentTokenFile,
EnvVar: version.ProgramUpper + "_AGENT_TOKEN_FILE",
},
cli.StringFlag{
Name: "server,s",
Usage: "(cluster) Server to connect to, used to join a cluster",
EnvVar: version.ProgramUpper + "_URL",
Destination: &ServerConfig.ServerURL,
},
cli.BoolFlag{
Name: "cluster-init",
Usage: "(cluster) Initialize a new cluster using embedded Etcd",
EnvVar: version.ProgramUpper + "_CLUSTER_INIT",
Destination: &ServerConfig.ClusterInit,
},
cli.BoolFlag{
Name: "cluster-reset",
Usage: "(cluster) Forget all peers and become sole member of a new cluster",
EnvVar: version.ProgramUpper + "_CLUSTER_RESET",
Destination: &ServerConfig.ClusterReset,
},
&cli.StringFlag{
Name: "cluster-reset-restore-path",
Usage: "(db) Path to snapshot file to be restored",
Destination: &ServerConfig.ClusterResetRestorePath,
},
cli.BoolFlag{
Name: "secrets-encryption",
Usage: "(experimental) Enable Secret encryption at rest",
Destination: &ServerConfig.EncryptSecrets,
},
cli.StringFlag{
Name: "system-default-registry",
Usage: "(image) Private registry to be used for all system images",
EnvVar: version.ProgramUpper + "_SYSTEM_DEFAULT_REGISTRY",
Destination: &ServerConfig.SystemDefaultRegistry,
},
&SELinuxFlag,
LBServerPortFlag,
// Hidden/Deprecated flags below
&DisableSELinuxFlag,
FlannelFlag,
cli.StringSliceFlag{
Name: "no-deploy",
Usage: "(deprecated) Do not deploy packaged components (valid items: " + DisableItems + ")",
},
cli.StringFlag{
Name: "cluster-secret",
Usage: "(deprecated) use --token",
Destination: &ServerConfig.ClusterSecret,
EnvVar: version.ProgramUpper + "_CLUSTER_SECRET",
},
cli.BoolFlag{
Name: "disable-agent",
Usage: "Do not run a local agent and register a local kubelet",
Hidden: true,
Destination: &ServerConfig.DisableAgent,
},
cli.StringSliceFlag{
Hidden: true,
Name: "kube-controller-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Value: &ServerConfig.ExtraControllerArgs,
},
cli.StringSliceFlag{
Hidden: true,
Name: "kube-cloud-controller-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
},
Flags: ServerFlags,
}
}

View File

@ -1,18 +1,22 @@
package configfilearg
import (
"github.com/rancher/k3s/pkg/cli/cmds"
"github.com/rancher/k3s/pkg/version"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var defaultParser = &Parser{
After: []string{"server", "agent", "etcd-snapshot:1"},
FlagNames: []string{"--config", "-c"},
EnvName: version.ProgramUpper + "_CONFIG_FILE",
DefaultConfig: "/etc/rancher/" + version.Program + "/config.yaml",
ValidFlags: map[string][]cli.Flag{"server": cmds.ServerFlags, "etcd-snapshot": cmds.EtcdSnapshotFlags},
}
func MustParse(args []string) []string {
parser := &Parser{
After: []string{"server", "agent", "etcd-snapshot"},
FlagNames: []string{"--config", "-c"},
EnvName: version.ProgramUpper + "_CONFIG_FILE",
DefaultConfig: "/etc/rancher/" + version.Program + "/config.yaml",
}
result, err := parser.Parse(args)
result, err := defaultParser.Parse(args)
if err != nil {
logrus.Fatal(err)
}

View File

@ -0,0 +1,74 @@
package configfilearg
import (
"reflect"
"testing"
)
func Test_UnitMustParse(t *testing.T) {
tests := []struct {
name string
args []string
config string
want []string
}{
{
name: "Basic server",
args: []string{"k3s", "server"},
want: []string{"k3s", "server"},
},
{
name: "Server with known flags",
args: []string{"k3s", "server", "-t 12345", "--write-kubeconfig-mode 644"},
want: []string{"k3s", "server", "-t 12345", "--write-kubeconfig-mode 644"},
},
{
name: "Server with known flags and config with known and unknown flags",
args: []string{"k3s", "server", "--write-kubeconfig-mode 644"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "server", "--token=12345", "--node-label=DEAFBEEF",
"--etcd-s3=true", "--etcd-s3-bucket=my-backup", "--write-kubeconfig-mode 644"},
},
{
name: "Basic etcd-snapshot",
args: []string{"k3s", "etcd-snapshot", "save"},
want: []string{"k3s", "etcd-snapshot", "save"},
},
{
name: "Etcd-snapshot with known flags",
args: []string{"k3s", "etcd-snapshot", "save", "--s3=true"},
want: []string{"k3s", "etcd-snapshot", "save", "--s3=true"},
},
{
name: "Etcd-snapshot with config with known and unknown flags",
args: []string{"k3s", "etcd-snapshot", "save"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "etcd-snapshot", "save", "--etcd-s3=true", "--etcd-s3-bucket=my-backup"},
},
{
name: "Agent with known flags",
args: []string{"k3s", "agent", "--token=12345"},
want: []string{"k3s", "agent", "--token=12345"},
},
{
name: "Agent with config with known and unknown flags, flags are not skipped",
args: []string{"k3s", "agent"},
config: "./testdata/defaultdata.yaml",
want: []string{"k3s", "agent", "--token=12345", "--node-label=DEAFBEEF",
"--etcd-s3=true", "--etcd-s3-bucket=my-backup", "--notaflag=true"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defaultParser.DefaultConfig = tt.config
if got := MustParse(tt.args); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MustParse() = %+v\nWant = %+v", got, tt.want)
}
})
}
}

View File

@ -7,10 +7,14 @@ import (
"net/url"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/rancher/k3s/pkg/agent/util"
"github.com/rancher/wrangler/pkg/data/convert"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"gopkg.in/yaml.v2"
)
@ -19,6 +23,7 @@ type Parser struct {
FlagNames []string
EnvName string
DefaultConfig string
ValidFlags map[string][]cli.Flag
}
// Parse will parse an os.Args style slice looking for Parser.FlagNames after Parse.After.
@ -42,12 +47,55 @@ func (p *Parser) Parse(args []string) ([]string, error) {
} else if err != nil {
return nil, err
}
if len(args) > 1 {
values, err = p.stripInvalidFlags(args[1], values)
if err != nil {
return nil, err
}
}
return append(prefix, append(values, suffix...)...), nil
}
return args, nil
}
func (p *Parser) stripInvalidFlags(command string, args []string) ([]string, error) {
var result []string
var cmdFlags []cli.Flag
for k, v := range p.ValidFlags {
if k == command {
cmdFlags = v
}
}
if len(cmdFlags) == 0 {
return args, nil
}
validFlags := make(map[string]bool, len(cmdFlags))
for _, f := range cmdFlags {
//split flags with aliases into 2 entries
for _, s := range strings.Split(f.GetName(), ",") {
validFlags[s] = true
}
}
re, err := regexp.Compile("^-+(.+)=")
if err != nil {
return args, err
}
for _, arg := range args {
mArg := arg
if match := re.FindAllStringSubmatch(arg, -1); match != nil {
mArg = match[0][1]
}
if validFlags[mArg] {
result = append(result, arg)
} else {
logrus.Warnf("Unknown flag %s found in config.yaml, skipping\n", arg)
}
}
return result, nil
}
func (p *Parser) FindString(args []string, target string) (string, error) {
configFile, isSet := p.findConfigFileFlag(args)
if configFile != "" {
@ -100,15 +148,37 @@ func (p *Parser) findStart(args []string) ([]string, []string, bool) {
if len(p.After) == 0 {
return []string{}, args, true
}
for i, val := range args {
for _, test := range p.After {
if val == test {
return args[0 : i+1], args[i+1:], true
afterTemp := append([]string{}, p.After...)
afterIndex := make(map[string]int)
re, err := regexp.Compile(`(.+):(\d+)`)
if err != nil {
return args, nil, false
}
// After keywords ending with ":<NUM>" can set + NUM of arguments as the split point.
// used for matching on subcommmands
for i, arg := range afterTemp {
if match := re.FindAllStringSubmatch(arg, -1); match != nil {
afterTemp[i] = match[0][1]
afterIndex[match[0][1]], err = strconv.Atoi(match[0][2])
if err != nil {
return args, nil, false
}
}
}
for i, val := range args {
for _, test := range afterTemp {
if val == test {
if skip := afterIndex[test]; skip != 0 {
if len(args) <= i+skip || strings.HasPrefix(args[i+skip], "-") {
return args[0 : i+1], args[i+1:], true
}
return args[0 : i+skip+1], args[i+skip+1:], true
}
return args[0 : i+1], args[i+1:], true
}
}
}
return args, nil, false
}

View File

@ -48,11 +48,53 @@ func Test_UnitParser_findStart(t *testing.T) {
prefix: []string{"not-server", "foo", "bar"},
found: false,
},
{
name: "command (with optional subcommands) but no flags",
args: []string{"etcd-snapshot"},
prefix: []string{"etcd-snapshot"},
suffix: []string{},
found: true,
},
{
name: "command (with optional subcommands) and flags",
args: []string{"etcd-snapshot", "-f"},
prefix: []string{"etcd-snapshot"},
suffix: []string{"-f"},
found: true,
},
{
name: "command and subcommand with no flags",
args: []string{"etcd-snapshot", "list"},
prefix: []string{"etcd-snapshot", "list"},
suffix: []string{},
found: true,
},
{
name: "command and subcommand with flags",
args: []string{"etcd-snapshot", "list", "-f"},
prefix: []string{"etcd-snapshot", "list"},
suffix: []string{"-f"},
found: true,
},
{
name: "another command and subcommand with flags",
args: []string{"etcd-snapshot", "save", "--s3"},
prefix: []string{"etcd-snapshot", "save"},
suffix: []string{"--s3"},
found: true,
},
{
name: "command and too many subcommands",
args: []string{"etcd-snapshot", "list", "delete", "foo", "bar"},
prefix: []string{"etcd-snapshot", "list"},
suffix: []string{"delete", "foo", "bar"},
found: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := Parser{
After: []string{"server", "agent"},
After: []string{"server", "agent", "etcd-snapshot:1"},
}
prefix, suffix, found := p.findStart(tt.args)
if !reflect.DeepEqual(prefix, tt.prefix) {

View File

@ -0,0 +1,5 @@
token: 12345
node-label: DEAFBEEF
etcd-s3: true
etcd-s3-bucket: my-backup
notaflag : true