Skip to content

Commit

Permalink
Add support set host or member cluster (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
LinuxSuRen committed Apr 10, 2021
1 parent 35ca477 commit ab24479
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 23 deletions.
34 changes: 34 additions & 0 deletions kubectl-plugin/common/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package common

// KSInstaller is the installer for KubeSphere
type KSInstaller struct {
Spec KSInstallerSpec `yaml:"spec"`
}

// KSInstallerSpec is ks-installer
type KSInstallerSpec struct {
Version string
ImageNamespace string

Servicemesh ComponentStatus
Openpitrix ComponentStatus
Notification ComponentStatus
NetworkPolicy ComponentStatus
MetricsServer ComponentStatus
Logging ComponentStatus
Events ComponentStatus
DevOps ComponentStatus
Auditing ComponentStatus
Alerting ComponentStatus
Multicluster Multicluster `yaml:"multicluster"`
}

// ComponentStatus is a common status
type ComponentStatus struct {
Enabled bool
}

// Multicluster represents multi-cluster
type Multicluster struct {
ClusterRole string `yaml:"clusterRole"`
}
124 changes: 124 additions & 0 deletions kubectl-plugin/config/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package config

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"github.com/linuxsuren/ks/kubectl-plugin/common"
kstypes "github.com/linuxsuren/ks/kubectl-plugin/types"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/dynamic"
"sigs.k8s.io/yaml"
)

func newClusterCmd(client dynamic.Interface) (cmd *cobra.Command) {
opt := clusterOption{
client: client,
}

cmd = &cobra.Command{
Use: "cluster",
Short: "Set multi cluster",
RunE: opt.runE,
PostRunE: opt.postRunE,
}

flags := cmd.Flags()
flags.StringVarP(&opt.role, "role", "r", "",
"Set current KubeSphere cluster as your desired role (none, host, member)")
flags.StringVarP(&opt.jwtSecret, "jwtSecret", "", "",
"Need this if you want to set the cluster as the member role")

_ = cmd.RegisterFlagCompletionFunc("role", common.ArrayCompletion("none", "host", "member"))
return
}

func (o *clusterOption) runE(cmd *cobra.Command, args []string) (err error) {
switch o.role {
case "member":
if o.jwtSecret == "" {
err = errors.New("please provide the jwtSecret from the host cluster")
} else {
err = o.updateJwtSecret()
}

if err != nil {
return
}
fallthrough
case "none", "host":
err = o.updateClusterRole()
case "":
default:
err = fmt.Errorf("invalid cluster role: %s", o.role)
}
return
}

func (o *clusterOption) postRunE(cmd *cobra.Command, args []string) (err error) {
err = o.showClusterRole()
return
}

func (o *clusterOption) updateJwtSecret() (err error) {
patch := fmt.Sprintf(`[{"op": "replace", "path": "/spec/authentication/jwtSecret", "value": "%s"}]`, o.jwtSecret)
ctx := context.TODO()
_, err = o.client.Resource(kstypes.GetClusterConfiguration()).Namespace("kubesphere-system").Patch(ctx,
"ks-installer", types.JSONPatchType,
[]byte(patch),
metav1.PatchOptions{})
return
}

func (o *clusterOption) updateClusterRole() (err error) {
patch := fmt.Sprintf(`[{"op": "replace", "path": "/spec/multicluster/clusterRole", "value": "%s"}]`, o.role)
ctx := context.TODO()
_, err = o.client.Resource(kstypes.GetClusterConfiguration()).Namespace("kubesphere-system").Patch(ctx,
"ks-installer", types.JSONPatchType,
[]byte(patch),
metav1.PatchOptions{})
return
}

