package spec import ( "encoding/json" "fmt" "net/url" "strings" "github.com/cloudbase/garm-provider-common/params" corev1 "k8s.io/api/core/v1" ) type GitHubScopeDetails struct { BaseURL string Repo string Org string Enterprise string } type RunnerExtraSpecs struct { 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) { if gitRepoURL == "" { return GitHubScopeDetails{}, fmt.Errorf("no gitRepoURL supplied") } u, err := url.Parse(gitRepoURL) if err != nil { return GitHubScopeDetails{}, fmt.Errorf("invalid URL: %w", err) } if u.Scheme == "" || u.Host == "" { return GitHubScopeDetails{}, fmt.Errorf("invalid URL: %s", gitRepoURL) } pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") scope := GitHubScopeDetails{ BaseURL: u.Scheme + "://" + u.Host, } switch { case len(pathParts) == 1: scope.Org = pathParts[0] case len(pathParts) == 2 && pathParts[0] == "enterprises": scope.Enterprise = pathParts[1] case len(pathParts) == 2: scope.Org = pathParts[0] scope.Repo = pathParts[1] default: return GitHubScopeDetails{}, fmt.Errorf("URL does not match the expected patterns") } return scope, nil } 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 == "" { runnerWorkDir = "/runner/_work/" } disableRunnerUpdate := "true" if extraSpecs.DisableRunnerUpdate != nil { disableRunnerUpdate = fmt.Sprintf("%t", *extraSpecs.DisableRunnerUpdate) } runnerEphemeral := "true" if extraSpecs.RunnerEphemeral != nil { runnerEphemeral = fmt.Sprintf("%t", *extraSpecs.RunnerEphemeral) } return []corev1.EnvVar{ { Name: "RUNNER_GITEA_INSTANCE", Value: bootstrapParams.RepoURL, }, { Name: "RUNNER_GROUP", Value: bootstrapParams.GitHubRunnerGroup, }, { Name: "RUNNER_NAME", Value: bootstrapParams.Name, }, { Name: "RUNNER_LABELS", Value: strings.Join(bootstrapParams.Labels, ","), }, { Name: "RUNNER_NO_DEFAULT_LABELS", Value: "true", }, { Name: "DISABLE_RUNNER_UPDATE", Value: disableRunnerUpdate, }, { Name: "RUNNER_WORKDIR", Value: runnerWorkDir, }, { Name: "GITHUB_URL", Value: gitHubScope.BaseURL, }, { Name: "RUNNER_EPHEMERAL", Value: runnerEphemeral, }, { Name: "RUNNER_TOKEN", Value: "dummy", }, { Name: "METADATA_URL", Value: bootstrapParams.MetadataURL, }, { Name: "BEARER_TOKEN", Value: bootstrapParams.InstanceToken, }, { Name: "CALLBACK_URL", Value: bootstrapParams.CallbackURL, }, { Name: "JIT_CONFIG_ENABLED", Value: fmt.Sprintf("%t", bootstrapParams.JitConfigEnabled), }, } } 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.RestartPolicyAlways, Containers: []corev1.Container{ { Name: "runner", Image: "edp.buildth.ing/devfw-cicd/garm-act-runner:1", ImagePullPolicy: "Always", Env: envs, VolumeMounts: []corev1.VolumeMount{ { Name: "buildkitd", MountPath: "/run/user/1000/buildkit", SubPath: "buildkitd.sock", }, }, }, { Name: "buildkitd", Image: "moby/buildkit:v0.25.1-rootless", Args: []string{ "--allow-insecure-entitlement=network.host", "--oci-worker-no-process-sandbox", }, ImagePullPolicy: corev1.PullIfNotPresent, ReadinessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ Command: []string{ "buildctl", "debug", "workers", }, }, }, FailureThreshold: 3, PeriodSeconds: 10, SuccessThreshold: 1, TimeoutSeconds: 1, }, VolumeMounts: []corev1.VolumeMount{ { Name: "buildkitd", MountPath: "/run/user/1000/buildkit", SubPath: "buildkitd.sock", }, }, }, }, Volumes: []corev1.Volume{ { Name: "buildkitd", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{}, }, }, }, } }