Skip to content

Commit

Permalink
fix: connect with wrong role after kb upgrade (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
1aal authored Dec 26, 2023
1 parent 0af9e3b commit 757341c
Show file tree
Hide file tree
Showing 22 changed files with 212 additions and 196 deletions.
11 changes: 11 additions & 0 deletions docs/user_docs/cli/kbcli_cluster_create_redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,23 @@ kbcli cluster create redis NAME [flags]
--memory float Memory, the unit is Gi. Value range [0.5, 1000]. (default 0.5)
--mode string Cluster topology mode. Legal values [standalone, replication]. (default "standalone")
--monitoring-interval int The monitoring interval of cluster, 0 is disabled, the unit is second. Value range [0, 60].
--node-port-enabled Whether NodePort service is enabled, default is true
--publicly-accessible Specify whether the cluster can be accessed from the public internet.
--rbac-enabled Specify whether rbac resources will be created by client, otherwise KubeBlocks server will try to create rbac resources.
--replicas int The number of replicas, for standalone mode, the replicas is 1, for replication mode, the default replicas is 2. Value range [1, 5]. (default 1)
--sentinel.cpu float Sentinel component cpu cores. Value range [0.1, 8]. (default 0.2)
--sentinel.enabled Whether have sentinel component, default is true (default true)
--sentinel.memory float Sentinel component memory, the unit is Gi. Value range [0.1, 4]. (default 0.2)
--sentinel.replicas float Sentinel component replicas Value range [1, 5]. (default 3)
--sentinel.storage float Sentinel component storage size, the unit is Gi. Value range [1, 10]. (default 5)
--storage float Storage size, the unit is Gi. Value range [1, 10000]. (default 20)
--tenancy string The tenancy of cluster. Legal values [SharedNode, DedicatedNode]. (default "SharedNode")
--termination-policy string The termination policy of cluster. Legal values [DoNotTerminate, Halt, Delete, WipeOut]. (default "Delete")
--twemproxy.cpu float twemproxy component cpu cores. Value range [0.1, 8]. (default 0.2)
--twemproxy.enabled Whether have twemproxy component, default is false
--twemproxy.memory float twemproxy component memory, the unit is Gi. Value range [0.1, 4]. (default 0.2)
--twemproxy.replicas float twemproxy component replicas Value range [1, 5]. (default 3)
--use-legacy-comp-def if useLegacyCompDef is false ,cluster will be rendered by compDef rather than componentDefRef in cluster definition
--version string Cluster version.
```

Expand Down
Binary file modified pkg/cluster/charts/oceanbase-cluster.tgz
Binary file not shown.
Binary file modified pkg/cluster/charts/redis-cluster.tgz
Binary file not shown.
70 changes: 50 additions & 20 deletions pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,25 @@ import (
// ConditionsError cluster displays this status on list cmd when the status of ApplyResources or ProvisioningStarted condition is "False".
const ConditionsError = "ConditionsError"

type TypeNeed int

const (
NoNeed = iota
Need
Maybe
)

type GetOptions struct {
WithClusterDef bool
WithClusterVersion bool
WithConfigMap bool
WithPVC bool
WithService bool
WithSecret bool
WithPod bool
WithEvent bool
WithDataProtection bool
WithCompDef bool
WithClusterDef TypeNeed
WithClusterVersion TypeNeed
WithConfigMap TypeNeed
WithPVC TypeNeed
WithService TypeNeed
WithSecret TypeNeed
WithPod TypeNeed
WithEvent TypeNeed
WithDataProtection TypeNeed
WithCompDef TypeNeed
}

type ObjectsGetter struct {
Expand Down Expand Up @@ -132,7 +140,7 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
objs.Cluster.Status.Phase = ConditionsError
}
// get cluster definition
if o.WithClusterDef {
if o.WithClusterDef == Need {
cd := &appsv1alpha1.ClusterDefinition{}
if err = getResource(types.ClusterDefGVR(), objs.Cluster.Spec.ClusterDefRef, "", cd); err != nil {
return nil, err
Expand All @@ -141,7 +149,7 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}

// get cluster version
if o.WithClusterVersion {
if o.WithClusterVersion == Need {
v := &appsv1alpha1.ClusterVersion{}
if err = getResource(types.ClusterVersionGVR(), objs.Cluster.Spec.ClusterVersionRef, "", v); err != nil {
return nil, err
Expand All @@ -150,35 +158,35 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}

// get services
if o.WithService {
if o.WithService == Need {
if objs.Services, err = client.Services(o.Namespace).List(ctx, listOpts()); err != nil {
return nil, err
}
}

// get secrets
if o.WithSecret {
if o.WithSecret == Need {
if objs.Secrets, err = client.Secrets(o.Namespace).List(ctx, listOpts()); err != nil {
return nil, err
}
}

// get configmaps
if o.WithConfigMap {
if o.WithConfigMap == Need {
if objs.ConfigMaps, err = client.ConfigMaps(o.Namespace).List(ctx, listOpts()); err != nil {
return nil, err
}
}

// get PVCs
if o.WithPVC {
if o.WithPVC == Need {
if objs.PVCs, err = client.PersistentVolumeClaims(o.Namespace).List(ctx, listOpts()); err != nil {
return nil, err
}
}

// get pods
if o.WithPod {
if o.WithPod == Need {
if objs.Pods, err = client.Pods(o.Namespace).List(ctx, listOpts()); err != nil {
return nil, err
}
Expand Down Expand Up @@ -217,7 +225,7 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}

// get events
if o.WithEvent {
if o.WithEvent == Need {
// get all events of cluster
if objs.Events, err = client.Events(o.Namespace).Search(scheme.Scheme, objs.Cluster); err != nil {
return nil, err
Expand All @@ -237,7 +245,7 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}
}

if o.WithDataProtection {
if o.WithDataProtection == Need {
dpListOpts := metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s",
constant.AppInstanceLabelKey, o.Name),
Expand All @@ -261,7 +269,7 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}
}

if o.WithCompDef {
if o.WithCompDef == Need {
comps := []*appsv1alpha1.ComponentDefinition{}
if err = listResources(o.Dynamic, types.CompDefGVR(), "", metav1.ListOptions{}, &comps); err != nil {
return nil, err
Expand All @@ -275,6 +283,28 @@ func (o *ObjectsGetter) Get() (*ClusterObjects, error) {
}
}
}
// get cluster definition
if o.WithClusterDef == Maybe {
cd := &appsv1alpha1.ClusterDefinition{}
if err = getResource(types.ClusterDefGVR(), objs.Cluster.Spec.ClusterDefRef, "", cd); err == nil {
objs.ClusterDef = cd
}
}

if o.WithCompDef == Maybe {
comps := []*appsv1alpha1.ComponentDefinition{}
if err = listResources(o.Dynamic, types.CompDefGVR(), "", metav1.ListOptions{}, &comps); err == nil {
for _, compSpec := range objs.Cluster.Spec.ComponentSpecs {
for _, comp := range comps {
if compSpec.ComponentDef == comp.Name {
objs.CompDef = append(objs.CompDef, comp)
break
}
}
}
}
}

return objs, nil
}

Expand Down
34 changes: 3 additions & 31 deletions pkg/cluster/cluster_chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ import (
"github.com/apecloud/kbcli/pkg/util/helm"
)

const (
templatesDir = "templates"
clusterFile = "cluster.yaml"
)

type SchemaPropName string

// the common schema property name
Expand All @@ -66,6 +61,9 @@ type ChartInfo struct {
// ClusterDef is the cluster definition
ClusterDef string

// ComponentDef refer cluster component.spec[x].ComponentDef
ComponentDef []string

// Chart is the cluster helm chart object
Chart *chart.Chart

Expand Down Expand Up @@ -169,32 +167,6 @@ func (c *ChartInfo) buildClusterSchema() error {
return nil
}

func (c *ChartInfo) buildClusterDef() error {
cht := c.Chart
// We use embed FS to read chart's tgz files. In embed FS, the file path format is compatible with Linux and does not change with the operating system.
// Therefore, we cannot use filepath.Join to generate different path formats for different systems,
// instead, we need to use a path format that is the same as Linux.
clusterFilePath := templatesDir + "/" + clusterFile
for _, tpl := range cht.Templates {
if tpl.Name != clusterFilePath {
continue
}

// get cluster definition from cluster.yaml
pattern := " clusterDefinitionRef: "
str := string(tpl.Data)
start := strings.Index(str, pattern)
if start != -1 {
end := strings.IndexAny(str[start+len(pattern):], " \n")
if end != -1 {
c.ClusterDef = strings.TrimSpace(str[start+len(pattern) : start+len(pattern)+end])
return nil
}
}
}
return fmt.Errorf("failed to find the cluster definition of %s", cht.Name())
}

// ValidateValues validates the given values against the schema.
func ValidateValues(c *ChartInfo, values map[string]interface{}) error {
validateFn := func(s *spec.Schema, values map[string]interface{}) error {
Expand Down
16 changes: 8 additions & 8 deletions pkg/cluster/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ var _ = Describe("cluster util", func() {
testing.FakeClusterVersion())

getOptions := GetOptions{
WithClusterDef: true,
WithClusterVersion: true,
WithConfigMap: true,
WithService: true,
WithSecret: true,
WithPVC: true,
WithPod: true,
WithDataProtection: true,
WithClusterDef: Need,
WithClusterVersion: Need,
WithConfigMap: Need,
WithService: Need,
WithSecret: Need,
WithPVC: Need,
WithPod: Need,
WithDataProtection: Need,
}

It("get cluster objects", func() {
Expand Down
14 changes: 7 additions & 7 deletions pkg/cluster/external_charts.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func GetChartCacheFiles() []fs.DirEntry {
}

func ClearCharts(c ClusterType) {
// if the fail clusterType is from external config, remove the config and the elated charts
// if the fail clusterType is from external config, remove the config and the related charts
if GlobalClusterChartConfig.RemoveConfig(c) {
if err := GlobalClusterChartConfig.WriteConfigs(CliClusterChartConfig); err != nil {
klog.V(2).Info(fmt.Sprintf("Warning: auto clear %s config fail due to: %s\n", c, err.Error()))
Expand All @@ -166,6 +166,7 @@ type TypeInstance struct {

// PreCheck is used by `cluster register` command
func (h *TypeInstance) PreCheck() error {

chartInfo := &ChartInfo{}
// load helm chart from embed tgz file
{
Expand All @@ -188,16 +189,15 @@ func (h *TypeInstance) PreCheck() error {
if err := chartInfo.buildClusterSchema(); err != nil {
return err
}
if err := chartInfo.buildClusterDef(); err != nil {
return err
}

// pre-check build sub-command flags
if err := flags.BuildFlagsBySchema(&cobra.Command{}, chartInfo.Schema); err != nil {
return err
}

return flags.BuildFlagsBySchema(&cobra.Command{}, chartInfo.SubSchema)
err := flags.BuildFlagsBySchema(&cobra.Command{}, chartInfo.SubSchema)
if err != nil {
return err
}
return nil
}

func (h *TypeInstance) loadChart() (io.ReadCloser, error) {
Expand Down
87 changes: 23 additions & 64 deletions pkg/cluster/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,74 +49,10 @@ func GetSimpleInstanceInfos(dynamic dynamic.Interface, name, namespace string) [

// GetSimpleInstanceInfosForComponent returns simple instance info that only contains instance name and role for a component
func GetSimpleInstanceInfosForComponent(dynamic dynamic.Interface, name, componentName, namespace string) []*InstanceInfo {
// first get instance info from status, using the status as a cache
if infos := getInstanceInfoFromStatus(dynamic, name, componentName, namespace); len(infos) > 0 {
return infos
}

// missed in the status, try to list all pods and build instance info
return getInstanceInfoByList(dynamic, name, componentName, namespace)
}

// getInstancesInfoFromCluster gets instances info from cluster status
// Deprecated: getInstanceInfoFromStatus is deprecated. getInstanceInfoByList should be used instead.
func getInstanceInfoFromStatus(dynamic dynamic.Interface, name, componentName, namespace string) []*InstanceInfo {
var infos []*InstanceInfo
cluster, err := GetClusterByName(dynamic, name, namespace)
if err != nil {
return nil
}
// traverse all components, check the workload type
for compName, c := range cluster.Status.Components {
// filter by component name
if len(componentName) > 0 && compName != componentName {
continue
}

var info *InstanceInfo
// workload type is Consensus
if c.ConsensusSetStatus != nil {
buildInfoByStatus := func(status *appsv1alpha1.ConsensusMemberStatus) {
if status == nil {
return
}
info = &InstanceInfo{Role: status.Name, Name: status.Pod}
infos = append(infos, info)
}

// leader must be first
buildInfoByStatus(&c.ConsensusSetStatus.Leader)

// followers
for _, f := range c.ConsensusSetStatus.Followers {
buildInfoByStatus(&f)
}

// learner
buildInfoByStatus(c.ConsensusSetStatus.Learner)
}

// workload type is Replication
if c.ReplicationSetStatus != nil {
buildInfoByStatus := func(status *appsv1alpha1.ReplicationMemberStatus) {
if status == nil {
return
}
info = &InstanceInfo{Name: status.Pod}
infos = append(infos, info)
}
// primary
buildInfoByStatus(&c.ReplicationSetStatus.Primary)

// secondaries
for _, f := range c.ReplicationSetStatus.Secondaries {
buildInfoByStatus(&f)
}
}
}
return infos
}

// getInstanceInfoByList gets instances info by listing all pods
func getInstanceInfoByList(dynamic dynamic.Interface, name, componentName, namespace string) []*InstanceInfo {
var infos []*InstanceInfo
Expand Down Expand Up @@ -450,3 +386,26 @@ func GetDefaultServiceRef(cd *appsv1alpha1.ClusterDefinition) (string, error) {
}
return serviceRefs[0], nil
}

func GetDefaultVersionByCompDefs(dynamic dynamic.Interface, compDefs []string) (string, error) {
cv := ""
if compDefs == nil {
return "", fmt.Errorf("failed to find default cluster version referencing the nil compDefs")
}
for _, compDef := range compDefs {
comp, err := dynamic.Resource(types.CompDefGVR()).Get(context.Background(), compDef, metav1.GetOptions{})
if err != nil {
return "", fmt.Errorf("fail to get cluster version due to: %s", err.Error())
}
labels := comp.GetLabels()
kind := labels[constant.AppNameLabelKey]
version := labels[constant.AppVersionLabelKey]
// todo: fix cv like: mongodb-sharding-5.0, ac-mysql-8.0.30-auditlog
if cv == "" {
cv = fmt.Sprintf("%s-%s", kind, version)
} else if cv != fmt.Sprintf("%s-%s", kind, version) {
return "", fmt.Errorf("can't get the same cluster version by component definition:[%s]", strings.Join(compDefs, ","))
}
}
return cv, nil
}
Loading

0 comments on commit 757341c

Please sign in to comment.