github.com/kubeshop/testkube@v1.17.23/pkg/tcl/mapperstcl/testworkflows/openapi_kube.go (about)

     1  // Copyright 2024 Testkube.
     2  //
     3  // Licensed as a Testkube Pro file under the Testkube Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //	https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt
     8  
     9  package testworkflows
    10  
    11  import (
    12  	"encoding/json"
    13  	"strconv"
    14  
    15  	corev1 "k8s.io/api/core/v1"
    16  	"k8s.io/apimachinery/pkg/api/resource"
    17  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    18  	"k8s.io/apimachinery/pkg/util/intstr"
    19  
    20  	testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3"
    21  	testworkflowsv1 "github.com/kubeshop/testkube-operator/api/testworkflows/v1"
    22  	"github.com/kubeshop/testkube/internal/common"
    23  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    24  )
    25  
    26  func MapStringToIntOrString(i string) intstr.IntOrString {
    27  	if v, err := strconv.ParseInt(i, 10, 32); err == nil {
    28  		return intstr.IntOrString{Type: intstr.Int, IntVal: int32(v)}
    29  	}
    30  	return intstr.IntOrString{Type: intstr.String, StrVal: i}
    31  }
    32  
    33  func MapBoxedStringToIntOrString(v *testkube.BoxedString) *intstr.IntOrString {
    34  	if v == nil {
    35  		return nil
    36  	}
    37  	if vv, err := strconv.ParseInt(v.Value, 10, 32); err == nil {
    38  		return &intstr.IntOrString{Type: intstr.Int, IntVal: int32(vv)}
    39  	}
    40  	return &intstr.IntOrString{Type: intstr.String, StrVal: v.Value}
    41  }
    42  
    43  func MapStringPtrToIntOrStringPtr(i *string) *intstr.IntOrString {
    44  	if i == nil {
    45  		return nil
    46  	}
    47  	return common.Ptr(MapStringToIntOrString(*i))
    48  }
    49  
    50  func MapBoxedStringToString(v *testkube.BoxedString) *string {
    51  	if v == nil {
    52  		return nil
    53  	}
    54  	return &v.Value
    55  }
    56  
    57  func MapBoxedStringToType[T ~string](v *testkube.BoxedString) *T {
    58  	if v == nil {
    59  		return nil
    60  	}
    61  	return common.Ptr(T(v.Value))
    62  }
    63  
    64  func MapBoxedStringToQuantity(v testkube.BoxedString) resource.Quantity {
    65  	q, _ := resource.ParseQuantity(v.Value)
    66  	return q
    67  }
    68  
    69  func MapBoxedBooleanToBool(v *testkube.BoxedBoolean) *bool {
    70  	if v == nil {
    71  		return nil
    72  	}
    73  	return &v.Value
    74  }
    75  
    76  func MapBoxedStringListToStringSlice(v *testkube.BoxedStringList) *[]string {
    77  	if v == nil {
    78  		return nil
    79  	}
    80  	return &v.Value
    81  }
    82  
    83  func MapBoxedIntegerToInt64(v *testkube.BoxedInteger) *int64 {
    84  	if v == nil {
    85  		return nil
    86  	}
    87  	return common.Ptr(int64(v.Value))
    88  }
    89  
    90  func MapBoxedIntegerToInt32(v *testkube.BoxedInteger) *int32 {
    91  	if v == nil {
    92  		return nil
    93  	}
    94  	return &v.Value
    95  }
    96  
    97  func MapDynamicListMapAPIToKube(v map[string]interface{}) map[string]testworkflowsv1.DynamicList {
    98  	if len(v) == 0 {
    99  		return nil
   100  	}
   101  	result := make(map[string]testworkflowsv1.DynamicList, len(v))
   102  	for k := range v {
   103  		var item testworkflowsv1.DynamicList
   104  		b, err := json.Marshal(v[k])
   105  		if err == nil {
   106  			err = json.Unmarshal(b, &item)
   107  			if err == nil {
   108  				result[k] = item
   109  			}
   110  		}
   111  	}
   112  	return result
   113  }
   114  
   115  func MapEnvVarAPIToKube(v testkube.EnvVar) corev1.EnvVar {
   116  	return corev1.EnvVar{
   117  		Name:      v.Name,
   118  		Value:     v.Value,
   119  		ValueFrom: common.MapPtr(v.ValueFrom, MapEnvVarSourceAPIToKube),
   120  	}
   121  }
   122  
   123  func MapConfigMapKeyRefAPIToKube(v *testkube.EnvVarSourceConfigMapKeyRef) *corev1.ConfigMapKeySelector {
   124  	if v == nil {
   125  		return nil
   126  	}
   127  	return &corev1.ConfigMapKeySelector{
   128  		Key:                  v.Key,
   129  		LocalObjectReference: corev1.LocalObjectReference{Name: v.Name},
   130  		Optional:             common.PtrOrNil(v.Optional),
   131  	}
   132  }
   133  
   134  func MapFieldRefAPIToKube(v *testkube.EnvVarSourceFieldRef) *corev1.ObjectFieldSelector {
   135  	if v == nil {
   136  		return nil
   137  	}
   138  	return &corev1.ObjectFieldSelector{
   139  		APIVersion: v.ApiVersion,
   140  		FieldPath:  v.FieldPath,
   141  	}
   142  }
   143  
   144  func MapResourceFieldRefAPIToKube(v *testkube.EnvVarSourceResourceFieldRef) *corev1.ResourceFieldSelector {
   145  	if v == nil {
   146  		return nil
   147  	}
   148  	divisor, _ := resource.ParseQuantity(v.Divisor)
   149  	return &corev1.ResourceFieldSelector{
   150  		ContainerName: v.ContainerName,
   151  		Divisor:       divisor,
   152  		Resource:      v.Resource,
   153  	}
   154  }
   155  
   156  func MapSecretKeyRefAPIToKube(v *testkube.EnvVarSourceSecretKeyRef) *corev1.SecretKeySelector {
   157  	if v == nil {
   158  		return nil
   159  	}
   160  	return &corev1.SecretKeySelector{
   161  		Key:                  v.Key,
   162  		LocalObjectReference: corev1.LocalObjectReference{Name: v.Name},
   163  		Optional:             common.PtrOrNil(v.Optional),
   164  	}
   165  }
   166  
   167  func MapEnvVarSourceAPIToKube(v testkube.EnvVarSource) corev1.EnvVarSource {
   168  	return corev1.EnvVarSource{
   169  		ConfigMapKeyRef:  MapConfigMapKeyRefAPIToKube(v.ConfigMapKeyRef),
   170  		FieldRef:         MapFieldRefAPIToKube(v.FieldRef),
   171  		ResourceFieldRef: MapResourceFieldRefAPIToKube(v.ResourceFieldRef),
   172  		SecretKeyRef:     MapSecretKeyRefAPIToKube(v.SecretKeyRef),
   173  	}
   174  }
   175  
   176  func MapConfigMapEnvSourceAPIToKube(v *testkube.ConfigMapEnvSource) *corev1.ConfigMapEnvSource {
   177  	if v == nil {
   178  		return nil
   179  	}
   180  	return &corev1.ConfigMapEnvSource{
   181  		LocalObjectReference: corev1.LocalObjectReference{Name: v.Name},
   182  		Optional:             common.PtrOrNil(v.Optional),
   183  	}
   184  }
   185  
   186  func MapSecretEnvSourceAPIToKube(v *testkube.SecretEnvSource) *corev1.SecretEnvSource {
   187  	if v == nil {
   188  		return nil
   189  	}
   190  	return &corev1.SecretEnvSource{
   191  		LocalObjectReference: corev1.LocalObjectReference{Name: v.Name},
   192  		Optional:             common.PtrOrNil(v.Optional),
   193  	}
   194  }
   195  
   196  func MapEnvFromSourceAPIToKube(v testkube.EnvFromSource) corev1.EnvFromSource {
   197  	return corev1.EnvFromSource{
   198  		Prefix:       v.Prefix,
   199  		ConfigMapRef: MapConfigMapEnvSourceAPIToKube(v.ConfigMapRef),
   200  		SecretRef:    MapSecretEnvSourceAPIToKube(v.SecretRef),
   201  	}
   202  }
   203  
   204  func MapSecurityContextAPIToKube(v *testkube.SecurityContext) *corev1.SecurityContext {
   205  	if v == nil {
   206  		return nil
   207  	}
   208  	return &corev1.SecurityContext{
   209  		Privileged:               MapBoxedBooleanToBool(v.Privileged),
   210  		RunAsUser:                MapBoxedIntegerToInt64(v.RunAsUser),
   211  		RunAsGroup:               MapBoxedIntegerToInt64(v.RunAsGroup),
   212  		RunAsNonRoot:             MapBoxedBooleanToBool(v.RunAsNonRoot),
   213  		ReadOnlyRootFilesystem:   MapBoxedBooleanToBool(v.ReadOnlyRootFilesystem),
   214  		AllowPrivilegeEscalation: MapBoxedBooleanToBool(v.AllowPrivilegeEscalation),
   215  	}
   216  }
   217  
   218  func MapLocalObjectReferenceAPIToKube(v testkube.LocalObjectReference) corev1.LocalObjectReference {
   219  	return corev1.LocalObjectReference{Name: v.Name}
   220  }
   221  
   222  func MapConfigValueAPIToKube(v map[string]string) map[string]intstr.IntOrString {
   223  	return common.MapMap(v, MapStringToIntOrString)
   224  }
   225  
   226  func MapParameterTypeAPIToKube(v *testkube.TestWorkflowParameterType) testworkflowsv1.ParameterType {
   227  	if v == nil {
   228  		return ""
   229  	}
   230  	return testworkflowsv1.ParameterType(*v)
   231  }
   232  
   233  func MapGitAuthTypeAPIToKube(v *testkube.ContentGitAuthType) testsv3.GitAuthType {
   234  	if v == nil {
   235  		return ""
   236  	}
   237  	return testsv3.GitAuthType(*v)
   238  }
   239  
   240  func MapImagePullPolicyAPIToKube(v *testkube.ImagePullPolicy) corev1.PullPolicy {
   241  	if v == nil {
   242  		return ""
   243  	}
   244  	return corev1.PullPolicy(*v)
   245  }
   246  
   247  func MapParameterSchemaAPIToKube(v testkube.TestWorkflowParameterSchema) testworkflowsv1.ParameterSchema {
   248  	var example *intstr.IntOrString
   249  	if v.Example != "" {
   250  		example = common.Ptr(MapStringToIntOrString(v.Example))
   251  	}
   252  	return testworkflowsv1.ParameterSchema{
   253  		Description: v.Description,
   254  		Type:        MapParameterTypeAPIToKube(v.Type_),
   255  		Enum:        v.Enum,
   256  		Example:     example,
   257  		Default:     MapStringPtrToIntOrStringPtr(MapBoxedStringToString(v.Default_)),
   258  		ParameterStringSchema: testworkflowsv1.ParameterStringSchema{
   259  			Format:    v.Format,
   260  			Pattern:   v.Pattern,
   261  			MinLength: MapBoxedIntegerToInt64(v.MinLength),
   262  			MaxLength: MapBoxedIntegerToInt64(v.MaxLength),
   263  		},
   264  		ParameterNumberSchema: testworkflowsv1.ParameterNumberSchema{
   265  			Minimum:          MapBoxedIntegerToInt64(v.Minimum),
   266  			Maximum:          MapBoxedIntegerToInt64(v.Maximum),
   267  			ExclusiveMinimum: MapBoxedIntegerToInt64(v.ExclusiveMinimum),
   268  			ExclusiveMaximum: MapBoxedIntegerToInt64(v.ExclusiveMaximum),
   269  			MultipleOf:       MapBoxedIntegerToInt64(v.MultipleOf),
   270  		},
   271  	}
   272  }
   273  
   274  func MapTemplateRefAPIToKube(v testkube.TestWorkflowTemplateRef) testworkflowsv1.TemplateRef {
   275  	return testworkflowsv1.TemplateRef{
   276  		Name:   v.Name,
   277  		Config: MapConfigValueAPIToKube(v.Config),
   278  	}
   279  }
   280  
   281  func MapContentGitAPIToKube(v testkube.TestWorkflowContentGit) testworkflowsv1.ContentGit {
   282  	return testworkflowsv1.ContentGit{
   283  		Uri:          v.Uri,
   284  		Revision:     v.Revision,
   285  		Username:     v.Username,
   286  		UsernameFrom: common.MapPtr(v.UsernameFrom, MapEnvVarSourceAPIToKube),
   287  		Token:        v.Token,
   288  		TokenFrom:    common.MapPtr(v.TokenFrom, MapEnvVarSourceAPIToKube),
   289  		AuthType:     MapGitAuthTypeAPIToKube(v.AuthType),
   290  		MountPath:    v.MountPath,
   291  		Paths:        v.Paths,
   292  	}
   293  }
   294  
   295  func MapContentAPIToKube(v testkube.TestWorkflowContent) testworkflowsv1.Content {
   296  	return testworkflowsv1.Content{
   297  		Git:   common.MapPtr(v.Git, MapContentGitAPIToKube),
   298  		Files: common.MapSlice(v.Files, MapContentFileAPIToKube),
   299  	}
   300  }
   301  
   302  func MapContentFileAPIToKube(v testkube.TestWorkflowContentFile) testworkflowsv1.ContentFile {
   303  	return testworkflowsv1.ContentFile{
   304  		Path:        v.Path,
   305  		Content:     v.Content,
   306  		ContentFrom: common.MapPtr(v.ContentFrom, MapEnvVarSourceAPIToKube),
   307  		Mode:        MapBoxedIntegerToInt32(v.Mode),
   308  	}
   309  }
   310  
   311  func MapResourcesListAPIToKube(v *testkube.TestWorkflowResourcesList) map[corev1.ResourceName]intstr.IntOrString {
   312  	if v == nil {
   313  		return nil
   314  	}
   315  	res := make(map[corev1.ResourceName]intstr.IntOrString)
   316  	if v.Cpu != "" {
   317  		res[corev1.ResourceCPU] = MapStringToIntOrString(v.Cpu)
   318  	}
   319  	if v.Memory != "" {
   320  		res[corev1.ResourceMemory] = MapStringToIntOrString(v.Memory)
   321  	}
   322  	if v.Storage != "" {
   323  		res[corev1.ResourceStorage] = MapStringToIntOrString(v.Storage)
   324  	}
   325  	if v.EphemeralStorage != "" {
   326  		res[corev1.ResourceEphemeralStorage] = MapStringToIntOrString(v.EphemeralStorage)
   327  	}
   328  	return res
   329  }
   330  
   331  func MapResourcesAPIToKube(v testkube.TestWorkflowResources) testworkflowsv1.Resources {
   332  	return testworkflowsv1.Resources{
   333  		Limits:   MapResourcesListAPIToKube(v.Limits),
   334  		Requests: MapResourcesListAPIToKube(v.Requests),
   335  	}
   336  }
   337  
   338  func MapJobConfigAPIToKube(v testkube.TestWorkflowJobConfig) testworkflowsv1.JobConfig {
   339  	return testworkflowsv1.JobConfig{
   340  		Labels:      v.Labels,
   341  		Annotations: v.Annotations,
   342  	}
   343  }
   344  
   345  func MapEventAPIToKube(v testkube.TestWorkflowEvent) testworkflowsv1.Event {
   346  	return testworkflowsv1.Event{
   347  		Cronjob: common.MapPtr(v.Cronjob, MapCronJobConfigAPIToKube),
   348  	}
   349  }
   350  
   351  func MapCronJobConfigAPIToKube(v testkube.TestWorkflowCronJobConfig) testworkflowsv1.CronJobConfig {
   352  	return testworkflowsv1.CronJobConfig{
   353  		Cron:        v.Cron,
   354  		Labels:      v.Labels,
   355  		Annotations: v.Annotations,
   356  	}
   357  }
   358  func MapHostPathVolumeSourceAPIToKube(v testkube.HostPathVolumeSource) corev1.HostPathVolumeSource {
   359  	return corev1.HostPathVolumeSource{
   360  		Path: v.Path,
   361  		Type: MapBoxedStringToType[corev1.HostPathType](v.Type_),
   362  	}
   363  }
   364  
   365  func MapEmptyDirVolumeSourceAPIToKube(v testkube.EmptyDirVolumeSource) corev1.EmptyDirVolumeSource {
   366  	return corev1.EmptyDirVolumeSource{
   367  		Medium:    corev1.StorageMedium(v.Medium),
   368  		SizeLimit: common.MapPtr(v.SizeLimit, MapBoxedStringToQuantity),
   369  	}
   370  }
   371  
   372  func MapGCEPersistentDiskVolumeSourceAPIToKube(v testkube.GcePersistentDiskVolumeSource) corev1.GCEPersistentDiskVolumeSource {
   373  	return corev1.GCEPersistentDiskVolumeSource{
   374  		PDName:    v.PdName,
   375  		FSType:    v.FsType,
   376  		Partition: v.Partition,
   377  		ReadOnly:  v.ReadOnly,
   378  	}
   379  }
   380  
   381  func MapAWSElasticBlockStoreVolumeSourceAPIToKube(v testkube.AwsElasticBlockStoreVolumeSource) corev1.AWSElasticBlockStoreVolumeSource {
   382  	return corev1.AWSElasticBlockStoreVolumeSource{
   383  		VolumeID:  v.VolumeID,
   384  		FSType:    v.FsType,
   385  		Partition: v.Partition,
   386  		ReadOnly:  v.ReadOnly,
   387  	}
   388  }
   389  
   390  func MapKeyToPathAPIToKube(v testkube.SecretVolumeSourceItems) corev1.KeyToPath {
   391  	return corev1.KeyToPath{
   392  		Key:  v.Key,
   393  		Path: v.Path,
   394  		Mode: MapBoxedIntegerToInt32(v.Mode),
   395  	}
   396  }
   397  
   398  func MapSecretVolumeSourceAPIToKube(v testkube.SecretVolumeSource) corev1.SecretVolumeSource {
   399  	return corev1.SecretVolumeSource{
   400  		SecretName:  v.SecretName,
   401  		Items:       common.MapSlice(v.Items, MapKeyToPathAPIToKube),
   402  		DefaultMode: MapBoxedIntegerToInt32(v.DefaultMode),
   403  		Optional:    common.PtrOrNil(v.Optional),
   404  	}
   405  }
   406  
   407  func MapNFSVolumeSourceAPIToKube(v testkube.NfsVolumeSource) corev1.NFSVolumeSource {
   408  	return corev1.NFSVolumeSource{
   409  		Server:   v.Server,
   410  		Path:     v.Path,
   411  		ReadOnly: v.ReadOnly,
   412  	}
   413  }
   414  
   415  func MapPersistentVolumeClaimVolumeSourceAPIToKube(v testkube.PersistentVolumeClaimVolumeSource) corev1.PersistentVolumeClaimVolumeSource {
   416  	return corev1.PersistentVolumeClaimVolumeSource{
   417  		ClaimName: v.ClaimName,
   418  		ReadOnly:  v.ReadOnly,
   419  	}
   420  }
   421  
   422  func MapCephFSVolumeSourceAPIToKube(v testkube.CephFsVolumeSource) corev1.CephFSVolumeSource {
   423  	return corev1.CephFSVolumeSource{
   424  		Monitors:   v.Monitors,
   425  		Path:       v.Path,
   426  		User:       v.User,
   427  		SecretFile: v.SecretFile,
   428  		SecretRef:  common.MapPtr(v.SecretRef, MapLocalObjectReferenceAPIToKube),
   429  		ReadOnly:   v.ReadOnly,
   430  	}
   431  }
   432  
   433  func MapAzureFileVolumeSourceAPIToKube(v testkube.AzureFileVolumeSource) corev1.AzureFileVolumeSource {
   434  	return corev1.AzureFileVolumeSource{
   435  		SecretName: v.SecretName,
   436  		ShareName:  v.ShareName,
   437  		ReadOnly:   v.ReadOnly,
   438  	}
   439  }
   440  
   441  func MapConfigMapVolumeSourceAPIToKube(v testkube.ConfigMapVolumeSource) corev1.ConfigMapVolumeSource {
   442  	return corev1.ConfigMapVolumeSource{
   443  		LocalObjectReference: corev1.LocalObjectReference{Name: v.Name},
   444  		Items:                common.MapSlice(v.Items, MapKeyToPathAPIToKube),
   445  		DefaultMode:          MapBoxedIntegerToInt32(v.DefaultMode),
   446  		Optional:             common.PtrOrNil(v.Optional),
   447  	}
   448  }
   449  
   450  func MapAzureDiskVolumeSourceAPIToKube(v testkube.AzureDiskVolumeSource) corev1.AzureDiskVolumeSource {
   451  	return corev1.AzureDiskVolumeSource{
   452  		DiskName:    v.DiskName,
   453  		DataDiskURI: v.DiskURI,
   454  		CachingMode: MapBoxedStringToType[corev1.AzureDataDiskCachingMode](v.CachingMode),
   455  		FSType:      MapBoxedStringToString(v.FsType),
   456  		ReadOnly:    common.PtrOrNil(v.ReadOnly),
   457  		Kind:        MapBoxedStringToType[corev1.AzureDataDiskKind](v.Kind),
   458  	}
   459  }
   460  
   461  func MapVolumeAPIToKube(v testkube.Volume) corev1.Volume {
   462  	// TODO: Add rest of VolumeSource types in future,
   463  	//       so they will be recognized by JSON API and persisted with Execution.
   464  	return corev1.Volume{
   465  		Name: v.Name,
   466  		VolumeSource: corev1.VolumeSource{
   467  			HostPath:              common.MapPtr(v.HostPath, MapHostPathVolumeSourceAPIToKube),
   468  			EmptyDir:              common.MapPtr(v.EmptyDir, MapEmptyDirVolumeSourceAPIToKube),
   469  			GCEPersistentDisk:     common.MapPtr(v.GcePersistentDisk, MapGCEPersistentDiskVolumeSourceAPIToKube),
   470  			AWSElasticBlockStore:  common.MapPtr(v.AwsElasticBlockStore, MapAWSElasticBlockStoreVolumeSourceAPIToKube),
   471  			Secret:                common.MapPtr(v.Secret, MapSecretVolumeSourceAPIToKube),
   472  			NFS:                   common.MapPtr(v.Nfs, MapNFSVolumeSourceAPIToKube),
   473  			PersistentVolumeClaim: common.MapPtr(v.PersistentVolumeClaim, MapPersistentVolumeClaimVolumeSourceAPIToKube),
   474  			CephFS:                common.MapPtr(v.Cephfs, MapCephFSVolumeSourceAPIToKube),
   475  			AzureFile:             common.MapPtr(v.AzureFile, MapAzureFileVolumeSourceAPIToKube),
   476  			ConfigMap:             common.MapPtr(v.ConfigMap, MapConfigMapVolumeSourceAPIToKube),
   477  			AzureDisk:             common.MapPtr(v.AzureDisk, MapAzureDiskVolumeSourceAPIToKube),
   478  		},
   479  	}
   480  }
   481  
   482  func MapPodConfigAPIToKube(v testkube.TestWorkflowPodConfig) testworkflowsv1.PodConfig {
   483  	return testworkflowsv1.PodConfig{
   484  		ServiceAccountName: v.ServiceAccountName,
   485  		ImagePullSecrets:   common.MapSlice(v.ImagePullSecrets, MapLocalObjectReferenceAPIToKube),
   486  		NodeSelector:       v.NodeSelector,
   487  		Labels:             v.Labels,
   488  		Annotations:        v.Annotations,
   489  		Volumes:            common.MapSlice(v.Volumes, MapVolumeAPIToKube),
   490  	}
   491  }
   492  
   493  func MapVolumeMountAPIToKube(v testkube.VolumeMount) corev1.VolumeMount {
   494  	return corev1.VolumeMount{
   495  		Name:             v.Name,
   496  		ReadOnly:         v.ReadOnly,
   497  		MountPath:        v.MountPath,
   498  		SubPath:          v.SubPath,
   499  		MountPropagation: MapBoxedStringToType[corev1.MountPropagationMode](v.MountPropagation),
   500  		SubPathExpr:      v.SubPathExpr,
   501  	}
   502  }
   503  
   504  func MapContainerConfigAPIToKube(v testkube.TestWorkflowContainerConfig) testworkflowsv1.ContainerConfig {
   505  	return testworkflowsv1.ContainerConfig{
   506  		WorkingDir:      MapBoxedStringToString(v.WorkingDir),
   507  		Image:           v.Image,
   508  		ImagePullPolicy: MapImagePullPolicyAPIToKube(v.ImagePullPolicy),
   509  		Env:             common.MapSlice(v.Env, MapEnvVarAPIToKube),
   510  		EnvFrom:         common.MapSlice(v.EnvFrom, MapEnvFromSourceAPIToKube),
   511  		Command:         MapBoxedStringListToStringSlice(v.Command),
   512  		Args:            MapBoxedStringListToStringSlice(v.Args),
   513  		Resources:       common.MapPtr(v.Resources, MapResourcesAPIToKube),
   514  		SecurityContext: MapSecurityContextAPIToKube(v.SecurityContext),
   515  		VolumeMounts:    common.MapSlice(v.VolumeMounts, MapVolumeMountAPIToKube),
   516  	}
   517  }
   518  
   519  func MapStepRunAPIToKube(v testkube.TestWorkflowStepRun) testworkflowsv1.StepRun {
   520  	return testworkflowsv1.StepRun{
   521  		ContainerConfig: testworkflowsv1.ContainerConfig{
   522  			WorkingDir:      MapBoxedStringToString(v.WorkingDir),
   523  			Image:           v.Image,
   524  			ImagePullPolicy: MapImagePullPolicyAPIToKube(v.ImagePullPolicy),
   525  			Env:             common.MapSlice(v.Env, MapEnvVarAPIToKube),
   526  			EnvFrom:         common.MapSlice(v.EnvFrom, MapEnvFromSourceAPIToKube),
   527  			Command:         MapBoxedStringListToStringSlice(v.Command),
   528  			Args:            MapBoxedStringListToStringSlice(v.Args),
   529  			Resources:       common.MapPtr(v.Resources, MapResourcesAPIToKube),
   530  			SecurityContext: MapSecurityContextAPIToKube(v.SecurityContext),
   531  			VolumeMounts:    common.MapSlice(v.VolumeMounts, MapVolumeMountAPIToKube),
   532  		},
   533  		Shell: MapBoxedStringToString(v.Shell),
   534  	}
   535  }
   536  
   537  func MapTestVariableAPIToKube(v testkube.Variable) testsv3.Variable {
   538  	var valueFrom corev1.EnvVarSource
   539  	if v.ConfigMapRef != nil {
   540  		valueFrom.ConfigMapKeyRef = &corev1.ConfigMapKeySelector{
   541  			LocalObjectReference: corev1.LocalObjectReference{Name: v.ConfigMapRef.Name},
   542  			Key:                  v.ConfigMapRef.Key,
   543  		}
   544  	}
   545  	if v.SecretRef != nil {
   546  		valueFrom.SecretKeyRef = &corev1.SecretKeySelector{
   547  			LocalObjectReference: corev1.LocalObjectReference{Name: v.SecretRef.Name},
   548  			Key:                  v.SecretRef.Key,
   549  		}
   550  	}
   551  	return testsv3.Variable{
   552  		Type_:     string(common.ResolvePtr[testkube.VariableType](v.Type_, "")),
   553  		Name:      v.Name,
   554  		Value:     v.Value,
   555  		ValueFrom: valueFrom,
   556  	}
   557  }
   558  
   559  func MapTestArtifactRequestAPIToKube(v testkube.ArtifactRequest) testsv3.ArtifactRequest {
   560  	return testsv3.ArtifactRequest{
   561  		StorageClassName:           v.StorageClassName,
   562  		VolumeMountPath:            v.VolumeMountPath,
   563  		Dirs:                       v.Dirs,
   564  		Masks:                      v.Masks,
   565  		StorageBucket:              v.StorageBucket,
   566  		OmitFolderPerExecution:     v.OmitFolderPerExecution,
   567  		SharedBetweenPods:          v.SharedBetweenPods,
   568  		UseDefaultStorageClassName: v.UseDefaultStorageClassName,
   569  	}
   570  }
   571  
   572  func MapTestEnvReferenceAPIToKube(v testkube.EnvReference) testsv3.EnvReference {
   573  	return testsv3.EnvReference{
   574  		LocalObjectReference: common.ResolvePtr(common.MapPtr(v.Reference, MapLocalObjectReferenceAPIToKube), corev1.LocalObjectReference{}),
   575  		Mount:                v.Mount,
   576  		MountPath:            v.MountPath,
   577  		MapToVariables:       v.MapToVariables,
   578  	}
   579  }
   580  
   581  func MapStepExecuteTestExecutionRequestAPIToKube(v testkube.TestWorkflowStepExecuteTestExecutionRequest) testworkflowsv1.TestExecutionRequest {
   582  	return testworkflowsv1.TestExecutionRequest{
   583  		Name:                               v.Name,
   584  		ExecutionLabels:                    v.ExecutionLabels,
   585  		VariablesFile:                      v.VariablesFile,
   586  		IsVariablesFileUploaded:            v.IsVariablesFileUploaded,
   587  		Variables:                          common.MapMap(v.Variables, MapTestVariableAPIToKube),
   588  		TestSecretUUID:                     v.TestSecretUUID,
   589  		Args:                               v.Args,
   590  		ArgsMode:                           testsv3.ArgsModeType(v.ArgsMode),
   591  		Command:                            v.Command,
   592  		Image:                              v.Image,
   593  		ImagePullSecrets:                   common.MapSlice(v.ImagePullSecrets, MapLocalObjectReferenceAPIToKube),
   594  		Sync:                               v.Sync,
   595  		HttpProxy:                          v.HttpProxy,
   596  		HttpsProxy:                         v.HttpsProxy,
   597  		NegativeTest:                       v.NegativeTest,
   598  		ActiveDeadlineSeconds:              v.ActiveDeadlineSeconds,
   599  		ArtifactRequest:                    common.MapPtr(v.ArtifactRequest, MapTestArtifactRequestAPIToKube),
   600  		JobTemplate:                        v.JobTemplate,
   601  		CronJobTemplate:                    v.CronJobTemplate,
   602  		PreRunScript:                       v.PreRunScript,
   603  		PostRunScript:                      v.PostRunScript,
   604  		ExecutePostRunScriptBeforeScraping: v.ExecutePostRunScriptBeforeScraping,
   605  		SourceScripts:                      v.SourceScripts,
   606  		ScraperTemplate:                    v.ScraperTemplate,
   607  		EnvConfigMaps:                      common.MapSlice(v.EnvConfigMaps, MapTestEnvReferenceAPIToKube),
   608  		EnvSecrets:                         common.MapSlice(v.EnvSecrets, MapTestEnvReferenceAPIToKube),
   609  		ExecutionNamespace:                 v.ExecutionNamespace,
   610  	}
   611  }
   612  
   613  func MapStepExecuteTestAPIToKube(v testkube.TestWorkflowStepExecuteTestRef) testworkflowsv1.StepExecuteTest {
   614  	return testworkflowsv1.StepExecuteTest{
   615  		Name:             v.Name,
   616  		Description:      v.Description,
   617  		ExecutionRequest: common.MapPtr(v.ExecutionRequest, MapStepExecuteTestExecutionRequestAPIToKube),
   618  		StepExecuteStrategy: testworkflowsv1.StepExecuteStrategy{
   619  			Count:    MapBoxedStringToIntOrString(v.Count),
   620  			MaxCount: MapBoxedStringToIntOrString(v.MaxCount),
   621  			Matrix:   MapDynamicListMapAPIToKube(v.Matrix),
   622  			Shards:   MapDynamicListMapAPIToKube(v.Shards),
   623  		},
   624  	}
   625  }
   626  
   627  func MapStepExecuteTestWorkflowAPIToKube(v testkube.TestWorkflowStepExecuteTestWorkflowRef) testworkflowsv1.StepExecuteWorkflow {
   628  	return testworkflowsv1.StepExecuteWorkflow{
   629  		Name:          v.Name,
   630  		Description:   v.Description,
   631  		ExecutionName: v.ExecutionName,
   632  		Config:        MapConfigValueAPIToKube(v.Config),
   633  		StepExecuteStrategy: testworkflowsv1.StepExecuteStrategy{
   634  			Count:    MapBoxedStringToIntOrString(v.Count),
   635  			MaxCount: MapBoxedStringToIntOrString(v.MaxCount),
   636  			Matrix:   MapDynamicListMapAPIToKube(v.Matrix),
   637  			Shards:   MapDynamicListMapAPIToKube(v.Shards),
   638  		},
   639  	}
   640  }
   641  
   642  func MapStepExecuteAPIToKube(v testkube.TestWorkflowStepExecute) testworkflowsv1.StepExecute {
   643  	return testworkflowsv1.StepExecute{
   644  		Parallelism: v.Parallelism,
   645  		Async:       v.Async,
   646  		Tests:       common.MapSlice(v.Tests, MapStepExecuteTestAPIToKube),
   647  		Workflows:   common.MapSlice(v.Workflows, MapStepExecuteTestWorkflowAPIToKube),
   648  	}
   649  }
   650  
   651  func MapStepArtifactsCompressionAPIToKube(v testkube.TestWorkflowStepArtifactsCompression) testworkflowsv1.ArtifactCompression {
   652  	return testworkflowsv1.ArtifactCompression{
   653  		Name: v.Name,
   654  	}
   655  }
   656  
   657  func MapStepArtifactsAPIToKube(v testkube.TestWorkflowStepArtifacts) testworkflowsv1.StepArtifacts {
   658  	return testworkflowsv1.StepArtifacts{
   659  		WorkingDir: MapBoxedStringToString(v.WorkingDir),
   660  		Compress:   common.MapPtr(v.Compress, MapStepArtifactsCompressionAPIToKube),
   661  		Paths:      v.Paths,
   662  	}
   663  }
   664  
   665  func MapRetryPolicyAPIToKube(v testkube.TestWorkflowRetryPolicy) testworkflowsv1.RetryPolicy {
   666  	return testworkflowsv1.RetryPolicy{
   667  		Count: v.Count,
   668  		Until: v.Until,
   669  	}
   670  }
   671  
   672  func MapStepAPIToKube(v testkube.TestWorkflowStep) testworkflowsv1.Step {
   673  	return testworkflowsv1.Step{
   674  		StepBase: testworkflowsv1.StepBase{
   675  			Name:       v.Name,
   676  			Condition:  v.Condition,
   677  			Negative:   v.Negative,
   678  			Optional:   v.Optional,
   679  			Retry:      common.MapPtr(v.Retry, MapRetryPolicyAPIToKube),
   680  			Timeout:    v.Timeout,
   681  			Delay:      v.Delay,
   682  			Content:    common.MapPtr(v.Content, MapContentAPIToKube),
   683  			Shell:      v.Shell,
   684  			Run:        common.MapPtr(v.Run, MapStepRunAPIToKube),
   685  			WorkingDir: MapBoxedStringToString(v.WorkingDir),
   686  			Container:  common.MapPtr(v.Container, MapContainerConfigAPIToKube),
   687  			Execute:    common.MapPtr(v.Execute, MapStepExecuteAPIToKube),
   688  			Artifacts:  common.MapPtr(v.Artifacts, MapStepArtifactsAPIToKube),
   689  		},
   690  		Use:      common.MapSlice(v.Use, MapTemplateRefAPIToKube),
   691  		Template: common.MapPtr(v.Template, MapTemplateRefAPIToKube),
   692  		Setup:    common.MapSlice(v.Setup, MapStepAPIToKube),
   693  		Steps:    common.MapSlice(v.Steps, MapStepAPIToKube),
   694  	}
   695  }
   696  
   697  func MapIndependentStepAPIToKube(v testkube.TestWorkflowIndependentStep) testworkflowsv1.IndependentStep {
   698  	return testworkflowsv1.IndependentStep{
   699  		StepBase: testworkflowsv1.StepBase{
   700  			Name:       v.Name,
   701  			Condition:  v.Condition,
   702  			Negative:   v.Negative,
   703  			Optional:   v.Optional,
   704  			Retry:      common.MapPtr(v.Retry, MapRetryPolicyAPIToKube),
   705  			Timeout:    v.Timeout,
   706  			Delay:      v.Delay,
   707  			Content:    common.MapPtr(v.Content, MapContentAPIToKube),
   708  			Shell:      v.Shell,
   709  			Run:        common.MapPtr(v.Run, MapStepRunAPIToKube),
   710  			WorkingDir: MapBoxedStringToString(v.WorkingDir),
   711  			Container:  common.MapPtr(v.Container, MapContainerConfigAPIToKube),
   712  			Execute:    common.MapPtr(v.Execute, MapStepExecuteAPIToKube),
   713  			Artifacts:  common.MapPtr(v.Artifacts, MapStepArtifactsAPIToKube),
   714  		},
   715  		Setup: common.MapSlice(v.Setup, MapIndependentStepAPIToKube),
   716  		Steps: common.MapSlice(v.Steps, MapIndependentStepAPIToKube),
   717  	}
   718  }
   719  
   720  func MapSpecAPIToKube(v testkube.TestWorkflowSpec) testworkflowsv1.TestWorkflowSpec {
   721  	return testworkflowsv1.TestWorkflowSpec{
   722  		TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{
   723  			Config:    common.MapMap(v.Config, MapParameterSchemaAPIToKube),
   724  			Content:   common.MapPtr(v.Content, MapContentAPIToKube),
   725  			Container: common.MapPtr(v.Container, MapContainerConfigAPIToKube),
   726  			Job:       common.MapPtr(v.Job, MapJobConfigAPIToKube),
   727  			Pod:       common.MapPtr(v.Pod, MapPodConfigAPIToKube),
   728  			Events:    common.MapSlice(v.Events, MapEventAPIToKube),
   729  		},
   730  		Use:   common.MapSlice(v.Use, MapTemplateRefAPIToKube),
   731  		Setup: common.MapSlice(v.Setup, MapStepAPIToKube),
   732  		Steps: common.MapSlice(v.Steps, MapStepAPIToKube),
   733  		After: common.MapSlice(v.After, MapStepAPIToKube),
   734  	}
   735  }
   736  
   737  func MapTemplateSpecAPIToKube(v testkube.TestWorkflowTemplateSpec) testworkflowsv1.TestWorkflowTemplateSpec {
   738  	return testworkflowsv1.TestWorkflowTemplateSpec{
   739  		TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{
   740  			Config:    common.MapMap(v.Config, MapParameterSchemaAPIToKube),
   741  			Content:   common.MapPtr(v.Content, MapContentAPIToKube),
   742  			Container: common.MapPtr(v.Container, MapContainerConfigAPIToKube),
   743  			Job:       common.MapPtr(v.Job, MapJobConfigAPIToKube),
   744  			Pod:       common.MapPtr(v.Pod, MapPodConfigAPIToKube),
   745  			Events:    common.MapSlice(v.Events, MapEventAPIToKube),
   746  		},
   747  		Setup: common.MapSlice(v.Setup, MapIndependentStepAPIToKube),
   748  		Steps: common.MapSlice(v.Steps, MapIndependentStepAPIToKube),
   749  		After: common.MapSlice(v.After, MapIndependentStepAPIToKube),
   750  	}
   751  }
   752  
   753  func MapTestWorkflowAPIToKube(w testkube.TestWorkflow) testworkflowsv1.TestWorkflow {
   754  	return testworkflowsv1.TestWorkflow{
   755  		TypeMeta: metav1.TypeMeta{
   756  			Kind:       "TestWorkflow",
   757  			APIVersion: testworkflowsv1.GroupVersion.Group + "/" + testworkflowsv1.GroupVersion.Version,
   758  		},
   759  		ObjectMeta: metav1.ObjectMeta{
   760  			Name:              w.Name,
   761  			Namespace:         w.Namespace,
   762  			Labels:            w.Labels,
   763  			Annotations:       w.Annotations,
   764  			CreationTimestamp: metav1.Time{Time: w.Created},
   765  		},
   766  		Description: w.Description,
   767  		Spec:        common.ResolvePtr(common.MapPtr(w.Spec, MapSpecAPIToKube), testworkflowsv1.TestWorkflowSpec{}),
   768  	}
   769  }
   770  
   771  func MapTestWorkflowTemplateAPIToKube(w testkube.TestWorkflowTemplate) testworkflowsv1.TestWorkflowTemplate {
   772  	return testworkflowsv1.TestWorkflowTemplate{
   773  		TypeMeta: metav1.TypeMeta{
   774  			Kind:       "TestWorkflowTemplate",
   775  			APIVersion: testworkflowsv1.GroupVersion.Group + "/" + testworkflowsv1.GroupVersion.Version,
   776  		},
   777  		ObjectMeta: metav1.ObjectMeta{
   778  			Name:              w.Name,
   779  			Namespace:         w.Namespace,
   780  			Labels:            w.Labels,
   781  			Annotations:       w.Annotations,
   782  			CreationTimestamp: metav1.Time{Time: w.Created},
   783  		},
   784  		Description: w.Description,
   785  		Spec:        common.ResolvePtr(common.MapPtr(w.Spec, MapTemplateSpecAPIToKube), testworkflowsv1.TestWorkflowTemplateSpec{}),
   786  	}
   787  }
   788  
   789  func MapTemplateAPIToKube(w *testkube.TestWorkflowTemplate) *testworkflowsv1.TestWorkflowTemplate {
   790  	return common.MapPtr(w, MapTestWorkflowTemplateAPIToKube)
   791  }
   792  
   793  func MapAPIToKube(w *testkube.TestWorkflow) *testworkflowsv1.TestWorkflow {
   794  	return common.MapPtr(w, MapTestWorkflowAPIToKube)
   795  }
   796  
   797  func MapListAPIToKube(v []testkube.TestWorkflow) testworkflowsv1.TestWorkflowList {
   798  	items := make([]testworkflowsv1.TestWorkflow, len(v))
   799  	for i, item := range v {
   800  		items[i] = MapTestWorkflowAPIToKube(item)
   801  	}
   802  	return testworkflowsv1.TestWorkflowList{
   803  		TypeMeta: metav1.TypeMeta{
   804  			Kind:       "TestWorkflowList",
   805  			APIVersion: testworkflowsv1.GroupVersion.String(),
   806  		},
   807  		Items: items,
   808  	}
   809  }
   810  
   811  func MapTemplateListAPIToKube(v []testkube.TestWorkflowTemplate) testworkflowsv1.TestWorkflowTemplateList {
   812  	items := make([]testworkflowsv1.TestWorkflowTemplate, len(v))
   813  	for i, item := range v {
   814  		items[i] = MapTestWorkflowTemplateAPIToKube(item)
   815  	}
   816  	return testworkflowsv1.TestWorkflowTemplateList{
   817  		TypeMeta: metav1.TypeMeta{
   818  			Kind:       "TestWorkflowTemplateList",
   819  			APIVersion: testworkflowsv1.GroupVersion.String(),
   820  		},
   821  		Items: items,
   822  	}
   823  }