karmada/pkg/karmadactl/addons/init/enable_option.go

201 lines
6.4 KiB
Go

package init
import (
"context"
"fmt"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/utils/strings/slices"
cmdinit "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/kubernetes"
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
"github.com/karmada-io/karmada/pkg/version"
)
// CommandAddonsEnableOption options for addons list.
type CommandAddonsEnableOption struct {
GlobalCommandOptions
KarmadaSearchImage string
KarmadaSearchReplicas int32
KarmadaDeschedulerImage string
KarmadaDeschedulerReplicas int32
KarmadaSchedulerEstimatorImage string
KarmadaEstimatorReplicas int32
KarmadaKubeClientSet *kubernetes.Clientset
ImageRegistry string
WaitComponentReadyTimeout int
WaitAPIServiceReadyTimeout int
MemberKubeConfig string
MemberContext string
HostClusterDomain string
}
var (
// DefaultKarmadaDeschedulerImage Karmada descheduler image
DefaultKarmadaDeschedulerImage string
// DefaultKarmadaSchedulerEstimatorImage Karmada scheduler-estimator image
DefaultKarmadaSchedulerEstimatorImage string
// DefaultKarmadaSearchImage Karmada search estimator image
DefaultKarmadaSearchImage string
karmadaRelease string
)
func init() {
releaseVer, err := version.ParseGitVersion(version.Get().GitVersion)
if err != nil {
klog.Infof("No default release version found. build version: %s", version.Get().String())
releaseVer = &version.ReleaseVersion{} // initialize to avoid panic
}
karmadaRelease = releaseVer.PatchRelease()
DefaultKarmadaDeschedulerImage = fmt.Sprintf("docker.io/karmada/karmada-descheduler:%s", releaseVer.PatchRelease())
DefaultKarmadaSchedulerEstimatorImage = fmt.Sprintf("docker.io/karmada/karmada-scheduler-estimator:%s", releaseVer.PatchRelease())
DefaultKarmadaSearchImage = fmt.Sprintf("docker.io/karmada/karmada-search:%s", releaseVer.PatchRelease())
}
// KarmadaDeschedulerImage get karmada descheduler image
func KarmadaDeschedulerImage(o *CommandAddonsEnableOption) string {
if o.ImageRegistry != "" && o.KarmadaDeschedulerImage == DefaultKarmadaDeschedulerImage {
return o.ImageRegistry + "/karmada-descheduler:" + karmadaRelease
}
return o.KarmadaDeschedulerImage
}
// KarmadaSchedulerEstimatorImage get karmada scheduler-estimator image
func KarmadaSchedulerEstimatorImage(o *CommandAddonsEnableOption) string {
if o.ImageRegistry != "" && o.KarmadaSchedulerEstimatorImage == DefaultKarmadaSchedulerEstimatorImage {
return o.ImageRegistry + "/karmada-scheduler-estimator:" + karmadaRelease
}
return o.KarmadaSchedulerEstimatorImage
}
// KarmadaSearchImage get karmada search image
func KarmadaSearchImage(o *CommandAddonsEnableOption) string {
if o.ImageRegistry != "" && o.KarmadaSearchImage == DefaultKarmadaSearchImage {
return o.ImageRegistry + "/karmada-search:" + karmadaRelease
}
return o.KarmadaSearchImage
}
// Complete the conditions required to be able to run enable.
func (o *CommandAddonsEnableOption) Complete() error {
err := o.GlobalCommandOptions.Complete()
if err != nil {
return err
}
o.KarmadaKubeClientSet, err = apiclient.NewClientSet(o.KarmadaRestConfig)
if err != nil {
return err
}
return nil
}
// Validate Check that there are enough conditions to run addon enable.
func (o *CommandAddonsEnableOption) Validate(args []string) error {
err := validAddonNames(args)
if err != nil {
return err
}
secretClient := o.KubeClientSet.CoreV1().Secrets(o.Namespace)
_, err = secretClient.Get(context.TODO(), cmdinit.KubeConfigSecretAndMountName, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return fmt.Errorf("secrets `kubeconfig` is not found in namespace %s, please execute karmadactl init to deploy karmada first", o.Namespace)
}
}
if o.Cluster == "" {
if slices.Contains(args, EstimatorResourceName) {
return fmt.Errorf("member cluster is needed when enable karmada-scheduler-estimator,use `--cluster=member --member-kubeconfig /root/.kube/config --member-context member1` to enable karmada-scheduler-estimator")
}
} else {
if !slices.Contains(args, EstimatorResourceName) && !slices.Contains(args, "all") {
return fmt.Errorf("cluster is needed only when enable karmada-scheduler-estimator or enable all")
}
if o.MemberKubeConfig == "" {
return fmt.Errorf("member config is needed when enable karmada-scheduler-estimator,use `--cluster=member --member-kubeconfig /root/.kube/member.config --member-context member1` to enable karmada-scheduler-estimator")
}
// Check member kubeconfig and context is valid
memberConfig, err := apiclient.RestConfig(o.MemberContext, o.MemberKubeConfig)
if err != nil {
return fmt.Errorf("failed to get member cluster config. error: %v", err)
}
memberKubeClient := kubernetes.NewForConfigOrDie(memberConfig)
_, err = memberKubeClient.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to get nodes from cluster %s with member-kubeconfig and member-context. error: %v, Please check the Role or ClusterRole of the serviceAccount in your member-kubeconfig", o.Cluster, err)
}
_, err = memberKubeClient.CoreV1().Pods(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to get pods from cluster %s with member-kubeconfig and member-context. error: %v, Please check the Role or ClusterRole of the serviceAccount in your member-kubeconfig", o.Cluster, err)
}
}
return nil
}
// Run start enable Karmada addons
func (o *CommandAddonsEnableOption) Run(args []string) error {
var enableAddons = map[string]*Addon{}
// collect enabled addons
for _, item := range args {
if item == "all" {
enableAddons = Addons
break
}
if addon := Addons[item]; addon != nil {
enableAddons[item] = addon
}
}
// enable addons
for name, addon := range enableAddons {
klog.Infof("Start to enable addon %s", name)
if err := addon.Enable(o); err != nil {
klog.Errorf("Install addon %s failed", name)
return err
}
klog.Infof("Successfully enable addon %s", name)
}
return nil
}
// validAddonNames valid whether addon names is supported now
func validAddonNames(addonNames []string) error {
if len(addonNames) == 0 {
return fmt.Errorf("addonNames must be not be null")
}
for _, addonName := range addonNames {
if addonName == "all" {
continue
}
_, ok := Addons[addonName]
if !ok {
return fmt.Errorf("addon %s is not be supported now", addonName)
}
}
return nil
}