diff --git a/README.md b/README.md index f305b65..a18e4e4 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,9 @@ You can configure runner behavior by passing extra specifications as JSON in the | `runner_workdir` | string | `/runner/_work/` | The working directory for the runner | | `disable_runner_update` | boolean | `true` | Whether to disable automatic runner updates | | `runner_ephemeral` | boolean | `true` | Whether the runner should be ephemeral (single-use) | +| `pod_spec` | object | See default below | Custom Kubernetes PodSpec configuration | -### Example +### Basic Example ```json { @@ -40,3 +41,67 @@ You can configure runner behavior by passing extra specifications as JSON in the "runner_ephemeral": false } ``` + +### Custom PodSpec Example + +You can provide a complete custom PodSpec to configure resource limits, additional containers, volumes, security contexts, etc: + +```json +{ + "runner_workdir": "/runner/_work/", + "pod_spec": { + "restartPolicy": "Never", + "containers": [ + { + "name": "runner", + "image": "edp.buildth.ing/devfw-cicd/garm-act-runner:1", + "imagePullPolicy": "Always", + "env": [], + "resources": { + "requests": { + "memory": "2Gi", + "cpu": "1000m" + }, + "limits": { + "memory": "4Gi", + "cpu": "2000m" + } + }, + "volumeMounts": [ + { + "name": "runner-dir", + "mountPath": "/runner" + } + ] + } + ], + "volumes": [ + { + "name": "runner-dir", + "emptyDir": {} + } + ] + } +} +``` + +**Note:** When providing a custom `pod_spec`, the environment variables required for the runner (such as `RUNNER_TOKEN`, `METADATA_URL`, etc.) are automatically injected into the first container if not already present in the custom spec. If you provide a custom PodSpec without environment variables, make sure the container configuration is compatible with the runner requirements. + +### Default PodSpec + +If no `pod_spec` is provided, the following default configuration is used: + +```yaml +restartPolicy: Never +containers: + - name: runner + image: edp.buildth.ing/devfw-cicd/garm-act-runner:1 + imagePullPolicy: Always + env: [auto-generated environment variables] + volumeMounts: + - name: runner-dir + mountPath: /runner +volumes: + - name: runner-dir + emptyDir: {} +``` diff --git a/internal/spec/spec.go b/internal/spec/spec.go index 43931e3..8c8f8d3 100644 --- a/internal/spec/spec.go +++ b/internal/spec/spec.go @@ -18,9 +18,10 @@ type GitHubScopeDetails struct { } type RunnerExtraSpecs struct { - RunnerWorkDir string `json:"runner_workdir"` - DisableRunnerUpdate *bool `json:"disable_runner_update"` - RunnerEphemeral *bool `json:"runner_ephemeral"` + RunnerWorkDir string `json:"runner_workdir"` + DisableRunnerUpdate *bool `json:"disable_runner_update"` + RunnerEphemeral *bool `json:"runner_ephemeral"` + PodSpec *corev1.PodSpec `json:"pod_spec,omitempty"` } func ExtractGitHubScopeDetails(gitRepoURL string) (GitHubScopeDetails, error) { @@ -57,11 +58,16 @@ func ExtractGitHubScopeDetails(gitRepoURL string) (GitHubScopeDetails, error) { return scope, nil } -func GetRunnerEnvs(gitHubScope GitHubScopeDetails, bootstrapParams params.BootstrapInstance) []corev1.EnvVar { +func ParseExtraSpecs(bootstrapParams params.BootstrapInstance) RunnerExtraSpecs { var extraSpecs RunnerExtraSpecs if len(bootstrapParams.ExtraSpecs) > 0 { _ = json.Unmarshal(bootstrapParams.ExtraSpecs, &extraSpecs) } + return extraSpecs +} + +func GetRunnerEnvs(gitHubScope GitHubScopeDetails, bootstrapParams params.BootstrapInstance) []corev1.EnvVar { + extraSpecs := ParseExtraSpecs(bootstrapParams) runnerWorkDir := extraSpecs.RunnerWorkDir if runnerWorkDir == "" { @@ -137,3 +143,39 @@ func GetRunnerEnvs(gitHubScope GitHubScopeDetails, bootstrapParams params.Bootst }, } } + +func GetPodSpec(gitHubScope GitHubScopeDetails, bootstrapParams params.BootstrapInstance) corev1.PodSpec { + extraSpecs := ParseExtraSpecs(bootstrapParams) + + if extraSpecs.PodSpec != nil { + return *extraSpecs.PodSpec + } + + envs := GetRunnerEnvs(gitHubScope, bootstrapParams) + + return corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyNever, + Containers: []corev1.Container{ + { + Name: "runner", + Image: "edp.buildth.ing/devfw-cicd/garm-act-runner:1", + ImagePullPolicy: "Always", + Env: envs, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "runner-dir", + MountPath: "/runner", + }, + }, + }, + }, + Volumes: []corev1.Volume{ + { + Name: "runner-dir", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + } +} diff --git a/provider/provider.go b/provider/provider.go index 7dd9222..e8e32f4 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -89,7 +89,7 @@ func (a *edgeConnectProvider) CreateInstance(ctx context.Context, bootstrapParam return params.ProviderInstance{}, err } - envs := spec.GetRunnerEnvs(gitHubScopeDetails, bootstrapParams) + podSpec := spec.GetPodSpec(gitHubScopeDetails, bootstrapParams) deployment := appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ @@ -109,31 +109,7 @@ func (a *edgeConnectProvider) CreateInstance(ctx context.Context, bootstrapParam ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"app": instancename}, }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - Containers: []corev1.Container{ - { - Name: "runner", - Image: "edp.buildth.ing/devfw-cicd/garm-act-runner:1", - ImagePullPolicy: "Always", - Env: envs, - VolumeMounts: []corev1.VolumeMount{ - { - Name: "runner-dir", - MountPath: "/runner", - }, - }, - }, - }, - Volumes: []corev1.Volume{ - { - Name: "runner-dir", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, - }, - }, + Spec: podSpec, }, }, }