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 }