Skip to content

Commit

Permalink
Merge pull request #310 from ffromani/detect-control-plane-0.20-redo
Browse files Browse the repository at this point in the history
 [release-0.20][manual add utilities and options to detect control plane
  • Loading branch information
ffromani authored Jul 31, 2024
2 parents 7e9709a + b0b2d35 commit 3657d32
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 38 deletions.
10 changes: 9 additions & 1 deletion cmd/deployer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package main

import (
"context"
"fmt"
"log"
"os"

"github.com/go-logr/stdr"
"github.com/spf13/cobra"

"k8s.io/klog/v2/klogr"
Expand Down Expand Up @@ -61,7 +64,12 @@ func NewVersionCommand(env *deployer.Environment, commonOpts *options.Options) *
func main() {
ctrllog.SetLogger(klogr.NewWithOptions(klogr.WithFormat(klogr.FormatKlog)))

root := commands.NewRootCommand(NewVersionCommand)
env := deployer.Environment{
Ctx: context.Background(),
Log: stdr.New(log.New(os.Stderr, "", log.LstdFlags)),
}

root := commands.NewRootCommand(&env, NewVersionCommand)
if err := root.Execute(); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
Expand Down
8 changes: 6 additions & 2 deletions pkg/clientutil/nodes/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,19 @@ import (
)

const (
// RoleWorker contains the worker role
RoleWorker = "worker"
RoleControlPlane = "control-plane"
RoleWorker = "worker"
)

const (
// LabelRole contains the key for the role label
LabelRole = "node-role.kubernetes.io"
)

func GetControlPlane(env *deployer.Environment) ([]corev1.Node, error) {
return GetByRole(env, RoleControlPlane)
}

func GetWorkers(env *deployer.Environment) ([]corev1.Node, error) {
return GetByRole(env, RoleWorker)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/commands/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func NewDeployAPICommand(env *deployer.Environment, commonOpts *options.Options)
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
if err := api.Deploy(env, options.API{Platform: commonOpts.ClusterPlatform}); err != nil {
return err
}
Expand Down Expand Up @@ -100,7 +100,7 @@ func NewDeploySchedulerPluginCommand(env *deployer.Environment, commonOpts *opti
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
return sched.Deploy(env, options.Scheduler{
Platform: commonOpts.ClusterPlatform,
WaitCompletion: commonOpts.WaitCompletion,
Expand Down Expand Up @@ -143,7 +143,7 @@ func NewDeployTopologyUpdaterCommand(env *deployer.Environment, commonOpts *opti
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
return updaters.Deploy(env, commonOpts.UpdaterType, options.Updater{
Platform: commonOpts.ClusterPlatform,
PlatformVersion: commonOpts.ClusterVersion,
Expand Down
36 changes: 27 additions & 9 deletions pkg/commands/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import (
)

type detectOptions struct {
jsonOutput bool
controlPlane bool
jsonOutput bool
}

func NewDetectCommand(env *deployer.Environment, commonOpts *options.Options) *cobra.Command {
Expand All @@ -42,26 +43,43 @@ 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)

env.Log.Info("detection", "platform", platKind, "reason", kindReason, "version", platVer, "source", verReason)
env.Log.V(3).Info("detection", "platform", platKind, "reason", kindReason, "version", platVer, "source", verReason)

cluster := detect.ClusterInfo{
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)
}
8 changes: 4 additions & 4 deletions pkg/commands/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewRemoveCommand(env *deployer.Environment, commonOpts *options.Options) *c
if commonOpts.ClusterVersion == platform.MissingVersion {
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}
env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)

err = sched.Remove(env, options.Scheduler{
Platform: commonOpts.ClusterPlatform,
Expand Down Expand Up @@ -123,7 +123,7 @@ func NewRemoveAPICommand(env *deployer.Environment, commonOpts *options.Options)
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
if err := api.Remove(env, options.API{Platform: commonOpts.ClusterPlatform}); err != nil {
return err
}
Expand Down Expand Up @@ -156,7 +156,7 @@ func NewRemoveSchedulerPluginCommand(env *deployer.Environment, commonOpts *opti
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
return sched.Remove(env, options.Scheduler{
Platform: commonOpts.ClusterPlatform,
WaitCompletion: commonOpts.WaitCompletion,
Expand Down Expand Up @@ -199,7 +199,7 @@ func NewRemoveTopologyUpdaterCommand(env *deployer.Environment, commonOpts *opti
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
return updaters.Remove(env, commonOpts.UpdaterType, options.Updater{
Platform: commonOpts.ClusterPlatform,
PlatformVersion: commonOpts.ClusterVersion,
Expand Down
53 changes: 35 additions & 18 deletions pkg/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
package commands

import (
"context"
"fmt"
"log"
"os"
"strings"
"time"
Expand All @@ -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"
Expand All @@ -38,6 +37,8 @@ import (
)

type internalOptions struct {
verbose int
replicas int
rteConfigFile string
schedScoringStratConfigFile string
schedCacheParamsConfigFile string
Expand All @@ -52,11 +53,7 @@ func ShowHelp(cmd *cobra.Command, args []string) error {
type NewCommandFunc func(ev *deployer.Environment, ko *options.Options) *cobra.Command

// NewRootCommand returns entrypoint command to interact with all other commands
func NewRootCommand(extraCmds ...NewCommandFunc) *cobra.Command {
env := deployer.Environment{
Ctx: context.Background(),
Log: stdr.New(log.New(os.Stderr, "", log.LstdFlags)),
}
func NewRootCommand(env *deployer.Environment, extraCmds ...NewCommandFunc) *cobra.Command {
internalOpts := internalOptions{}
commonOpts := options.Options{}

Expand All @@ -65,7 +62,7 @@ func NewRootCommand(extraCmds ...NewCommandFunc) *cobra.Command {
Short: "deployer helps setting up all the topology-aware-scheduling components on a kubernetes cluster",

PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return PostSetupOptions(&env, &commonOpts, &internalOpts)
return PostSetupOptions(env, &commonOpts, &internalOpts)
},
RunE: func(cmd *cobra.Command, args []string) error {
return ShowHelp(cmd, args)
Expand All @@ -77,28 +74,29 @@ func NewRootCommand(extraCmds ...NewCommandFunc) *cobra.Command {
InitFlags(root.PersistentFlags(), &commonOpts, &internalOpts)

root.AddCommand(
NewRenderCommand(&env, &commonOpts),
NewValidateCommand(&env, &commonOpts),
NewDeployCommand(&env, &commonOpts),
NewRemoveCommand(&env, &commonOpts),
NewSetupCommand(&env, &commonOpts),
NewDetectCommand(&env, &commonOpts),
NewImagesCommand(&env, &commonOpts),
NewRenderCommand(env, &commonOpts),
NewValidateCommand(env, &commonOpts),
NewDeployCommand(env, &commonOpts),
NewRemoveCommand(env, &commonOpts),
NewSetupCommand(env, &commonOpts),
NewDetectCommand(env, &commonOpts),
NewImagesCommand(env, &commonOpts),
)
for _, extraCmd := range extraCmds {
root.AddCommand(extraCmd(&env, &commonOpts))
root.AddCommand(extraCmd(env, &commonOpts))
}

return root
}

func InitFlags(flags *pflag.FlagSet, commonOpts *options.Options, internalOpts *internalOptions) {
flags.IntVarP(&internalOpts.verbose, "verbose", "v", 1, "set the tool verbosity.")
flags.StringVarP(&internalOpts.plat, "platform", "P", "", "platform kind:version to deploy on (example kubernetes:v1.22)")
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.")
Expand All @@ -116,9 +114,28 @@ func InitFlags(flags *pflag.FlagSet, commonOpts *options.Options, internalOpts *
}

func PostSetupOptions(env *deployer.Environment, commonOpts *options.Options, internalOpts *internalOptions) error {
env.Log.V(3).Info("global polling interval=%v timeout=%v", commonOpts.WaitInterval, commonOpts.WaitTimeout)
stdr.SetVerbosity(internalOpts.verbose) // MUST be the very first thing

env.Log.V(3).Info("global polling settings", "interval", commonOpts.WaitInterval, "timeout", commonOpts.WaitTimeout)
wait.SetBaseValues(commonOpts.WaitInterval, commonOpts.WaitTimeout)

if internalOpts.replicas < 0 {
err := env.EnsureClient()
if err != nil {
return err
}

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
Expand Down
2 changes: 1 addition & 1 deletion pkg/deploy/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func OnCluster(env *deployer.Environment, commonOpts *options.Options) error {
return fmt.Errorf("cannot autodetect the platform version, and no version given")
}

env.Log.Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
env.Log.V(3).Info("detection", "platform", commonOpts.ClusterPlatform, "reason", reason, "version", commonOpts.ClusterVersion, "source", source)
if err := api.Deploy(env, options.API{
Platform: commonOpts.ClusterPlatform,
}); err != nil {
Expand Down
16 changes: 16 additions & 0 deletions pkg/deployer/platform/detect/autoselection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
29 changes: 29 additions & 0 deletions pkg/deployer/platform/detect/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 3657d32

Please sign in to comment.