From 14a53f56b62639e82d12baff33eeeddb7f2340d4 Mon Sep 17 00:00:00 2001 From: Francesco Romani Date: Wed, 31 Jul 2024 10:50:18 +0200 Subject: [PATCH] add and use controlplane detection expose control plane detection Signed-off-by: Francesco Romani --- pkg/commands/detect.go | 34 ++++++++++++++----- pkg/commands/root.go | 20 ++++++++--- pkg/deployer/platform/detect/autoselection.go | 16 +++++++++ pkg/deployer/platform/detect/detect.go | 29 ++++++++++++++++ 4 files changed, 87 insertions(+), 12 deletions(-) diff --git a/pkg/commands/detect.go b/pkg/commands/detect.go index 95829fb8..8560d030 100644 --- a/pkg/commands/detect.go +++ b/pkg/commands/detect.go @@ -27,7 +27,8 @@ import ( ) type detectOptions struct { - jsonOutput bool + controlPlane bool + jsonOutput bool } func NewDetectCommand(env *deployer.Environment, commonOpts *options.Options) *cobra.Command { @@ -42,6 +43,13 @@ func NewDetectCommand(env *deployer.Environment, commonOpts *options.Options) *c return err } + if opts.controlPlane { + info, _ := detect.ControlPlaneFromLister(env.Ctx, env.Cli) + serialize(opts, info) + return nil + + } + platKind, kindReason, _ := detect.FindPlatform(env.Ctx, commonOpts.UserPlatform) platVer, verReason, _ := detect.FindVersion(env.Ctx, platKind.Discovered, commonOpts.UserPlatformVersion) @@ -51,17 +59,27 @@ func NewDetectCommand(env *deployer.Environment, commonOpts *options.Options) *c Platform: platKind, Version: platVer, } - var out string - if opts.jsonOutput { - out = cluster.ToJSON() - } else { - out = cluster.String() - } - fmt.Printf("%s\n", out) + serialize(opts, cluster) return nil }, Args: cobra.NoArgs, } detect.Flags().BoolVarP(&opts.jsonOutput, "json", "J", false, "output JSON, not text.") + detect.Flags().BoolVar(&opts.controlPlane, "control-plane", false, "detect control plane info, not cluster info") return detect } + +type serializer interface { + ToJSON() string + String() string +} + +func serialize(opts *detectOptions, sr serializer) { + var out string + if opts.jsonOutput { + out = sr.ToJSON() + } else { + out = sr.String() + } + fmt.Printf("%s\n", out) +} diff --git a/pkg/commands/root.go b/pkg/commands/root.go index c9deb81d..be0cff03 100644 --- a/pkg/commands/root.go +++ b/pkg/commands/root.go @@ -17,9 +17,7 @@ package commands import ( - "context" "fmt" - "log" "os" "strings" "time" @@ -30,6 +28,7 @@ import ( "github.com/k8stopologyawareschedwg/deployer/pkg/deployer" "github.com/k8stopologyawareschedwg/deployer/pkg/deployer/platform" + "github.com/k8stopologyawareschedwg/deployer/pkg/deployer/platform/detect" "github.com/k8stopologyawareschedwg/deployer/pkg/deployer/updaters" "github.com/k8stopologyawareschedwg/deployer/pkg/deployer/wait" "github.com/k8stopologyawareschedwg/deployer/pkg/manifests" @@ -39,6 +38,7 @@ import ( type internalOptions struct { verbose int + replicas int rteConfigFile string schedScoringStratConfigFile string schedCacheParamsConfigFile string @@ -95,8 +95,8 @@ func InitFlags(flags *pflag.FlagSet, commonOpts *options.Options, internalOpts * flags.StringVar(&internalOpts.rteConfigFile, "rte-config-file", "", "inject rte configuration reading from this file.") flags.StringVar(&internalOpts.schedScoringStratConfigFile, "sched-scoring-strat-config-file", "", "inject scheduler scoring strategy configuration reading from this file.") flags.StringVar(&internalOpts.schedCacheParamsConfigFile, "sched-cache-params-config-file", "", "inject scheduler fine cache params configuration reading from this file.") + flags.IntVarP(&internalOpts.replicas, "replicas", "R", 1, "set the replica value - where relevant.") - flags.IntVarP(&commonOpts.Replicas, "replicas", "R", 1, "set the replica value - where relevant.") flags.DurationVarP(&commonOpts.WaitInterval, "wait-interval", "E", 2*time.Second, "wait interval.") flags.DurationVarP(&commonOpts.WaitTimeout, "wait-timeout", "T", 2*time.Minute, "wait timeout.") flags.BoolVar(&commonOpts.PullIfNotPresent, "pull-if-not-present", false, "force pull policies to IfNotPresent.") @@ -116,9 +116,21 @@ func InitFlags(flags *pflag.FlagSet, commonOpts *options.Options, internalOpts * func PostSetupOptions(env *deployer.Environment, commonOpts *options.Options, internalOpts *internalOptions) error { stdr.SetVerbosity(internalOpts.verbose) // MUST be the very first thing - env.Log.V(3).Info("global polling interval=%v timeout=%v", commonOpts.WaitInterval, commonOpts.WaitTimeout) + env.Log.V(3).Info("global polling settings", "interval", commonOpts.WaitInterval, "timeout", commonOpts.WaitTimeout) wait.SetBaseValues(commonOpts.WaitInterval, commonOpts.WaitTimeout) + if internalOpts.replicas < 0 { + env.Log.V(4).Info("autodetecting replicas from control plane") + info, err := detect.ControlPlaneFromLister(env.Ctx, env.Cli) + if err != nil { + return err + } + commonOpts.Replicas = info.NodeCount + env.Log.V(3).Info("autodetected control plane nodes, set replicas accordingly", "controlPlaneNodes", info.NodeCount) + } else { + commonOpts.Replicas = internalOpts.replicas + } + // if it is unknown, it's fine if internalOpts.plat == "" { commonOpts.UserPlatform = platform.Unknown diff --git a/pkg/deployer/platform/detect/autoselection.go b/pkg/deployer/platform/detect/autoselection.go index c470e9dd..c3ca54a5 100644 --- a/pkg/deployer/platform/detect/autoselection.go +++ b/pkg/deployer/platform/detect/autoselection.go @@ -41,6 +41,22 @@ type ClusterInfo struct { Version VersionInfo `json:"version"` } +type ControlPlaneInfo struct { + NodeCount int `json:"nodeCount"` +} + +func (cpi ControlPlaneInfo) String() string { + return fmt.Sprintf("nodes=%d", cpi.NodeCount) +} + +func (cpi ControlPlaneInfo) ToJSON() string { + data, err := json.Marshal(cpi) + if err != nil { + return `{"error":` + fmt.Sprintf("%q", err) + `}` + } + return string(data) +} + func (ci ClusterInfo) String() string { return fmt.Sprintf("%s:%s", ci.Platform.Discovered, ci.Version.Discovered) } diff --git a/pkg/deployer/platform/detect/detect.go b/pkg/deployer/platform/detect/detect.go index 3ed844aa..4519e6ad 100644 --- a/pkg/deployer/platform/detect/detect.go +++ b/pkg/deployer/platform/detect/detect.go @@ -20,16 +20,45 @@ import ( "context" "fmt" + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/discovery" + "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/k8stopologyawareschedwg/deployer/pkg/clientutil" + "github.com/k8stopologyawareschedwg/deployer/pkg/clientutil/nodes" + "github.com/k8stopologyawareschedwg/deployer/pkg/deployer" "github.com/k8stopologyawareschedwg/deployer/pkg/deployer/platform" ocpconfigv1 "github.com/openshift/api/config/v1" ) +func ControlPlane(ctx context.Context) (ControlPlaneInfo, error) { + cli, err := clientutil.New() + if err != nil { + return ControlPlaneInfo{}, err + } + return ControlPlaneFromLister(ctx, cli) +} + +func ControlPlaneFromLister(ctx context.Context, cli client.Client) (ControlPlaneInfo, error) { + info := ControlPlaneInfo{} + env := deployer.Environment{ + Ctx: ctx, + Cli: cli, + Log: logr.Discard(), // TODO + } + nodes, err := nodes.GetControlPlane(&env) + if err != nil { + return info, err + } + info.NodeCount = len(nodes) + return info, nil +} + func Platform(ctx context.Context) (platform.Platform, error) { ocpCli, err := clientutil.NewOCPClientSet() if err != nil {