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:
leonnicolas 2021-08-18 22:42:09 +02:00
parent cad15d9961
commit 2b4487ba9a
No known key found for this signature in database
GPG Key ID: 088D0743E2B65C07
3 changed files with 81 additions and 49 deletions

View File

@ -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)
}

1
go.mod
View File

@ -14,7 +14,6 @@ require (
github.com/oklog/run v1.0.0
github.com/prometheus/client_golang v1.7.1
github.com/spf13/cobra v1.1.3
github.com/spf13/pflag v1.0.5
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b

1
vendor/modules.txt vendored
View File

@ -121,7 +121,6 @@ github.com/prometheus/procfs/internal/util
## explicit
github.com/spf13/cobra
# github.com/spf13/pflag v1.0.5
## explicit
github.com/spf13/pflag
# github.com/vishvananda/netlink v1.0.0
## explicit