mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Implement finalizer
This commit is contained in:
@@ -38,9 +38,17 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
containerName = "runner"
|
containerName = "runner"
|
||||||
|
finalizerName = "runner.actions.summerwind.dev"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RegistrationToken struct {
|
type GitHubRunner struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitHubRegistrationToken struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
ExpiresAt string `json:"expires_at"`
|
ExpiresAt string `json:"expires_at"`
|
||||||
}
|
}
|
||||||
@@ -69,6 +77,48 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
|||||||
return ctrl.Result{}, client.IgnoreNotFound(err)
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runner.ObjectMeta.DeletionTimestamp.IsZero() {
|
||||||
|
finalizers, added := addFinalizer(runner.ObjectMeta.Finalizers)
|
||||||
|
|
||||||
|
if added {
|
||||||
|
newRunner := runner.DeepCopy()
|
||||||
|
newRunner.ObjectMeta.Finalizers = finalizers
|
||||||
|
|
||||||
|
if err := r.Update(ctx, newRunner); err != nil {
|
||||||
|
log.Error(err, "Failed to update runner")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finalizers, removed := removeFinalizer(runner.ObjectMeta.Finalizers)
|
||||||
|
|
||||||
|
if removed {
|
||||||
|
ok, err := r.unregisterRunner(ctx, runner.Spec.Repository, runner.Name)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err, "Failed to unregister runner")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
log.V(1).Info("Runner no longer exists on GitHub")
|
||||||
|
}
|
||||||
|
|
||||||
|
newRunner := runner.DeepCopy()
|
||||||
|
newRunner.ObjectMeta.Finalizers = finalizers
|
||||||
|
|
||||||
|
if err := r.Update(ctx, newRunner); err != nil {
|
||||||
|
log.Error(err, "Failed to update runner")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Removed runner from GitHub", "repository", runner.Spec.Repository)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
if !runner.IsRegisterable() {
|
if !runner.IsRegisterable() {
|
||||||
reg, err := r.newRegistration(ctx, runner.Spec.Repository)
|
reg, err := r.newRegistration(ctx, runner.Spec.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -190,8 +240,8 @@ func (r *RunnerReconciler) newRegistration(ctx context.Context, repo string) (v1
|
|||||||
return reg, err
|
return reg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RunnerReconciler) getRegistrationToken(ctx context.Context, repo string) (RegistrationToken, error) {
|
func (r *RunnerReconciler) getRegistrationToken(ctx context.Context, repo string) (GitHubRegistrationToken, error) {
|
||||||
var regToken RegistrationToken
|
var regToken GitHubRegistrationToken
|
||||||
|
|
||||||
req, err := r.GitHubClient.NewRequest("POST", fmt.Sprintf("/repos/%s/actions/runners/registration-token", repo), nil)
|
req, err := r.GitHubClient.NewRequest("POST", fmt.Sprintf("/repos/%s/actions/runners/registration-token", repo), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -210,6 +260,69 @@ func (r *RunnerReconciler) getRegistrationToken(ctx context.Context, repo string
|
|||||||
return regToken, nil
|
return regToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *RunnerReconciler) unregisterRunner(ctx context.Context, repo, name string) (bool, error) {
|
||||||
|
runners, err := r.listRunners(ctx, repo)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := 0
|
||||||
|
for _, runner := range runners {
|
||||||
|
if runner.Name == name {
|
||||||
|
id = runner.ID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if id == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.removeRunner(ctx, repo, id); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunnerReconciler) listRunners(ctx context.Context, repo string) ([]GitHubRunner, error) {
|
||||||
|
runners := []GitHubRunner{}
|
||||||
|
|
||||||
|
req, err := r.GitHubClient.NewRequest("GET", fmt.Sprintf("/repos/%s/actions/runners", repo), nil)
|
||||||
|
if err != nil {
|
||||||
|
return runners, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := r.GitHubClient.Do(ctx, req, &runners)
|
||||||
|
if err != nil {
|
||||||
|
return runners, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode != 200 {
|
||||||
|
return runners, fmt.Errorf("unexpected status: %d", res.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return runners, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RunnerReconciler) removeRunner(ctx context.Context, repo string, id int) error {
|
||||||
|
req, err := r.GitHubClient.NewRequest("DELETE", fmt.Sprintf("/repos/%s/actions/runners/%d", repo, id), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := r.GitHubClient.Do(ctx, req, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode != 204 {
|
||||||
|
return fmt.Errorf("unexpected status: %d", res.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
|
func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
|
||||||
var (
|
var (
|
||||||
privileged bool = true
|
privileged bool = true
|
||||||
@@ -297,3 +410,33 @@ func (r *RunnerReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||||||
Owns(&corev1.Pod{}).
|
Owns(&corev1.Pod{}).
|
||||||
Complete(r)
|
Complete(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addFinalizer(finalizers []string) ([]string, bool) {
|
||||||
|
exists := false
|
||||||
|
for _, name := range finalizers {
|
||||||
|
if name == finalizerName {
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
return finalizers, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(finalizers, finalizerName), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeFinalizer(finalizers []string) ([]string, bool) {
|
||||||
|
removed := false
|
||||||
|
result := []string{}
|
||||||
|
|
||||||
|
for _, name := range finalizers {
|
||||||
|
if name == finalizerName {
|
||||||
|
removed = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, removed
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user