How to use Label method of ginkgo Package

Best Ginkgo code snippet using ginkgo.Label

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

serial.go

Source: serial.go Github

copy
1// Copyright 2019 PingCAP, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package tidbcluster
15
16import (
17	"context"
18	"fmt"
19	_ "net/http/pprof"
20	"strings"
21	"time"
22
23	"github.com/onsi/ginkgo"
24	"github.com/onsi/gomega"
25	asclientset "github.com/pingcap/advanced-statefulset/client/client/clientset/versioned"
26	"github.com/pingcap/errors"
27	v1 "k8s.io/api/core/v1"
28	apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
29	"k8s.io/apimachinery/pkg/api/resource"
30	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31	"k8s.io/apimachinery/pkg/labels"
32	"k8s.io/apimachinery/pkg/selection"
33	"k8s.io/apimachinery/pkg/util/wait"
34	clientset "k8s.io/client-go/kubernetes"
35	typedappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
36	restclient "k8s.io/client-go/rest"
37	aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
38	"k8s.io/kubernetes/test/e2e/framework"
39	"k8s.io/kubernetes/test/e2e/framework/log"
40	"k8s.io/utils/pointer"
41	"sigs.k8s.io/controller-runtime/pkg/client"
42	"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
43
44	"github.com/pingcap/tidb-operator/pkg/apis/label"
45	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
46	"github.com/pingcap/tidb-operator/pkg/client/clientset/versioned"
47	"github.com/pingcap/tidb-operator/pkg/controller"
48	"github.com/pingcap/tidb-operator/pkg/monitor/monitor"
49	"github.com/pingcap/tidb-operator/pkg/scheme"
50	"github.com/pingcap/tidb-operator/tests"
51	e2econfig "github.com/pingcap/tidb-operator/tests/e2e/config"
52	e2eframework "github.com/pingcap/tidb-operator/tests/e2e/framework"
53	"github.com/pingcap/tidb-operator/tests/e2e/util"
54	utildb "github.com/pingcap/tidb-operator/tests/e2e/util/db"
55	"github.com/pingcap/tidb-operator/tests/e2e/util/db/blockwriter"
56	utilimage "github.com/pingcap/tidb-operator/tests/e2e/util/image"
57	utilpod "github.com/pingcap/tidb-operator/tests/e2e/util/pod"
58	"github.com/pingcap/tidb-operator/tests/e2e/util/portforward"
59	utiltidb "github.com/pingcap/tidb-operator/tests/e2e/util/tidb"
60	utiltc "github.com/pingcap/tidb-operator/tests/e2e/util/tidbcluster"
61	"github.com/pingcap/tidb-operator/tests/pkg/fixture"
62)
63
64const (
65	OperatorLatestVersion    string = "v1.3.1"
66	OperatorPrevMajorVersion string = "v1.2.7"
67)
68
69// Serial specs describe tests which cannot run in parallel.
70var _ = ginkgo.Describe("[Serial]", func() {
71	f := e2eframework.NewDefaultFramework("serial")
72
73	var ns string
74	var c clientset.Interface
75	var cli versioned.Interface
76	var asCli asclientset.Interface
77	var genericCli client.Client
78	var aggrCli aggregatorclient.Interface
79	var apiExtCli apiextensionsclientset.Interface
80	var cfg *tests.Config
81	var config *restclient.Config
82	var fw portforward.PortForward
83	var fwCancel context.CancelFunc
84	var stsGetter typedappsv1.StatefulSetsGetter
85	/**
86	 * StatefulSet or AdvancedStatefulSet getter interface.
87	 */
88
89	ginkgo.BeforeEach(func() {
90		ns = f.Namespace.Name
91		c = f.ClientSet
92		var err error
93		config, err = framework.LoadConfig()
94		framework.ExpectNoError(err, "failed to load config")
95		cli, err = versioned.NewForConfig(config)
96		framework.ExpectNoError(err, "failed to create clientset")
97		asCli, err = asclientset.NewForConfig(config)
98		framework.ExpectNoError(err, "failed to create clientset")
99		mapper, err := apiutil.NewDynamicRESTMapper(config, apiutil.WithLazyDiscovery)
100		framework.ExpectNoError(err, "failed to create dynamic RESTMapper")
101		genericCli, err = client.New(config, client.Options{
102			Scheme: scheme.Scheme,
103			Mapper: mapper,
104		})
105		framework.ExpectNoError(err, "failed to create clientset for controller-runtime")
106		aggrCli, err = aggregatorclient.NewForConfig(config)
107		framework.ExpectNoError(err, "failed to create clientset for kube-aggregator")
108		apiExtCli, err = apiextensionsclientset.NewForConfig(config)
109		framework.ExpectNoError(err, "failed to create clientset for apiextensions-apiserver")
110		clientRawConfig, err := e2econfig.LoadClientRawConfig()
111		framework.ExpectNoError(err, "failed to load raw config for tidb operator")
112		ctx, cancel := context.WithCancel(context.Background())
113		fw, err = portforward.NewPortForwarder(ctx, e2econfig.NewSimpleRESTClientGetter(clientRawConfig))
114		framework.ExpectNoError(err, "failed to create port forwarder")
115		fwCancel = cancel
116		cfg = e2econfig.TestConfig
117		stsGetter = c.AppsV1()
118	})
119
120	ginkgo.AfterEach(func() {
121		if fwCancel != nil {
122			fwCancel()
123		}
124	})
125
126	// tidb-operator with pod admission webhook enabled
127	ginkgo.Describe("[Feature: PodAdmissionWebhook]", func() {
128
129		var ocfg *tests.OperatorConfig
130		var oa *tests.OperatorActions
131
132		ginkgo.BeforeEach(func() {
133			ocfg = &tests.OperatorConfig{
134				Namespace:         ns,
135				ReleaseName:       "operator",
136				Image:             cfg.OperatorImage,
137				Tag:               cfg.OperatorTag,
138				SchedulerImage:    "k8s.gcr.io/kube-scheduler",
139				LogLevel:          "4",
140				ImagePullPolicy:   v1.PullIfNotPresent,
141				TestMode:          true,
142				WebhookEnabled:    true,
143				StsWebhookEnabled: true,
144			}
145			oa = tests.NewOperatorActions(cli, c, asCli, aggrCli, apiExtCli, tests.DefaultPollInterval, ocfg, e2econfig.TestConfig, fw, f)
146			ginkgo.By("Installing CRDs")
147			oa.CleanCRDOrDie()
148			oa.CreateCRDOrDie(ocfg)
149			ginkgo.By("Installing tidb-operator")
150			oa.CleanOperatorOrDie(ocfg)
151			oa.DeployOperatorOrDie(ocfg)
152		})
153
154		ginkgo.AfterEach(func() {
155			ginkgo.By("Uninstall tidb-operator")
156			oa.CleanOperatorOrDie(ocfg)
157			ginkgo.By("Uninstalling CRDs")
158			oa.CleanCRDOrDie()
159		})
160
161		ginkgo.It(fmt.Sprintf("should be able to upgrade TiDB Cluster from %s to %s", utilimage.TiDBLatestPrev, utilimage.TiDBLatest), func() {
162			log.Logf("start to upgrade tidbcluster with pod admission webhook")
163			// deploy new cluster and test upgrade and scale-in/out with pod admission webhook
164			ginkgo.By(fmt.Sprintf("start initial TidbCluster %q", utilimage.TiDBLatestPrev))
165			tc := fixture.GetTidbCluster(ns, "admission", utilimage.TiDBLatestPrev)
166			tc.Spec.PD.Replicas = 3
167			tc.Spec.TiKV.Replicas = 3
168			tc.Spec.TiDB.Replicas = 2
169			tc, err := cli.PingcapV1alpha1().TidbClusters(tc.Namespace).Create(context.TODO(), tc, metav1.CreateOptions{})
170			framework.ExpectNoError(err, "failed to create TidbCluster: %v", tc)
171			err = oa.WaitForTidbClusterReady(tc, 30*time.Minute, 5*time.Second)
172			framework.ExpectNoError(err, "failed to wait for TidbCluster ready: %v", tc)
173
174			ginkgo.By("Set tikv partition annotation to 1")
175			err = setPartitionAnnotation(ns, tc.Name, label.TiKVLabelVal, 1)
176			framework.ExpectNoError(err, "set tikv Partition annotation failed")
177
178			ginkgo.By(fmt.Sprintf("Upgrade TidbCluster version to %q", utilimage.TiDBLatest))
179			err = controller.GuaranteedUpdate(genericCli, tc, func() error {
180				tc.Spec.Version = utilimage.TiDBLatest
181				return nil
182			})
183			framework.ExpectNoError(err, "failed to update TidbCluster to upgrade tidb version to %v", utilimage.TiDBLatest)
184
185			ginkgo.By(fmt.Sprintf("wait for tikv-1 pod upgrading to %q", utilimage.TiDBLatest))
186			err = wait.Poll(5*time.Second, 10*time.Minute, func() (done bool, err error) {
187				tikvPod, err := c.CoreV1().Pods(ns).Get(context.TODO(), fmt.Sprintf("%s-tikv-1", tc.Name), metav1.GetOptions{})
188				if err != nil {
189					return false, nil
190				}
191				if tikvPod.Spec.Containers[0].Image != fmt.Sprintf("pingcap/tikv:%s", utilimage.TiDBLatest) {
192					return false, nil
193				}
194				return true, nil
195			})
196			framework.ExpectNoError(err, "failed to upgrade tikv-1 to %q", utilimage.TiDBLatest)
197
198			ginkgo.By("Wait to see if tikv sts partition annotation remains 1 for 3 min")
199			// TODO: explain the purpose of this testing
200			err = wait.Poll(5*time.Second, 3*time.Minute, func() (done bool, err error) {
201				tikvSts, err := c.AppsV1().StatefulSets(ns).Get(context.TODO(), fmt.Sprintf("%s-tikv", tc.Name), metav1.GetOptions{})
202				if err != nil {
203					return false, err
204				}
205				strategy := tikvSts.Spec.UpdateStrategy
206				if strategy.RollingUpdate != nil && strategy.RollingUpdate.Partition != nil &&
207					*strategy.RollingUpdate.Partition == int32(1) {
208					return false, nil
209				}
210				return true, nil
211			})
212			framework.ExpectEqual(err, wait.ErrWaitTimeout, "tikv sts partition annotation should remain 1 for 3 min")
213
214			ginkgo.By("Set tc annotations to nil")
215			err = controller.GuaranteedUpdate(genericCli, tc, func() error {
216				tc.Annotations = nil
217				return nil
218			})
219			framework.ExpectNoError(err, "failed to set TidbCluster annotation to nil: %v", tc)
220
221			// TODO: find a more graceful way to check tidbcluster during upgrading
222			err = oa.WaitForTidbClusterReady(tc, 30*time.Minute, 5*time.Second)
223			framework.ExpectNoError(err, "failed to wait for TidbCluster ready: %v", tc)
224		})
225	})
226
227	ginkgo.Describe("[Feature: Defaulting and Validating]", func() {
228		var ocfg *tests.OperatorConfig
229		var oa *tests.OperatorActions
230
231		ginkgo.BeforeEach(func() {
232			ocfg = &tests.OperatorConfig{
233				Namespace:                 ns,
234				ReleaseName:               "operator",
235				Image:                     cfg.OperatorImage,
236				Tag:                       cfg.OperatorTag,
237				SchedulerImage:            "k8s.gcr.io/kube-scheduler",
238				LogLevel:                  "4",
239				ImagePullPolicy:           v1.PullIfNotPresent,
240				TestMode:                  true,
241				WebhookEnabled:            false,
242				ValidatingEnabled:         true,
243				DefaultingEnabled:         true,
244				SchedulerReplicas:         util.IntPtr(0),
245				ControllerManagerReplicas: util.IntPtr(0),
246			}
247			oa = tests.NewOperatorActions(cli, c, asCli, aggrCli, apiExtCli, tests.DefaultPollInterval, ocfg, e2econfig.TestConfig, fw, f)
248			ginkgo.By("Installing CRDs")
249			oa.CleanCRDOrDie()
250			oa.CreateCRDOrDie(ocfg)
251			ginkgo.By("Installing tidb-operator")
252			oa.CleanOperatorOrDie(ocfg)
253			oa.DeployOperatorOrDie(ocfg)
254		})
255
256		ginkgo.AfterEach(func() {
257			ginkgo.By("Uninstall tidb-operator")
258			oa.CleanOperatorOrDie(ocfg)
259			ginkgo.By("Uninstalling CRDs")
260			oa.CleanCRDOrDie()
261		})
262
263		ginkgo.It("should perform defaulting and validating properly", func() {
264			ginkgo.By("Deploy a legacy tc")
265			legacyTc := &v1alpha1.TidbCluster{
266				ObjectMeta: metav1.ObjectMeta{
267					Namespace: ns,
268					Name:      "created-by-helm",
269				},
270				Spec: v1alpha1.TidbClusterSpec{
271					TiDB: &v1alpha1.TiDBSpec{
272						Replicas: 1,
273						ComponentSpec: v1alpha1.ComponentSpec{
274							Image: fmt.Sprintf("pingcap/tidb:%s", utilimage.TiDBLatestPrev),
275						},
276					},
277					TiKV: &v1alpha1.TiKVSpec{
278						Replicas: 1,
279						ComponentSpec: v1alpha1.ComponentSpec{
280							Image: fmt.Sprintf("pingcap/tikv:%s", utilimage.TiDBLatestPrev),
281						},
282						ResourceRequirements: v1.ResourceRequirements{
283							Requests: v1.ResourceList{
284								v1.ResourceStorage: resource.MustParse("10G"),
285							},
286						},
287					},
288					PD: &v1alpha1.PDSpec{
289						Replicas: 1,
290						ComponentSpec: v1alpha1.ComponentSpec{
291							Image: fmt.Sprintf("pingcap/pd:%s", utilimage.TiDBLatestPrev),
292						},
293						ResourceRequirements: v1.ResourceRequirements{
294							Requests: v1.ResourceList{
295								v1.ResourceStorage: resource.MustParse("10G"),
296							},
297						},
298					},
299				},
300			}
301			var err error
302			legacyTc, err = cli.PingcapV1alpha1().TidbClusters(ns).Create(context.TODO(), legacyTc, metav1.CreateOptions{})
303			// err := genericCli.Create(context.TODO(),context.TODO(), legacyTc)
304			framework.ExpectNoError(err, "Expected create tidbcluster without defaulting and validating")
305
306			ginkgo.By("Enable webhook in operator")
307			ocfg.WebhookEnabled = true
308			oa.UpgradeOperatorOrDie(ocfg)
309			// now the webhook enabled
310			err = controller.GuaranteedUpdate(genericCli, legacyTc, func() error {
311				legacyTc.Spec.TiDB.Image = fmt.Sprintf("pingcap/tidb:%s", utilimage.TiDBLatest)
312				return nil
313			})
314			framework.ExpectNoError(err, "Update legacy TidbCluster should not be influenced by validating")
315			framework.ExpectEqual(legacyTc.Spec.TiDB.BaseImage, "", "Update legacy tidbcluster should not be influenced by defaulting")
316
317			ginkgo.By("Update TidbCluster to use webhook")
318			err = controller.GuaranteedUpdate(genericCli, legacyTc, func() error {
319				legacyTc.Spec.TiDB.BaseImage = "pingcap/tidb"
320				legacyTc.Spec.TiKV.BaseImage = "pingcap/tikv"
321				legacyTc.Spec.PD.BaseImage = "pingcap/pd"
322				legacyTc.Spec.PD.Version = pointer.StringPtr(utilimage.TiDBLatest)
323				return nil
324			})
325			framework.ExpectNoError(err, "failed to update TidbCluster")
326
327			ginkgo.By("Set empty values to test validating")
328			err = controller.GuaranteedUpdate(genericCli, legacyTc, func() error {
329				legacyTc.Spec.TiDB.BaseImage = ""
330				legacyTc.Spec.PD.Version = pointer.StringPtr("")
331				return nil
332			})
333			framework.ExpectError(err, "Validating should reject empty mandatory fields")
334
335			ginkgo.By("Deploy a new tc with legacy fields")
336			// TODO: explain the purpose of this testing
337			newTC := &v1alpha1.TidbCluster{
338				ObjectMeta: metav1.ObjectMeta{
339					Namespace: ns,
340					Name:      "newly-created",
341				},
342				Spec: v1alpha1.TidbClusterSpec{
343					TiDB: &v1alpha1.TiDBSpec{
344						ComponentSpec: v1alpha1.ComponentSpec{
345							Image: fmt.Sprintf("pingcap/tidb:%s", utilimage.TiDBLatest),
346						},
347					},
348					TiKV: &v1alpha1.TiKVSpec{
349						ComponentSpec: v1alpha1.ComponentSpec{
350							Image: fmt.Sprintf("pingcap/tikv:%s", utilimage.TiDBLatest),
351						},
352						ResourceRequirements: v1.ResourceRequirements{
353							Requests: v1.ResourceList{
354								v1.ResourceStorage: resource.MustParse("10G"),
355							},
356						},
357					},
358					PD: &v1alpha1.PDSpec{
359						ComponentSpec: v1alpha1.ComponentSpec{
360							Image: fmt.Sprintf("pingcap/pd:%s", utilimage.TiDBLatest),
361						},
362						ResourceRequirements: v1.ResourceRequirements{
363							Requests: v1.ResourceList{
364								v1.ResourceStorage: resource.MustParse("10G"),
365							},
366						},
367					},
368				},
369			}
370			_, err = cli.PingcapV1alpha1().TidbClusters(ns).Create(context.TODO(), newTC, metav1.CreateOptions{})
371			framework.ExpectError(err, "Validating should reject legacy fields for newly created cluster")
372
373			ginkgo.By("Deploy a new tc")
374			newTC = &v1alpha1.TidbCluster{
375				ObjectMeta: metav1.ObjectMeta{
376					Namespace: ns,
377					Name:      "newly-created",
378				},
379				Spec: v1alpha1.TidbClusterSpec{
380					Version: utilimage.TiDBLatest,
381					TiDB: &v1alpha1.TiDBSpec{
382						Replicas: 1,
383					},
384					TiKV: &v1alpha1.TiKVSpec{
385						Replicas: 1,
386						ResourceRequirements: v1.ResourceRequirements{
387							Requests: v1.ResourceList{
388								v1.ResourceStorage: resource.MustParse("10G"),
389							},
390						},
391					},
392					PD: &v1alpha1.PDSpec{
393						Replicas: 1,
394						ResourceRequirements: v1.ResourceRequirements{
395							Requests: v1.ResourceList{
396								v1.ResourceStorage: resource.MustParse("10G"),
397							},
398						},
399					},
400				},
401			}
402			newTC, err = cli.PingcapV1alpha1().TidbClusters(ns).Create(context.TODO(), newTC, metav1.CreateOptions{})
403			framework.ExpectNoError(err, "required fields should be set by defaulting")
404			// don't have to check all fields, just take some to test if defaulting set
405			if empty, err := gomega.BeEmpty().Match(newTC.Spec.TiDB.BaseImage); empty {
406				log.Failf("Expected tidb.baseImage has default value set, %v", err)
407			}
408
409			ginkgo.By("Update tc with invalid instance label value")
410			err = controller.GuaranteedUpdate(genericCli, newTC, func() error {
411				newTC.Labels = map[string]string{
412					label.InstanceLabelKey: "some-insane-label-value",
413				}
414				return nil
415			})
416			framework.ExpectError(err, "Could not set instance label with value other than cluster name")
417
418			ginkgo.By("Update pd replication config in tc")
419			err = controller.GuaranteedUpdate(genericCli, newTC, func() error {
420				c := v1alpha1.NewPDConfig()
421				c.Set("replication.max-replicas", 5)
422				newTC.Spec.PD.Config = c
423				return nil
424			})
425			framework.ExpectError(err, "PD replication config is immutable through CR")
426		})
427	})
428
429	ginkgo.Describe("Canary Deploy TiDB Operator", func() {
430		var oa *tests.OperatorActions
431		var ocfg *tests.OperatorConfig
432
433		ginkgo.BeforeEach(func() {
434			ocfg = &tests.OperatorConfig{
435				Namespace:       ns,
436				ReleaseName:     "operator",
437				Image:           cfg.OperatorImage,
438				Tag:             cfg.OperatorTag,
439				ImagePullPolicy: v1.PullIfNotPresent,
440			}
441			oa = tests.NewOperatorActions(cli, c, asCli, aggrCli, apiExtCli, tests.DefaultPollInterval, ocfg, e2econfig.TestConfig, fw, f)
442			ginkgo.By("Installing CRDs")
443			oa.CleanCRDOrDie()
444			oa.CreateCRDOrDie(ocfg)
445			ginkgo.By("Installing tidb-operator")
446			oa.CleanOperatorOrDie(ocfg)
447			oa.DeployOperatorOrDie(ocfg)
448		})
449
450		ginkgo.AfterEach(func() {
451			ginkgo.By("Uninstall tidb-operator")
452			oa.CleanOperatorOrDie(ocfg)
453			ginkgo.By("Uninstalling CRDs")
454			oa.CleanCRDOrDie()
455		})
456
457		ginkgo.It("Deploy TidbCluster and check the result", func() {
458			tcName := "tidbcluster1"
459			tc := fixture.GetTidbCluster(ns, tcName, utilimage.TiDBLatestPrev)
460			tc.Spec.PD.Replicas = 1
461			tc.Spec.TiKV.Replicas = 1
462			tc.Spec.TiDB.Replicas = 1
463
464			ginkgo.By(fmt.Sprintf("deploy original tc %q", utilimage.TiDBLatestPrev))
465			utiltc.MustCreateTCWithComponentsReady(genericCli, oa, tc, 10*time.Minute, 5*time.Second)
466			pdPods := utilpod.MustListPods(labels.SelectorFromSet(label.New().Instance(tcName).PD().Labels()).String(), ns, c)
467
468			ginkgo.By("Set --selector=version=old for the default TiDB Operator")
469			ocfg.Selector = []string{"version=old"}
470			oa.UpgradeOperatorOrDie(ocfg)
471			log.Logf("Upgrade operator with --set-string \"selector=version=old\"")
472
473			ginkgo.By("Upgrade TidbCluster 1 version, wait for 2 minutes, check that no rolling update occurs")
474			err := controller.GuaranteedUpdate(genericCli, tc, func() error {
475				tc.Spec.Version = utilimage.TiDBLatest
476				return nil
477			})
478			framework.ExpectNoError(err, "failed to update TidbCluster 1 to upgrade PD version to %v", utilimage.TiDBLatest)
479
480			err = wait.Poll(5*time.Second, 2*time.Minute, func() (done bool, err error) {
481				// confirm the TidbCluster 1 PD haven't been changed
482				changed, err := utilpod.PodsAreChanged(c, pdPods)()
483				if err != nil {
484					log.Logf("ERROR: meet error during verify TidbCluster 1 PD pods, err:%v", err)
485					return false, err
486				}
487				if changed {
488					return true, nil
489				}
490				log.Logf("confirm TidbCluster 1 PD pods haven't been changed this time")
491				return false, nil
492			})
493			framework.ExpectEqual(err, wait.ErrWaitTimeout, "expect TidbCluster 1 PD haven't been changed for 2 minutes")
494			log.Logf("Upgrade TidbCluster 1 to new version, but no rolling update occurs")
495
496			ginkgo.By("Set label version=old to TidbCluster 1, check that PD of TidbCluster 1 has been rolling updated")
497			err = controller.GuaranteedUpdate(genericCli, tc, func() error {
498				tc.Labels = map[string]string{"version": "old"}
499				return nil
500			})
501			framework.ExpectNoError(err, "failed to update TidbCluster 1 to set label version=old")
502
503			err = wait.Poll(5*time.Second, 5*time.Minute, func() (done bool, err error) {
504				// confirm the PD Pods have been changed
505				changed, err := utilpod.PodsAreChanged(c, pdPods)()
506				if err != nil {
507					log.Logf("ERROR: meet error during verify PD pods, err:%v", err)
508					return false, err
509				}
510				if changed {
511					return true, nil
512				}
513				log.Logf("PD pods haven't been changed yet")
514				return false, nil
515			})
516			framework.ExpectNoError(err, "expect PD pods have been changed in 5 minutes")
517			log.Logf("Upgrade TidbCluster 1 with label version=old and PD pods have been rolling updated.")
518
519			ginkgo.By("Deploy TidbCluster 2 with label version=new")
520			tc2Name := "tidbcluster2"
521			tc2 := fixture.GetTidbCluster(ns, tc2Name, utilimage.TiDBLatestPrev)
522			tc2.Spec.PD.Replicas = 1
523			tc2.Spec.TiKV.Replicas = 1
524			tc2.Spec.TiDB.Replicas = 1
525			tc2.Labels = map[string]string{"version": "new"}
526
527			err = genericCli.Create(context.TODO(), tc2)
528			framework.ExpectNoError(err, "Expected Tidbcluster 2 be created")
529			log.Logf("Finished deploying TidbCluster 2 with label version=new")
530
531			ginkgo.By("Wait for 2 minutes and check that no PD Pod is created")
532			err = wait.Poll(5*time.Second, 2*time.Minute, func() (created bool, err error) {
533				// confirm the Tidbcluster 2 PD Pods don't be created
534				pdPods, err = utilpod.ListPods(labels.SelectorFromSet(label.New().Instance(tc2Name).PD().Labels()).String(), ns, c)
535				if err != nil {
536					log.Logf("ERROR: meet error during get PD pods, err:%v", err)
537					return false, nil
538				}
539				if len(pdPods) != 0 {
540					return true, nil
541				}
542				log.Logf("Tidbcluster 2 PD pods have not been created yet")
543				return false, nil
544			})
545			framework.ExpectEqual(err, wait.ErrWaitTimeout, "No PD Pods created for Tidbcluster 2")
546			log.Logf("Confirm that no PD Pods created for Tidbcluster 2")
547
548			ginkgo.By("Deploy TiDB Operator 2 with --selector=version=new")
549			ocfg2 := &tests.OperatorConfig{
550				Namespace:       ns + "-canary-deploy",
551				ReleaseName:     "operator2",
552				Image:           cfg.OperatorImage,
553				Tag:             cfg.OperatorTag,
554				ImagePullPolicy: v1.PullIfNotPresent,
555				Selector:        []string{"version=new"},
556				//FIXME: AppendReleaseSuffix: true,
557			}
558			oa.DeployOperatorOrDie(ocfg2)
559			log.Logf("Finished deploying TiDB Operator 2 with --selector=version=new")
560
561			ginkgo.By("Check TidbCluster 2 is ready")
562			err = oa.WaitForTidbClusterReady(tc2, 10*time.Minute, 5*time.Second)
563			framework.ExpectNoError(err, "Expected TiDB cluster2 ready")
564			log.Logf("confirm TidbCluster 2 is ready")
565
566			ginkgo.By("Delete the default TiDB Operator")
567			oa.CleanOperatorOrDie(ocfg)
568			log.Logf("Finished deleting the default Operator")
569
570			ginkgo.By("Upgrade TiDB version of TidbCluster 2")
571			err = controller.GuaranteedUpdate(genericCli, tc2, func() error {
572				tc2.Spec.Version = utilimage.TiDBLatest
573				return nil
574			})
575			framework.ExpectNoError(err, "failed to update TidbCluster 2 to upgrade tidb version to %v", utilimage.TiDBLatest)
576			log.Logf("Finished upgrading TidbCluster 2")
577
578			err = oa.WaitForTidbClusterReady(tc2, 10*time.Minute, 10*time.Second)
579			framework.ExpectNoError(err, "failed to wait for TidbCluster %s/%s components ready", ns, tc2.Name)
580
581			ginkgo.By(fmt.Sprintf("wait for TidbCluster 2 pd-0 pod upgrading to %q", utilimage.TiDBLatest))
582			err = wait.Poll(5*time.Second, 10*time.Minute, func() (done bool, err error) {
583				pdPod, err := c.CoreV1().Pods(ns).Get(context.TODO(), fmt.Sprintf("%s-pd-0", tc2.Name), metav1.GetOptions{})
584				if err != nil {
585					return false, nil
586				}
587				if pdPod.Spec.Containers[0].Image != fmt.Sprintf("pingcap/pd:%s", utilimage.TiDBLatest) {
588					return false, nil
589				}
590				return true, nil
591			})
592			framework.ExpectNoError(err, "failed to upgrade TidbCluster 2 pd-0 to %q", utilimage.TiDBLatest)
593			log.Logf("Finished upgrading TidbCluster 2")
594
595			ginkgo.By("Deploy the default TiDB Operator with --selector=version=old")
596			ocfg = &tests.OperatorConfig{
597				Namespace:       ns,
598				ReleaseName:     "operator",
599				Image:           cfg.OperatorImage,
600				Tag:             cfg.OperatorTag,
601				ImagePullPolicy: v1.PullIfNotPresent,
602				Selector:        []string{"version=old"},
603			}
604			oa.DeployOperatorOrDie(ocfg)
605			log.Logf("Finished deploying TiDB Operator 1 with --selector=version=old")
606
607			ginkgo.By("Delete the TiDB Operator 2")
608			oa.CleanOperatorOrDie(ocfg2)
609			log.Logf("Finished deleting the Operator 2")
610
611			ginkgo.By("Scale-out TiDB of TidbCluster 1, wait for 5 minuts, check that scale up occurs")
612			err = controller.GuaranteedUpdate(genericCli, tc, func() error {
613				tc.Spec.TiDB.Replicas = 2
614				return nil
615			})
616			framework.ExpectNoError(err, "failed to scale out TidbCluster 1")
617
618			err = wait.Poll(5*time.Second, 5*time.Minute, func() (done bool, err error) {
619				tidbStatefulSet, err := c.AppsV1().StatefulSets(ns).Get(context.TODO(), fmt.Sprintf("%s-tidb", tc.Name), metav1.GetOptions{})
620				if err != nil {
621					return false, nil
622				}
623				if *tidbStatefulSet.Spec.Replicas != 2 {
624					return false, nil
625				}
626				return true, nil
627			})
628			framework.ExpectNoError(err, "expect TiDB in tidbcluster 1 to scale out to 2")
629			log.Logf("Succeed to scale out TiDB of TidbCluster 1")
630		})
631	})
632
633	ginkgo.Describe("Upgrade TiDB Operator", func() {
634		var (
635			operatorVersion string
636			oa              *tests.OperatorActions
637			ocfg            *tests.OperatorConfig
638		)
639
640		ginkgo.JustBeforeEach(func() {
641			// deploy older operator and CRDs
642			ocfg = &tests.OperatorConfig{
643				Namespace:   ns,
644				ReleaseName: "operator",
645				Tag:         operatorVersion,
646				Image:       fmt.Sprintf("pingcap/tidb-operator:%s", operatorVersion),
647			}
648			oa = tests.NewOperatorActions(cli, c, asCli, aggrCli, apiExtCli, tests.DefaultPollInterval, ocfg, e2econfig.TestConfig, fw, f)
649			ginkgo.By("Installing CRDs")
650			oa.CleanCRDOrDie()
651			oa.CreateReleasedCRDOrDie(operatorVersion)
652			ginkgo.By("Installing TiDB Operator")
653			oa.CleanOperatorOrDie(ocfg)
654			oa.DeployOperatorOrDie(ocfg)
655		})
656
657		ginkgo.JustAfterEach(func() {
658			// clean current operator and CRDs
659			ginkgo.By("Uninstall tidb-operator")
660			oa.CleanOperatorOrDie(ocfg)
661			ginkgo.By("Uninstalling CRDs")
662			oa.CleanCRDOrDie()
663		})
664
665		ginkgo.Context("From latest version", func() {
666			ginkgo.BeforeEach(func() {
667				operatorVersion = OperatorLatestVersion
668			})
669
670			ginkgo.It("should not trigger rolling-update", func() {
671				tcName := fmt.Sprintf("upgrade-operator-from-%s", strings.ReplaceAll(operatorVersion, ".", "x"))
672				tc := fixture.GetTidbCluster(ns, tcName, utilimage.TiDBLatest)
673				tc = fixture.AddTiFlashForTidbCluster(tc)
674				tc = fixture.AddTiCDCForTidbCluster(tc)
675				tc = fixture.AddPumpForTidbCluster(tc)
676				tc.Spec.PD.Replicas = 1
677				tc.Spec.TiKV.Replicas = 1
678				tc.Spec.TiDB.Replicas = 1
679				tc.Spec.TiFlash.Replicas = 1
680
681				ginkgo.By("Deploy original TiDB cluster")
682				utiltc.MustCreateTCWithComponentsReady(genericCli, oa, tc, 6*time.Minute, 5*time.Second)
683				selector := MustGetLabelSelectorForComponents(tcName, label.DiscoveryLabelVal) // ingore discovery
684				pods := utilpod.MustListPods(selector.String(), ns, c)
685
686				ginkgo.By("Upgrade TiDB Operator and CRDs to current version")
687				ocfg.Tag = cfg.OperatorTag
688				ocfg.Image = cfg.OperatorImage
689				oa.ReplaceCRDOrDie(ocfg)
690				oa.UpgradeOperatorOrDie(ocfg)
691
692				ginkgo.By("Wait for pods are not changed in 5 minutes")
693				err := utilpod.WaitForPodsAreChanged(c, pods, time.Minute*5)
694				framework.ExpectEqual(err, wait.ErrWaitTimeout, "pods should not change in 5 minutes")
695			})
696		})
697
698		ginkgo.Context("From prev major version", func() {
699
700			ginkgo.BeforeEach(func() {
701				operatorVersion = OperatorPrevMajorVersion
702			})
703
704			type testCase struct {
705				name string
706				tls  bool
707			}
708			cases := []testCase{
709				{
710					name: "should not trigger rolling-update and database work fine",
711					tls:  false,
712				},
713				{
714					name: "should not trigger rolling-update and database work fine with TLS-enabled",
715					tls:  true,
716				},
717			}
718
719			for i := range cases {
720				testcase := cases[i]
721				ginkgo.It(testcase.name, func() {
722					dbName := "test"
723					tables := []string{"test_0", "test_1", "test_2"}
724					recordCount := 30
725					batchCount := 100
726					expectCount := recordCount * batchCount
727					bw := blockwriter.New(blockwriter.WithTableNum(len(tables)),
728						blockwriter.WithRecordNum(recordCount),
729						blockwriter.WithBatchSize(batchCount),
730						blockwriter.WithGenTableName(func(nr int) string {
731							return tables[nr]
732						}))
733
734					tcName := fmt.Sprintf("upgrade-operator-from-%s", strings.ReplaceAll(operatorVersion, ".", "x"))
735					tc := fixture.GetTidbCluster(ns, tcName, utilimage.TiDBLatestPrev)
736					tc = fixture.AddTiFlashForTidbCluster(tc)
737					tc = fixture.AddTiCDCForTidbCluster(tc)
738					tc = fixture.AddPumpForTidbCluster(tc)
739					tc.Spec.PD.Replicas = 1
740					tc.Spec.TiKV.Replicas = 1
741					tc.Spec.TiDB.Replicas = 1
742					tc.Spec.TiFlash.Replicas = 1
743
744					if testcase.tls {
745						tc.Spec.TiDB.TLSClient = &v1alpha1.TiDBTLSClient{Enabled: true}
746						tc.Spec.TLSCluster = &v1alpha1.TLSCluster{Enabled: true}
747
748						ginkgo.By("Installing tidb CA certificate")
749						err := InstallTiDBIssuer(ns, tcName)
750						framework.ExpectNoError(err, "failed to install CA certificate")
751
752						ginkgo.By("Installing tidb server and client certificate")
753						err = InstallTiDBCertificates(ns, tcName)
754						framework.ExpectNoError(err, "failed to install tidb server and client certificate")
755
756						ginkgo.By("Installing tidbInitializer client certificate")
757						err = installTiDBInitializerCertificates(ns, tcName)
758						framework.ExpectNoError(err, "failed to install tidbInitializer client certificate")
759
760						ginkgo.By("Installing dashboard client certificate")
761						err = installPDDashboardCertificates(ns, tcName)
762						framework.ExpectNoError(err, "failed to install dashboard client certificate")
763
764						ginkgo.By("Installing tidb components certificates")
765						err = InstallTiDBComponentsCertificates(ns, tcName)
766						framework.ExpectNoError(err, "failed to install tidb components certificates")
767					}
768
769					ginkgo.By("Deploy original TiDB cluster with prev version")
770					utiltc.MustCreateTCWithComponentsReady(genericCli, oa, tc, 6*time.Minute, 5*time.Second)
771					selector := MustGetLabelSelectorForComponents(tcName, label.DiscoveryLabelVal) // ingore discovery
772					pods := utilpod.MustListPods(selector.String(), ns, c)
773
774					dsn, fwcancel, err := utiltidb.PortForwardAndGetTiDBDSN(fw, ns, tcName, "root", "", dbName)
775					framework.ExpectNoError(err, "failed to get dsn")
776					defer fwcancel()
777					db := utildb.NewDatabaseOrDie(dsn)
778					defer db.Close()
779
780					ginkgo.By("Prepare data in database")
781					err = bw.Write(context.Background(), dsn)
782					framework.ExpectNoError(err, "failed to write data")
783
784					ginkgo.By("Create TiFlash replicas for table 0 and ensure it is ready")
785					MustCreateTiFlashReplicationForTable(db, dbName, tables[0], expectCount)
786
787					ginkgo.By("Upgrade TiDB Operator and CRDs to current version")
788					ocfg.Tag = cfg.OperatorTag
789					ocfg.Image = cfg.OperatorImage
790					oa.ReplaceCRDOrDie(ocfg)
791					oa.UpgradeOperatorOrDie(ocfg)
792
793					ginkgo.By("Wait for pods are not changed in 5 minutes")
794					err = utilpod.WaitForPodsAreChanged(c, pods, time.Minute*5)
795					framework.ExpectEqual(err, wait.ErrWaitTimeout, "pods should not change in 5 minutes")
796
797					ginkgo.By("Ensure records in table 0 have not changed after upgrading TiDB Operator")
798					EnsureRecordsNotChangedForTables(db, "tiflash", dbName, tables[0:1], expectCount)
799					EnsureRecordsNotChangedForTables(db, "tikv", dbName, tables[0:1], expectCount)
800
801					ginkgo.By("Create TiFlash replicas for table 1 and ensure it is ready")
802					MustCreateTiFlashReplicationForTable(db, dbName, tables[1], expectCount)
803
804					ginkgo.By("Update TiDB cluster to latest version")
805					err = controller.GuaranteedUpdate(genericCli, tc, func() error {
806						tc.Spec.Version = utilimage.TiDBLatest
807						return nil
808					})
809					framework.ExpectNoError(err, "failed to upgrade TidbCluster: %q", tc.Name)
810					err = oa.WaitForTidbClusterReady(tc, 7*time.Minute, 5*time.Second)
811					framework.ExpectNoError(err, "waiting for cluster %q ready", tcName)
812
813					// reopen db after upgrade
814					dsn2, fwcancel2, err := utiltidb.PortForwardAndGetTiDBDSN(fw, ns, tcName, "root", "", dbName)
815					framework.ExpectNoError(err, "failed to get dsn")
816					defer fwcancel2()
817					db2 := utildb.NewDatabaseOrDie(dsn2)
818					defer db2.Close()
819
820					ginkgo.By("Ensure records in table 0 and table 1 have not changed after upgrading TiDB Operator")
821					EnsureRecordsNotChangedForTables(db2, "tiflash", dbName, tables[0:2], expectCount)
822					EnsureRecordsNotChangedForTables(db2, "tikv", dbName, tables[0:2], expectCount)
823
824					ginkgo.By("Create TiFlash replicas for table 2 and ensure it is ready")
825					MustCreateTiFlashReplicationForTable(db2, dbName, tables[2], expectCount)
826				})
827			}
828
829		})
830
831		ginkgo.Context("From v1.1.7", func() {
832			ginkgo.BeforeEach(func() {
833				operatorVersion = "v1.1.7"
834			})
835
836			ginkgo.It("should not change old TidbCluster", func() {
837				tcName := fmt.Sprintf("upgrade-operator-from-%s", strings.ReplaceAll(operatorVersion, ".", "x"))
838				tc := fixture.GetTidbCluster(ns, tcName, utilimage.TiDBV5x3)
839				tc = fixture.AddTiFlashForTidbCluster(tc)
840				tc = fixture.AddTiCDCForTidbCluster(tc)
841				tc = fixture.AddPumpForTidbCluster(tc)
842				tc.Spec.PD.Replicas = 3
843				tc.Spec.TiKV.Replicas = 1
844				tc.Spec.TiDB.Replicas = 1
845				tc.Spec.TiCDC.Config = nil
846
847				ginkgo.By("Deploy original TiDB cluster")
848				utiltc.MustCreateTCWithComponentsReady(genericCli, oa, tc, 10*time.Minute, 5*time.Second)
849				selector := MustGetLabelSelectorForComponents(tcName,
850					label.DiscoveryLabelVal,
851					label.PumpLabelVal,
852					label.TiCDCLabelVal, // ingore ticdc because of PR #4494
853				)
854				pods := utilpod.MustListPods(selector.String(), ns, c)
855
856				ginkgo.By("Upgrade TiDB Operator and CRDs to current version")
857				ocfg.Tag = cfg.OperatorTag
858				ocfg.Image = cfg.OperatorImage
859				oa.ReplaceCRDOrDie(ocfg)
860				oa.UpgradeOperatorOrDie(ocfg)
861
862				ginkgo.By("Wait for pods are not changed in 5 minutes")
863				err := utilpod.WaitForPodsAreChanged(c, pods, time.Minute*5)
864				framework.ExpectEqual(err, wait.ErrWaitTimeout, "pods should not change in 5 minutes")
865			})
866
867			/*
868			  Release: v1.2.0
869			  new feature in https://github.com/pingcap/tidb-operator/pull/3440
870			  deploy tidbmonitor and upgrade tidb-perator, then tidbmonitor should switch from deployment to statefulset
871			*/
872			ginkgo.It("should migrate tidbmonitor from deployment to sts", func() {
873				tcName := "smooth-tidbcluster"
874				tc := fixture.GetTidbCluster(ns, tcName, utilimage.TiDBLatest)
875				tc.Spec.PD.Replicas = 1
876				tc.Spec.TiKV.Replicas = 1
877				tc.Spec.TiDB.Replicas = 1
878
879				ginkgo.By("Deploy original TiDB cluster")
880				utiltc.MustCreateTCWithComponentsReady(genericCli, oa, tc, 6*time.Minute, 5*time.Second)
881
882				ginkgo.By("Deploy tidb monitor")
883				monitorName := "smooth-migrate"
884				tc, err := cli.PingcapV1alpha1().TidbClusters(ns).Get(context.TODO(), tcName, metav1.GetOptions{})
885				framework.ExpectNoError(err, "failed to get tidbcluster")
886				tm := fixture.NewTidbMonitor(monitorName, ns, tc, true, true, true)
887				_, err = cli.PingcapV1alpha1().TidbMonitors(ns).Create(context.TODO(), tm, metav1.CreateOptions{})
888				framework.ExpectNoError(err, "Expected tidbmonitor deployed success")
889				err = tests.CheckTidbMonitor(tm, cli, c, fw)
890				framework.ExpectNoError(err, "Expected tidbmonitor checked success")
891
892				deploymentPvcName := fmt.Sprintf("%s-monitor", monitorName)
893				deploymentPvc, err := c.CoreV1().PersistentVolumeClaims(ns).Get(context.TODO(), deploymentPvcName, metav1.GetOptions{})
894				framework.ExpectNoError(err, "Expected tidbmonitor deployment pvc success")
895				oldVolumeName := deploymentPvc.Spec.VolumeName
896
897				ginkgo.By("Upgrade tidb-operator and CRDs to the latest version")
898				ocfg.Tag = cfg.OperatorTag
899				ocfg.Image = cfg.OperatorImage
900				oa.ReplaceCRDOrDie(ocfg)
901				oa.UpgradeOperatorOrDie(ocfg)
902				err = tests.CheckTidbMonitor(tm, cli, c, fw)
903				framework.ExpectNoError(err, "Expected tidbmonitor checked success under migration")
904				err = wait.Poll(5*time.Second, 3*time.Minute, func() (done bool, err error) {
905					tmSet, err := stsGetter.StatefulSets(ns).Get(context.TODO(), monitor.GetMonitorObjectName(tm), metav1.GetOptions{})
906					if err != nil {
907						log.Logf("ERROR: failed to get statefulset: %s/%s, %v", ns, tmSet, err)
908						return false, nil
909					}
910					return true, nil
911				})
912				framework.ExpectNoError(err, "Expected tidbmonitor sts success")
913				err = wait.Poll(5*time.Second, 5*time.Minute, func() (done bool, err error) {
914					newStsPvcName := monitor.GetMonitorFirstPVCName(tm.Name)
915					log.Logf("tidbmonitor newStsPvcName:%s", newStsPvcName)
916					stsPvc, err := c.CoreV1().PersistentVolumeClaims(ns).Get(context.TODO(), newStsPvcName, metav1.GetOptions{})
917					if err != nil {
918						if errors.IsNotFound(err) {
919							log.Logf("tm[%s/%s]'s first sts pvc not found,tag:%s,image:%s", ns, tm.Name, cfg.OperatorTag, cfg.OperatorImage)
920							return false, nil
921						}
922						log.Logf("ERROR: get tidbmonitor sts pvc err:%v", err)
923						return false, nil
924					}
925					if stsPvc.Spec.VolumeName == oldVolumeName {
926						return true, nil
927					}
928					log.Logf("tidbmonitor sts pv unequal to old deployment pv")
929					return false, nil
930				})
931				framework.ExpectNoError(err, "Expected tidbmonitor sts use pv of old deployment")
932				err = tests.CheckTidbMonitor(tm, cli, c, fw)
933				framework.ExpectNoError(err, "Expected tidbmonitor checked success")
934			})
935		})
936	})
937})
938
939func setPartitionAnnotation(namespace, tcName, component string, ordinal int) error {
940	// add annotation to pause statefulset upgrade process
941	output, err := framework.RunKubectl(namespace, "annotate", "tc", tcName, fmt.Sprintf("tidb.pingcap.com/%s-partition=%d", component, ordinal), "--overwrite")
942	if err != nil {
943		return fmt.Errorf("fail to set annotation for [%s/%s], component: %s, partition: %d, err: %v, output: %s", namespace, tcName, component, ordinal, err, output)
944	}
945	return nil
946}
947
948func MustGetLabelSelectorForComponents(tcName string, filterComponents ...string) labels.Selector {
949	selector := labels.SelectorFromSet(label.New().Instance(tcName).Labels())
950
951	r, err := labels.NewRequirement(label.ComponentLabelKey, selection.NotIn, filterComponents)
952	framework.ExpectNoError(err, "failed to create label requirement")
953
954	return selector.Add(*r)
955}
956
957// MustCreateTiFlashReplicationForTable create TiFLash replication and ensure it is ready
958func MustCreateTiFlashReplicationForTable(db *utildb.Database, dbName string, table string, expectCount int) {
959	err := utildb.CreateTiFlashReplicationAndWaitToComplete(db.TiFlashAction(), dbName, table, 1, time.Minute)
960	framework.ExpectNoError(err, "failed to create TiFlash replication for %s", table)
961	count, err := utildb.Count(db, "tiflash", dbName, table)
962	framework.ExpectNoError(err, "failed to count records in %s by using %s", table, "tiflash")
963	framework.ExpectEqual(count, expectCount, "count of records in %s changed by using %s", table, "tiflash")
964}
965
966// EnsureRecordsNotChangedForTables ensure records not changed for tables
967func EnsureRecordsNotChangedForTables(db *utildb.Database, engine string, dbName string, tables []string, expectCount int) {
968	for _, table := range tables {
969		count, err := utildb.Count(db, engine, dbName, table)
970		framework.ExpectNoError(err, "failed to count records in %s by using %s", table, engine)
971		framework.ExpectEqual(count, expectCount, "count of records in %s changed by using %s", table, engine)
972	}
973}
974
Full Screen

