github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/cluster/update_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package cluster
    21  
    22  import (
    23  	. "github.com/onsi/ginkgo/v2"
    24  	. "github.com/onsi/gomega"
    25  	"github.com/spf13/cobra"
    26  	"k8s.io/cli-runtime/pkg/genericiooptions"
    27  	"k8s.io/client-go/dynamic"
    28  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    29  
    30  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    31  
    32  	"github.com/1aal/kubeblocks/pkg/cli/patch"
    33  	"github.com/1aal/kubeblocks/pkg/cli/testing"
    34  	"github.com/1aal/kubeblocks/pkg/cli/types"
    35  )
    36  
    37  var _ = Describe("cluster update", func() {
    38  	var streams genericiooptions.IOStreams
    39  	var tf *cmdtesting.TestFactory
    40  
    41  	BeforeEach(func() {
    42  		streams, _, _, _ = genericiooptions.NewTestIOStreams()
    43  		tf = cmdtesting.NewTestFactory().WithNamespace("default")
    44  	})
    45  
    46  	AfterEach(func() {
    47  		tf.Cleanup()
    48  	})
    49  
    50  	It("update command", func() {
    51  		cmd := NewUpdateCmd(tf, streams)
    52  		Expect(cmd).ShouldNot(BeNil())
    53  	})
    54  
    55  	Context("complete", func() {
    56  		var o *updateOptions
    57  		var cmd *cobra.Command
    58  		var args []string
    59  		BeforeEach(func() {
    60  			cmd = NewUpdateCmd(tf, streams)
    61  			o = &updateOptions{Options: patch.NewOptions(tf, streams, types.ClusterGVR())}
    62  			args = []string{"c1"}
    63  
    64  		})
    65  
    66  		It("args is empty", func() {
    67  			Expect(o.complete(cmd, nil)).Should(HaveOccurred())
    68  		})
    69  
    70  		It("the length of args greater than 1", func() {
    71  			Expect(o.complete(cmd, []string{"c1", "c2"})).Should(HaveOccurred())
    72  		})
    73  
    74  		It("args only contains one cluster name", func() {
    75  			Expect(o.complete(cmd, args)).Should(Succeed())
    76  			Expect(o.Names[0]).Should(Equal("c1"))
    77  		})
    78  
    79  		It("set termination-policy", func() {
    80  			Expect(cmd.Flags().Set("termination-policy", "Delete")).Should(Succeed())
    81  			Expect(o.complete(cmd, args)).Should(Succeed())
    82  			Expect(o.namespace).Should(Equal("default"))
    83  			Expect(o.dynamic).ShouldNot(BeNil())
    84  			Expect(o.Patch).Should(ContainSubstring("terminationPolicy"))
    85  		})
    86  
    87  		It("set monitoring interval", func() {
    88  			fakeCluster := testing.FakeCluster("c1", "default")
    89  			tf.FakeDynamicClient = testing.FakeDynamicClient(fakeCluster)
    90  			Expect(cmd.Flags().Set("monitoring-interval", "15")).Should(Succeed())
    91  			Expect(o.complete(cmd, args)).Should(Succeed())
    92  			Expect(o.Patch).Should(ContainSubstring("\"monitor\":true"))
    93  		})
    94  
    95  		It("set enable-all-logs", func() {
    96  			fakeCluster := testing.FakeCluster("c1", "default")
    97  			tf.FakeDynamicClient = testing.FakeDynamicClient(fakeCluster)
    98  			Expect(cmd.Flags().Set("enable-all-logs", "false")).Should(Succeed())
    99  			Expect(o.complete(cmd, args)).Should(Succeed())
   100  		})
   101  
   102  		It("set node-labels", func() {
   103  			fakeCluster := testing.FakeCluster("c1", "default")
   104  			tf.FakeDynamicClient = testing.FakeDynamicClient(fakeCluster)
   105  			Expect(cmd.Flags().Set("node-labels", "k1=v1,k2=v2")).Should(Succeed())
   106  			Expect(o.complete(cmd, args)).Should(Succeed())
   107  			Expect(o.Patch).Should(ContainSubstring("k1"))
   108  		})
   109  	})
   110  	Context("logs variables reconfiguring tests", func() {
   111  		var (
   112  			c        *appsv1alpha1.Cluster
   113  			cd       *appsv1alpha1.ClusterDefinition
   114  			myConfig string
   115  		)
   116  		BeforeEach(func() {
   117  			c = testing.FakeCluster("c1", "default")
   118  			cd = testing.FakeClusterDef()
   119  			myConfig = `
   120  {{ block "logsBlock" . }}
   121  log_statements_unsafe_for_binlog=OFF
   122  log_error_verbosity=2
   123  log_output=FILE
   124  {{- if hasKey $.component "enabledLogs" }}
   125  {{- if mustHas "error" $.component.enabledLogs }}
   126  log_error=/data/mysql/log/mysqld-error.log
   127  {{- end }}
   128  {{- if mustHas "slow" $.component.enabledLogs }}
   129  slow_query_log=ON
   130  long_query_time=5
   131  slow_query_log_file=/data/mysql/log/mysqld-slowquery.log
   132  {{- end }}
   133  {{- if mustHas "general" $.component.enabledLogs }}
   134  general_log=ON
   135  general_log_file=/data/mysql/log/mysqld.log
   136  {{- end }}
   137  {{- end }}
   138  {{ end }}
   139  `
   140  		})
   141  
   142  		It("findFirstConfigSpec tests", func() {
   143  			tests := []struct {
   144  				compSpecs   []appsv1alpha1.ClusterComponentSpec
   145  				cdCompSpecs []appsv1alpha1.ClusterComponentDefinition
   146  				compName    string
   147  				expectedErr bool
   148  			}{
   149  				{
   150  					compSpecs:   nil,
   151  					cdCompSpecs: nil,
   152  					compName:    "name",
   153  					expectedErr: true,
   154  				},
   155  				{
   156  					compSpecs:   c.Spec.ComponentSpecs,
   157  					cdCompSpecs: cd.Spec.ComponentDefs,
   158  					compName:    testing.ComponentName,
   159  					expectedErr: false,
   160  				},
   161  				{
   162  					compSpecs:   c.Spec.ComponentSpecs,
   163  					cdCompSpecs: cd.Spec.ComponentDefs,
   164  					compName:    "error-name",
   165  					expectedErr: true,
   166  				},
   167  			}
   168  			for _, test := range tests {
   169  				configSpec, err := findFirstConfigSpec(test.compSpecs, test.cdCompSpecs, test.compName)
   170  				if test.expectedErr {
   171  					Expect(err).Should(HaveOccurred())
   172  				} else {
   173  					Expect(configSpec).ShouldNot(BeNil())
   174  					Expect(err).ShouldNot(HaveOccurred())
   175  				}
   176  			}
   177  		})
   178  
   179  		It("findConfigTemplateInfo tests", func() {
   180  			tests := []struct {
   181  				dynamic     dynamic.Interface
   182  				configSpec  *appsv1alpha1.ComponentConfigSpec
   183  				expectedErr bool
   184  			}{{
   185  				dynamic:     nil,
   186  				configSpec:  nil,
   187  				expectedErr: true,
   188  			}, {
   189  				dynamic: testing.FakeDynamicClient(testing.FakeConfigMap("config-template", testing.Namespace, map[string]string{"fake": "fake"})),
   190  				configSpec: &appsv1alpha1.ComponentConfigSpec{
   191  					ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
   192  						TemplateRef: "config-template",
   193  						Namespace:   testing.Namespace,
   194  					},
   195  				},
   196  				expectedErr: true,
   197  			}, {
   198  				dynamic: testing.FakeDynamicClient(testing.FakeConfigMap("config-template", testing.Namespace, map[string]string{"fake": "fake"})),
   199  				configSpec: &appsv1alpha1.ComponentConfigSpec{
   200  					ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
   201  						TemplateRef: "config-template",
   202  						Namespace:   testing.Namespace,
   203  					},
   204  				},
   205  				expectedErr: true,
   206  			}, {
   207  				dynamic: testing.FakeDynamicClient(testing.FakeConfigMap("config-template", testing.Namespace, map[string]string{"fake": "fake"}), testing.FakeConfigConstraint("config-constraint")),
   208  				configSpec: &appsv1alpha1.ComponentConfigSpec{
   209  					ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
   210  						TemplateRef: "config-template",
   211  
   212  						Namespace: testing.Namespace,
   213  					},
   214  					ConfigConstraintRef: "config-constraint",
   215  				},
   216  				expectedErr: false,
   217  			}}
   218  			for _, test := range tests {
   219  				cm, format, err := findConfigTemplateInfo(test.dynamic, test.configSpec)
   220  				if test.expectedErr {
   221  					Expect(err).Should(HaveOccurred())
   222  				} else {
   223  					Expect(cm).ShouldNot(BeNil())
   224  					Expect(format).ShouldNot(BeNil())
   225  					Expect(err).ShouldNot(HaveOccurred())
   226  				}
   227  			}
   228  		})
   229  
   230  		It("findLogsBlockTPL tests", func() {
   231  			tests := []struct {
   232  				confData    map[string]string
   233  				keyName     string
   234  				expectedErr bool
   235  				expectedNil bool
   236  			}{{
   237  				confData:    nil,
   238  				keyName:     "",
   239  				expectedErr: false,
   240  				expectedNil: true,
   241  			}, {
   242  				confData: map[string]string{
   243  					"test.cnf": "test",
   244  					"my.cnf":   "{{ logsBlock",
   245  				},
   246  				keyName:     "my.cnf",
   247  				expectedErr: true,
   248  			}, {
   249  				confData: map[string]string{
   250  					"my.cnf": myConfig,
   251  				},
   252  				keyName:     "my.cnf",
   253  				expectedErr: false,
   254  			},
   255  			}
   256  			for _, test := range tests {
   257  				key, tpl, err := findLogsBlockTPL(test.confData)
   258  				if test.expectedErr {
   259  					Expect(err).Should(HaveOccurred())
   260  				} else {
   261  					Expect(key).Should(Equal(test.keyName))
   262  					if !test.expectedNil {
   263  						Expect(tpl).ShouldNot(BeNil())
   264  					}
   265  					Expect(err).ShouldNot(HaveOccurred())
   266  				}
   267  			}
   268  		})
   269  
   270  		It("buildLogsTPLValues tests", func() {
   271  			configSpec := testing.FakeCluster("test", "test").Spec.ComponentSpecs[0]
   272  			tplValue, err := buildLogsTPLValues(&configSpec)
   273  			Expect(err).ShouldNot(HaveOccurred())
   274  			Expect(tplValue).ShouldNot(BeNil())
   275  		})
   276  
   277  		It("buildLogsReconfiguringOps tests", func() {
   278  			opsRequest := buildLogsReconfiguringOps("clusterName", "namespace", "compName", "configName", "keyName", map[string]string{"key1": "value1", "key2": "value2"})
   279  			Expect(opsRequest).ShouldNot(BeNil())
   280  			Expect(opsRequest.Spec.Reconfigure.ComponentName).Should(Equal("compName"))
   281  			Expect(opsRequest.Spec.Reconfigure.Configurations).Should(HaveLen(1))
   282  			Expect(opsRequest.Spec.Reconfigure.Configurations[0].Keys).Should(HaveLen(1))
   283  			Expect(opsRequest.Spec.Reconfigure.Configurations[0].Keys[0].Parameters).Should(HaveLen(2))
   284  		})
   285  
   286  	})
   287  })