201 lines
6.4 KiB
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
|
|
}
|