Adding parameter to configure the runner set name. (#2279)

Co-authored-by: TingluoHuang <TingluoHuang@github.com>
This commit is contained in:
Chris Patterson
2023-03-03 08:36:14 -05:00
committed by GitHub
parent 00996ec799
commit 41f2ca3ed9
10 changed files with 252 additions and 7 deletions

View File

@@ -99,6 +99,7 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
}
log.Info("Successfully removed finalizer after cleanup")
return ctrl.Result{}, nil
}
if !controllerutil.ContainsFinalizer(autoscalingListener, autoscalingListenerFinalizerName) {

View File

@@ -46,6 +46,7 @@ const (
LabelKeyRunnerSpecHash = "runner-spec-hash"
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
runnerScaleSetIdKey = "runner-scale-set-id"
runnerScaleSetNameKey = "runner-scale-set-name"
runnerScaleSetRunnerGroupNameKey = "runner-scale-set-runner-group-name"
)
@@ -123,6 +124,7 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
}
log.Info("Successfully removed finalizer after cleanup")
return ctrl.Result{}, nil
}
if !controllerutil.ContainsFinalizer(autoscalingRunnerSet, autoscalingRunnerSetFinalizerName) {
@@ -158,6 +160,13 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
}
// Make sure the runner scale set name is up to date
currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameKey]
if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) {
log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.")
return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log)
}
secret := new(corev1.Secret)
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingRunnerSet.Namespace, Name: autoscalingRunnerSet.Spec.GitHubConfigSecret}, secret); err != nil {
log.Error(err, "Failed to find GitHub config secret.",
@@ -297,11 +306,14 @@ func (r *AutoscalingRunnerSetReconciler) deleteEphemeralRunnerSets(ctx context.C
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
logger.Info("Creating a new runner scale set")
actionsClient, err := r.actionsClientFor(ctx, autoscalingRunnerSet)
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
autoscalingRunnerSet.Spec.RunnerScaleSetName = autoscalingRunnerSet.Name
}
if err != nil {
logger.Error(err, "Failed to initialize Actions service client for creating a new runner scale set")
return ctrl.Result{}, err
}
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, autoscalingRunnerSet.Name)
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, autoscalingRunnerSet.Spec.RunnerScaleSetName)
if err != nil {
logger.Error(err, "Failed to get runner scale set from Actions service")
return ctrl.Result{}, err
@@ -322,11 +334,11 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
runnerScaleSet, err = actionsClient.CreateRunnerScaleSet(
ctx,
&actions.RunnerScaleSet{
Name: autoscalingRunnerSet.Name,
Name: autoscalingRunnerSet.Spec.RunnerScaleSetName,
RunnerGroupId: runnerGroupId,
Labels: []actions.Label{
{
Name: autoscalingRunnerSet.Name,
Name: autoscalingRunnerSet.Spec.RunnerScaleSetName,
Type: "System",
},
},
@@ -346,16 +358,20 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
autoscalingRunnerSet.Annotations = map[string]string{}
}
logger.Info("Adding runner scale set ID and runner group name as an annotation")
logger.Info("Adding runner scale set ID, name and runner group name as an annotation")
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[runnerScaleSetNameKey] = runnerScaleSet.Name
obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id)
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName
}); err != nil {
logger.Error(err, "Failed to add runner scale set ID and runner group name as an annotation")
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
return ctrl.Result{}, err
}
logger.Info("Updated with runner scale set ID and runner group name as an annotation")
logger.Info("Updated with runner scale set ID, name and runner group name as an annotation",
"id", runnerScaleSet.Id,
"name", runnerScaleSet.Name,
"runnerGroupName", runnerScaleSet.RunnerGroupName)
return ctrl.Result{}, nil
}
@@ -383,7 +399,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
runnerGroupId = int(runnerGroup.ID)
}
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{Name: autoscalingRunnerSet.Name, RunnerGroupId: runnerGroupId})
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{RunnerGroupId: runnerGroupId})
if err != nil {
logger.Error(err, "Failed to update runner scale set", "runnerScaleSetId", runnerScaleSetId)
return ctrl.Result{}, err
@@ -401,6 +417,42 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
return ctrl.Result{}, nil
}
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
if err != nil {
logger.Error(err, "Failed to parse runner scale set ID")
return ctrl.Result{}, err
}
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
logger.Info("Runner scale set name is not specified, skipping")
return ctrl.Result{}, nil
}
actionsClient, err := r.actionsClientFor(ctx, autoscalingRunnerSet)
if err != nil {
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
return ctrl.Result{}, err
}
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{Name: autoscalingRunnerSet.Spec.RunnerScaleSetName})
if err != nil {
logger.Error(err, "Failed to update runner scale set", "runnerScaleSetId", runnerScaleSetId)
return ctrl.Result{}, err
}
logger.Info("Updating runner scale set name as an annotation")
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[runnerScaleSetNameKey] = updatedRunnerScaleSet.Name
}); err != nil {
logger.Error(err, "Failed to update runner scale set name annotation")
return ctrl.Result{}, err
}
logger.Info("Updated runner scale set with match name", "name", updatedRunnerScaleSet.Name)
return ctrl.Result{}, nil
}
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
logger.Info("Deleting the runner scale set from Actions service")
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])

