feat: bootstrap official runner through SPIFFE facade
This commit is contained in:
@@ -35,6 +35,7 @@ type PodManifest struct {
|
||||
Image string
|
||||
ServiceAccount string
|
||||
Args []string
|
||||
Environment map[string]string
|
||||
}
|
||||
|
||||
// IdentityEntry is a ClusterStaticEntry pinned to one concrete Pod UID.
|
||||
@@ -89,24 +90,25 @@ func (b Backend) Find(ctx context.Context, assignmentID string) (*taskworker.Exe
|
||||
return executor(pods[0]), nil
|
||||
}
|
||||
|
||||
func (b Backend) Create(ctx context.Context, assignment taskassignment.Assignment, metadata taskworker.Metadata) (*taskworker.Executor, error) {
|
||||
func (b Backend) Create(ctx context.Context, assignment taskassignment.Assignment, launch taskworker.LaunchSpec) (*taskworker.Executor, error) {
|
||||
if err := b.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if assignment.Backend != taskassignment.BackendPod {
|
||||
return nil, fmt.Errorf("Pod backend cannot create %q assignment", assignment.Backend)
|
||||
}
|
||||
labels := clone(metadata.Labels)
|
||||
labels := clone(launch.Metadata.Labels)
|
||||
labels["app.kubernetes.io/name"] = "gitea-dynamic-runner"
|
||||
labels["app.kubernetes.io/component"] = "executor"
|
||||
pod, err := b.API.CreatePod(ctx, PodManifest{
|
||||
Name: assignment.ID,
|
||||
Namespace: b.Config.Namespace,
|
||||
Labels: labels,
|
||||
Annotations: clone(metadata.Annotations),
|
||||
Annotations: clone(launch.Metadata.Annotations),
|
||||
Image: b.Config.Image,
|
||||
ServiceAccount: b.Config.ServiceAccount,
|
||||
Args: append(append([]string{}, b.Config.ExecutorArgs...), assignment.ID),
|
||||
Environment: clone(launch.Environment),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create assignment Pod: %w", err)
|
||||
|
||||
@@ -75,7 +75,9 @@ func TestFindRecoversPodByAssignmentLabel(t *testing.T) {
|
||||
func TestCreateUsesDeterministicNameAndRecoveryMetadata(t *testing.T) {
|
||||
api := &fakeAPI{}
|
||||
metadata := taskworker.BackendMetadata(assignment())
|
||||
executor, err := backend(api).Create(context.Background(), assignment(), metadata)
|
||||
executor, err := backend(api).Create(context.Background(), assignment(), taskworker.LaunchSpec{
|
||||
Metadata: metadata, Environment: map[string]string{"CI_RUNNER_CAPABILITY": "capability"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -85,6 +87,9 @@ func TestCreateUsesDeterministicNameAndRecoveryMetadata(t *testing.T) {
|
||||
if api.created.Annotations["ci.ddupan.top/spiffe-id"] != assignment().Identity.SPIFFEID {
|
||||
t.Fatalf("annotations = %#v", api.created.Annotations)
|
||||
}
|
||||
if api.created.Environment["CI_RUNNER_CAPABILITY"] != "capability" {
|
||||
t.Fatalf("environment = %#v", api.created.Environment)
|
||||
}
|
||||
if len(api.created.Args) != 2 || api.created.Args[1] != "gitea-task-42" || executor.IdentityTarget != "pod-uid" {
|
||||
t.Fatalf("args=%v executor=%#v", api.created.Args, executor)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ func (c *Client) ListPods(ctx context.Context, namespace, selector string) ([]Po
|
||||
}
|
||||
|
||||
func (c *Client) CreatePod(ctx context.Context, manifest PodManifest) (Pod, error) {
|
||||
environment := make([]corev1.EnvVar, 0, len(manifest.Environment))
|
||||
for name, value := range manifest.Environment {
|
||||
environment = append(environment, corev1.EnvVar{Name: name, Value: value})
|
||||
}
|
||||
document := &corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: manifest.Name, Namespace: manifest.Namespace,
|
||||
@@ -68,7 +72,7 @@ func (c *Client) CreatePod(ctx context.Context, manifest PodManifest) (Pod, erro
|
||||
ServiceAccountName: manifest.ServiceAccount,
|
||||
RestartPolicy: corev1.RestartPolicyNever,
|
||||
Containers: []corev1.Container{{
|
||||
Name: "executor", Image: manifest.Image, Args: manifest.Args,
|
||||
Name: "executor", Image: manifest.Image, Args: manifest.Args, Env: environment,
|
||||
SecurityContext: &corev1.SecurityContext{Privileged: boolPointer(true)},
|
||||
VolumeMounts: []corev1.VolumeMount{{
|
||||
Name: "spire-agent-socket", MountPath: "/run/spire/agent-sockets", ReadOnly: true,
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestClientPodLifecycleUsesTypedClient(t *testing.T) {
|
||||
Name: "gitea-task-42", Namespace: "gitea-actions",
|
||||
Labels: map[string]string{assignmentLabel: "gitea-task-42"},
|
||||
Image: "zot/ci-executor:main", ServiceAccount: "gitea-task-executor",
|
||||
Args: []string{"execute", "gitea-task-42"},
|
||||
Args: []string{"execute", "gitea-task-42"}, Environment: map[string]string{"CI_RUNNER_CAPABILITY": "capability"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -34,6 +34,9 @@ func TestClientPodLifecycleUsesTypedClient(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := pod.Spec.Containers[0].Env; len(got) != 1 || got[0].Name != "CI_RUNNER_CAPABILITY" || got[0].Value != "capability" {
|
||||
t.Fatalf("environment = %#v", got)
|
||||
}
|
||||
pod.UID = types.UID("pod-uid")
|
||||
pod.Status.Phase = corev1.PodRunning
|
||||
if _, err := client.Kubernetes.CoreV1().Pods("gitea-actions").Update(context.Background(), pod, metav1.UpdateOptions{}); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user