etcd_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package etcd_test
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. utils "github.com/bitnami/charts/.vib/common-tests/ginkgo-utils"
  7. . "github.com/onsi/ginkgo/v2"
  8. . "github.com/onsi/gomega"
  9. appsv1 "k8s.io/api/apps/v1"
  10. batchv1 "k8s.io/api/batch/v1"
  11. v1 "k8s.io/api/core/v1"
  12. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  13. "k8s.io/client-go/kubernetes"
  14. )
  15. const (
  16. PollingInterval = 1 * time.Second
  17. )
  18. var _ = Describe("etcd", Ordered, func() {
  19. var c *kubernetes.Clientset
  20. var ctx context.Context
  21. var cancel context.CancelFunc
  22. BeforeEach(func() {
  23. ctx, cancel = context.WithCancel(context.Background())
  24. conf := utils.MustBuildClusterConfig(kubeconfig)
  25. c = kubernetes.NewForConfigOrDie(conf)
  26. })
  27. When("a key-value is created and etcd is scaled down to 0 replicas and back up", func() {
  28. It("should have access to the created database", func() {
  29. getAvailableReplicas := func(ss *appsv1.StatefulSet) int32 { return ss.Status.AvailableReplicas }
  30. getRestartedAtAnnotation := func(pod *v1.Pod) string { return pod.Annotations["kubectl.kubernetes.io/restartedAt"] }
  31. getSucceededJobs := func(j *batchv1.Job) int32 { return j.Status.Succeeded }
  32. getOpts := metav1.GetOptions{}
  33. By("checking all the replicas are available")
  34. ss, err := c.AppsV1().StatefulSets(namespace).Get(ctx, stsName, getOpts)
  35. Expect(err).NotTo(HaveOccurred())
  36. Expect(ss.Status.Replicas).NotTo(BeZero())
  37. origReplicas := *ss.Spec.Replicas
  38. Eventually(func() (*appsv1.StatefulSet, error) {
  39. return c.AppsV1().StatefulSets(namespace).Get(ctx, stsName, getOpts)
  40. }, timeout, PollingInterval).Should(WithTransform(getAvailableReplicas, Equal(origReplicas)))
  41. svc, err := c.CoreV1().Services(namespace).Get(ctx, stsName, getOpts)
  42. Expect(err).NotTo(HaveOccurred())
  43. port, err := utils.SvcGetPortByName(svc, "client")
  44. Expect(err).NotTo(HaveOccurred())
  45. image, err := utils.StsGetContainerImageByName(ss, "etcd")
  46. Expect(err).NotTo(HaveOccurred())
  47. jobSuffix := time.Now().Format("20060102150405")
  48. By("creating a job to create a new key-pair")
  49. createKeyJobName := fmt.Sprintf("%s-put-%s",
  50. stsName, jobSuffix)
  51. keyName := fmt.Sprintf("k%s", jobSuffix)
  52. valueName := fmt.Sprintf("v%s", jobSuffix)
  53. err = createJob(ctx, c, createKeyJobName, port, image, "put", keyName, valueName)
  54. Expect(err).NotTo(HaveOccurred())
  55. Eventually(func() (*batchv1.Job, error) {
  56. return c.BatchV1().Jobs(namespace).Get(ctx, createKeyJobName, getOpts)
  57. }, timeout, PollingInterval).Should(WithTransform(getSucceededJobs, Equal(int32(1))))
  58. By("rollout restart the statefulset")
  59. _, err = utils.StsRolloutRestart(ctx, c, ss)
  60. Expect(err).NotTo(HaveOccurred())
  61. for i := int(origReplicas) - 1; i >= 0; i-- {
  62. Eventually(func() (*v1.Pod, error) {
  63. return c.CoreV1().Pods(namespace).Get(ctx, fmt.Sprintf("%s-%d", stsName, i), getOpts)
  64. }, timeout, PollingInterval).Should(WithTransform(getRestartedAtAnnotation, Not(BeEmpty())))
  65. }
  66. Eventually(func() (*appsv1.StatefulSet, error) {
  67. return c.AppsV1().StatefulSets(namespace).Get(ctx, stsName, getOpts)
  68. }, timeout, PollingInterval).Should(WithTransform(getAvailableReplicas, Equal(origReplicas)))
  69. By("creating a job to delete the key-pair")
  70. deleteKeyJobName := fmt.Sprintf("%s-del-%s",
  71. stsName, jobSuffix)
  72. err = createJob(ctx, c, deleteKeyJobName, port, image, "del", keyName)
  73. Expect(err).NotTo(HaveOccurred())
  74. Eventually(func() (*batchv1.Job, error) {
  75. return c.BatchV1().Jobs(namespace).Get(ctx, deleteKeyJobName, getOpts)
  76. }, timeout, PollingInterval).Should(WithTransform(getSucceededJobs, Equal(int32(1))))
  77. })
  78. })
  79. AfterEach(func() {
  80. cancel()
  81. })
  82. })