diff --git a/api/v1/testkube.yaml b/api/v1/testkube.yaml index 7f1905e67bd..502aa0f343b 100644 --- a/api/v1/testkube.yaml +++ b/api/v1/testkube.yaml @@ -8621,6 +8621,11 @@ components: description: plain text token to fetch with tokenFrom: $ref: "#/components/schemas/EnvVarSource" + sshKey: + type: string + description: plain text SSH private key to fetch with + sshKeyFrom: + $ref: "#/components/schemas/EnvVarSource" authType: $ref: "#/components/schemas/ContentGitAuthType" mountPath: diff --git a/build/testworkflow-toolkit/Dockerfile b/build/testworkflow-toolkit/Dockerfile index 689083dfbc2..5327d9d0645 100644 --- a/build/testworkflow-toolkit/Dockerfile +++ b/build/testworkflow-toolkit/Dockerfile @@ -1,7 +1,8 @@ # syntax=docker/dockerfile:1 ARG ALPINE_IMAGE FROM ${ALPINE_IMAGE} -RUN apk --no-cache add ca-certificates libssl3 git skopeo +RUN apk --no-cache add ca-certificates libssl3 git skopeo openssh-client COPY testworkflow-toolkit /toolkit +RUN adduser --disabled-password --home / --no-create-home --uid 1001 default USER 1001 ENTRYPOINT ["/toolkit"] diff --git a/cmd/tcl/testworkflow-toolkit/commands/clone.go b/cmd/tcl/testworkflow-toolkit/commands/clone.go index 17d4186efca..c03c0d37374 100644 --- a/cmd/tcl/testworkflow-toolkit/commands/clone.go +++ b/cmd/tcl/testworkflow-toolkit/commands/clone.go @@ -14,8 +14,10 @@ import ( "os" "path/filepath" + "github.com/kballard/go-shellquote" "github.com/spf13/cobra" + "github.com/kubeshop/testkube/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants" "github.com/kubeshop/testkube/pkg/ui" ) @@ -24,6 +26,7 @@ func NewCloneCmd() *cobra.Command { paths []string username string token string + sshKey string authType string revision string ) @@ -63,6 +66,14 @@ func NewCloneCmd() *cobra.Command { } } + // Use the SSH key + if sshKey != "" { + sshKeyPath := filepath.Join(constants.DefaultTmpDirPath, "id_rsa") + err := os.WriteFile(sshKeyPath, []byte(sshKey), 0400) + ui.ExitOnError("saving SSH key temporarily", err) + os.Setenv("GIT_SSH_COMMAND", shellquote.Join("ssh", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null", "-i", sshKeyPath)) + } + // Mark directory as safe configArgs := []string{"-c", fmt.Sprintf("safe.directory=%s", outputPath), "-c", "advice.detachedHead=false"} @@ -100,6 +111,7 @@ func NewCloneCmd() *cobra.Command { cmd.Flags().StringSliceVarP(&paths, "paths", "p", nil, "paths for sparse checkout") cmd.Flags().StringVarP(&username, "username", "u", "", "") cmd.Flags().StringVarP(&token, "token", "t", "", "") + cmd.Flags().StringVarP(&sshKey, "sshKey", "s", "", "") cmd.Flags().StringVarP(&authType, "authType", "a", "basic", "allowed: basic, header") cmd.Flags().StringVarP(&revision, "revision", "r", "", "commit hash, branch name or tag") diff --git a/go.mod b/go.mod index 2785c688e1d..badfa1069a7 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/kelseyhightower/envconfig v1.4.0 github.com/kubepug/kubepug v1.7.1 - github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240603124058-c5cda10c9435 + github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240604113004-a56be5477d4f github.com/minio/minio-go/v7 v7.0.47 github.com/montanaflynn/stats v0.6.6 github.com/moogar0880/problems v0.1.1 diff --git a/go.sum b/go.sum index 2e2d109c602..21895ee54b0 100644 --- a/go.sum +++ b/go.sum @@ -358,10 +358,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubepug/kubepug v1.7.1 h1:LKhfSxS8Y5mXs50v+3Lpyec+cogErDLcV7CMUuiaisw= github.com/kubepug/kubepug v1.7.1/go.mod h1:lv+HxD0oTFL7ZWjj0u6HKhMbbTIId3eG7aWIW0gyF8g= -github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240603112528-59da49d6dd3f h1:sz5lyO2v48W3QnsCIYWvUJrYQMbwTQfTq4CAGiKPGHc= -github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240603112528-59da49d6dd3f/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk= -github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240603124058-c5cda10c9435 h1:/RHpaOtQigIknqusDt3uBifDr/Jce1OvZ/e5rJbA8q8= -github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240603124058-c5cda10c9435/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk= +github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240604113004-a56be5477d4f h1:zXYCjLe15EzD26k5QEcFBwX3D7fod0goNBz7pIFL+/k= +github.com/kubeshop/testkube-operator v1.15.2-beta1.0.20240604113004-a56be5477d4f/go.mod h1:P47tw1nKQFufdsZndyq2HG2MSa0zK/lU0XpRfZtEmIk= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= diff --git a/pkg/api/v1/testkube/model_test_workflow_content_git.go b/pkg/api/v1/testkube/model_test_workflow_content_git.go index 24ec57835a1..c56d8c14d60 100644 --- a/pkg/api/v1/testkube/model_test_workflow_content_git.go +++ b/pkg/api/v1/testkube/model_test_workflow_content_git.go @@ -18,9 +18,12 @@ type TestWorkflowContentGit struct { Username string `json:"username,omitempty"` UsernameFrom *EnvVarSource `json:"usernameFrom,omitempty"` // plain text token to fetch with - Token string `json:"token,omitempty"` - TokenFrom *EnvVarSource `json:"tokenFrom,omitempty"` - AuthType *ContentGitAuthType `json:"authType,omitempty"` + Token string `json:"token,omitempty"` + TokenFrom *EnvVarSource `json:"tokenFrom,omitempty"` + // plain text SSH private key to fetch with + SshKey string `json:"sshKey,omitempty"` + SshKeyFrom *EnvVarSource `json:"sshKeyFrom,omitempty"` + AuthType *ContentGitAuthType `json:"authType,omitempty"` // where to mount the fetched repository contents (defaults to \"repo\" directory in the data volume) MountPath string `json:"mountPath,omitempty"` // paths to fetch for the sparse checkout diff --git a/pkg/api/v1/testkube/model_test_workflow_independent_service_spec.go b/pkg/api/v1/testkube/model_test_workflow_independent_service_spec.go index 6be427954f2..192eeadb608 100644 --- a/pkg/api/v1/testkube/model_test_workflow_independent_service_spec.go +++ b/pkg/api/v1/testkube/model_test_workflow_independent_service_spec.go @@ -25,12 +25,6 @@ type TestWorkflowIndependentServiceSpec struct { SecurityContext *SecurityContext `json:"securityContext,omitempty"` // volumes to mount to the container VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"` - Count *BoxedString `json:"count,omitempty"` - MaxCount *BoxedString `json:"maxCount,omitempty"` - // matrix of parameters to spawn instances - Matrix map[string]interface{} `json:"matrix,omitempty"` - // parameters that should be distributed across sharded instances - Shards map[string]interface{} `json:"shards,omitempty"` // service description to display Description string `json:"description,omitempty"` // maximum time until reaching readiness @@ -42,4 +36,10 @@ type TestWorkflowIndependentServiceSpec struct { Logs *BoxedString `json:"logs,omitempty"` RestartPolicy string `json:"restartPolicy,omitempty"` ReadinessProbe *Probe `json:"readinessProbe,omitempty"` + Count *BoxedString `json:"count,omitempty"` + MaxCount *BoxedString `json:"maxCount,omitempty"` + // matrix of parameters to spawn instances + Matrix map[string]interface{} `json:"matrix,omitempty"` + // parameters that should be distributed across sharded instances + Shards map[string]interface{} `json:"shards,omitempty"` } diff --git a/pkg/api/v1/testkube/model_test_workflow_independent_step_parallel.go b/pkg/api/v1/testkube/model_test_workflow_independent_step_parallel.go index c1ac53328aa..3ca736332e0 100644 --- a/pkg/api/v1/testkube/model_test_workflow_independent_step_parallel.go +++ b/pkg/api/v1/testkube/model_test_workflow_independent_step_parallel.go @@ -28,10 +28,19 @@ type TestWorkflowIndependentStepParallel struct { // delay before the step Delay string `json:"delay,omitempty"` // script to run in a default shell for the container - Shell string `json:"shell,omitempty"` - Run *TestWorkflowStepRun `json:"run,omitempty"` - Execute *TestWorkflowStepExecute `json:"execute,omitempty"` - Artifacts *TestWorkflowStepArtifacts `json:"artifacts,omitempty"` + Shell string `json:"shell,omitempty"` + Run *TestWorkflowStepRun `json:"run,omitempty"` + Execute *TestWorkflowStepExecute `json:"execute,omitempty"` + Artifacts *TestWorkflowStepArtifacts `json:"artifacts,omitempty"` + // how many resources could be scheduled in parallel + Parallelism int32 `json:"parallelism,omitempty"` + // worker description to display + Description string `json:"description,omitempty"` + Logs *BoxedString `json:"logs,omitempty"` + // list of files to send to parallel steps + Transfer []TestWorkflowStepParallelTransfer `json:"transfer,omitempty"` + // list of files to fetch from parallel steps + Fetch []TestWorkflowStepParallelFetch `json:"fetch,omitempty"` Config map[string]TestWorkflowParameterSchema `json:"config,omitempty"` Content *TestWorkflowContent `json:"content,omitempty"` Services map[string]TestWorkflowIndependentServiceSpec `json:"services,omitempty"` @@ -42,13 +51,4 @@ type TestWorkflowIndependentStepParallel struct { Steps []TestWorkflowIndependentStep `json:"steps,omitempty"` After []TestWorkflowIndependentStep `json:"after,omitempty"` Events []TestWorkflowEvent `json:"events,omitempty"` - // how many resources could be scheduled in parallel - Parallelism int32 `json:"parallelism,omitempty"` - // worker description to display - Description string `json:"description,omitempty"` - Logs *BoxedString `json:"logs,omitempty"` - // list of files to send to parallel steps - Transfer []TestWorkflowStepParallelTransfer `json:"transfer,omitempty"` - // list of files to fetch from parallel steps - Fetch []TestWorkflowStepParallelFetch `json:"fetch,omitempty"` } diff --git a/pkg/api/v1/testkube/model_test_workflow_service_spec.go b/pkg/api/v1/testkube/model_test_workflow_service_spec.go index 671cf96a65e..ad915dd162e 100644 --- a/pkg/api/v1/testkube/model_test_workflow_service_spec.go +++ b/pkg/api/v1/testkube/model_test_workflow_service_spec.go @@ -36,11 +36,11 @@ type TestWorkflowServiceSpec struct { Logs *BoxedString `json:"logs,omitempty"` RestartPolicy string `json:"restartPolicy,omitempty"` ReadinessProbe *Probe `json:"readinessProbe,omitempty"` + Use []TestWorkflowTemplateRef `json:"use,omitempty"` Count *BoxedString `json:"count,omitempty"` MaxCount *BoxedString `json:"maxCount,omitempty"` // matrix of parameters to spawn instances Matrix map[string]interface{} `json:"matrix,omitempty"` // parameters that should be distributed across sharded instances - Shards map[string]interface{} `json:"shards,omitempty"` - Use []TestWorkflowTemplateRef `json:"use,omitempty"` + Shards map[string]interface{} `json:"shards,omitempty"` } diff --git a/pkg/api/v1/testkube/model_test_workflow_step_execute_test_ref.go b/pkg/api/v1/testkube/model_test_workflow_step_execute_test_ref.go index 974209ed35b..d9943d51ddc 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_execute_test_ref.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_execute_test_ref.go @@ -10,16 +10,16 @@ package testkube type TestWorkflowStepExecuteTestRef struct { - Count *BoxedString `json:"count,omitempty"` - MaxCount *BoxedString `json:"maxCount,omitempty"` - // matrix of parameters to spawn instances - Matrix map[string]interface{} `json:"matrix,omitempty"` - // parameters that should be distributed across sharded instances - Shards map[string]interface{} `json:"shards,omitempty"` // test name to schedule Name string `json:"name,omitempty"` // test execution description to display Description string `json:"description,omitempty"` + Count *BoxedString `json:"count,omitempty"` + MaxCount *BoxedString `json:"maxCount,omitempty"` ExecutionRequest *TestWorkflowStepExecuteTestExecutionRequest `json:"executionRequest,omitempty"` Tarball map[string]TestWorkflowTarballRequest `json:"tarball,omitempty"` + // matrix of parameters to spawn instances + Matrix map[string]interface{} `json:"matrix,omitempty"` + // parameters that should be distributed across sharded instances + Shards map[string]interface{} `json:"shards,omitempty"` } diff --git a/pkg/api/v1/testkube/model_test_workflow_step_execute_test_workflow_ref.go b/pkg/api/v1/testkube/model_test_workflow_step_execute_test_workflow_ref.go index f2e131a22e2..c2bcd5b1d1f 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_execute_test_workflow_ref.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_execute_test_workflow_ref.go @@ -10,12 +10,6 @@ package testkube type TestWorkflowStepExecuteTestWorkflowRef struct { - Count *BoxedString `json:"count,omitempty"` - MaxCount *BoxedString `json:"maxCount,omitempty"` - // matrix of parameters to spawn instances - Matrix map[string]interface{} `json:"matrix,omitempty"` - // parameters that should be distributed across sharded instances - Shards map[string]interface{} `json:"shards,omitempty"` // TestWorkflow name to include Name string `json:"name,omitempty"` // TestWorkflow execution description to display @@ -24,4 +18,10 @@ type TestWorkflowStepExecuteTestWorkflowRef struct { ExecutionName string `json:"executionName,omitempty"` Tarball map[string]TestWorkflowTarballRequest `json:"tarball,omitempty"` Config map[string]string `json:"config,omitempty"` + Count *BoxedString `json:"count,omitempty"` + MaxCount *BoxedString `json:"maxCount,omitempty"` + // matrix of parameters to spawn instances + Matrix map[string]interface{} `json:"matrix,omitempty"` + // parameters that should be distributed across sharded instances + Shards map[string]interface{} `json:"shards,omitempty"` } diff --git a/pkg/api/v1/testkube/model_test_workflow_step_parallel.go b/pkg/api/v1/testkube/model_test_workflow_step_parallel.go index fbea0caff01..d8b4de8e7ff 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_parallel.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_parallel.go @@ -28,10 +28,20 @@ type TestWorkflowStepParallel struct { // delay before the step Delay string `json:"delay,omitempty"` // script to run in a default shell for the container - Shell string `json:"shell,omitempty"` - Run *TestWorkflowStepRun `json:"run,omitempty"` - Execute *TestWorkflowStepExecute `json:"execute,omitempty"` - Artifacts *TestWorkflowStepArtifacts `json:"artifacts,omitempty"` + Shell string `json:"shell,omitempty"` + Run *TestWorkflowStepRun `json:"run,omitempty"` + Execute *TestWorkflowStepExecute `json:"execute,omitempty"` + Artifacts *TestWorkflowStepArtifacts `json:"artifacts,omitempty"` + // how many resources could be scheduled in parallel + Parallelism int32 `json:"parallelism,omitempty"` + // worker description to display + Description string `json:"description,omitempty"` + Logs *BoxedString `json:"logs,omitempty"` + // list of files to send to parallel steps + Transfer []TestWorkflowStepParallelTransfer `json:"transfer,omitempty"` + // list of files to fetch from parallel steps + Fetch []TestWorkflowStepParallelFetch `json:"fetch,omitempty"` + Template *TestWorkflowTemplateRef `json:"template,omitempty"` Use []TestWorkflowTemplateRef `json:"use,omitempty"` Config map[string]TestWorkflowParameterSchema `json:"config,omitempty"` Content *TestWorkflowContent `json:"content,omitempty"` @@ -43,14 +53,4 @@ type TestWorkflowStepParallel struct { Steps []TestWorkflowStep `json:"steps,omitempty"` After []TestWorkflowStep `json:"after,omitempty"` Events []TestWorkflowEvent `json:"events,omitempty"` - // how many resources could be scheduled in parallel - Parallelism int32 `json:"parallelism,omitempty"` - // worker description to display - Description string `json:"description,omitempty"` - Logs *BoxedString `json:"logs,omitempty"` - // list of files to send to parallel steps - Transfer []TestWorkflowStepParallelTransfer `json:"transfer,omitempty"` - // list of files to fetch from parallel steps - Fetch []TestWorkflowStepParallelFetch `json:"fetch,omitempty"` - Template *TestWorkflowTemplateRef `json:"template,omitempty"` } diff --git a/pkg/tcl/mapperstcl/testworkflows/kube_openapi.go b/pkg/tcl/mapperstcl/testworkflows/kube_openapi.go index 030ad5dd3cc..19a5b2c8f30 100644 --- a/pkg/tcl/mapperstcl/testworkflows/kube_openapi.go +++ b/pkg/tcl/mapperstcl/testworkflows/kube_openapi.go @@ -397,6 +397,8 @@ func MapContentGitKubeToAPI(v testworkflowsv1.ContentGit) testkube.TestWorkflowC UsernameFrom: common.MapPtr(v.UsernameFrom, MapEnvVarSourceKubeToAPI), Token: v.Token, TokenFrom: common.MapPtr(v.TokenFrom, MapEnvVarSourceKubeToAPI), + SshKey: v.SshKey, + SshKeyFrom: common.MapPtr(v.SshKeyFrom, MapEnvVarSourceKubeToAPI), AuthType: MapGitAuthTypeKubeToAPI(v.AuthType), MountPath: v.MountPath, Paths: v.Paths, diff --git a/pkg/tcl/mapperstcl/testworkflows/openapi_kube.go b/pkg/tcl/mapperstcl/testworkflows/openapi_kube.go index 1a435249906..dcaa4cdeb1a 100644 --- a/pkg/tcl/mapperstcl/testworkflows/openapi_kube.go +++ b/pkg/tcl/mapperstcl/testworkflows/openapi_kube.go @@ -295,6 +295,8 @@ func MapContentGitAPIToKube(v testkube.TestWorkflowContentGit) testworkflowsv1.C UsernameFrom: common.MapPtr(v.UsernameFrom, MapEnvVarSourceAPIToKube), Token: v.Token, TokenFrom: common.MapPtr(v.TokenFrom, MapEnvVarSourceAPIToKube), + SshKey: v.SshKey, + SshKeyFrom: common.MapPtr(v.SshKeyFrom, MapEnvVarSourceAPIToKube), AuthType: MapGitAuthTypeAPIToKube(v.AuthType), MountPath: v.MountPath, Paths: v.Paths, diff --git a/pkg/tcl/testworkflowstcl/testworkflowprocessor/configmapfiles.go b/pkg/tcl/testworkflowstcl/testworkflowprocessor/configmapfiles.go index 550622a3762..6050603e6ea 100644 --- a/pkg/tcl/testworkflowstcl/testworkflowprocessor/configmapfiles.go +++ b/pkg/tcl/testworkflowstcl/testworkflowprocessor/configmapfiles.go @@ -34,8 +34,8 @@ type configMapFiles struct { type ConfigMapFiles interface { Volumes() []corev1.Volume ConfigMaps() []corev1.ConfigMap - AddTextFile(content string) (corev1.VolumeMount, corev1.Volume, error) - AddFile(content []byte) (corev1.VolumeMount, corev1.Volume, error) + AddTextFile(content string, mode *int32) (corev1.VolumeMount, corev1.Volume, error) + AddFile(content []byte, mode *int32) (corev1.VolumeMount, corev1.Volume, error) FilesCount() int } @@ -60,9 +60,13 @@ func (c *configMapFiles) FilesCount() int { return len(c.Mounts) } -func (c *configMapFiles) next(minBytes int) (*corev1.ConfigMap, *corev1.Volume, int) { +func (c *configMapFiles) next(minBytes int, mode *int32) (*corev1.ConfigMap, *corev1.Volume, int) { for i := range c.Cfgs { size := 0 + cfgMode := c.Vols[i].ConfigMap.DefaultMode + if (cfgMode == nil && mode != nil) || (cfgMode != nil && mode == nil) || (cfgMode != nil && *cfgMode != *mode) { + continue + } for k := range c.Cfgs[i].Data { size += len(c.Cfgs[i].Data[k]) } @@ -90,6 +94,7 @@ func (c *configMapFiles) next(minBytes int) (*corev1.ConfigMap, *corev1.Volume, Name: cfg.Name, VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ + DefaultMode: mode, LocalObjectReference: corev1.LocalObjectReference{Name: cfg.Name}, }, }, @@ -97,31 +102,31 @@ func (c *configMapFiles) next(minBytes int) (*corev1.ConfigMap, *corev1.Volume, return &c.Cfgs[index], &c.Vols[index], index } -func (c *configMapFiles) AddTextFile(file string) (corev1.VolumeMount, corev1.Volume, error) { +func (c *configMapFiles) AddTextFile(file string, mode *int32) (corev1.VolumeMount, corev1.Volume, error) { if len(file) > maxConfigMapFileSize { return corev1.VolumeMount{}, corev1.Volume{}, fmt.Errorf("the maximum file size is %s", humanize.Bytes(maxConfigMapFileSize)) } hash := fmt.Sprintf("%x", sha256.Sum256([]byte(file))) if _, ok := c.Mounts[hash]; !ok { - cfg, vol, index := c.next(len(file)) + cfg, vol, index := c.next(len(file), mode) key := fmt.Sprintf("%d", len(cfg.Data)+len(cfg.BinaryData)) cfg.Data[key] = file - c.Mounts[hash] = corev1.VolumeMount{Name: vol.Name, ReadOnly: true, SubPath: key} + c.Mounts[hash] = corev1.VolumeMount{Name: vol.Name, SubPath: key} c.VolRefs[hash] = index } return c.Mounts[hash], c.Vols[c.VolRefs[hash]], nil } -func (c *configMapFiles) AddFile(file []byte) (corev1.VolumeMount, corev1.Volume, error) { +func (c *configMapFiles) AddFile(file []byte, mode *int32) (corev1.VolumeMount, corev1.Volume, error) { if len(file) > maxConfigMapFileSize { return corev1.VolumeMount{}, corev1.Volume{}, fmt.Errorf("the maximum file size is %s", humanize.Bytes(maxConfigMapFileSize)) } hash := fmt.Sprintf("%x", sha256.Sum256(file)) if _, ok := c.Mounts[hash]; !ok { - cfg, vol, index := c.next(len(file)) + cfg, vol, index := c.next(len(file), mode) key := fmt.Sprintf("%d", len(cfg.Data)+len(cfg.BinaryData)) cfg.BinaryData[key] = file - c.Mounts[hash] = corev1.VolumeMount{Name: vol.Name, ReadOnly: true, SubPath: key} + c.Mounts[hash] = corev1.VolumeMount{Name: vol.Name, SubPath: key} c.VolRefs[hash] = index } return c.Mounts[hash], c.Vols[c.VolRefs[hash]], nil diff --git a/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants/constants.go b/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants/constants.go index 5a2a8e61e5e..b08ed16cf74 100644 --- a/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants/constants.go +++ b/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants/constants.go @@ -37,6 +37,7 @@ var ( DefaultInitPath = filepath.Join(DefaultInternalPath, "init") DefaultStatePath = filepath.Join(DefaultInternalPath, "state") DefaultTransferDirPath = filepath.Join(DefaultInternalPath, "transfer") + DefaultTmpDirPath = filepath.Join(DefaultInternalPath, "tmp") DefaultTransferPort = 60433 InitScript = strings.TrimSpace(strings.NewReplacer( "", InternalBinPath, diff --git a/pkg/tcl/testworkflowstcl/testworkflowprocessor/intermediate.go b/pkg/tcl/testworkflowstcl/testworkflowprocessor/intermediate.go index 8328f921650..bf74ac9099d 100644 --- a/pkg/tcl/testworkflowstcl/testworkflowprocessor/intermediate.go +++ b/pkg/tcl/testworkflowstcl/testworkflowprocessor/intermediate.go @@ -38,8 +38,8 @@ type Intermediate interface { AddEmptyDirVolume(source *corev1.EmptyDirVolumeSource, mountPath string) corev1.VolumeMount - AddTextFile(file string) (corev1.VolumeMount, error) - AddBinaryFile(file []byte) (corev1.VolumeMount, error) + AddTextFile(file string, mode *int32) (corev1.VolumeMount, error) + AddBinaryFile(file []byte, mode *int32) (corev1.VolumeMount, error) } type intermediate struct { @@ -130,12 +130,12 @@ func (s *intermediate) AddEmptyDirVolume(source *corev1.EmptyDirVolumeSource, mo // Handling files -func (s *intermediate) AddTextFile(file string) (corev1.VolumeMount, error) { - mount, _, err := s.Files.AddTextFile(file) +func (s *intermediate) AddTextFile(file string, mode *int32) (corev1.VolumeMount, error) { + mount, _, err := s.Files.AddTextFile(file, mode) return mount, err } -func (s *intermediate) AddBinaryFile(file []byte) (corev1.VolumeMount, error) { - mount, _, err := s.Files.AddFile(file) +func (s *intermediate) AddBinaryFile(file []byte, mode *int32) (corev1.VolumeMount, error) { + mount, _, err := s.Files.AddFile(file, mode) return mount, err } diff --git a/pkg/tcl/testworkflowstcl/testworkflowprocessor/mock_intermediate.go b/pkg/tcl/testworkflowstcl/testworkflowprocessor/mock_intermediate.go index fef24c00cd0..18485248f6a 100644 --- a/pkg/tcl/testworkflowstcl/testworkflowprocessor/mock_intermediate.go +++ b/pkg/tcl/testworkflowstcl/testworkflowprocessor/mock_intermediate.go @@ -36,18 +36,18 @@ func (m *MockIntermediate) EXPECT() *MockIntermediateMockRecorder { } // AddBinaryFile mocks base method. -func (m *MockIntermediate) AddBinaryFile(arg0 []byte) (v10.VolumeMount, error) { +func (m *MockIntermediate) AddBinaryFile(arg0 []byte, arg1 *int32) (v10.VolumeMount, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddBinaryFile", arg0) + ret := m.ctrl.Call(m, "AddBinaryFile", arg0, arg1) ret0, _ := ret[0].(v10.VolumeMount) ret1, _ := ret[1].(error) return ret0, ret1 } // AddBinaryFile indicates an expected call of AddBinaryFile. -func (mr *MockIntermediateMockRecorder) AddBinaryFile(arg0 interface{}) *gomock.Call { +func (mr *MockIntermediateMockRecorder) AddBinaryFile(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBinaryFile", reflect.TypeOf((*MockIntermediate)(nil).AddBinaryFile), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBinaryFile", reflect.TypeOf((*MockIntermediate)(nil).AddBinaryFile), arg0, arg1) } // AddConfigMap mocks base method. @@ -93,18 +93,18 @@ func (mr *MockIntermediateMockRecorder) AddSecret(arg0 interface{}) *gomock.Call } // AddTextFile mocks base method. -func (m *MockIntermediate) AddTextFile(arg0 string) (v10.VolumeMount, error) { +func (m *MockIntermediate) AddTextFile(arg0 string, arg1 *int32) (v10.VolumeMount, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddTextFile", arg0) + ret := m.ctrl.Call(m, "AddTextFile", arg0, arg1) ret0, _ := ret[0].(v10.VolumeMount) ret1, _ := ret[1].(error) return ret0, ret1 } // AddTextFile indicates an expected call of AddTextFile. -func (mr *MockIntermediateMockRecorder) AddTextFile(arg0 interface{}) *gomock.Call { +func (mr *MockIntermediateMockRecorder) AddTextFile(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTextFile", reflect.TypeOf((*MockIntermediate)(nil).AddTextFile), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTextFile", reflect.TypeOf((*MockIntermediate)(nil).AddTextFile), arg0, arg1) } // AddVolume mocks base method. diff --git a/pkg/tcl/testworkflowstcl/testworkflowprocessor/operations.go b/pkg/tcl/testworkflowstcl/testworkflowprocessor/operations.go index fa6da46b440..14a0eb1207c 100644 --- a/pkg/tcl/testworkflowstcl/testworkflowprocessor/operations.go +++ b/pkg/tcl/testworkflowstcl/testworkflowprocessor/operations.go @@ -158,7 +158,7 @@ func ProcessContentFiles(_ InternalProcessor, layer Intermediate, container Cont } for _, f := range step.Content.Files { if f.ContentFrom == nil { - vm, err := layer.AddTextFile(f.Content) + vm, err := layer.AddTextFile(f.Content, f.Mode) if err != nil { return nil, fmt.Errorf("file %s: could not append: %s", f.Path, err.Error()) } @@ -267,6 +267,19 @@ func ProcessContentGit(_ InternalProcessor, layer Intermediate, container Contai args = append(args, "-t", step.Content.Git.Token) } + // Provide SSH key + if step.Content.Git.SshKeyFrom != nil { + container.AppendEnv(corev1.EnvVar{Name: "TK_SSH_KEY", ValueFrom: step.Content.Git.SshKeyFrom}) + args = append(args, "-s", "{{env.TK_SSH_KEY}}") + } else if step.Content.Git.SshKey != "" { + args = append(args, "-s", step.Content.Git.SshKey) + } + + // Provide temporary directory for SSH key to avoid issues with permissions + if step.Content.Git.SshKeyFrom != nil || step.Content.Git.SshKey != "" { + container.AppendVolumeMounts(layer.AddEmptyDirVolume(nil, constants.DefaultTmpDirPath)) + } + // Provide auth type if step.Content.Git.AuthType != "" { args = append(args, "-a", string(step.Content.Git.AuthType))