318 lines
11 KiB
Go
318 lines
11 KiB
Go
package terminus
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path"
|
|
"time"
|
|
|
|
"github.com/beclab/Olares/cli/pkg/core/logger"
|
|
"github.com/beclab/Olares/cli/pkg/storage"
|
|
|
|
"github.com/beclab/Olares/cli/pkg/clientset"
|
|
"github.com/beclab/Olares/cli/pkg/common"
|
|
cc "github.com/beclab/Olares/cli/pkg/core/common"
|
|
"github.com/beclab/Olares/cli/pkg/core/connector"
|
|
"github.com/beclab/Olares/cli/pkg/core/task"
|
|
"github.com/beclab/Olares/cli/pkg/core/util"
|
|
configmaptemplates "github.com/beclab/Olares/cli/pkg/terminus/templates"
|
|
"github.com/beclab/Olares/cli/pkg/utils"
|
|
"github.com/pkg/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
)
|
|
|
|
type InstallOsSystem struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (t *InstallOsSystem) Execute(runtime connector.Runtime) error {
|
|
kubectl, err := util.GetCommand(common.CommandKubectl)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "kubectl not found")
|
|
}
|
|
|
|
if !runtime.GetSystemInfo().IsDarwin() {
|
|
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("mkdir -p %s && chown 1000:1000 %s", storage.OlaresSharedLibDir, storage.OlaresSharedLibDir), false, false); err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "failed to create shared lib dir")
|
|
}
|
|
}
|
|
|
|
var cmd = fmt.Sprintf("%s get secret -n kubesphere-system redis-secret -o jsonpath='{.data.auth}' |base64 -d", kubectl)
|
|
redisPwd, err := runtime.GetRunner().SudoCmd(cmd, false, false)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "get redis secret error")
|
|
}
|
|
|
|
if redisPwd == "" {
|
|
return fmt.Errorf("redis secret not found")
|
|
}
|
|
|
|
config, err := ctrl.GetConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
actionConfig, settings, err := utils.InitConfig(config, common.NamespaceOsPlatform)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var ctx, cancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
|
defer cancel()
|
|
|
|
vals := map[string]interface{}{
|
|
"kubesphere": map[string]interface{}{"redis_password": redisPwd},
|
|
"backup": map[string]interface{}{
|
|
"bucket": t.KubeConf.Arg.Storage.BackupClusterBucket,
|
|
"key_prefix": t.KubeConf.Arg.Storage.StoragePrefix,
|
|
"is_cloud_version": cloudValue(t.KubeConf.Arg.IsCloudInstance),
|
|
"sync_secret": t.KubeConf.Arg.Storage.StorageSyncSecret,
|
|
},
|
|
"gpu": getGpuType(t.KubeConf.Arg.GPU.Enable),
|
|
"s3_bucket": t.KubeConf.Arg.Storage.StorageBucket,
|
|
"fs_type": getRootFSType(),
|
|
common.HelmValuesKeyTerminusGlobalEnvs: common.TerminusGlobalEnvs,
|
|
common.HelmValuesKeyOlaresRootFSPath: storage.OlaresRootDir,
|
|
}
|
|
|
|
if !runtime.GetSystemInfo().IsDarwin() {
|
|
vals["sharedlib"] = storage.OlaresSharedLibDir
|
|
}
|
|
|
|
var platformPath = path.Join(runtime.GetInstallerDir(), "wizard", "config", "os-platform")
|
|
if err := utils.UpgradeCharts(ctx, actionConfig, settings, common.ChartNameOSPlatform, platformPath, "", common.NamespaceOsPlatform, vals, false); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: wait for the platform to be ready
|
|
|
|
actionConfig, settings, err = utils.InitConfig(config, common.NamespaceOsFramework)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ctx, cancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
|
defer cancel()
|
|
var frameworkPath = path.Join(runtime.GetInstallerDir(), "wizard", "config", "os-framework")
|
|
if err := utils.UpgradeCharts(ctx, actionConfig, settings, common.ChartNameOSFramework, frameworkPath, "", common.NamespaceOsFramework, vals, false); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type CreateBackupConfigMap struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (t *CreateBackupConfigMap) Execute(runtime connector.Runtime) error {
|
|
var backupConfigMapFile = path.Join(runtime.GetInstallerDir(), "deploy", configmaptemplates.BackupConfigMap.Name())
|
|
var data = util.Data{
|
|
"CloudInstance": cloudValue(t.KubeConf.Arg.IsCloudInstance),
|
|
"StorageBucket": t.KubeConf.Arg.Storage.BackupClusterBucket,
|
|
"StoragePrefix": t.KubeConf.Arg.Storage.StoragePrefix,
|
|
"StorageSyncSecret": t.KubeConf.Arg.Storage.StorageSyncSecret,
|
|
}
|
|
|
|
backupConfigStr, err := util.Render(configmaptemplates.BackupConfigMap, data)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "render backup configmap template failed")
|
|
}
|
|
if err := util.WriteFile(backupConfigMapFile, []byte(backupConfigStr), cc.FileMode0644); err != nil {
|
|
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("write backup configmap %s failed", backupConfigMapFile))
|
|
}
|
|
|
|
var kubectl, _ = util.GetCommand(common.CommandKubectl)
|
|
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, backupConfigMapFile), false, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type CreateReverseProxyConfigMap struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (c *CreateReverseProxyConfigMap) Execute(runtime connector.Runtime) error {
|
|
var defaultReverseProxyConfigMapFile = path.Join(runtime.GetInstallerDir(), "deploy", configmaptemplates.ReverseProxyConfigMap.Name())
|
|
var data = util.Data{
|
|
"EnableCloudflare": c.KubeConf.Arg.Cloudflare.Enable,
|
|
"EnableFrp": c.KubeConf.Arg.Frp.Enable,
|
|
"FrpServer": c.KubeConf.Arg.Frp.Server,
|
|
"FrpPort": c.KubeConf.Arg.Frp.Port,
|
|
"FrpAuthMethod": c.KubeConf.Arg.Frp.AuthMethod,
|
|
"FrpAuthToken": c.KubeConf.Arg.Frp.AuthToken,
|
|
}
|
|
|
|
reverseProxyConfigStr, err := util.Render(configmaptemplates.ReverseProxyConfigMap, data)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "render default reverse proxy configmap template failed")
|
|
}
|
|
if err := util.WriteFile(defaultReverseProxyConfigMapFile, []byte(reverseProxyConfigStr), cc.FileMode0644); err != nil {
|
|
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("write default reverse proxy configmap %s failed", defaultReverseProxyConfigMapFile))
|
|
}
|
|
|
|
var kubectl, _ = util.GetCommand(common.CommandKubectl)
|
|
if _, err := runtime.GetRunner().SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, defaultReverseProxyConfigMapFile), false, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type Patch struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (p *Patch) Execute(runtime connector.Runtime) error {
|
|
var err error
|
|
var kubectl, _ = util.GetCommand(common.CommandKubectl)
|
|
var globalRoleWorkspaceManager = path.Join(runtime.GetInstallerDir(), "deploy", "patch-globalrole-workspace-manager.yaml")
|
|
if _, err = runtime.GetRunner().SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, globalRoleWorkspaceManager), false, true); err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "patch globalrole workspace manager failed")
|
|
}
|
|
|
|
//var notificationManager = path.Join(runtime.GetInstallerDir(), "deploy", "patch-notification-manager.yaml")
|
|
//if _, err = runtime.GetRunner().SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, notificationManager), false, true); err != nil {
|
|
// return errors.Wrap(errors.WithStack(err), "patch notification manager failed")
|
|
//}
|
|
//var notificationManager = path.Join(runtime.GetInstallerDir(), "deploy", "patch-notification-manager.yaml")
|
|
//if _, err = runtime.GetRunner().Host.SudoCmd(fmt.Sprintf("%s apply -f %s", kubectl, notificationManager), false, true); err != nil {
|
|
// return errors.Wrap(errors.WithStack(err), "patch notification manager failed")
|
|
//}
|
|
//
|
|
//patchAdminContent := `{"metadata":{"finalizers":["finalizers.kubesphere.io/users"]}}`
|
|
//patchAdminCMD := fmt.Sprintf(
|
|
// "%s patch user admin -p '%s' --type='merge' ",
|
|
// kubectl,
|
|
// patchAdminContent)
|
|
//_, err = runtime.GetRunner().SudoCmd(patchAdminCMD, false, true)
|
|
//if err != nil {
|
|
// return errors.Wrap(errors.WithStack(err), "patch user admin failed")
|
|
//}
|
|
//patchAdminContent := "{\\\"metadata\\\":{\\\"finalizers\\\":[\\\"finalizers.kubesphere.io/users\\\"]}}"
|
|
//patchAdminCMD := fmt.Sprintf(
|
|
// "%s patch user admin -p '%s' --type='merge' ",
|
|
// kubectl,
|
|
// patchAdminContent)
|
|
//_, err = runtime.GetRunner().Host.SudoCmd(patchAdminCMD, false, true)
|
|
//if err != nil {
|
|
// return errors.Wrap(errors.WithStack(err), "patch user admin failed")
|
|
//}
|
|
|
|
//deleteAdminCMD := fmt.Sprintf("%s delete user admin --ignore-not-found", kubectl)
|
|
//_, err = runtime.GetRunner().SudoCmd(deleteAdminCMD, false, true)
|
|
//if err != nil {
|
|
// return errors.Wrap(errors.WithStack(err), "failed to delete ks admin user")
|
|
//}
|
|
deleteKubectlAdminCMD := fmt.Sprintf("%s -n kubesphere-controls-system delete deploy kubectl-admin --ignore-not-found", kubectl)
|
|
_, err = runtime.GetRunner().SudoCmd(deleteKubectlAdminCMD, false, true)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "failed to delete ks kubectl admin deployment")
|
|
}
|
|
deleteHTTPBackendCMD := fmt.Sprintf("%s -n kubesphere-controls-system delete deploy default-http-backend --ignore-not-found", kubectl)
|
|
_, err = runtime.GetRunner().SudoCmd(deleteHTTPBackendCMD, false, true)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "failed to delete ks default http backend")
|
|
}
|
|
|
|
patchFelixConfigContent := `{"spec":{"featureDetectOverride": "SNATFullyRandom=false,MASQFullyRandom=false"}}`
|
|
patchFelixConfigCMD := fmt.Sprintf(
|
|
"%s patch felixconfiguration default -p '%s' --type='merge'",
|
|
kubectl,
|
|
patchFelixConfigContent,
|
|
)
|
|
_, err = runtime.GetRunner().SudoCmd(patchFelixConfigCMD, false, true)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "failed to patch felix configuration")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type InstallOsSystemModule struct {
|
|
common.KubeModule
|
|
}
|
|
|
|
func (m *InstallOsSystemModule) Init() {
|
|
logger.InfoInstallationProgress("Installing appservice ...")
|
|
m.Name = "InstallOsSystemModule"
|
|
|
|
installOsSystem := &task.LocalTask{
|
|
Name: "InstallOsSystem",
|
|
Action: &InstallOsSystem{},
|
|
Retry: 1,
|
|
}
|
|
|
|
createBackupConfigMap := &task.LocalTask{
|
|
Name: "CreateBackupConfigMap",
|
|
Action: &CreateBackupConfigMap{},
|
|
}
|
|
|
|
createReverseProxyConfigMap := &task.LocalTask{
|
|
Name: "CreateReverseProxyConfigMap",
|
|
Action: &CreateReverseProxyConfigMap{},
|
|
}
|
|
|
|
checkSystemService := &task.LocalTask{
|
|
Name: "CheckSystemServiceStatus",
|
|
Action: &CheckPodsRunning{
|
|
labels: map[string][]string{
|
|
"os-framework": {"tier=app-service"},
|
|
},
|
|
},
|
|
Retry: 20,
|
|
Delay: 10 * time.Second,
|
|
}
|
|
|
|
patchOs := &task.LocalTask{
|
|
Name: "PatchOs",
|
|
Action: &Patch{},
|
|
Retry: 3,
|
|
Delay: 30 * time.Second,
|
|
}
|
|
|
|
m.Tasks = []task.Interface{
|
|
installOsSystem,
|
|
createBackupConfigMap,
|
|
createReverseProxyConfigMap,
|
|
checkSystemService,
|
|
patchOs,
|
|
}
|
|
}
|
|
|
|
func getGpuType(gpuEnable bool) (gpuType string) {
|
|
if gpuEnable {
|
|
return "nvidia"
|
|
}
|
|
return "none"
|
|
}
|
|
|
|
func cloudValue(cloudInstance bool) string {
|
|
if cloudInstance {
|
|
return "true"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func getRootFSType() string {
|
|
if util.IsExist(storage.JuiceFsServiceFile) {
|
|
return "jfs"
|
|
}
|
|
return "fs"
|
|
}
|
|
|
|
func getRedisPassword(client clientset.Client, runtime connector.Runtime) (string, error) {
|
|
secret, err := client.Kubernetes().CoreV1().Secrets(common.NamespaceKubesphereSystem).Get(context.Background(), "redis-secret", metav1.GetOptions{})
|
|
if err != nil {
|
|
return "", errors.Wrap(errors.WithStack(err), "get redis secret failed")
|
|
}
|
|
if secret == nil || secret.Data == nil || secret.Data["auth"] == nil {
|
|
return "", fmt.Errorf("redis secret not found")
|
|
}
|
|
|
|
return string(secret.Data["auth"]), nil
|
|
|
|
}
|