mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 19:50:30 +00:00
Co-authored-by: Cory Miller <cory-miller@github.com> Co-authored-by: Nikola Jokic <nikola-jokic@github.com> Co-authored-by: Ava Stancu <AvaStancu@github.com> Co-authored-by: Ferenc Hammerl <fhammerl@github.com> Co-authored-by: Francesco Renzi <rentziass@github.com> Co-authored-by: Bassem Dghaidi <Link-@github.com>
130 lines
3.8 KiB
Go
130 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
|
jsonpatch "github.com/evanphx/json-patch"
|
|
"github.com/go-logr/logr"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/rest"
|
|
)
|
|
|
|
type AutoScalerKubernetesManager struct {
|
|
*kubernetes.Clientset
|
|
|
|
logger logr.Logger
|
|
}
|
|
|
|
func NewKubernetesManager(logger *logr.Logger) (*AutoScalerKubernetesManager, error) {
|
|
conf, err := rest.InClusterConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
kubeClient, err := kubernetes.NewForConfig(conf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var manager = &AutoScalerKubernetesManager{
|
|
Clientset: kubeClient,
|
|
logger: logger.WithName("KubernetesManager"),
|
|
}
|
|
return manager, nil
|
|
}
|
|
|
|
func (k *AutoScalerKubernetesManager) ScaleEphemeralRunnerSet(ctx context.Context, namespace, resourceName string, runnerCount int) error {
|
|
original := &v1alpha1.EphemeralRunnerSet{
|
|
Spec: v1alpha1.EphemeralRunnerSetSpec{
|
|
Replicas: -1,
|
|
},
|
|
}
|
|
originalJson, err := json.Marshal(original)
|
|
if err != nil {
|
|
k.logger.Error(err, "could not marshal empty ephemeral runner set")
|
|
}
|
|
|
|
patch := &v1alpha1.EphemeralRunnerSet{
|
|
Spec: v1alpha1.EphemeralRunnerSetSpec{
|
|
Replicas: runnerCount,
|
|
},
|
|
}
|
|
patchJson, err := json.Marshal(patch)
|
|
if err != nil {
|
|
k.logger.Error(err, "could not marshal patch ephemeral runner set")
|
|
}
|
|
mergePatch, err := jsonpatch.CreateMergePatch(originalJson, patchJson)
|
|
if err != nil {
|
|
k.logger.Error(err, "could not create merge patch json for ephemeral runner set")
|
|
}
|
|
|
|
k.logger.Info("Created merge patch json for EphemeralRunnerSet update", "json", string(mergePatch))
|
|
|
|
patchedEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{}
|
|
err = k.RESTClient().
|
|
Patch(types.MergePatchType).
|
|
Prefix("apis", "actions.github.com", "v1alpha1").
|
|
Namespace(namespace).
|
|
Resource("EphemeralRunnerSets").
|
|
Name(resourceName).
|
|
Body([]byte(mergePatch)).
|
|
Do(ctx).
|
|
Into(patchedEphemeralRunnerSet)
|
|
if err != nil {
|
|
return fmt.Errorf("could not patch ephemeral runner set , patch JSON: %s, error: %w", string(mergePatch), err)
|
|
}
|
|
|
|
k.logger.Info("Ephemeral runner set scaled.", "namespace", namespace, "name", resourceName, "replicas", patchedEphemeralRunnerSet.Spec.Replicas)
|
|
return nil
|
|
}
|
|
|
|
func (k *AutoScalerKubernetesManager) UpdateEphemeralRunnerWithJobInfo(ctx context.Context, namespace, resourceName, ownerName, repositoryName, jobWorkflowRef, jobDisplayName string, workflowRunId, jobRequestId int64) error {
|
|
original := &v1alpha1.EphemeralRunner{}
|
|
originalJson, err := json.Marshal(original)
|
|
if err != nil {
|
|
return fmt.Errorf("could not marshal empty ephemeral runner, error: %w", err)
|
|
}
|
|
|
|
patch := &v1alpha1.EphemeralRunner{
|
|
Status: v1alpha1.EphemeralRunnerStatus{
|
|
JobRequestId: jobRequestId,
|
|
JobRepositoryName: fmt.Sprintf("%s/%s", ownerName, repositoryName),
|
|
WorkflowRunId: workflowRunId,
|
|
JobWorkflowRef: jobWorkflowRef,
|
|
JobDisplayName: jobDisplayName,
|
|
},
|
|
}
|
|
patchedJson, err := json.Marshal(patch)
|
|
if err != nil {
|
|
return fmt.Errorf("could not marshal patched ephemeral runner, error: %w", err)
|
|
}
|
|
|
|
mergePatch, err := jsonpatch.CreateMergePatch(originalJson, patchedJson)
|
|
if err != nil {
|
|
k.logger.Error(err, "could not create merge patch json for ephemeral runner")
|
|
}
|
|
|
|
k.logger.Info("Created merge patch json for EphemeralRunner status update", "json", string(mergePatch))
|
|
|
|
patchedStatus := &v1alpha1.EphemeralRunner{}
|
|
err = k.RESTClient().
|
|
Patch(types.MergePatchType).
|
|
Prefix("apis", "actions.github.com", "v1alpha1").
|
|
Namespace(namespace).
|
|
Resource("EphemeralRunners").
|
|
Name(resourceName).
|
|
SubResource("status").
|
|
Body(mergePatch).
|
|
Do(ctx).
|
|
Into(patchedStatus)
|
|
if err != nil {
|
|
return fmt.Errorf("could not patch ephemeral runner status, patch JSON: %s, error: %w", string(mergePatch), err)
|
|
}
|
|
|
|
return nil
|
|
}
|