github.com/kubeshop/testkube@v1.17.23/pkg/mapper/tests/kube_openapi.go (about) 1 package tests 2 3 import ( 4 v1 "k8s.io/api/core/v1" 5 6 commonv1 "github.com/kubeshop/testkube-operator/api/common/v1" 7 testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" 8 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 9 mappertcl "github.com/kubeshop/testkube/pkg/tcl/mappertcl/tests" 10 ) 11 12 // MapTestListKubeToAPI maps CRD list data to OpenAPI spec tests list 13 func MapTestListKubeToAPI(crTests testsv3.TestList) (tests []testkube.Test) { 14 tests = []testkube.Test{} 15 for _, item := range crTests.Items { 16 tests = append(tests, MapTestCRToAPI(item)) 17 } 18 19 return 20 } 21 22 // MapTestCRToAPI maps CRD to OpenAPI spec test 23 func MapTestCRToAPI(crTest testsv3.Test) (test testkube.Test) { 24 test.Name = crTest.Name 25 test.Namespace = crTest.Namespace 26 test.Description = crTest.Spec.Description 27 test.Content = MapTestContentFromSpec(crTest.Spec.Content) 28 test.Created = crTest.CreationTimestamp.Time 29 test.Source = crTest.Spec.Source 30 test.Type_ = crTest.Spec.Type_ 31 test.Labels = crTest.Labels 32 test.Schedule = crTest.Spec.Schedule 33 test.ExecutionRequest = MapExecutionRequestFromSpec(crTest.Spec.ExecutionRequest) 34 test.Uploads = crTest.Spec.Uploads 35 test.Status = MapStatusFromSpec(crTest.Status) 36 return 37 } 38 39 func MergeVariablesAndParams(variables map[string]testsv3.Variable, params map[string]string) map[string]testkube.Variable { 40 out := map[string]testkube.Variable{} 41 for k, v := range params { 42 out[k] = testkube.NewBasicVariable(k, v) 43 } 44 45 for k, v := range variables { 46 if v.Type_ == commonv1.VariableTypeSecret { 47 if v.ValueFrom.SecretKeyRef == nil { 48 out[k] = testkube.NewSecretVariable(v.Name, v.Value) 49 } else { 50 out[k] = testkube.NewSecretVariableReference(v.Name, v.ValueFrom.SecretKeyRef.Name, v.ValueFrom.SecretKeyRef.Key) 51 } 52 } 53 if v.Type_ == commonv1.VariableTypeBasic { 54 if v.ValueFrom.ConfigMapKeyRef == nil { 55 out[k] = testkube.NewBasicVariable(v.Name, v.Value) 56 } else { 57 out[k] = testkube.NewConfigMapVariableReference(v.Name, v.ValueFrom.ConfigMapKeyRef.Name, v.ValueFrom.ConfigMapKeyRef.Key) 58 } 59 } 60 } 61 62 return out 63 } 64 65 // MapTestContentFromSpec maps CRD to OpenAPI spec TestContent 66 func MapTestContentFromSpec(specContent *testsv3.TestContent) *testkube.TestContent { 67 68 content := &testkube.TestContent{} 69 if specContent != nil { 70 content.Type_ = string(specContent.Type_) 71 content.Data = specContent.Data 72 content.Uri = specContent.Uri 73 if specContent.Repository != nil { 74 content.Repository = &testkube.Repository{ 75 Type_: specContent.Repository.Type_, 76 Uri: specContent.Repository.Uri, 77 Branch: specContent.Repository.Branch, 78 Commit: specContent.Repository.Commit, 79 Path: specContent.Repository.Path, 80 WorkingDir: specContent.Repository.WorkingDir, 81 CertificateSecret: specContent.Repository.CertificateSecret, 82 AuthType: string(specContent.Repository.AuthType), 83 } 84 85 if specContent.Repository.UsernameSecret != nil { 86 content.Repository.UsernameSecret = &testkube.SecretRef{ 87 Name: specContent.Repository.UsernameSecret.Name, 88 Key: specContent.Repository.UsernameSecret.Key, 89 } 90 } 91 92 if specContent.Repository.TokenSecret != nil { 93 content.Repository.TokenSecret = &testkube.SecretRef{ 94 Name: specContent.Repository.TokenSecret.Name, 95 Key: specContent.Repository.TokenSecret.Key, 96 } 97 } 98 } 99 } 100 101 return content 102 } 103 104 // MapTestArrayKubeToAPI maps CRD array data to OpenAPI spec tests list 105 func MapTestArrayKubeToAPI(crTests []testsv3.Test) (tests []testkube.Test) { 106 tests = []testkube.Test{} 107 for _, crTest := range crTests { 108 tests = append(tests, MapTestCRToAPI(crTest)) 109 } 110 111 return 112 } 113 114 // MapExecutionRequestFromSpec maps CRD to OpenAPI spec ExecutionREquest 115 func MapExecutionRequestFromSpec(specExecutionRequest *testsv3.ExecutionRequest) *testkube.ExecutionRequest { 116 if specExecutionRequest == nil { 117 return nil 118 } 119 120 var artifactRequest *testkube.ArtifactRequest 121 if specExecutionRequest.ArtifactRequest != nil { 122 artifactRequest = &testkube.ArtifactRequest{ 123 StorageClassName: specExecutionRequest.ArtifactRequest.StorageClassName, 124 VolumeMountPath: specExecutionRequest.ArtifactRequest.VolumeMountPath, 125 Dirs: specExecutionRequest.ArtifactRequest.Dirs, 126 Masks: specExecutionRequest.ArtifactRequest.Masks, 127 StorageBucket: specExecutionRequest.ArtifactRequest.StorageBucket, 128 OmitFolderPerExecution: specExecutionRequest.ArtifactRequest.OmitFolderPerExecution, 129 SharedBetweenPods: specExecutionRequest.ArtifactRequest.SharedBetweenPods, 130 UseDefaultStorageClassName: specExecutionRequest.ArtifactRequest.UseDefaultStorageClassName, 131 } 132 } 133 134 var podRequest *testkube.PodRequest 135 if specExecutionRequest.SlavePodRequest != nil { 136 podRequest = &testkube.PodRequest{} 137 if specExecutionRequest.SlavePodRequest.Resources != nil { 138 podRequest.Resources = &testkube.PodResourcesRequest{} 139 if specExecutionRequest.SlavePodRequest.Resources.Requests != nil { 140 podRequest.Resources.Requests = &testkube.ResourceRequest{ 141 Cpu: specExecutionRequest.SlavePodRequest.Resources.Requests.Cpu, 142 Memory: specExecutionRequest.SlavePodRequest.Resources.Requests.Memory, 143 } 144 } 145 146 if specExecutionRequest.SlavePodRequest.Resources.Limits != nil { 147 podRequest.Resources.Limits = &testkube.ResourceRequest{ 148 Cpu: specExecutionRequest.SlavePodRequest.Resources.Limits.Cpu, 149 Memory: specExecutionRequest.SlavePodRequest.Resources.Limits.Memory, 150 } 151 } 152 } 153 154 podRequest.PodTemplate = specExecutionRequest.SlavePodRequest.PodTemplate 155 podRequest.PodTemplateReference = specExecutionRequest.SlavePodRequest.PodTemplateReference 156 } 157 158 result := &testkube.ExecutionRequest{ 159 Name: specExecutionRequest.Name, 160 TestSuiteName: specExecutionRequest.TestSuiteName, 161 Number: specExecutionRequest.Number, 162 ExecutionLabels: specExecutionRequest.ExecutionLabels, 163 Namespace: specExecutionRequest.Namespace, 164 IsVariablesFileUploaded: specExecutionRequest.IsVariablesFileUploaded, 165 VariablesFile: specExecutionRequest.VariablesFile, 166 Variables: MergeVariablesAndParams(specExecutionRequest.Variables, nil), 167 TestSecretUUID: specExecutionRequest.TestSecretUUID, 168 TestSuiteSecretUUID: specExecutionRequest.TestSuiteSecretUUID, 169 Command: specExecutionRequest.Command, 170 Args: specExecutionRequest.Args, 171 ArgsMode: string(specExecutionRequest.ArgsMode), 172 Image: specExecutionRequest.Image, 173 ImagePullSecrets: MapImagePullSecrets(specExecutionRequest.ImagePullSecrets), 174 Envs: specExecutionRequest.Envs, 175 SecretEnvs: specExecutionRequest.SecretEnvs, 176 Sync: specExecutionRequest.Sync, 177 HttpProxy: specExecutionRequest.HttpProxy, 178 HttpsProxy: specExecutionRequest.HttpsProxy, 179 ActiveDeadlineSeconds: specExecutionRequest.ActiveDeadlineSeconds, 180 ArtifactRequest: artifactRequest, 181 JobTemplate: specExecutionRequest.JobTemplate, 182 JobTemplateReference: specExecutionRequest.JobTemplateReference, 183 CronJobTemplate: specExecutionRequest.CronJobTemplate, 184 CronJobTemplateReference: specExecutionRequest.CronJobTemplateReference, 185 PreRunScript: specExecutionRequest.PreRunScript, 186 PostRunScript: specExecutionRequest.PostRunScript, 187 ExecutePostRunScriptBeforeScraping: specExecutionRequest.ExecutePostRunScriptBeforeScraping, 188 SourceScripts: specExecutionRequest.SourceScripts, 189 PvcTemplate: specExecutionRequest.PvcTemplate, 190 PvcTemplateReference: specExecutionRequest.PvcTemplateReference, 191 ScraperTemplate: specExecutionRequest.ScraperTemplate, 192 ScraperTemplateReference: specExecutionRequest.ScraperTemplateReference, 193 NegativeTest: specExecutionRequest.NegativeTest, 194 EnvConfigMaps: MapEnvReferences(specExecutionRequest.EnvConfigMaps), 195 EnvSecrets: MapEnvReferences(specExecutionRequest.EnvSecrets), 196 SlavePodRequest: podRequest, 197 } 198 199 // Pro edition only (tcl protected code) 200 return mappertcl.MapExecutionRequestFromSpec(specExecutionRequest, result) 201 } 202 203 // MapImagePullSecrets maps Kubernetes spec to testkube model 204 func MapImagePullSecrets(lor []v1.LocalObjectReference) []testkube.LocalObjectReference { 205 if lor == nil { 206 return nil 207 } 208 var res []testkube.LocalObjectReference 209 for _, ref := range lor { 210 res = append(res, testkube.LocalObjectReference{Name: ref.Name}) 211 } 212 213 return res 214 } 215 216 // MapStatusFromSpec maps CRD to OpenAPI spec TestStatus 217 func MapStatusFromSpec(specStatus testsv3.TestStatus) *testkube.TestStatus { 218 if specStatus.LatestExecution == nil { 219 return nil 220 } 221 222 return &testkube.TestStatus{ 223 LatestExecution: &testkube.ExecutionCore{ 224 Id: specStatus.LatestExecution.Id, 225 Number: specStatus.LatestExecution.Number, 226 Status: (*testkube.ExecutionStatus)(specStatus.LatestExecution.Status), 227 StartTime: specStatus.LatestExecution.StartTime.Time, 228 EndTime: specStatus.LatestExecution.EndTime.Time, 229 }, 230 } 231 } 232 233 // MapEnvReferences maps CRD to OpenAPI spec EnvReference 234 func MapEnvReferences(envs []testsv3.EnvReference) []testkube.EnvReference { 235 if envs == nil { 236 return nil 237 } 238 var res []testkube.EnvReference 239 for _, env := range envs { 240 res = append(res, testkube.EnvReference{ 241 Reference: &testkube.LocalObjectReference{ 242 Name: env.Name, 243 }, 244 Mount: env.Mount, 245 MountPath: env.MountPath, 246 MapToVariables: env.MapToVariables, 247 }) 248 } 249 250 return res 251 } 252 253 // MapSpecToUpdate maps Test CRD spec to TestUpdateRequest 254 func MapSpecToUpdate(test *testsv3.Test) (request testkube.TestUpdateRequest) { 255 var fields = []struct { 256 source *string 257 destination **string 258 }{ 259 { 260 &test.Name, 261 &request.Name, 262 }, 263 { 264 &test.Namespace, 265 &request.Namespace, 266 }, 267 { 268 &test.Spec.Description, 269 &request.Description, 270 }, 271 { 272 &test.Spec.Type_, 273 &request.Type_, 274 }, 275 { 276 &test.Spec.Source, 277 &request.Source, 278 }, 279 { 280 &test.Spec.Schedule, 281 &request.Schedule, 282 }, 283 } 284 285 for _, field := range fields { 286 *field.destination = field.source 287 } 288 289 if test.Spec.Content != nil { 290 content := MapSpecContentToUpdateContent(test.Spec.Content) 291 request.Content = &content 292 } 293 294 if test.Spec.ExecutionRequest != nil { 295 executionRequest := MapSpecExecutionRequestToExecutionUpdateRequest(test.Spec.ExecutionRequest) 296 request.ExecutionRequest = &executionRequest 297 } 298 299 request.Labels = &test.Labels 300 301 request.Uploads = &test.Spec.Uploads 302 303 return request 304 } 305 306 // MapSpecContentToUpdateContent maps TestContent CRD spec to TestUpdateContent OpenAPI spec 307 func MapSpecContentToUpdateContent(testContent *testsv3.TestContent) (content *testkube.TestContentUpdate) { 308 content = &testkube.TestContentUpdate{} 309 310 var fields = []struct { 311 source *string 312 destination **string 313 }{ 314 { 315 &testContent.Data, 316 &content.Data, 317 }, 318 { 319 &testContent.Uri, 320 &content.Uri, 321 }, 322 } 323 324 for _, field := range fields { 325 *field.destination = field.source 326 } 327 328 content.Type_ = (*string)(&testContent.Type_) 329 330 if testContent.Repository != nil { 331 repository := &testkube.RepositoryUpdate{} 332 content.Repository = &repository 333 334 var fields = []struct { 335 source *string 336 destination **string 337 }{ 338 { 339 &testContent.Repository.Type_, 340 &(*content.Repository).Type_, 341 }, 342 { 343 &testContent.Repository.Uri, 344 &(*content.Repository).Uri, 345 }, 346 { 347 &testContent.Repository.Branch, 348 &(*content.Repository).Branch, 349 }, 350 { 351 &testContent.Repository.Commit, 352 &(*content.Repository).Commit, 353 }, 354 { 355 &testContent.Repository.Path, 356 &(*content.Repository).Path, 357 }, 358 { 359 &testContent.Repository.WorkingDir, 360 &(*content.Repository).WorkingDir, 361 }, 362 { 363 &testContent.Repository.CertificateSecret, 364 &(*content.Repository).CertificateSecret, 365 }, 366 } 367 368 for _, field := range fields { 369 *field.destination = field.source 370 } 371 372 (*content.Repository).AuthType = (*string)(&testContent.Repository.AuthType) 373 374 if testContent.Repository.UsernameSecret != nil { 375 secetRef := &testkube.SecretRef{ 376 Name: testContent.Repository.UsernameSecret.Name, 377 Key: testContent.Repository.UsernameSecret.Key, 378 } 379 380 (*content.Repository).TokenSecret = &secetRef 381 } 382 383 if testContent.Repository.TokenSecret != nil { 384 secretRef := &testkube.SecretRef{ 385 Name: testContent.Repository.TokenSecret.Name, 386 Key: testContent.Repository.TokenSecret.Key, 387 } 388 389 (*content.Repository).TokenSecret = &secretRef 390 } 391 } 392 393 return content 394 } 395 396 // MapSpecExecutionRequestToExecutionUpdateRequest maps ExecutionRequest CRD spec to ExecutionUpdateRequest OpenAPI spec to 397 func MapSpecExecutionRequestToExecutionUpdateRequest( 398 request *testsv3.ExecutionRequest) (executionRequest *testkube.ExecutionUpdateRequest) { 399 executionRequest = &testkube.ExecutionUpdateRequest{} 400 401 var fields = []struct { 402 source *string 403 destination **string 404 }{ 405 { 406 &request.Name, 407 &executionRequest.Name, 408 }, 409 { 410 &request.TestSuiteName, 411 &executionRequest.TestSuiteName, 412 }, 413 { 414 &request.Namespace, 415 &executionRequest.Namespace, 416 }, 417 { 418 &request.VariablesFile, 419 &executionRequest.VariablesFile, 420 }, 421 { 422 &request.TestSecretUUID, 423 &executionRequest.TestSecretUUID, 424 }, 425 { 426 &request.TestSuiteSecretUUID, 427 &executionRequest.TestSuiteSecretUUID, 428 }, 429 { 430 &request.HttpProxy, 431 &executionRequest.HttpProxy, 432 }, 433 { 434 &request.HttpsProxy, 435 &executionRequest.HttpsProxy, 436 }, 437 { 438 &request.Image, 439 &executionRequest.Image, 440 }, 441 { 442 &request.JobTemplate, 443 &executionRequest.JobTemplate, 444 }, 445 { 446 &request.JobTemplateReference, 447 &executionRequest.JobTemplateReference, 448 }, 449 { 450 &request.PreRunScript, 451 &executionRequest.PreRunScript, 452 }, 453 { 454 &request.PostRunScript, 455 &executionRequest.PostRunScript, 456 }, 457 { 458 &request.CronJobTemplate, 459 &executionRequest.CronJobTemplate, 460 }, 461 { 462 &request.CronJobTemplateReference, 463 &executionRequest.CronJobTemplateReference, 464 }, 465 { 466 &request.PvcTemplate, 467 &executionRequest.PvcTemplate, 468 }, 469 { 470 &request.PvcTemplateReference, 471 &executionRequest.PvcTemplateReference, 472 }, 473 { 474 &request.ScraperTemplate, 475 &executionRequest.ScraperTemplate, 476 }, 477 { 478 &request.ScraperTemplateReference, 479 &executionRequest.ScraperTemplateReference, 480 }, 481 } 482 483 for _, field := range fields { 484 *field.destination = field.source 485 } 486 487 executionRequest.ArgsMode = (*string)(&request.ArgsMode) 488 489 var slices = []struct { 490 source *map[string]string 491 destination **map[string]string 492 }{ 493 { 494 &request.ExecutionLabels, 495 &executionRequest.ExecutionLabels, 496 }, 497 { 498 &request.Envs, 499 &executionRequest.Envs, 500 }, 501 { 502 &request.SecretEnvs, 503 &executionRequest.SecretEnvs, 504 }, 505 } 506 507 for _, slice := range slices { 508 *slice.destination = slice.source 509 } 510 511 executionRequest.Number = &request.Number 512 executionRequest.Sync = &request.Sync 513 executionRequest.NegativeTest = &request.NegativeTest 514 executionRequest.ActiveDeadlineSeconds = &request.ActiveDeadlineSeconds 515 executionRequest.Args = &request.Args 516 executionRequest.Command = &request.Command 517 518 vars := MergeVariablesAndParams(request.Variables, nil) 519 executionRequest.Variables = &vars 520 imagePullSecrets := MapImagePullSecrets(request.ImagePullSecrets) 521 executionRequest.ImagePullSecrets = &imagePullSecrets 522 envConfigMaps := MapEnvReferences(request.EnvConfigMaps) 523 executionRequest.EnvConfigMaps = &envConfigMaps 524 envSecrets := MapEnvReferences(request.EnvSecrets) 525 executionRequest.EnvSecrets = &envSecrets 526 executionRequest.ExecutePostRunScriptBeforeScraping = &request.ExecutePostRunScriptBeforeScraping 527 executionRequest.SourceScripts = &request.SourceScripts 528 529 // Pro edition only (tcl protected code) 530 mappertcl.MapSpecExecutionRequestToExecutionUpdateRequest(request, executionRequest) 531 532 if request.ArtifactRequest != nil { 533 artifactRequest := &testkube.ArtifactUpdateRequest{ 534 StorageClassName: &request.ArtifactRequest.StorageClassName, 535 VolumeMountPath: &request.ArtifactRequest.VolumeMountPath, 536 Dirs: &request.ArtifactRequest.Dirs, 537 Masks: &request.ArtifactRequest.Masks, 538 StorageBucket: &request.ArtifactRequest.StorageBucket, 539 OmitFolderPerExecution: &request.ArtifactRequest.OmitFolderPerExecution, 540 SharedBetweenPods: &request.ArtifactRequest.SharedBetweenPods, 541 UseDefaultStorageClassName: &request.ArtifactRequest.UseDefaultStorageClassName, 542 } 543 544 executionRequest.ArtifactRequest = &artifactRequest 545 } 546 547 if request.SlavePodRequest != nil { 548 podRequest := &testkube.PodUpdateRequest{ 549 PodTemplate: &request.SlavePodRequest.PodTemplate, 550 PodTemplateReference: &request.SlavePodRequest.PodTemplateReference, 551 } 552 553 if request.SlavePodRequest.Resources != nil { 554 resources := &testkube.PodResourcesUpdateRequest{} 555 if request.SlavePodRequest.Resources.Requests != nil { 556 requests := testkube.ResourceUpdateRequest{ 557 Cpu: &request.SlavePodRequest.Resources.Requests.Cpu, 558 Memory: &request.SlavePodRequest.Resources.Requests.Memory, 559 } 560 561 resources.Requests = &requests 562 } 563 564 if request.SlavePodRequest.Resources.Limits != nil { 565 limits := testkube.ResourceUpdateRequest{ 566 Cpu: &request.SlavePodRequest.Resources.Limits.Cpu, 567 Memory: &request.SlavePodRequest.Resources.Limits.Memory, 568 } 569 570 resources.Limits = &limits 571 } 572 573 podRequest.Resources = &resources 574 } 575 576 executionRequest.SlavePodRequest = &podRequest 577 } 578 579 return executionRequest 580 }