label_test.go

Source: label_test.go Github

copy
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package label
18
19import (
20	"net/http"
21
22	"github.com/onsi/ginkgo"
23
24	"github.com/apisix/manager-api/test/e2enew/base"
25)
26
27var _ = ginkgo.Describe("Test label", func() {
28	ginkgo.Context("test label", func() {
29		ginkgo.It("config route", func() {
30			base.RunTestCase(base.HttpTestCase{
31				Object: base.ManagerApiExpect(),
32				Path:   "/apisix/admin/routes/r1",
33				Method: http.MethodPut,
34				Body: `{
35					 "name": "route1",
36					 "uri": "/hello",
37					 "labels": {
38						 "build":"16",
39						 "env":"production",
40						 "version":"v2"
41					 },
42					 "upstream": {
43						 "type": "roundrobin",
44						 "nodes": [{
45							 "host": "` + base.UpstreamIp + `",
46							 "port": 1980,
47							 "weight": 1
48						 }]
49					 }
50				 }`,
51				Headers:      map[string]string{"Authorization": base.GetToken()},
52				ExpectStatus: http.StatusOK,
53			})
54		})
55		ginkgo.It("create consumer", func() {
56			base.RunTestCase(base.HttpTestCase{
57				Object: base.ManagerApiExpect(),
58				Path:   "/apisix/admin/consumers/c1",
59				Method: http.MethodPut,
60				Body: `{
61					 "username": "c1",
62					 "plugins": {
63						 "key-auth": {
64							 "key": "auth-one"
65						 }
66					 },
67					 "labels": {
68						 "build":"16",
69						 "env":"production",
70						 "version":"v3"
71					 },
72					 "desc": "test description"
73				 }`,
74				Headers:      map[string]string{"Authorization": base.GetToken()},
75				ExpectStatus: http.StatusOK,
76			})
77		})
78		ginkgo.It("create upstream", func() {
79			base.RunTestCase(base.HttpTestCase{
80				Object: base.ManagerApiExpect(),
81				Method: http.MethodPut,
82				Path:   "/apisix/admin/upstreams/u1",
83				Body: `{
84					 "nodes": [{
85						 "host": "` + base.UpstreamIp + `",
86						 "port": 1980,
87						 "weight": 1
88					 }],
89					 "labels": {
90						 "build":"17",
91						 "env":"production",
92						 "version":"v2"
93					 },
94					 "type": "roundrobin"
95				 }`,
96				Headers:      map[string]string{"Authorization": base.GetToken()},
97				ExpectStatus: http.StatusOK,
98			})
99		})
100		ginkgo.It("create service", func() {
101			base.RunTestCase(base.HttpTestCase{
102				Object: base.ManagerApiExpect(),
103				Method: http.MethodPost,
104				Path:   "/apisix/admin/services",
105				Body: `{
106					 "id": "s1",
107					 "plugins": {
108						 "limit-count": {
109							 "count": 2,
110							 "time_window": 60,
111							 "rejected_code": 503,
112							 "key": "remote_addr"
113						 }
114					 },
115					 "upstream": {
116						 "type": "roundrobin",
117						 "nodes": [{
118							 "host": "39.97.63.215",
119							 "port": 80,
120							 "weight": 1
121						 }]
122					 },
123					 "labels": {
124						 "build":"16",
125						 "env":"production",
126						 "version":"v2",
127						 "extra": "test"
128					 }
129				 }`,
130				Headers:      map[string]string{"Authorization": base.GetToken()},
131				ExpectStatus: http.StatusOK,
132			})
133		})
134		ginkgo.It("create plugin_config", func() {
135			base.RunTestCase(base.HttpTestCase{
136				Object: base.ManagerApiExpect(),
137				Method: http.MethodPut,
138				Path:   "/apisix/admin/plugin_configs/1",
139				Body: `{
140					 "plugins": {
141						 "response-rewrite": {
142							 "headers": {
143								 "X-VERSION":"22.0"
144							 }
145						 }
146					 },
147					 "labels": {
148						 "version": "v2",
149						 "build":   "17",
150						 "extra":   "test"
151					 }
152				 }`,
153				Headers:      map[string]string{"Authorization": base.GetToken()},
154				ExpectStatus: http.StatusOK,
155			})
156		})
157		ginkgo.It("get route label", func() {
158			base.RunTestCase(base.HttpTestCase{
159				Object:       base.ManagerApiExpect(),
160				Method:       http.MethodGet,
161				Headers:      map[string]string{"Authorization": base.GetToken()},
162				Path:         "/apisix/admin/labels/route",
163				ExpectStatus: http.StatusOK,
164				ExpectBody:   "{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v2\"}",
165				Sleep:        base.SleepTime,
166			})
167		})
168		ginkgo.It("get consumer label", func() {
169			base.RunTestCase(base.HttpTestCase{
170				Object:       base.ManagerApiExpect(),
171				Method:       http.MethodGet,
172				Headers:      map[string]string{"Authorization": base.GetToken()},
173				Path:         "/apisix/admin/labels/consumer",
174				ExpectStatus: http.StatusOK,
175				ExpectBody:   "{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v3\"}",
176			})
177		})
178		ginkgo.It("get upstream label", func() {
179			base.RunTestCase(base.HttpTestCase{
180				Object:       base.ManagerApiExpect(),
181				Method:       http.MethodGet,
182				Headers:      map[string]string{"Authorization": base.GetToken()},
183				Path:         "/apisix/admin/labels/upstream",
184				ExpectStatus: http.StatusOK,
185				ExpectBody:   "{\"build\":\"17\"},{\"env\":\"production\"},{\"version\":\"v2\"}",
186			})
187		})
188		ginkgo.It("get service label", func() {
189			base.RunTestCase(base.HttpTestCase{
190				Object:       base.ManagerApiExpect(),
191				Method:       http.MethodGet,
192				Headers:      map[string]string{"Authorization": base.GetToken()},
193				Path:         "/apisix/admin/labels/service",
194				ExpectStatus: http.StatusOK,
195				ExpectBody:   "{\"build\":\"16\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"}",
196			})
197		})
198		ginkgo.It("get plugin_config label", func() {
199			base.RunTestCase(base.HttpTestCase{
200				Object:       base.ManagerApiExpect(),
201				Method:       http.MethodGet,
202				Headers:      map[string]string{"Authorization": base.GetToken()},
203				Path:         "/apisix/admin/labels/plugin_config",
204				ExpectStatus: http.StatusOK,
205				ExpectBody:   "{\"build\":\"17\"},{\"extra\":\"test\"},{\"version\":\"v2\"}",
206			})
207		})
208		ginkgo.It("update plugin_config", func() {
209			base.RunTestCase(base.HttpTestCase{
210				Object: base.ManagerApiExpect(),
211				Method: http.MethodPut,
212				Path:   "/apisix/admin/plugin_configs/1",
213				Body: `{
214					 "plugins": {
215						 "response-rewrite": {
216							 "headers": {
217								 "X-VERSION":"22.0"
218							 }
219						 }
220					 },
221					 "labels": {
222						 "version": "v3",
223						 "build":   "16",
224						 "extra":   "test"
225					 }
226				 }`,
227				Headers:      map[string]string{"Authorization": base.GetToken()},
228				ExpectStatus: http.StatusOK,
229			})
230		})
231		ginkgo.It("get plugin_config label again to verify update", func() {
232			base.RunTestCase(base.HttpTestCase{
233				Object:       base.ManagerApiExpect(),
234				Method:       http.MethodGet,
235				Headers:      map[string]string{"Authorization": base.GetToken()},
236				Path:         "/apisix/admin/labels/plugin_config",
237				ExpectStatus: http.StatusOK,
238				ExpectBody:   "{\"build\":\"16\"},{\"extra\":\"test\"},{\"version\":\"v3\"}",
239				Sleep:        base.SleepTime,
240			})
241		})
242		ginkgo.It("get all label", func() {
243			base.RunTestCase(base.HttpTestCase{
244				Object:       base.ManagerApiExpect(),
245				Method:       http.MethodGet,
246				Headers:      map[string]string{"Authorization": base.GetToken()},
247				Path:         "/apisix/admin/labels/all",
248				ExpectStatus: http.StatusOK,
249				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"},{\"version\":\"v3\"}",
250			})
251		})
252		ginkgo.It("get label with page", func() {
253			base.RunTestCase(base.HttpTestCase{
254				Object:       base.ManagerApiExpect(),
255				Method:       http.MethodGet,
256				Query:        "page=1&page_size=1",
257				Headers:      map[string]string{"Authorization": base.GetToken()},
258				Path:         "/apisix/admin/labels/all",
259				ExpectStatus: http.StatusOK,
260				ExpectBody:   "{\"build\":\"16\"}",
261			})
262		})
263		ginkgo.It("get label with page", func() {
264			base.RunTestCase(base.HttpTestCase{
265				Object:       base.ManagerApiExpect(),
266				Method:       http.MethodGet,
267				Query:        "page=3&page_size=1",
268				Headers:      map[string]string{"Authorization": base.GetToken()},
269				Path:         "/apisix/admin/labels/all",
270				ExpectStatus: http.StatusOK,
271				ExpectBody:   "{\"env\":\"production\"}",
272			})
273		})
274		ginkgo.It("get labels (key = build)", func() {
275			base.RunTestCase(base.HttpTestCase{
276				Object:       base.ManagerApiExpect(),
277				Method:       http.MethodGet,
278				Headers:      map[string]string{"Authorization": base.GetToken()},
279				Query:        "label=build",
280				Path:         "/apisix/admin/labels/all",
281				ExpectStatus: http.StatusOK,
282				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"}",
283			})
284		})
285		ginkgo.It("get labels with the same key (key = build)", func() {
286			base.RunTestCase(base.HttpTestCase{
287				Object:       base.ManagerApiExpect(),
288				Method:       http.MethodGet,
289				Headers:      map[string]string{"Authorization": base.GetToken()},
290				Query:        "label=build:16,build:17",
291				Path:         "/apisix/admin/labels/all",
292				ExpectStatus: http.StatusOK,
293				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"}",
294			})
295		})
296		ginkgo.It("get labels (key = build) with page", func() {
297			base.RunTestCase(base.HttpTestCase{
298				Object:       base.ManagerApiExpect(),
299				Method:       http.MethodGet,
300				Headers:      map[string]string{"Authorization": base.GetToken()},
301				Query:        "label=build&page=2&page_size=1",
302				Path:         "/apisix/admin/labels/all",
303				ExpectStatus: http.StatusOK,
304				ExpectBody:   "{\"build\":\"17\"}",
305			})
306		})
307		ginkgo.It("get labels with same key (key = build) and page", func() {
308			base.RunTestCase(base.HttpTestCase{
309				Object:       base.ManagerApiExpect(),
310				Method:       http.MethodGet,
311				Headers:      map[string]string{"Authorization": base.GetToken()},
312				Query:        "label=build:16,build:17&page=1&page_size=2",
313				Path:         "/apisix/admin/labels/all",
314				ExpectStatus: http.StatusOK,
315				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"}",
316			})
317		})
318		ginkgo.It("get labels with same key (key = build) and page", func() {
319			base.RunTestCase(base.HttpTestCase{
320				Object:       base.ManagerApiExpect(),
321				Method:       http.MethodGet,
322				Headers:      map[string]string{"Authorization": base.GetToken()},
323				Query:        "label=build:16,build:17&page=2&page_size=1",
324				Path:         "/apisix/admin/labels/all",
325				ExpectStatus: http.StatusOK,
326				ExpectBody:   "{\"build\":\"17\"}",
327			})
328		})
329		ginkgo.It("get labels (key = build && env = production)", func() {
330			base.RunTestCase(base.HttpTestCase{
331				Object:       base.ManagerApiExpect(),
332				Method:       http.MethodGet,
333				Headers:      map[string]string{"Authorization": base.GetToken()},
334				Query:        "label=build,env:production",
335				Path:         "/apisix/admin/labels/all",
336				ExpectStatus: http.StatusOK,
337				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"}",
338			})
339		})
340		ginkgo.It("get labels (build=16 | 17 and env = production)", func() {
341			base.RunTestCase(base.HttpTestCase{
342				Object:       base.ManagerApiExpect(),
343				Method:       http.MethodGet,
344				Headers:      map[string]string{"Authorization": base.GetToken()},
345				Query:        "label=build:16,build:17,env:production",
346				Path:         "/apisix/admin/labels/all",
347				ExpectStatus: http.StatusOK,
348				ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"}",
349			})
350		})
351		ginkgo.It("get labels (key = build && env = production) with page", func() {
352			base.RunTestCase(base.HttpTestCase{
353				Object:       base.ManagerApiExpect(),
354				Method:       http.MethodGet,
355				Headers:      map[string]string{"Authorization": base.GetToken()},
356				Query:        "label=build,env:production&page=3&page_size=1",
357				Path:         "/apisix/admin/labels/all",
358				ExpectStatus: http.StatusOK,
359				ExpectBody:   "{\"env\":\"production\"}",
360			})
361		})
362		ginkgo.It("delete route", func() {
363			base.RunTestCase(base.HttpTestCase{
364				Object:       base.ManagerApiExpect(),
365				Method:       http.MethodDelete,
366				Path:         "/apisix/admin/routes/r1",
367				Headers:      map[string]string{"Authorization": base.GetToken()},
368				ExpectStatus: http.StatusOK,
369			})
370		})
371		ginkgo.It("delete consumer", func() {
372			base.RunTestCase(base.HttpTestCase{
373				Object:       base.ManagerApiExpect(),
374				Method:       http.MethodDelete,
375				Path:         "/apisix/admin/consumers/c1",
376				Headers:      map[string]string{"Authorization": base.GetToken()},
377				ExpectStatus: http.StatusOK,
378			})
379		})
380		ginkgo.It("delete service", func() {
381			base.RunTestCase(base.HttpTestCase{
382				Object:       base.ManagerApiExpect(),
383				Method:       http.MethodDelete,
384				Path:         "/apisix/admin/services/s1",
385				Headers:      map[string]string{"Authorization": base.GetToken()},
386				ExpectStatus: http.StatusOK,
387			})
388		})
389		ginkgo.It("delete upstream", func() {
390			base.RunTestCase(base.HttpTestCase{
391				Object:       base.ManagerApiExpect(),
392				Method:       http.MethodDelete,
393				Path:         "/apisix/admin/upstreams/u1",
394				Headers:      map[string]string{"Authorization": base.GetToken()},
395				ExpectStatus: http.StatusOK,
396			})
397		})
398		ginkgo.It("delete plugin_config", func() {
399			base.RunTestCase(base.HttpTestCase{
400				Object:       base.ManagerApiExpect(),
401				Method:       http.MethodDelete,
402				Path:         "/apisix/admin/plugin_configs/1",
403				Headers:      map[string]string{"Authorization": base.GetToken()},
404				ExpectStatus: http.StatusOK,
405			})
406		})
407	})
408})
409
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)