Skip to content

Commit

Permalink
Merge pull request #453 from nicolehanjing/nicoleh-improve-main
Browse files Browse the repository at this point in the history
Refactor main.go based on sample main from k8s go module version v0.20.6
  • Loading branch information
k8s-ci-robot authored May 5, 2021
2 parents 6aee3ab + 2e1e459 commit 52978b8
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 204 deletions.
204 changes: 24 additions & 180 deletions cmd/vsphere-cloud-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,17 @@ import (
goflag "flag"
"fmt"
"math/rand"
"net"
"net/http"
"os"
"strings"
"time"

"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
cloudprovider "k8s.io/cloud-provider"
"k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphere"
"k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphere/loadbalancer"
"k8s.io/cloud-provider-vsphere/pkg/cloudprovider/vsphereparavirtual"
"k8s.io/cloud-provider/app"
cloudcontrollerconfig "k8s.io/cloud-provider/app/config"
cloudnodecontroller "k8s.io/cloud-provider/controllers/node"
cloudnodelifecyclecontroller "k8s.io/cloud-provider/controllers/nodelifecycle"
routecontroller "k8s.io/cloud-provider/controllers/route"
servicecontroller "k8s.io/cloud-provider/controllers/service"
appconfig "k8s.io/cloud-provider/app/config"
"k8s.io/cloud-provider/options"
"k8s.io/component-base/cli/flag"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/cli/globalflag"
"k8s.io/component-base/logs"
Expand All @@ -52,7 +42,6 @@ import (
"k8s.io/component-base/term"
"k8s.io/component-base/version/verflag"
klog "k8s.io/klog/v2"
netutils "k8s.io/utils/net"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand All @@ -69,7 +58,7 @@ func main() {

rand.Seed(time.Now().UTC().UnixNano())

s, err := options.NewCloudControllerManagerOptions()
ccmOptions, err := options.NewCloudControllerManagerOptions()
if err != nil {
klog.Fatalf("unable to initialize command options: %v", err)
}
Expand All @@ -82,7 +71,7 @@ func main() {
verflag.PrintAndExitIfRequested()
cliflag.PrintFlags(cmd.Flags())

c, err := s.Config(KnownControllers(), app.ControllersDisabledByDefault.List())
c, err := ccmOptions.Config(app.ControllerNames(app.DefaultInitFuncConstructors), app.ControllersDisabledByDefault.List())
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
Expand All @@ -101,33 +90,11 @@ func main() {
klog.Fatalf("unknown cloud provider %s, only 'vsphere' and 'vsphere-paravirtual' are supported", cloudProvider)
}

// initialize cloud provider with the cloud provider name and config file provided
cloud, err := cloudprovider.InitCloudProvider(cloudProvider, c.ComponentConfig.KubeCloudShared.CloudProvider.CloudConfigFile)
if err != nil {
klog.Fatalf("Cloud provider could not be initialized: %v", err)
}
if cloud == nil {
klog.Fatalf("Cloud provider is nil")
}
completedConfig := c.Complete()
cloud := cloudInitializer(completedConfig, cloudProvider)
controllerInitializers = app.ConstructControllerInitializers(app.DefaultInitFuncConstructors, completedConfig, cloud)

if !cloud.HasClusterID() {
if c.ComponentConfig.KubeCloudShared.AllowUntaggedCloud {
klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues")
} else {
klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option")
}
}

// Initialize the cloud provider with a reference to the clientBuilder
cloud.Initialize(c.ClientBuilder, make(chan struct{}))
// Set the informer on the user cloud object
if informerUserCloud, ok := cloud.(cloudprovider.InformerUser); ok {
informerUserCloud.SetInformers(c.SharedInformers)
}

controllerInitializers = app.DefaultControllerInitializers(c.Complete(), cloud)

if err := app.Run(c.Complete(), controllerInitializers, wait.NeverStop); err != nil {
if err := app.Run(completedConfig, cloud, controllerInitializers, wait.NeverStop); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
Expand All @@ -143,13 +110,14 @@ func main() {
}

fs := command.Flags()
namedFlagSets := s.Flags(KnownControllers(), app.ControllersDisabledByDefault.List())
namedFlagSets := ccmOptions.Flags(app.ControllerNames(app.DefaultInitFuncConstructors), app.ControllersDisabledByDefault.List())
verflag.AddFlags(namedFlagSets.FlagSet("global"))
globalflag.AddGlobalFlags(namedFlagSets.FlagSet("global"), command.Name())

for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f)
}

usageFmt := "Usage:\n %s\n"
cols, _, _ := term.TerminalSize(command.OutOrStdout())
command.SetUsageFunc(func(cmd *cobra.Command) error {
Expand All @@ -165,7 +133,7 @@ func main() {
// TODO: once we switch everything over to Cobra commands, we can go back to calling
// utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
// normalize func and add the go flag set by hand.
pflag.CommandLine.SetNormalizeFunc(flag.WordSepNormalizeFunc)
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
// utilflag.InitFlags()
logs.InitLogs()
Expand Down Expand Up @@ -210,148 +178,24 @@ func main() {
}
}

// initFunc is used to launch a particular controller. It may run additional "should I activate checks".
// Any error returned will cause the controller process to `Fatal`
// The bool indicates whether the controller was enabled.
type initFunc func(ctx *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface, stop <-chan struct{}) (debuggingHandler http.Handler, enabled bool, err error)
func cloudInitializer(config *appconfig.CompletedConfig, cloudProvider string) cloudprovider.Interface {
cloudConfig := config.ComponentConfig.KubeCloudShared.CloudProvider

// KnownControllers indicate the default controller we are known.
func KnownControllers() []string {
ret := sets.StringKeySet(newControllerInitializers())
return ret.List()
}

// newControllerInitializers is a private map of named controller groups (you can start more than one in an init func)
// paired to their initFunc. This allows for structured downstream composition and subdivision.
func newControllerInitializers() map[string]initFunc {
controllers := map[string]initFunc{}
controllers["cloud-node"] = startCloudNodeController
controllers["cloud-node-lifecycle"] = startCloudNodeLifecycleController
controllers["service"] = startServiceController
controllers["route"] = startRouteController
return controllers
}

func startCloudNodeController(ctx *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
// Start the CloudNodeController
nodeController, err := cloudnodecontroller.NewCloudNodeController(
ctx.SharedInformers.Core().V1().Nodes(),
// cloud node controller uses existing cluster role from node-controller
ctx.ClientBuilder.ClientOrDie("node-controller"),
cloud,
ctx.ComponentConfig.NodeStatusUpdateFrequency.Duration,
)
if err != nil {
klog.Warningf("failed to start cloud node controller: %s", err)
return nil, false, nil
}

go nodeController.Run(stopCh)

return nil, true, nil
}

func startCloudNodeLifecycleController(ctx *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
// Start the cloudNodeLifecycleController
cloudNodeLifecycleController, err := cloudnodelifecyclecontroller.NewCloudNodeLifecycleController(
ctx.SharedInformers.Core().V1().Nodes(),
// cloud node lifecycle controller uses existing cluster role from node-controller
ctx.ClientBuilder.ClientOrDie("node-controller"),
cloud,
ctx.ComponentConfig.KubeCloudShared.NodeMonitorPeriod.Duration,
)
// initialize cloud provider with the cloud provider name and config file provided
cloud, err := cloudprovider.InitCloudProvider(cloudProvider, cloudConfig.CloudConfigFile)
if err != nil {
klog.Warningf("failed to start cloud node lifecycle controller: %s", err)
return nil, false, nil
klog.Fatalf("Cloud provider could not be initialized: %v", err)
}

go cloudNodeLifecycleController.Run(stopCh)

return nil, true, nil
}

func startServiceController(ctx *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
// Start the service controller
serviceController, err := servicecontroller.New(
cloud,
ctx.ClientBuilder.ClientOrDie("service-controller"),
ctx.SharedInformers.Core().V1().Services(),
ctx.SharedInformers.Core().V1().Nodes(),
ctx.ComponentConfig.KubeCloudShared.ClusterName,
utilfeature.DefaultFeatureGate,
)
if err != nil {
// This error shouldn't fail. It lives like this as a legacy.
klog.Errorf("Failed to start service controller: %v", err)
return nil, false, nil
if cloud == nil {
klog.Fatalf("Cloud provider is nil")
}

go serviceController.Run(stopCh, int(ctx.ComponentConfig.ServiceController.ConcurrentServiceSyncs))

return nil, true, nil
}

func startRouteController(ctx *cloudcontrollerconfig.CompletedConfig, cloud cloudprovider.Interface, stopCh <-chan struct{}) (http.Handler, bool, error) {
if !ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs || !ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes {
klog.Infof("Will not configure cloud provider routes for allocate-node-cidrs: %v, configure-cloud-routes: %v.", ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs, ctx.ComponentConfig.KubeCloudShared.ConfigureCloudRoutes)
return nil, false, nil
}

// If CIDRs should be allocated for pods and set on the CloudProvider, then start the route controller
routes, ok := cloud.Routes()
if !ok {
klog.Warning("configure-cloud-routes is set, but cloud provider does not support routes. Will not configure cloud provider routes.")
return nil, false, nil
}

// failure: bad cidrs in config
clusterCIDRs, dualStack, err := processCIDRs(ctx.ComponentConfig.KubeCloudShared.ClusterCIDR)
if err != nil {
return nil, false, err
}

// failure: more than one cidr and dual stack is not enabled
if len(clusterCIDRs) > 1 && !utilfeature.DefaultFeatureGate.Enabled(app.IPv6DualStack) {
return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and dualstack feature is not enabled", len(clusterCIDRs))
}

// failure: more than one cidr but they are not configured as dual stack
if len(clusterCIDRs) > 1 && !dualStack {
return nil, false, fmt.Errorf("len of ClusterCIDRs==%v and they are not configured as dual stack (at least one from each IPFamily", len(clusterCIDRs))
}

// failure: more than two cidrs is not allowed even with dual stack
if len(clusterCIDRs) > 2 {
return nil, false, fmt.Errorf("length of clusterCIDRs is:%v more than max allowed of 2", len(clusterCIDRs))
}

routeController := routecontroller.New(
routes,
ctx.ClientBuilder.ClientOrDie("route-controller"),
ctx.SharedInformers.Core().V1().Nodes(),
ctx.ComponentConfig.KubeCloudShared.ClusterName,
clusterCIDRs,
)
go routeController.Run(stopCh, ctx.ComponentConfig.KubeCloudShared.RouteReconciliationPeriod.Duration)

return nil, true, nil
}

// processCIDRs is a helper function that works on a comma separated cidrs and returns
// a list of typed cidrs
// a flag if cidrs represents a dual stack
// error if failed to parse any of the cidrs
func processCIDRs(cidrsList string) ([]*net.IPNet, bool, error) {
cidrsSplit := strings.Split(strings.TrimSpace(cidrsList), ",")

cidrs, err := netutils.ParseCIDRs(cidrsSplit)
if err != nil {
return nil, false, err
if !cloud.HasClusterID() {
if config.ComponentConfig.KubeCloudShared.AllowUntaggedCloud {
klog.Warning("detected a cluster without a ClusterID. A ClusterID will be required in the future. Please tag your cluster to avoid any future issues")
} else {
klog.Fatalf("no ClusterID found. A ClusterID is required for the cloud provider to function properly. This check can be bypassed by setting the allow-untagged-cloud option")
}
}

// if cidrs has an error then the previous call will fail
// safe to ignore error checking on next call
dualstack, _ := netutils.IsDualStackCIDRs(cidrs)

return cidrs, dualstack, nil
return cloud
}
12 changes: 5 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@ require (
gopkg.in/gcfg.v1 v1.2.3
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.3.0
k8s.io/api v0.20.2
k8s.io/apimachinery v0.20.2
k8s.io/apiserver v0.20.2
k8s.io/client-go v0.20.2
k8s.io/cloud-provider v0.20.2
k8s.io/component-base v0.20.2
k8s.io/api v0.20.6
k8s.io/apimachinery v0.20.6
k8s.io/client-go v0.20.6
k8s.io/cloud-provider v0.20.6
k8s.io/component-base v0.20.6
k8s.io/klog/v2 v2.4.0
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
sigs.k8s.io/controller-runtime v0.6.5
sigs.k8s.io/yaml v1.2.0
)
Loading

0 comments on commit 52978b8

Please sign in to comment.