github.com/verrazzano/verrazzano-monitoring-operator@v0.0.30/verrazzano-backup-hook/utilities/k8s/k8sHelper_test.go (about)

     1  // Copyright (c) 2022, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package k8s_test
     5  
     6  import (
     7  	"fmt"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/verrazzano/verrazzano-monitoring-operator/verrazzano-backup-hook/constants"
    10  	"github.com/verrazzano/verrazzano-monitoring-operator/verrazzano-backup-hook/log"
    11  	kutil "github.com/verrazzano/verrazzano-monitoring-operator/verrazzano-backup-hook/utilities/k8s"
    12  	vmofake "github.com/verrazzano/verrazzano-monitoring-operator/verrazzano-backup-hook/utilities/k8s/fake"
    13  	"go.uber.org/zap"
    14  	apps "k8s.io/api/apps/v1"
    15  	v1 "k8s.io/api/core/v1"
    16  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    17  	"k8s.io/apimachinery/pkg/runtime"
    18  	dynamicfake "k8s.io/client-go/dynamic/fake"
    19  	"k8s.io/client-go/kubernetes/fake"
    20  	"os"
    21  	"sigs.k8s.io/controller-runtime/pkg/client"
    22  	"strconv"
    23  	"strings"
    24  	"sync"
    25  	"testing"
    26  )
    27  
    28  var (
    29  	TestPod = v1.Pod{
    30  		ObjectMeta: metav1.ObjectMeta{
    31  			Name:        "foo",
    32  			Namespace:   "foo",
    33  			Annotations: map[string]string{},
    34  		},
    35  		Status: v1.PodStatus{
    36  			Phase: "Running",
    37  			Conditions: []v1.PodCondition{
    38  				{
    39  					Type:   "Ready",
    40  					Status: "True",
    41  				},
    42  				{
    43  					Type:   "NotReady",
    44  					Status: "True",
    45  				},
    46  			},
    47  		},
    48  	}
    49  )
    50  
    51  func logHelper() (*zap.SugaredLogger, string) {
    52  	file, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("verrazzano-%s-hook-*.log", strings.ToLower("TEST")))
    53  	if err != nil {
    54  		fmt.Printf("Unable to create temp file")
    55  		os.Exit(1)
    56  	}
    57  	defer file.Close()
    58  	log, _ := log.Logger(file.Name())
    59  	return log, file.Name()
    60  }
    61  
    62  // TestPopulateConnData tests the PopulateConnData method for the following use case.
    63  // GIVEN a Velero backup name
    64  // WHEN Velero backup is in progress
    65  // THEN fetches the secret associate with Velero backup
    66  func TestPopulateConnData(t *testing.T) {
    67  	t.Parallel()
    68  	log, f := logHelper()
    69  	defer os.Remove(f)
    70  
    71  	var clientk client.Client
    72  	fc := fake.NewSimpleClientset()
    73  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
    74  
    75  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
    76  	conData, err := k8s.PopulateConnData(constants.VeleroNameSpace, "Foo")
    77  	assert.Nil(t, conData)
    78  	assert.NotNil(t, err)
    79  }
    80  
    81  // TestGetBackupStorageLocation tests the GetBackupStorageLocation method for the following use case.
    82  // GIVEN a Velero backup storage location name
    83  // WHEN invoked
    84  // THEN fetches backup storage location object
    85  func TestGetBackupStorageLocation(t *testing.T) {
    86  	t.Parallel()
    87  	log, f := logHelper()
    88  	defer os.Remove(f)
    89  
    90  	var clientk client.Client
    91  	fc := fake.NewSimpleClientset()
    92  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
    93  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
    94  	_, err := k8s.GetBackupStorageLocation("system", "fsl")
    95  	assert.NotNil(t, err)
    96  }
    97  
    98  // TestGetBackup tests the GetBackup method for the following use case.
    99  // GIVEN a Velero backup name
   100  // WHEN invoked
   101  // THEN fetches backup object
   102  func TestGetBackup(t *testing.T) {
   103  	t.Parallel()
   104  	log, f := logHelper()
   105  	defer os.Remove(f)
   106  
   107  	var clientk client.Client
   108  	fc := fake.NewSimpleClientset()
   109  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   110  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
   111  
   112  	_, err := k8s.GetBackup("system", "foo")
   113  	assert.NotNil(t, err)
   114  }
   115  
   116  // TestCheckPodStatus tests the CheckPodStatus method for the following use case.
   117  // GIVEN a pod name
   118  // WHEN invoked
   119  // THEN fetches pod status and monitors it depending on the checkFlag
   120  func TestCheckPodStatus(t *testing.T) {
   121  	t.Parallel()
   122  	log, f := logHelper()
   123  	defer os.Remove(f)
   124  	var clientk client.Client
   125  	fc := fake.NewSimpleClientset()
   126  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   127  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
   128  
   129  	var wg sync.WaitGroup
   130  
   131  	wg.Add(1)
   132  	err := k8s.CheckPodStatus("foo", "foo", "up", "10m", &wg)
   133  	log.Infof("%v", err)
   134  	assert.NotNil(t, err)
   135  	wg.Wait()
   136  
   137  	fc = fake.NewSimpleClientset(&TestPod)
   138  	k8stest := kutil.New(dclient, clientk, fc, nil, "default", log)
   139  	wg.Add(1)
   140  	err = k8stest.CheckPodStatus("foo", "foo", "up", "10m", &wg)
   141  	log.Infof("%v", err)
   142  	assert.Nil(t, err)
   143  	wg.Wait()
   144  
   145  	wg.Add(1)
   146  	err = k8stest.CheckPodStatus("foo", "foo", "down", "1s", &wg)
   147  	log.Infof("%v", err)
   148  	assert.NotNil(t, err)
   149  	wg.Wait()
   150  }
   151  
   152  // TestCheckAllPodsAfterRestore tests the CheckAllPodsAfterRestore method for the following use case.
   153  // GIVEN k8s client
   154  // WHEN restore is complete
   155  // THEN checks kibana and ingest pods are Ready after reboot
   156  func TestCheckAllPodsAfterRestore(t *testing.T) {
   157  	t.Parallel()
   158  	IngestLabel := make(map[string]string)
   159  	KibanaLabel := make(map[string]string)
   160  	IngestLabel["app"] = "system-es-ingest"
   161  	KibanaLabel["app"] = "system-kibana"
   162  	IngestPod := v1.Pod{
   163  		ObjectMeta: metav1.ObjectMeta{
   164  			Name:        "foo",
   165  			Namespace:   constants.VerrazzanoSystemNamespace,
   166  			Annotations: map[string]string{},
   167  			Labels:      IngestLabel,
   168  		},
   169  		Status: v1.PodStatus{
   170  			Phase: "Running",
   171  			Conditions: []v1.PodCondition{
   172  				{
   173  					Type:   "Ready",
   174  					Status: "True",
   175  				},
   176  				{
   177  					Type:   "NotReady",
   178  					Status: "True",
   179  				},
   180  			},
   181  		},
   182  	}
   183  
   184  	KibanaPod := v1.Pod{
   185  		ObjectMeta: metav1.ObjectMeta{
   186  			Name:        "bar",
   187  			Namespace:   constants.VerrazzanoSystemNamespace,
   188  			Annotations: map[string]string{},
   189  			Labels:      KibanaLabel,
   190  		},
   191  		Status: v1.PodStatus{
   192  			Phase: "Running",
   193  			Conditions: []v1.PodCondition{
   194  				{
   195  					Type:   "Ready",
   196  					Status: "True",
   197  				},
   198  				{
   199  					Type:   "NotReady",
   200  					Status: "True",
   201  				},
   202  			},
   203  		},
   204  	}
   205  
   206  	log, f := logHelper()
   207  	defer os.Remove(f)
   208  
   209  	var clientk client.Client
   210  	fc := fake.NewSimpleClientset()
   211  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   212  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
   213  
   214  	os.Setenv(constants.OpenSearchHealthCheckTimeoutKey, "1s")
   215  
   216  	err := k8s.CheckAllPodsAfterRestore()
   217  	log.Infof("%v", err)
   218  	assert.Nil(t, err)
   219  
   220  	fc = fake.NewSimpleClientset(&IngestPod, &KibanaPod)
   221  	k8snew := kutil.New(dclient, clientk, fc, nil, "default", log)
   222  	err = k8snew.CheckAllPodsAfterRestore()
   223  	log.Infof("%v", err)
   224  	assert.Nil(t, err)
   225  
   226  }
   227  
   228  // TestCheckDeployment tests the CheckDeployment method for the following use case.
   229  // GIVEN k8s client
   230  // WHEN restore is complete
   231  // THEN checks kibana deployment is present on system
   232  func TestCheckDeployment(t *testing.T) {
   233  	t.Parallel()
   234  	KibanaLabel := make(map[string]string)
   235  	KibanaLabel["verrazzano-component"] = "kibana"
   236  	PrimaryDeploy := apps.Deployment{
   237  		ObjectMeta: metav1.ObjectMeta{
   238  			Name:        "foo",
   239  			Namespace:   constants.VerrazzanoSystemNamespace,
   240  			Annotations: map[string]string{},
   241  			Labels:      KibanaLabel,
   242  		},
   243  	}
   244  
   245  	SecondaryDeploy := apps.Deployment{
   246  		ObjectMeta: metav1.ObjectMeta{
   247  			Name:        "bar",
   248  			Namespace:   constants.VerrazzanoSystemNamespace,
   249  			Annotations: map[string]string{},
   250  			Labels:      KibanaLabel,
   251  		},
   252  	}
   253  
   254  	log, f := logHelper()
   255  	defer os.Remove(f)
   256  
   257  	var clientk client.Client
   258  	fc := fake.NewSimpleClientset()
   259  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   260  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
   261  	os.Setenv(constants.OpenSearchHealthCheckTimeoutKey, "1s")
   262  
   263  	fmt.Println("Deployment not found")
   264  	ok, err := k8s.CheckDeployment(constants.KibanaDeploymentLabelSelector, constants.VerrazzanoSystemNamespace)
   265  	log.Infof("%v", err)
   266  	assert.Nil(t, err)
   267  	assert.Equal(t, ok, false)
   268  
   269  	fmt.Println("Deployment found")
   270  	fc = fake.NewSimpleClientset(&PrimaryDeploy)
   271  	k8sPrimary := kutil.New(dclient, clientk, fc, nil, "default", log)
   272  	ok, err = k8sPrimary.CheckDeployment(constants.KibanaDeploymentLabelSelector, constants.VerrazzanoSystemNamespace)
   273  	log.Infof("%v", err)
   274  	assert.Nil(t, err)
   275  	assert.Equal(t, ok, true)
   276  
   277  	fmt.Println("Multiple Deployments found")
   278  	fc = fake.NewSimpleClientset(&PrimaryDeploy, &SecondaryDeploy)
   279  	k8sPrimarySec := kutil.New(dclient, clientk, fc, nil, "default", log)
   280  	ok, err = k8sPrimarySec.CheckDeployment(constants.KibanaDeploymentLabelSelector, constants.VerrazzanoSystemNamespace)
   281  	log.Infof("%v", err)
   282  	assert.Nil(t, err)
   283  	assert.Equal(t, ok, false)
   284  }
   285  
   286  // TestIsPodReady tests the IsPodReady method for the following use case.
   287  // GIVEN k8s client
   288  // WHEN restore is complete
   289  // THEN checks is pod is in ready state
   290  func TestIsPodReady(t *testing.T) {
   291  	t.Parallel()
   292  
   293  	ReadyPod := v1.Pod{
   294  		ObjectMeta: metav1.ObjectMeta{
   295  			Name:        "foo",
   296  			Namespace:   constants.VerrazzanoSystemNamespace,
   297  			Annotations: map[string]string{},
   298  		},
   299  		Status: v1.PodStatus{
   300  			Phase: "Running",
   301  			Conditions: []v1.PodCondition{
   302  				{
   303  					Type:   "Initialized",
   304  					Status: "True",
   305  				},
   306  				{
   307  					Type:   "Ready",
   308  					Status: "True",
   309  				},
   310  				{
   311  					Type:   "ContainersReady",
   312  					Status: "True",
   313  				},
   314  				{
   315  					Type:   "PodScheduled",
   316  					Status: "True",
   317  				},
   318  			},
   319  		},
   320  	}
   321  
   322  	NotReadyPod := v1.Pod{
   323  		ObjectMeta: metav1.ObjectMeta{
   324  			Name:        "foo",
   325  			Namespace:   constants.VerrazzanoSystemNamespace,
   326  			Annotations: map[string]string{},
   327  		},
   328  		Status: v1.PodStatus{
   329  			Phase: "Running",
   330  			Conditions: []v1.PodCondition{
   331  				{
   332  					Type:   "Initialized",
   333  					Status: "True",
   334  				},
   335  				{
   336  					Type:   "ContainersReady",
   337  					Status: "True",
   338  				},
   339  				{
   340  					Type:   "PodScheduled",
   341  					Status: "True",
   342  				},
   343  			},
   344  		},
   345  	}
   346  
   347  	log, f := logHelper()
   348  	defer os.Remove(f)
   349  
   350  	os.Setenv(constants.OpenSearchHealthCheckTimeoutKey, "1s")
   351  
   352  	var clientk client.Client
   353  	fc := fake.NewSimpleClientset()
   354  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   355  	k8s := kutil.New(dclient, clientk, fc, nil, "default", log)
   356  	ok, err := k8s.IsPodReady(&ReadyPod)
   357  	log.Infof("%v", err)
   358  	assert.Nil(t, err)
   359  	assert.Equal(t, ok, true)
   360  
   361  	ok, err = k8s.IsPodReady(&NotReadyPod)
   362  	log.Infof("%v", err)
   363  	assert.Nil(t, err)
   364  	assert.Equal(t, ok, false)
   365  
   366  }
   367  
   368  // TestExecRetry tests the ExecRetry method for the following use case.
   369  // GIVEN k8s client
   370  // WHEN exec command fails
   371  // THEN there is a retry of the exec command
   372  
   373  func TestExecRetry(t *testing.T) {
   374  
   375  	pod := &v1.Pod{
   376  		ObjectMeta: metav1.ObjectMeta{
   377  			Namespace: "ns",
   378  			Name:      "foo",
   379  		},
   380  	}
   381  
   382  	log, f := logHelper()
   383  	defer os.Remove(f)
   384  	defer os.Unsetenv(constants.DevKey)
   385  
   386  	os.Setenv(constants.OpenSearchHealthCheckTimeoutKey, "1s")
   387  	os.Setenv(constants.DevKey, constants.TrueString)
   388  
   389  	var clientk client.Client
   390  	config, fc := vmofake.NewClientsetConfig()
   391  	dclient := dynamicfake.NewSimpleDynamicClient(runtime.NewScheme())
   392  	k8s := kutil.New(dclient, clientk, fc, config, "default", log)
   393  
   394  	var accessKeyCmd []string
   395  	accessKeyCmd = append(accessKeyCmd, "/bin/sh", "-c", fmt.Sprintf("echo %s | %s", strconv.Quote("ACCESS_KEY"), constants.OpenSearchKeystoreAccessKeyCmd))
   396  
   397  	err := k8s.ExecRetry(pod, constants.OpenSearchDataPodContainerName, "1s", accessKeyCmd)
   398  	assert.Nil(t, err)
   399  }