mirror of
https://github.com/actions-runner-controller/actions-runner-controller.git
synced 2026-10-09 18:15:49 +02:00
Upgrade resources in-place, causing 1-1 mapping between autoscaling runner set and ephemeral runner set (#4516)
This commit is contained in:
@@ -17,11 +17,14 @@ limitations under the License.
|
||||
package actionsgithubcom
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
||||
@@ -32,7 +35,6 @@ import (
|
||||
"go.uber.org/multierr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
@@ -42,17 +44,16 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ephemeralRunnerSetFinalizerName = "ephemeralrunner.actions.github.com/finalizer"
|
||||
// EphemeralRunnerSetFinalizerName is the finalizer name used in EphemeralRunnerSet resource to protect the cleanup process of the child ephemeral runners and proxy secret.
|
||||
EphemeralRunnerSetFinalizerName = "ephemeralrunnerset.actions.github.com/finalizer"
|
||||
)
|
||||
|
||||
// EphemeralRunnerSetReconciler reconciles a EphemeralRunnerSet object
|
||||
type EphemeralRunnerSetReconciler struct {
|
||||
client.Client
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
PublishMetrics bool
|
||||
|
||||
ResourceBuilder
|
||||
}
|
||||
|
||||
@@ -77,19 +78,20 @@ type EphemeralRunnerSetReconciler struct {
|
||||
func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||
log := r.Log.WithValues("ephemeralrunnerset", req.NamespacedName)
|
||||
|
||||
ephemeralRunnerSet := new(v1alpha1.EphemeralRunnerSet)
|
||||
if err := r.Get(ctx, req.NamespacedName, ephemeralRunnerSet); err != nil {
|
||||
var ephemeralRunnerSet v1alpha1.EphemeralRunnerSet
|
||||
if err := r.Get(ctx, req.NamespacedName, &ephemeralRunnerSet); err != nil {
|
||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||
}
|
||||
original := ephemeralRunnerSet.DeepCopy()
|
||||
|
||||
// Requested deletion does not need reconciled.
|
||||
if !ephemeralRunnerSet.DeletionTimestamp.IsZero() {
|
||||
if !controllerutil.ContainsFinalizer(ephemeralRunnerSet, ephemeralRunnerSetFinalizerName) {
|
||||
if !controllerutil.ContainsFinalizer(&ephemeralRunnerSet, EphemeralRunnerSetFinalizerName) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
log.Info("Deleting resources")
|
||||
done, err := r.cleanUpEphemeralRunners(ctx, ephemeralRunnerSet, log)
|
||||
done, err := r.cleanUpEphemeralRunners(ctx, &ephemeralRunnerSet, log)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to clean up EphemeralRunners")
|
||||
return ctrl.Result{}, err
|
||||
@@ -99,25 +101,33 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
log.Info("Removing finalizer")
|
||||
if err := patch(ctx, r.Client, ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) {
|
||||
controllerutil.RemoveFinalizer(obj, ephemeralRunnerSetFinalizerName)
|
||||
}); err != nil && !kerrors.IsNotFound(err) {
|
||||
log.Error(err, "Failed to update ephemeral runner set with removed finalizer")
|
||||
done, err = r.cleanUpEphemeralRunnerSetProxySecret(ctx, &ephemeralRunnerSet, log)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to clean up EphemeralRunnerSet proxy secret")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
if !done {
|
||||
log.Info("Waiting for proxy secret to be deleted")
|
||||
return ctrl.Result{RequeueAfter: 1 * time.Second}, nil
|
||||
}
|
||||
|
||||
log.Info("Removing finalizer")
|
||||
if controllerutil.RemoveFinalizer(&ephemeralRunnerSet, EphemeralRunnerSetFinalizerName) {
|
||||
if err := r.Patch(ctx, &ephemeralRunnerSet, client.MergeFrom(original)); err != nil {
|
||||
log.Error(err, "Failed to update ephemeral runner set with removed finalizer")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Successfully removed finalizer after cleanup")
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Add finalizer if not present
|
||||
if !controllerutil.ContainsFinalizer(ephemeralRunnerSet, ephemeralRunnerSetFinalizerName) {
|
||||
if controllerutil.AddFinalizer(&ephemeralRunnerSet, EphemeralRunnerSetFinalizerName) {
|
||||
log.Info("Adding finalizer")
|
||||
if err := patch(ctx, r.Client, ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) {
|
||||
controllerutil.AddFinalizer(obj, ephemeralRunnerSetFinalizerName)
|
||||
}); err != nil {
|
||||
log.Error(err, "Failed to update ephemeral runner set with finalizer added")
|
||||
if err := r.Patch(ctx, &ephemeralRunnerSet, client.MergeFrom(original)); err != nil {
|
||||
log.Error(err, "Failed to update ephemeral runner set with new finalizer")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
@@ -125,34 +135,57 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
if ephemeralRunnerSet.Status.Phase == v1alpha1.EphemeralRunnerSetPhaseOutdated {
|
||||
log.Info("ephemeral runner set is outdated, waiting for autoscaling runner set to remove it")
|
||||
// If hash spec has changed, delete idle ephemeral runners
|
||||
// in order to apply the change to the runners that did not yet receive a job.
|
||||
ephemeralRunnerIntegrityHash := ephemeralRunnerSetIntegrityHash(&ephemeralRunnerSet)
|
||||
if ephemeralRunnerSet.Annotations[annotationKeyIntegrityHash] != ephemeralRunnerIntegrityHash {
|
||||
log.Info("EphemeralRunnerSpec has changed, deleting idle ephemeral runners to apply the new spec")
|
||||
if _, err := r.cleanUpEphemeralRunners(ctx, &ephemeralRunnerSet, log); err != nil {
|
||||
log.Error(err, "Failed to clean up EphemeralRunners")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
if _, _, err := r.reconcileEphemeralRunnerSetProxySecret(ctx, &ephemeralRunnerSet, log); err != nil {
|
||||
log.Error(err, "Failed to update EphemeralRunnerSet proxy secret")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
log.Info("Updating EphemeralRunnerSet with new spec hash")
|
||||
original := ephemeralRunnerSet.DeepCopy()
|
||||
if ephemeralRunnerSet.Annotations == nil {
|
||||
ephemeralRunnerSet.Annotations = make(map[string]string)
|
||||
}
|
||||
ephemeralRunnerSet.Annotations[annotationKeyIntegrityHash] = ephemeralRunnerIntegrityHash
|
||||
if err := r.Patch(ctx, &ephemeralRunnerSet, client.MergeFrom(original)); err != nil {
|
||||
log.Error(err, "Failed to update ephemeral runner set with new spec hash")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
log.Info("Updated ephemeral runner set with new spec hash")
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Create proxy secret if not present
|
||||
if ephemeralRunnerSet.Spec.EphemeralRunnerSpec.Proxy != nil {
|
||||
proxySecret := new(corev1.Secret)
|
||||
if err := r.Get(ctx, types.NamespacedName{Namespace: ephemeralRunnerSet.Namespace, Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet)}, proxySecret); err != nil {
|
||||
if !kerrors.IsNotFound(err) {
|
||||
log.Error(err, "Unable to get ephemeralRunnerSet proxy secret", "namespace", ephemeralRunnerSet.Namespace, "name", proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet))
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
// Create a compiled secret for the runner pods in the runnerset namespace
|
||||
log.Info("Creating a ephemeralRunnerSet proxy secret for the runner pods")
|
||||
if err := r.createProxySecret(ctx, ephemeralRunnerSet, log); err != nil {
|
||||
log.Error(err, "Unable to create ephemeralRunnerSet proxy secret", "namespace", ephemeralRunnerSet.Namespace, "set-name", ephemeralRunnerSet.Name)
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
if ephemeralRunnerSet.Status.Phase == v1alpha1.EphemeralRunnerSetPhaseOutdated {
|
||||
if _, err := r.cleanUpEphemeralRunners(ctx, &ephemeralRunnerSet, log); err != nil {
|
||||
log.Error(err, "Failed to clean up EphemeralRunners")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
// Create or update proxy secret if needed
|
||||
if _, updated, err := r.reconcileEphemeralRunnerSetProxySecret(ctx, &ephemeralRunnerSet, log); err != nil {
|
||||
log.Error(err, "Unable to reconcile ephemeralRunnerSet proxy secret", "namespace", ephemeralRunnerSet.Namespace, "name", proxyEphemeralRunnerSetSecretName(&ephemeralRunnerSet))
|
||||
return ctrl.Result{}, err
|
||||
} else if updated {
|
||||
return ctrl.Result{RequeueAfter: 1 * time.Second}, nil
|
||||
}
|
||||
|
||||
// Find all EphemeralRunner with matching namespace and own by this EphemeralRunnerSet.
|
||||
ephemeralRunnerList := new(v1alpha1.EphemeralRunnerList)
|
||||
var ephemeralRunnerList v1alpha1.EphemeralRunnerList
|
||||
if err := r.List(
|
||||
ctx,
|
||||
ephemeralRunnerList,
|
||||
&ephemeralRunnerList,
|
||||
client.InNamespace(req.Namespace),
|
||||
client.MatchingFields{resourceOwnerKey: req.Name},
|
||||
); err != nil {
|
||||
@@ -160,9 +193,10 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
ephemeralRunnersByState := newEphemeralRunnersByStates(ephemeralRunnerList)
|
||||
ephemeralRunnersByState := newEphemeralRunnersByStates(&ephemeralRunnerList)
|
||||
|
||||
log.Info("Ephemeral runner counts",
|
||||
log.Info(
|
||||
"Ephemeral runner counts",
|
||||
"outdated", len(ephemeralRunnersByState.outdated),
|
||||
"pending", len(ephemeralRunnersByState.pending),
|
||||
"running", len(ephemeralRunnersByState.running),
|
||||
@@ -172,7 +206,7 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
)
|
||||
|
||||
if r.PublishMetrics {
|
||||
githubConfigURL := ephemeralRunnerSet.Spec.EphemeralRunnerSpec.GitHubConfigUrl
|
||||
githubConfigURL := ephemeralRunnerSet.Spec.EphemeralRunnerSpec.GitHubConfigURL
|
||||
parsedURL, err := actions.ParseGitHubConfigFromURL(githubConfigURL)
|
||||
if err != nil {
|
||||
log.Error(err, "Github Config URL is invalid", "URL", githubConfigURL)
|
||||
@@ -206,7 +240,7 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
case total < ephemeralRunnerSet.Spec.Replicas: // Handle scale up
|
||||
count := ephemeralRunnerSet.Spec.Replicas - total
|
||||
log.Info("Creating new ephemeral runners (scale up)", "count", count)
|
||||
if err := r.createEphemeralRunners(ctx, ephemeralRunnerSet, count, log); err != nil {
|
||||
if err := r.createEphemeralRunners(ctx, &ephemeralRunnerSet, count, log); err != nil {
|
||||
log.Error(err, "failed to make ephemeral runner")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
@@ -221,7 +255,7 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
log.Info("Deleting ephemeral runners (scale down)", "count", count)
|
||||
if err := r.deleteIdleEphemeralRunners(
|
||||
ctx,
|
||||
ephemeralRunnerSet,
|
||||
&ephemeralRunnerSet,
|
||||
ephemeralRunnersByState.pending,
|
||||
ephemeralRunnersByState.running,
|
||||
count,
|
||||
@@ -233,10 +267,11 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl.Result{}, r.updateStatus(ctx, ephemeralRunnerSet, ephemeralRunnersByState, log)
|
||||
return ctrl.Result{}, r.updateStatus(ctx, &ephemeralRunnerSet, ephemeralRunnersByState, log)
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerSetReconciler) updateStatus(ctx context.Context, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, state *ephemeralRunnersByState, log logr.Logger) error {
|
||||
original := ephemeralRunnerSet.DeepCopy()
|
||||
total := state.scaleTotal()
|
||||
var phase v1alpha1.EphemeralRunnerSetPhase
|
||||
switch {
|
||||
@@ -257,15 +292,13 @@ func (r *EphemeralRunnerSetReconciler) updateStatus(ctx context.Context, ephemer
|
||||
|
||||
// Update the status if needed.
|
||||
if ephemeralRunnerSet.Status != desiredStatus {
|
||||
log.Info("Updating status with current runners count", "count", total)
|
||||
ephemeralRunnerSet := ephemeralRunnerSet.DeepCopy()
|
||||
ephemeralRunnerSet.Status.CurrentReplicas = -1 // ALWAYS update current replicas
|
||||
if err := patchSubResource(ctx, r.Status(), ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) {
|
||||
obj.Status = desiredStatus
|
||||
}); err != nil {
|
||||
log.Error(err, "Failed to update status with current runners count")
|
||||
ephemeralRunnerSet.Status = desiredStatus
|
||||
if err := r.Status().Patch(ctx, ephemeralRunnerSet, client.MergeFrom(original)); err != nil {
|
||||
log.Error(err, "Failed to update EphemeralRunnerSet status")
|
||||
return err
|
||||
}
|
||||
log.Info("Updated EphemeralRunnerSet status", "status", ephemeralRunnerSet.Status)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -323,7 +356,8 @@ func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunners(ctx context.Conte
|
||||
|
||||
ephemeralRunnerState := newEphemeralRunnersByStates(ephemeralRunnerList)
|
||||
|
||||
log.Info("Clean up runner counts",
|
||||
log.Info(
|
||||
"Clean up runner counts",
|
||||
"pending", len(ephemeralRunnerState.pending),
|
||||
"running", len(ephemeralRunnerState.running),
|
||||
"finished", len(ephemeralRunnerState.finished),
|
||||
@@ -359,7 +393,7 @@ func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunners(ctx context.Conte
|
||||
|
||||
log.Info("Cleanup pending or running ephemeral runners")
|
||||
errs = errs[0:0]
|
||||
for _, ephemeralRunner := range append(ephemeralRunnerState.pending, ephemeralRunnerState.running...) {
|
||||
for _, ephemeralRunner := range ephemeralRunnerState.pending {
|
||||
log.Info("Removing the ephemeral runner from the service", "name", ephemeralRunner.Name)
|
||||
_, err := r.deleteEphemeralRunnerWithActionsClient(ctx, ephemeralRunner, actionsClient, log)
|
||||
if err != nil {
|
||||
@@ -367,6 +401,24 @@ func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunners(ctx context.Conte
|
||||
}
|
||||
}
|
||||
|
||||
for _, ephemeralRunner := range ephemeralRunnerState.running {
|
||||
if ephemeralRunner.HasJob() {
|
||||
log.Info(
|
||||
"Skipping ephemeral runner since it is running a job",
|
||||
"name", ephemeralRunner.Name,
|
||||
"workflowRunId", ephemeralRunner.Status.WorkflowRunID,
|
||||
"jobId", ephemeralRunner.Status.JobID,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info("Removing the idle ephemeral runner from the service", "name", ephemeralRunner.Name)
|
||||
_, err := r.deleteEphemeralRunnerWithActionsClient(ctx, ephemeralRunner, actionsClient, log)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
mergedErrs := multierr.Combine(errs...)
|
||||
log.Error(mergedErrs, "Failed to remove ephemeral runners from the service")
|
||||
@@ -376,22 +428,124 @@ func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunners(ctx context.Conte
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerSetReconciler) cleanUpEphemeralRunnerSetProxySecret(ctx context.Context, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, log logr.Logger) (done bool, err error) {
|
||||
if ephemeralRunnerSet.Spec.EphemeralRunnerSpec.Proxy == nil {
|
||||
return true, nil
|
||||
}
|
||||
var proxySecret corev1.Secret
|
||||
err = r.Get(
|
||||
ctx,
|
||||
types.NamespacedName{
|
||||
Namespace: ephemeralRunnerSet.Namespace,
|
||||
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||
},
|
||||
&proxySecret,
|
||||
)
|
||||
switch {
|
||||
case err == nil:
|
||||
log.Info("Deleting proxy secret")
|
||||
if err := r.Delete(ctx, &proxySecret); err != nil && !kerrors.IsNotFound(err) {
|
||||
log.Error(err, "Failed to delete proxy secret")
|
||||
return false, err
|
||||
}
|
||||
log.Info("Deleted proxy secret")
|
||||
return false, nil
|
||||
case kerrors.IsNotFound(err):
|
||||
log.Info("Proxy secret already deleted")
|
||||
return true, nil
|
||||
default:
|
||||
log.Error(
|
||||
err,
|
||||
"Unable to get ephemeralRunnerSet proxy secret",
|
||||
"namespace",
|
||||
ephemeralRunnerSet.Namespace,
|
||||
"name",
|
||||
proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||
)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerSetReconciler) reconcileEphemeralRunnerSetProxySecret(ctx context.Context, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, log logr.Logger) (secret *corev1.Secret, updated bool, err error) {
|
||||
if ephemeralRunnerSet.Spec.EphemeralRunnerSpec.Proxy == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
var proxySecret corev1.Secret
|
||||
err = r.Get(
|
||||
ctx,
|
||||
types.NamespacedName{
|
||||
Namespace: ephemeralRunnerSet.Namespace,
|
||||
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||
},
|
||||
&proxySecret,
|
||||
)
|
||||
switch {
|
||||
case err == nil:
|
||||
proxySecretData, err := ephemeralRunnerSet.Spec.EphemeralRunnerSpec.Proxy.ToSecretData(func(s string) (*corev1.Secret, error) {
|
||||
secret := new(corev1.Secret)
|
||||
err := r.Get(ctx, types.NamespacedName{Namespace: ephemeralRunnerSet.Namespace, Name: s}, secret)
|
||||
return secret, err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to convert proxy config to secret data: %w", err)
|
||||
}
|
||||
|
||||
desiredRunnerSetProxy, err := r.newEphemeralRunnerSetProxySecret(ephemeralRunnerSet, proxySecretData)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("failed to build desired ephemeralRunnerSet proxy secret: %w", err)
|
||||
}
|
||||
|
||||
updatedProxySecret := proxySecret.DeepCopy()
|
||||
var shouldUpdate bool
|
||||
if !maps.EqualFunc(proxySecret.Data, desiredRunnerSetProxy.Data, bytes.Equal) {
|
||||
updatedProxySecret.Data = desiredRunnerSetProxy.Data
|
||||
shouldUpdate = true
|
||||
}
|
||||
desiredLabels := r.filterAndMergeLabels(proxySecret.Labels, desiredRunnerSetProxy.Labels)
|
||||
if !maps.Equal(proxySecret.Labels, desiredLabels) {
|
||||
updatedProxySecret.Labels = desiredLabels
|
||||
shouldUpdate = true
|
||||
}
|
||||
desiredAnnotations := r.mergeAnnotations(proxySecret.Annotations, desiredRunnerSetProxy.Annotations)
|
||||
if !maps.Equal(proxySecret.Annotations, desiredAnnotations) {
|
||||
updatedProxySecret.Annotations = desiredAnnotations
|
||||
shouldUpdate = true
|
||||
}
|
||||
if shouldUpdate {
|
||||
log.Info("Updating ephemeralRunnerSet proxy secret")
|
||||
if err := r.Update(ctx, updatedProxySecret); err != nil {
|
||||
return nil, false, fmt.Errorf("failed to update ephemeralRunnerSet proxy secret: %w", err)
|
||||
}
|
||||
return updatedProxySecret, true, nil
|
||||
}
|
||||
return &proxySecret, false, nil
|
||||
case kerrors.IsNotFound(err):
|
||||
// Create a compiled secret for the runner pods in the runnerset namespace
|
||||
log.Info("Creating a ephemeralRunnerSet proxy secret for the runner pods")
|
||||
if err := r.createProxySecret(ctx, ephemeralRunnerSet, log); err != nil {
|
||||
return nil, false, fmt.Errorf("failed to create ephemeralRunnerSet proxy secret: %w", err)
|
||||
}
|
||||
return nil, false, nil
|
||||
default:
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
// createEphemeralRunners provisions `count` number of v1alpha1.EphemeralRunner resources in the cluster.
|
||||
func (r *EphemeralRunnerSetReconciler) createEphemeralRunners(ctx context.Context, runnerSet *v1alpha1.EphemeralRunnerSet, count int, log logr.Logger) error {
|
||||
// Track multiple errors at once and return the bundle.
|
||||
errs := make([]error, 0)
|
||||
for i := range count {
|
||||
ephemeralRunner := r.newEphemeralRunner(runnerSet)
|
||||
if runnerSet.Spec.EphemeralRunnerSpec.Proxy != nil {
|
||||
ephemeralRunner.Spec.ProxySecretRef = proxyEphemeralRunnerSetSecretName(runnerSet)
|
||||
}
|
||||
|
||||
// Make sure that we own the resource we create.
|
||||
if err := ctrl.SetControllerReference(runnerSet, ephemeralRunner, r.Scheme); err != nil {
|
||||
log.Error(err, "failed to set controller reference on ephemeral runner")
|
||||
ephemeralRunner, err := r.newEphemeralRunner(runnerSet)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to build ephemeral runner")
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
if runnerSet.Spec.EphemeralRunnerSpec.Proxy != nil {
|
||||
ephemeralRunner.Spec.ProxySecretRef = proxyEphemeralRunnerSetSecretName(runnerSet)
|
||||
}
|
||||
|
||||
log.Info("Creating new ephemeral runner", "progress", i+1, "total", count)
|
||||
if err := r.Create(ctx, ephemeralRunner); err != nil {
|
||||
@@ -416,21 +570,9 @@ func (r *EphemeralRunnerSetReconciler) createProxySecret(ctx context.Context, ep
|
||||
return fmt.Errorf("failed to convert proxy config to secret data: %w", err)
|
||||
}
|
||||
|
||||
runnerPodProxySecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||
Namespace: ephemeralRunnerSet.Namespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyGitHubScaleSetName: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName],
|
||||
LabelKeyGitHubScaleSetNamespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||
},
|
||||
},
|
||||
Data: proxySecretData,
|
||||
}
|
||||
|
||||
// Make sure that we own the resource we create.
|
||||
if err := ctrl.SetControllerReference(ephemeralRunnerSet, runnerPodProxySecret, r.Scheme); err != nil {
|
||||
log.Error(err, "failed to set controller reference on proxy secret")
|
||||
runnerPodProxySecret, err := r.newEphemeralRunnerSetProxySecret(ephemeralRunnerSet, proxySecretData)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to build proxy secret")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -523,6 +665,8 @@ func (r *EphemeralRunnerSetReconciler) deleteEphemeralRunnerWithActionsClient(ct
|
||||
|
||||
// SetupWithManager sets up the controller with the Manager.
|
||||
func (r *EphemeralRunnerSetReconciler) SetupWithManager(mgr ctrl.Manager, opts ...Option) error {
|
||||
r.setSchemeIfUnset(r.Scheme)
|
||||
|
||||
return builderWithOptions(
|
||||
ctrl.NewControllerManagedBy(mgr).
|
||||
For(&v1alpha1.EphemeralRunnerSet{}).
|
||||
|
||||
Reference in New Issue
Block a user