package actionsgithubcom // import ( // "context" // "crypto/tls" // "encoding/base64" // "fmt" // "net/http" // "net/http/httptest" // "os" // "path/filepath" // "strings" // "time" // // "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1" // "github.com/actions/actions-runner-controller/github/actions" // "github.com/go-logr/logr" // // "github.com/actions/actions-runner-controller/github/actions/fake" // "github.com/actions/actions-runner-controller/github/actions/testserver" // . "github.com/onsi/ginkgo/v2" // . "github.com/onsi/gomega" // corev1 "k8s.io/api/core/v1" // kerrors "k8s.io/apimachinery/pkg/api/errors" // metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ctrl "sigs.k8s.io/controller-runtime" // "sigs.k8s.io/controller-runtime/pkg/client" // logf "sigs.k8s.io/controller-runtime/pkg/log" // ) // // const ( // timeout = time.Second * 10 // interval = time.Millisecond * 250 // runnerImage = "ghcr.io/actions/actions-runner:latest" // ) // // func newExampleRunner(name, namespace, configSecretName string) *v1alpha1.EphemeralRunner { // return &v1alpha1.EphemeralRunner{ // ObjectMeta: metav1.ObjectMeta{ // Name: name, // Namespace: namespace, // }, // Spec: v1alpha1.EphemeralRunnerSpec{ // GitHubConfigUrl: "https://github.com/owner/repo", // GitHubConfigSecret: configSecretName, // RunnerScaleSetId: 1, // PodTemplateSpec: corev1.PodTemplateSpec{ // Spec: corev1.PodSpec{ // Containers: []corev1.Container{ // { // Name: EphemeralRunnerContainerName, // Image: runnerImage, // Command: []string{"/runner/run.sh"}, // VolumeMounts: []corev1.VolumeMount{ // { // Name: "runner", // MountPath: "/runner", // }, // }, // }, // }, // InitContainers: []corev1.Container{ // { // Name: "setup", // Image: runnerImage, // Command: []string{"sh", "-c", "cp -r /home/runner/* /runner/"}, // VolumeMounts: []corev1.VolumeMount{ // { // Name: "runner", // MountPath: "/runner", // }, // }, // }, // }, // Volumes: []corev1.Volume{ // { // Name: "runner", // VolumeSource: corev1.VolumeSource{ // EmptyDir: &corev1.EmptyDirVolumeSource{}, // }, // }, // }, // }, // }, // }, // } // } // // var _ = Describe("EphemeralRunner", func() { // Describe("Resource manipulation", func() { // var ctx context.Context // var mgr ctrl.Manager // var autoscalingNS *corev1.Namespace // var configSecret *corev1.Secret // var controller *EphemeralRunnerReconciler // var ephemeralRunner *v1alpha1.EphemeralRunner // // BeforeEach(func() { // ctx = context.Background() // autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient) // configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name) // // controller = &EphemeralRunnerReconciler{ // Client: mgr.GetClient(), // Scheme: mgr.GetScheme(), // Log: logf.Log, // ActionsClient: fake.NewMultiClient(), // } // // err := controller.SetupWithManager(mgr) // Expect(err).To(BeNil(), "failed to setup controller") // // ephemeralRunner = newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name) // err = k8sClient.Create(ctx, ephemeralRunner) // Expect(err).To(BeNil(), "failed to create ephemeral runner") // // startManagers(GinkgoT(), mgr) // }) // // It("It should create/add all required resources for EphemeralRunner (finalizer, jit secret)", func() { // created := new(v1alpha1.EphemeralRunner) // // Check if finalizer is added // Eventually( // func() ([]string, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, created) // if err != nil { // return nil, err // } // if len(created.Finalizers) == 0 { // return nil, nil // } // // n := len(created.Finalizers) // avoid capacity mismatch // return created.Finalizers[:n:n], nil // }, // timeout, // interval, // ).Should(BeEquivalentTo([]string{ephemeralRunnerActionsFinalizerName, ephemeralRunnerFinalizerName})) // // Eventually( // func() (bool, error) { // secret := new(corev1.Secret) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, secret); err != nil { // return false, err // } // // _, ok := secret.Data[jitTokenKey] // return ok, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // Eventually( // func() (string, error) { // pod := new(corev1.Pod) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return "", err // } // // return pod.Name, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(ephemeralRunner.Name)) // }) // // It("It should re-create pod on failure", func() { // pod := new(corev1.Pod) // Eventually(func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }).Should(BeEquivalentTo(true)) // // err := k8sClient.Delete(ctx, pod) // Expect(err).To(BeNil(), "failed to delete pod") // // pod = new(corev1.Pod) // Eventually(func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // }) // // It("It should clean up resources when deleted", func() { // // wait for pod to be created // pod := new(corev1.Pod) // Eventually(func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }).Should(BeEquivalentTo(true)) // // // create runner-linked pod // runnerLinkedPod := &corev1.Pod{ // ObjectMeta: metav1.ObjectMeta{ // Name: "test-runner-linked-pod", // Namespace: ephemeralRunner.Namespace, // Labels: map[string]string{ // "runner-pod": ephemeralRunner.Name, // }, // }, // Spec: corev1.PodSpec{ // Containers: []corev1.Container{ // { // Name: "runner-linked-container", // Image: "ubuntu:latest", // }, // }, // }, // } // // err := k8sClient.Create(ctx, runnerLinkedPod) // Expect(err).To(BeNil(), "failed to create runner linked pod") // Eventually( // func() (bool, error) { // pod := new(corev1.Pod) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: runnerLinkedPod.Name, Namespace: runnerLinkedPod.Namespace}, pod); err != nil { // return false, nil // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // // create runner linked secret // runnerLinkedSecret := &corev1.Secret{ // ObjectMeta: metav1.ObjectMeta{ // Name: "test-runner-linked-secret", // Namespace: ephemeralRunner.Namespace, // Labels: map[string]string{ // "runner-pod": ephemeralRunner.Name, // }, // }, // Data: map[string][]byte{"test": []byte("test")}, // } // // err = k8sClient.Create(ctx, runnerLinkedSecret) // Expect(err).To(BeNil(), "failed to create runner linked secret") // Eventually( // func() (bool, error) { // secret := new(corev1.Secret) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: runnerLinkedSecret.Name, Namespace: runnerLinkedSecret.Namespace}, secret); err != nil { // return false, nil // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // err = k8sClient.Delete(ctx, ephemeralRunner) // Expect(err).To(BeNil(), "failed to delete ephemeral runner") // // Eventually( // func() (bool, error) { // pod := new(corev1.Pod) // err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // Eventually( // func() (bool, error) { // secret := new(corev1.Secret) // err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, secret) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // Eventually( // func() (bool, error) { // pod := new(corev1.Pod) // err = k8sClient.Get(ctx, client.ObjectKey{Name: runnerLinkedPod.Name, Namespace: runnerLinkedPod.Namespace}, pod) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // Eventually( // func() (bool, error) { // secret := new(corev1.Secret) // err = k8sClient.Get(ctx, client.ObjectKey{Name: runnerLinkedSecret.Name, Namespace: runnerLinkedSecret.Namespace}, secret) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // Eventually( // func() (bool, error) { // updated := new(v1alpha1.EphemeralRunner) // err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // }) // // It("It should eventually have runner id set", func() { // Eventually( // func() (int, error) { // updatedEphemeralRunner := new(v1alpha1.EphemeralRunner) // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updatedEphemeralRunner) // if err != nil { // return 0, err // } // return updatedEphemeralRunner.Status.RunnerId, nil // }, // timeout, // interval, // ).Should(BeNumerically(">", 0)) // }) // // It("It should patch the ephemeral runner non terminating status", func() { // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // for _, phase := range []corev1.PodPhase{corev1.PodRunning, corev1.PodPending} { // podCopy := pod.DeepCopy() // pod.Status.Phase = phase // // set container state to force status update // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{}, // }) // err := k8sClient.Status().Patch(ctx, pod, client.MergeFrom(podCopy)) // Expect(err).To(BeNil(), "failed to patch pod status") // // Eventually( // func() (corev1.PodPhase, error) { // updated := new(v1alpha1.EphemeralRunner) // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return "", err // } // return updated.Status.Phase, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(phase)) // } // }) // // It("It should not update phase if container state does not exist", func() { // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // pod.Status.Phase = corev1.PodRunning // err := k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "failed to patch pod status") // // Consistently( // func() (corev1.PodPhase, error) { // updated := new(v1alpha1.EphemeralRunner) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated); err != nil { // return corev1.PodUnknown, err // } // return updated.Status.Phase, nil // }, // timeout, // ).Should(BeEquivalentTo("")) // }) // // It("It should not re-create pod indefinitely", func() { // updated := new(v1alpha1.EphemeralRunner) // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return false, err // } // // err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err != nil { // if kerrors.IsNotFound(err) && len(updated.Status.Failures) > 5 { // return true, nil // } // // return false, err // } // // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{ // Terminated: &corev1.ContainerStateTerminated{ // ExitCode: 1, // }, // }, // }) // err = k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "Failed to update pod status") // return false, fmt.Errorf("pod haven't failed for 5 times.") // }, // timeout, // interval, // ).Should(BeEquivalentTo(true), "we should stop creating pod after 5 failures") // // // In case we still have pod created due to controller-runtime cache delay, mark the container as exited // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err == nil { // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{ // Terminated: &corev1.ContainerStateTerminated{ // ExitCode: 1, // }, // }, // }) // err := k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "Failed to update pod status") // } // // // EphemeralRunner should failed with reason TooManyPodFailures // Eventually(func() (string, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return "", err // } // return updated.Status.Reason, nil // }, timeout, interval).Should(BeEquivalentTo("TooManyPodFailures"), "Reason should be TooManyPodFailures") // // // EphemeralRunner should not have any pod // Eventually(func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err == nil { // return false, nil // } // return kerrors.IsNotFound(err), nil // }, timeout, interval).Should(BeEquivalentTo(true)) // }) // // It("It should re-create pod on eviction", func() { // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // if err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // pod.Status.Phase = corev1.PodFailed // pod.Status.Reason = "Evicted" // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{}, // }) // err := k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "failed to patch pod status") // // updated := new(v1alpha1.EphemeralRunner) // Eventually(func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return false, err // } // return len(updated.Status.Failures) == 1, nil // }, timeout, interval).Should(BeEquivalentTo(true)) // // // should re-create after failure // Eventually( // func() (bool, error) { // pod := new(corev1.Pod) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // }) // // It("It should re-create pod on exit status 0, but runner exists within the service", func() { // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{ // Terminated: &corev1.ContainerStateTerminated{ // ExitCode: 0, // }, // }, // }) // err := k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "failed to update pod status") // // updated := new(v1alpha1.EphemeralRunner) // Eventually(func() (bool, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return false, err // } // return len(updated.Status.Failures) == 1, nil // }, timeout, interval).Should(BeEquivalentTo(true)) // // // should re-create after failure // Eventually( // func() (bool, error) { // pod := new(corev1.Pod) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // }) // // It("It should not set the phase to succeeded without pod termination status", func() { // pod := new(corev1.Pod) // Eventually( // func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(true)) // // // first set phase to running // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{ // Running: &corev1.ContainerStateRunning{ // StartedAt: metav1.Now(), // }, // }, // }) // pod.Status.Phase = corev1.PodRunning // err := k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil()) // // Eventually( // func() (corev1.PodPhase, error) { // updated := new(v1alpha1.EphemeralRunner) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated); err != nil { // return "", err // } // return updated.Status.Phase, nil // }, // timeout, // interval, // ).Should(BeEquivalentTo(corev1.PodRunning)) // // // set phase to succeeded // pod.Status.Phase = corev1.PodSucceeded // err = k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil()) // // Consistently( // func() (corev1.PodPhase, error) { // updated := new(v1alpha1.EphemeralRunner) // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated); err != nil { // return "", err // } // return updated.Status.Phase, nil // }, // timeout, // ).Should(BeEquivalentTo(corev1.PodRunning)) // }) // }) // // Describe("Checking the API", func() { // var ctx context.Context // var autoscalingNS *corev1.Namespace // var configSecret *corev1.Secret // var controller *EphemeralRunnerReconciler // var mgr ctrl.Manager // // BeforeEach(func() { // ctx = context.Background() // autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient) // configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name) // // controller = &EphemeralRunnerReconciler{ // Client: mgr.GetClient(), // Scheme: mgr.GetScheme(), // Log: logf.Log, // ActionsClient: fake.NewMultiClient( // fake.WithDefaultClient( // fake.NewFakeClient( // fake.WithGetRunner( // nil, // &actions.ActionsError{ // StatusCode: http.StatusNotFound, // ExceptionName: "AgentNotFoundException", // }, // ), // ), // nil, // ), // ), // } // err := controller.SetupWithManager(mgr) // Expect(err).To(BeNil(), "failed to setup controller") // // startManagers(GinkgoT(), mgr) // }) // // It("It should set the Phase to Succeeded", func() { // ephemeralRunner := newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name) // // err := k8sClient.Create(ctx, ephemeralRunner) // Expect(err).To(BeNil()) // // pod := new(corev1.Pod) // Eventually(func() (bool, error) { // if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil { // return false, err // } // return true, nil // }, timeout, interval).Should(BeEquivalentTo(true)) // // pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{ // Name: EphemeralRunnerContainerName, // State: corev1.ContainerState{ // Terminated: &corev1.ContainerStateTerminated{ // ExitCode: 0, // }, // }, // }) // err = k8sClient.Status().Update(ctx, pod) // Expect(err).To(BeNil(), "failed to update pod status") // // updated := new(v1alpha1.EphemeralRunner) // Eventually(func() (corev1.PodPhase, error) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated) // if err != nil { // return "", nil // } // return updated.Status.Phase, nil // }, timeout, interval).Should(BeEquivalentTo(corev1.PodSucceeded)) // }) // }) // // Describe("Pod proxy config", func() { // var ctx context.Context // var mgr ctrl.Manager // var autoScalingNS *corev1.Namespace // var configSecret *corev1.Secret // var controller *EphemeralRunnerReconciler // // BeforeEach(func() { // ctx = context.Background() // autoScalingNS, mgr = createNamespace(GinkgoT(), k8sClient) // configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoScalingNS.Name) // // controller = &EphemeralRunnerReconciler{ // Client: mgr.GetClient(), // Scheme: mgr.GetScheme(), // Log: logf.Log, // ActionsClient: fake.NewMultiClient(), // } // err := controller.SetupWithManager(mgr) // Expect(err).To(BeNil(), "failed to setup controller") // // startManagers(GinkgoT(), mgr) // }) // // It("uses an actions client with proxy transport", func() { // // Use an actual client // controller.ActionsClient = actions.NewMultiClient("test", logr.Discard()) // // proxySuccessfulllyCalled := false // proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // header := r.Header.Get("Proxy-Authorization") // Expect(header).NotTo(BeEmpty()) // // header = strings.TrimPrefix(header, "Basic ") // decoded, err := base64.StdEncoding.DecodeString(header) // Expect(err).NotTo(HaveOccurred()) // Expect(string(decoded)).To(Equal("test:password")) // // proxySuccessfulllyCalled = true // w.WriteHeader(http.StatusOK) // })) // GinkgoT().Cleanup(func() { // proxy.Close() // }) // // secretCredentials := &corev1.Secret{ // ObjectMeta: metav1.ObjectMeta{ // Name: "proxy-credentials", // Namespace: autoScalingNS.Name, // }, // Data: map[string][]byte{ // "username": []byte("test"), // "password": []byte("password"), // }, // } // // err := k8sClient.Create(ctx, secretCredentials) // Expect(err).NotTo(HaveOccurred(), "failed to create secret credentials") // // ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name) // ephemeralRunner.Spec.GitHubConfigUrl = "http://example.com/org/repo" // ephemeralRunner.Spec.Proxy = &v1alpha1.ProxyConfig{ // HTTP: &v1alpha1.ProxyServerConfig{ // Url: proxy.URL, // CredentialSecretRef: "proxy-credentials", // }, // } // // err = k8sClient.Create(ctx, ephemeralRunner) // Expect(err).To(BeNil(), "failed to create ephemeral runner") // // Eventually( // func() bool { // return proxySuccessfulllyCalled // }, // 2*time.Second, // interval, // ).Should(BeEquivalentTo(true)) // }) // // It("It should create EphemeralRunner with proxy environment variables using ProxySecretRef", func() { // ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name) // ephemeralRunner.Spec.Proxy = &v1alpha1.ProxyConfig{ // HTTP: &v1alpha1.ProxyServerConfig{ // Url: "http://proxy.example.com:8080", // }, // HTTPS: &v1alpha1.ProxyServerConfig{ // Url: "http://proxy.example.com:8080", // }, // NoProxy: []string{"example.com"}, // } // ephemeralRunner.Spec.ProxySecretRef = "proxy-secret" // err := k8sClient.Create(ctx, ephemeralRunner) // Expect(err).To(BeNil(), "failed to create ephemeral runner") // // pod := new(corev1.Pod) // Eventually( // func(g Gomega) { // err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod) // g.Expect(err).To(BeNil(), "failed to get ephemeral runner pod") // }, // timeout, // interval, // ).Should(Succeed(), "failed to get ephemeral runner pod") // // Expect(pod.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ // Name: EnvVarHTTPProxy, // ValueFrom: &corev1.EnvVarSource{ // SecretKeyRef: &corev1.SecretKeySelector{ // LocalObjectReference: corev1.LocalObjectReference{ // Name: ephemeralRunner.Spec.ProxySecretRef, // }, // Key: "http_proxy", // }, // }, // })) // // Expect(pod.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ // Name: EnvVarHTTPSProxy, // ValueFrom: &corev1.EnvVarSource{ // SecretKeyRef: &corev1.SecretKeySelector{ // LocalObjectReference: corev1.LocalObjectReference{ // Name: ephemeralRunner.Spec.ProxySecretRef, // }, // Key: "https_proxy", // }, // }, // })) // // Expect(pod.Spec.Containers[0].Env).To(ContainElement(corev1.EnvVar{ // Name: EnvVarNoProxy, // ValueFrom: &corev1.EnvVarSource{ // SecretKeyRef: &corev1.SecretKeySelector{ // LocalObjectReference: corev1.LocalObjectReference{ // Name: ephemeralRunner.Spec.ProxySecretRef, // }, // Key: "no_proxy", // }, // }, // })) // }) // }) // // Describe("TLS config", func() { // var ctx context.Context // var mgr ctrl.Manager // var autoScalingNS *corev1.Namespace // var configSecret *corev1.Secret // var controller *EphemeralRunnerReconciler // var rootCAConfigMap *corev1.ConfigMap // // BeforeEach(func() { // ctx = context.Background() // autoScalingNS, mgr = createNamespace(GinkgoT(), k8sClient) // configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoScalingNS.Name) // // cert, err := os.ReadFile(filepath.Join( // "../../", // "github", // "actions", // "testdata", // "rootCA.crt", // )) // Expect(err).NotTo(HaveOccurred(), "failed to read root CA cert") // rootCAConfigMap = &corev1.ConfigMap{ // ObjectMeta: metav1.ObjectMeta{ // Name: "root-ca-configmap", // Namespace: autoScalingNS.Name, // }, // Data: map[string]string{ // "rootCA.crt": string(cert), // }, // } // err = k8sClient.Create(ctx, rootCAConfigMap) // Expect(err).NotTo(HaveOccurred(), "failed to create configmap with root CAs") // // controller = &EphemeralRunnerReconciler{ // Client: mgr.GetClient(), // Scheme: mgr.GetScheme(), // Log: logf.Log, // ActionsClient: fake.NewMultiClient(), // } // // err = controller.SetupWithManager(mgr) // Expect(err).To(BeNil(), "failed to setup controller") // // startManagers(GinkgoT(), mgr) // }) // // It("should be able to make requests to a server using root CAs", func() { // certsFolder := filepath.Join( // "../../", // "github", // "actions", // "testdata", // ) // certPath := filepath.Join(certsFolder, "server.crt") // keyPath := filepath.Join(certsFolder, "server.key") // // serverSuccessfullyCalled := false // server := testserver.NewUnstarted(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // serverSuccessfullyCalled = true // w.WriteHeader(http.StatusOK) // })) // cert, err := tls.LoadX509KeyPair(certPath, keyPath) // Expect(err).NotTo(HaveOccurred(), "failed to load server cert") // // server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}} // server.StartTLS() // // // Use an actual client // controller.ActionsClient = actions.NewMultiClient("test", logr.Discard()) // // ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name) // ephemeralRunner.Spec.GitHubConfigUrl = server.ConfigURLForOrg("my-org") // ephemeralRunner.Spec.GitHubServerTLS = &v1alpha1.GitHubServerTLSConfig{ // CertificateFrom: &v1alpha1.TLSCertificateSource{ // ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ // LocalObjectReference: corev1.LocalObjectReference{ // Name: rootCAConfigMap.Name, // }, // Key: "rootCA.crt", // }, // }, // } // // err = k8sClient.Create(ctx, ephemeralRunner) // Expect(err).To(BeNil(), "failed to create ephemeral runner") // // Eventually( // func() bool { // return serverSuccessfullyCalled // }, // 2*time.Second, // interval, // ).Should(BeTrue(), "failed to contact server") // }) // }) // })