View File

@@ -400,6 +400,129 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
})
})
var _ = Describe("Test AutoScalingController updates", func() {
Context("Creating autoscaling runner set with RunnerScaleSetName set", func() {
var ctx context.Context
var mgr ctrl.Manager
var autoscalingNS *corev1.Namespace
var autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet
var configSecret *corev1.Secret
BeforeEach(func() {
ctx = context.Background()
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
controller := &AutoscalingRunnerSetReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: logf.Log,
ControllerNamespace: autoscalingNS.Name,
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
ActionsClient: fake.NewMultiClient(
fake.WithDefaultClient(
fake.NewFakeClient(
fake.WithUpdateRunnerScaleSet(
&actions.RunnerScaleSet{
Id: 1,
Name: "testset_update",
RunnerGroupId: 1,
RunnerGroupName: "testgroup",
Labels: []actions.Label{{Type: "test", Name: "test"}},
RunnerSetting: actions.RunnerSetting{},
CreatedOn: time.Now(),
RunnerJitConfigUrl: "test.test.test",
Statistics: nil,
},
nil,
),
),
nil,
),
),
}
err := controller.SetupWithManager(mgr)
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
startManagers(GinkgoT(), mgr)
})
It("It should be create AutoScalingRunnerSet and has annotation for the RunnerScaleSetName", func() {
min := 1
max := 10
autoscalingRunnerSet = &v1alpha1.AutoscalingRunnerSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-asrs",
Namespace: autoscalingNS.Name,
},
Spec: v1alpha1.AutoscalingRunnerSetSpec{
GitHubConfigUrl: "https://github.com/owner/repo",
GitHubConfigSecret: configSecret.Name,
MaxRunners: &max,
MinRunners: &min,
RunnerScaleSetName: "testset",
RunnerGroup: "testgroup",
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "runner",
Image: "ghcr.io/actions/runner",
},
},
},
},
},
}
err := k8sClient.Create(ctx, autoscalingRunnerSet)
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
// Wait for the AutoScalingRunnerSet to be created with right annotation
ars := new(v1alpha1.AutoscalingRunnerSet)
Eventually(
func() (string, error) {
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, ars)
if err != nil {
return "", err
}
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
return val, nil
}
return "", nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(autoscalingRunnerSet.Spec.RunnerScaleSetName), "AutoScalingRunnerSet should have annotation for the RunnerScaleSetName")
update := autoscalingRunnerSet.DeepCopy()
update.Spec.RunnerScaleSetName = "testset_update"
err = k8sClient.Patch(ctx, update, client.MergeFrom(autoscalingRunnerSet))
Expect(err).NotTo(HaveOccurred(), "failed to update AutoScalingRunnerSet")
// Wait for the AutoScalingRunnerSet to be updated with right annotation
Eventually(
func() (string, error) {
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, ars)
if err != nil {
return "", err
}
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
return val, nil
}
return "", nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(update.Spec.RunnerScaleSetName), "AutoScalingRunnerSet should have a updated annotation for the RunnerScaleSetName")
})
})
})
var _ = Describe("Test AutoscalingController creation failures", func() {
Context("When autoscaling runner set creation fails on the client", func() {
var ctx context.Context