func (o *clusterOption) showClusterRole() (err error) {
ctx := context.TODO()
var rawData *unstructured.Unstructured
if rawData, err = o.client.Resource(kstypes.GetClusterConfiguration()).Namespace("kubesphere-system").
Get(ctx, "ks-installer", metav1.GetOptions{}); err == nil {
var data []byte
buf := bytes.NewBuffer(data)
enc := json.NewEncoder(buf)
if err = enc.Encode(rawData); err != nil {
return
}

var yamlData []byte
if yamlData, err = yaml.JSONToYAML(buf.Bytes()); err != nil {
return
}

installer := common.KSInstaller{}
if err = yaml.Unmarshal(yamlData, &installer); err == nil {
fmt.Printf("cluster role: %s\n", installer.Spec.Multicluster.ClusterRole)
}
}

var rawConfigMap *unstructured.Unstructured
if rawConfigMap, err = o.client.Resource(kstypes.GetConfigMapSchema()).Namespace("kubesphere-system").
Get(context.TODO(), "kubesphere-config", metav1.GetOptions{}); err == nil {
data := rawConfigMap.Object["data"]
dataMap := data.(map[string]interface{})
kubeSphereCfg := dataMap["kubesphere.yaml"]

cfg := kubeSphereConfig{}
if err = yaml.Unmarshal([]byte(fmt.Sprintf("%v", kubeSphereCfg)), &cfg); err == nil {
fmt.Printf("jwtSecret: %s\n", cfg.Authentication.JwtSecret)
}
}
return
}
18 changes: 18 additions & 0 deletions kubectl-plugin/config/config_root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package config

import (
"github.com/spf13/cobra"
"k8s.io/client-go/dynamic"
)

// NewConfigRootCmd returns the config command
func NewConfigRootCmd(client dynamic.Interface) (cmd *cobra.Command) {
cmd = &cobra.Command{
Use: "option",
Short: "Config KubeSphere as you need",
Aliases: []string{"opt"},
}

cmd.AddCommand(newClusterCmd(client))
return
}
19 changes: 19 additions & 0 deletions kubectl-plugin/config/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package config

import "k8s.io/client-go/dynamic"

type clusterOption struct {
role string
jwtSecret string

// inner fields
client dynamic.Interface
}

type kubeSphereConfig struct {
Authentication authentication
}

type authentication struct {
JwtSecret string
}
4 changes: 3 additions & 1 deletion kubectl-plugin/entrypoint/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/linuxsuren/ks/kubectl-plugin/auth"
"github.com/linuxsuren/ks/kubectl-plugin/common"
"github.com/linuxsuren/ks/kubectl-plugin/component"
"github.com/linuxsuren/ks/kubectl-plugin/config"
"github.com/linuxsuren/ks/kubectl-plugin/install"
"github.com/linuxsuren/ks/kubectl-plugin/pipeline"
"github.com/linuxsuren/ks/kubectl-plugin/registry"
Expand Down Expand Up @@ -46,6 +47,7 @@ See also https://github.com/kubesphere/kubesphere`,
registry.NewRegistryCmd(client),
auth.NewAuthCmd(client),
tool.NewToolCmd(),
install.NewInstallCmd())
install.NewInstallCmd(),
config.NewConfigRootCmd(client))
return
}
24 changes: 2 additions & 22 deletions kubectl-plugin/install/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type installerOption struct {

// inner fields
client dynamic.Interface
ksInstaller ksInstaller
ksInstaller common.KSInstallerSpec
}

func (o *installerOption) preRunE(_ *cobra.Command, args []string) (err error) {
Expand All @@ -54,7 +54,7 @@ func (o *installerOption) preRunE(_ *cobra.Command, args []string) (err error) {
_, o.nightly = common.GetNightlyTag(o.nightly)

// parse the ks-installer
o.ksInstaller = ksInstaller{
o.ksInstaller = common.KSInstallerSpec{
Version: o.version,
ImageNamespace: "kubesphere",
}
Expand Down Expand Up @@ -142,26 +142,6 @@ func (o *installerOption) runE(_ *cobra.Command, args []string) (err error) {
return
}

type ksInstaller struct {
Version string
ImageNamespace string

Servicemesh componentStatus
Openpitrix componentStatus
Notification componentStatus
NetworkPolicy componentStatus
MetricsServer componentStatus
Logging componentStatus
Events componentStatus
DevOps componentStatus
Auditing componentStatus
Alerting componentStatus
}

type componentStatus struct {
Enabled bool
}

var localStorageClass = `
apiVersion: storage.k8s.io/v1
kind: StorageClass
Expand Down

0 comments on commit ab24479

Please sign in to comment.