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  }