cmd/kg/main.go: use cobra
This commit uses cobra instead of pflags in kg to handle flags in preparation to add a new subcommand for the webhook server. Signed-off-by: leonnicolas <leonloechner@gmx.de>
This commit is contained in:
		
							
								
								
									
										128
									
								
								cmd/kg/main.go
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								cmd/kg/main.go
									
									
									
									
									
								
							| @@ -30,7 +30,7 @@ import ( | ||||
| 	"github.com/oklog/run" | ||||
| 	"github.com/prometheus/client_golang/prometheus" | ||||
| 	"github.com/prometheus/client_golang/prometheus/promhttp" | ||||
| 	flag "github.com/spf13/pflag" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| 	"k8s.io/client-go/tools/clientcmd" | ||||
| @@ -78,52 +78,86 @@ var ( | ||||
| 	}, ", ") | ||||
| ) | ||||
|  | ||||
| // Main is the principal function for the binary, wrapped only by `main` for convenience. | ||||
| func Main() error { | ||||
| 	backend := flag.String("backend", k8s.Backend, fmt.Sprintf("The backend for the mesh. Possible values: %s", availableBackends)) | ||||
| 	cleanUpIface := flag.Bool("clean-up-interface", false, "Should Kilo delete its interface when it shuts down?") | ||||
| 	createIface := flag.Bool("create-interface", true, "Should kilo create an interface on startup?") | ||||
| 	cni := flag.Bool("cni", true, "Should Kilo manage the node's CNI configuration?") | ||||
| 	cniPath := flag.String("cni-path", mesh.DefaultCNIPath, "Path to CNI config.") | ||||
| 	compatibility := flag.String("compatibility", "", fmt.Sprintf("Should Kilo run in compatibility mode? Possible values: %s", availableCompatibilities)) | ||||
| 	encapsulate := flag.String("encapsulate", string(encapsulation.Always), fmt.Sprintf("When should Kilo encapsulate packets within a location? Possible values: %s", availableEncapsulations)) | ||||
| 	granularity := flag.String("mesh-granularity", string(mesh.LogicalGranularity), fmt.Sprintf("The granularity of the network mesh to create. Possible values: %s", availableGranularities)) | ||||
| 	kubeconfig := flag.String("kubeconfig", "", "Path to kubeconfig.") | ||||
| 	hostname := flag.String("hostname", "", "Hostname of the node on which this process is running.") | ||||
| 	iface := flag.String("interface", mesh.DefaultKiloInterface, "Name of the Kilo interface to use; if it does not exist, it will be created.") | ||||
| 	listen := flag.String("listen", ":1107", "The address at which to listen for health and metrics.") | ||||
| 	local := flag.Bool("local", true, "Should Kilo manage routes within a location?") | ||||
| 	logLevel := flag.String("log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels)) | ||||
| 	master := flag.String("master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig).") | ||||
| 	mtu := flag.Uint("mtu", wireguard.DefaultMTU, "The MTU of the WireGuard interface created by Kilo.") | ||||
| 	topologyLabel := flag.String("topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.") | ||||
| 	var port uint | ||||
| 	flag.UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.") | ||||
| 	subnet := flag.String("subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.") | ||||
| 	resyncPeriod := flag.Duration("resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?") | ||||
| 	printVersion := flag.Bool("version", false, "Print version and exit") | ||||
| 	flag.Parse() | ||||
| var cmd = &cobra.Command{ | ||||
| 	Use:   "kg", | ||||
| 	Short: "kg is the Kilo agent", | ||||
| 	Long: `kg is the Kilo agent. | ||||
| 		It runs on every node of a cluster, | ||||
| 		setting up the public and private keys for the VPN | ||||
| 		as well as the necessary rules to route packets between locations.`, | ||||
| 	RunE: runRoot, | ||||
| } | ||||
|  | ||||
| 	if *printVersion { | ||||
| var ( | ||||
| 	backend       string | ||||
| 	cleanUpIface  bool | ||||
| 	createIface   bool | ||||
| 	cni           bool | ||||
| 	cniPath       string | ||||
| 	compatibility string | ||||
| 	encapsulate   string | ||||
| 	granularity   string | ||||
| 	hostname      string | ||||
| 	kubeconfig    string | ||||
| 	iface         string | ||||
| 	listen        string | ||||
| 	local         bool | ||||
| 	logLevel      string | ||||
| 	master        string | ||||
| 	mtu           uint | ||||
| 	topologyLabel string | ||||
| 	port          uint | ||||
| 	subnet        string | ||||
| 	resyncPeriod  time.Duration | ||||
| 	printVersion  bool | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	cmd.PersistentFlags().StringVar(&backend, "backend", k8s.Backend, fmt.Sprintf("The backend for the mesh. Possible values: %s", availableBackends)) | ||||
| 	cmd.PersistentFlags().BoolVar(&cleanUpIface, "clean-up-interface", false, "Should Kilo delete its interface when it shuts down?") | ||||
| 	cmd.PersistentFlags().BoolVar(&createIface, "create-interface", true, "Should kilo create an interface on startup?") | ||||
| 	cmd.PersistentFlags().BoolVar(&cni, "cni", true, "Should Kilo manage the node's CNI configuration?") | ||||
| 	cmd.PersistentFlags().StringVar(&cniPath, "cni-path", mesh.DefaultCNIPath, "Path to CNI config.") | ||||
| 	cmd.PersistentFlags().StringVar(&compatibility, "compatibility", "", fmt.Sprintf("Should Kilo run in compatibility mode? Possible values: %s", availableCompatibilities)) | ||||
| 	cmd.PersistentFlags().StringVar(&encapsulate, "encapsulate", string(encapsulation.Always), fmt.Sprintf("When should Kilo encapsulate packets within a location? Possible values: %s", availableEncapsulations)) | ||||
| 	cmd.PersistentFlags().StringVar(&granularity, "mesh-granularity", string(mesh.LogicalGranularity), fmt.Sprintf("The granularity of the network mesh to create. Possible values: %s", availableGranularities)) | ||||
| 	cmd.PersistentFlags().StringVar(&kubeconfig, "kubeconfig", "", "Path to kubeconfig.") | ||||
| 	cmd.PersistentFlags().StringVar(&hostname, "hostname", "", "Hostname of the node on which this process is running.") | ||||
| 	cmd.PersistentFlags().StringVar(&iface, "interface", mesh.DefaultKiloInterface, "Name of the Kilo interface to use; if it does not exist, it will be created.") | ||||
| 	cmd.PersistentFlags().StringVar(&listen, "listen", ":1107", "The address at which to listen for health and metrics.") | ||||
| 	cmd.PersistentFlags().BoolVar(&local, "local", true, "Should Kilo manage routes within a location?") | ||||
| 	cmd.PersistentFlags().StringVar(&logLevel, "log-level", logLevelInfo, fmt.Sprintf("Log level to use. Possible values: %s", availableLogLevels)) | ||||
| 	cmd.PersistentFlags().StringVar(&master, "master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig).") | ||||
| 	cmd.PersistentFlags().UintVar(&mtu, "mtu", wireguard.DefaultMTU, "The MTU of the WireGuard interface created by Kilo.") | ||||
| 	cmd.PersistentFlags().StringVar(&topologyLabel, "topology-label", k8s.RegionLabelKey, "Kubernetes node label used to group nodes into logical locations.") | ||||
| 	cmd.PersistentFlags().UintVar(&port, "port", mesh.DefaultKiloPort, "The port over which WireGuard peers should communicate.") | ||||
| 	cmd.PersistentFlags().StringVar(&subnet, "subnet", mesh.DefaultKiloSubnet.String(), "CIDR from which to allocate addresses for WireGuard interfaces.") | ||||
| 	cmd.PersistentFlags().DurationVar(&resyncPeriod, "resync-period", 30*time.Second, "How often should the Kilo controllers reconcile?") | ||||
| 	cmd.PersistentFlags().BoolVar(&printVersion, "version", false, "Print version and exit") | ||||
| } | ||||
|  | ||||
| // Main is the principal function for the binary, wrapped only by `main` for convenience. | ||||
| func runRoot(_ *cobra.Command, _ []string) error { | ||||
| 	if printVersion { | ||||
| 		fmt.Println(version.Version) | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	_, s, err := net.ParseCIDR(*subnet) | ||||
| 	_, s, err := net.ParseCIDR(subnet) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to parse %q as CIDR: %v", *subnet, err) | ||||
| 		return fmt.Errorf("failed to parse %q as CIDR: %v", subnet, err) | ||||
| 	} | ||||
|  | ||||
| 	if *hostname == "" { | ||||
| 	if hostname == "" { | ||||
| 		var err error | ||||
| 		*hostname, err = os.Hostname() | ||||
| 		if *hostname == "" || err != nil { | ||||
| 		hostname, err = os.Hostname() | ||||
| 		if hostname == "" || err != nil { | ||||
| 			return errors.New("failed to determine hostname") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	logger := log.NewJSONLogger(log.NewSyncWriter(os.Stdout)) | ||||
| 	switch *logLevel { | ||||
| 	switch logLevel { | ||||
| 	case logLevelAll: | ||||
| 		logger = level.NewFilter(logger, level.AllowAll()) | ||||
| 	case logLevelDebug: | ||||
| @@ -137,52 +171,52 @@ func Main() error { | ||||
| 	case logLevelNone: | ||||
| 		logger = level.NewFilter(logger, level.AllowNone()) | ||||
| 	default: | ||||
| 		return fmt.Errorf("log level %v unknown; possible values are: %s", *logLevel, availableLogLevels) | ||||
| 		return fmt.Errorf("log level %v unknown; possible values are: %s", logLevel, availableLogLevels) | ||||
| 	} | ||||
| 	logger = log.With(logger, "ts", log.DefaultTimestampUTC) | ||||
| 	logger = log.With(logger, "caller", log.DefaultCaller) | ||||
|  | ||||
| 	e := encapsulation.Strategy(*encapsulate) | ||||
| 	e := encapsulation.Strategy(encapsulate) | ||||
| 	switch e { | ||||
| 	case encapsulation.Never: | ||||
| 	case encapsulation.CrossSubnet: | ||||
| 	case encapsulation.Always: | ||||
| 	default: | ||||
| 		return fmt.Errorf("encapsulation %v unknown; possible values are: %s", *encapsulate, availableEncapsulations) | ||||
| 		return fmt.Errorf("encapsulation %v unknown; possible values are: %s", encapsulate, availableEncapsulations) | ||||
| 	} | ||||
|  | ||||
| 	var enc encapsulation.Encapsulator | ||||
| 	switch *compatibility { | ||||
| 	switch compatibility { | ||||
| 	case "flannel": | ||||
| 		enc = encapsulation.NewFlannel(e) | ||||
| 	default: | ||||
| 		enc = encapsulation.NewIPIP(e) | ||||
| 	} | ||||
|  | ||||
| 	gr := mesh.Granularity(*granularity) | ||||
| 	gr := mesh.Granularity(granularity) | ||||
| 	switch gr { | ||||
| 	case mesh.LogicalGranularity: | ||||
| 	case mesh.FullGranularity: | ||||
| 	default: | ||||
| 		return fmt.Errorf("mesh granularity %v unknown; possible values are: %s", *granularity, availableGranularities) | ||||
| 		return fmt.Errorf("mesh granularity %v unknown; possible values are: %s", granularity, availableGranularities) | ||||
| 	} | ||||
|  | ||||
| 	var b mesh.Backend | ||||
| 	switch *backend { | ||||
| 	switch backend { | ||||
| 	case k8s.Backend: | ||||
| 		config, err := clientcmd.BuildConfigFromFlags(*master, *kubeconfig) | ||||
| 		config, err := clientcmd.BuildConfigFromFlags(master, kubeconfig) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to create Kubernetes config: %v", err) | ||||
| 		} | ||||
| 		c := kubernetes.NewForConfigOrDie(config) | ||||
| 		kc := kiloclient.NewForConfigOrDie(config) | ||||
| 		ec := apiextensions.NewForConfigOrDie(config) | ||||
| 		b = k8s.New(c, kc, ec, *topologyLabel) | ||||
| 		b = k8s.New(c, kc, ec, topologyLabel) | ||||
| 	default: | ||||
| 		return fmt.Errorf("backend %v unknown; possible values are: %s", *backend, availableBackends) | ||||
| 		return fmt.Errorf("backend %v unknown; possible values are: %s", backend, availableBackends) | ||||
| 	} | ||||
|  | ||||
| 	m, err := mesh.New(b, enc, gr, *hostname, uint32(port), s, *local, *cni, *cniPath, *iface, *cleanUpIface, *createIface, *mtu, *resyncPeriod, log.With(logger, "component", "kilo")) | ||||
| 	m, err := mesh.New(b, enc, gr, hostname, uint32(port), s, local, cni, cniPath, iface, cleanUpIface, createIface, mtu, resyncPeriod, log.With(logger, "component", "kilo")) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create Kilo mesh: %v", err) | ||||
| 	} | ||||
| @@ -201,9 +235,9 @@ func Main() error { | ||||
| 		mux.HandleFunc("/health", healthHandler) | ||||
| 		mux.Handle("/graph", &graphHandler{m, gr, hostname, s}) | ||||
| 		mux.Handle("/metrics", promhttp.HandlerFor(r, promhttp.HandlerOpts{})) | ||||
| 		l, err := net.Listen("tcp", *listen) | ||||
| 		l, err := net.Listen("tcp", listen) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to listen on %s: %v", *listen, err) | ||||
| 			return fmt.Errorf("failed to listen on %s: %v", listen, err) | ||||
| 		} | ||||
|  | ||||
| 		g.Add(func() error { | ||||
| @@ -253,7 +287,7 @@ func Main() error { | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	if err := Main(); err != nil { | ||||
| 	if err := cmd.Execute(); err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, "%v\n", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user