runner-controller: do not delete runner if it is busy (#103)

Currently, after refreshing the token, the controller re-creates the runner with the new token. This results in jobs being interrupted. This PR makes sure the pod is not restarted if it is busy.

Closes #74
This commit is contained in:
Helder Moreira
2020-10-05 01:06:37 +01:00
committed by GitHub
parent 7b5e62e266
commit 7a2fa7fbce
16 changed files with 539 additions and 102 deletions

View File

@@ -14,8 +14,8 @@ const (
{
"total_count": 2,
"runners": [
{"id": 1, "name": "test1", "os": "linux", "status": "online"},
{"id": 2, "name": "test2", "os": "linux", "status": "offline"}
{"id": 1, "name": "test1", "os": "linux", "status": "online", "busy": false},
{"id": 2, "name": "test2", "os": "linux", "status": "offline", "busy": false}
]
}
`

74
github/fake/runners.go Normal file
View File

@@ -0,0 +1,74 @@
package fake
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strconv"
"github.com/google/go-github/v32/github"
"github.com/gorilla/mux"
)
type RunnersList struct {
runners []*github.Runner
}
func NewRunnersList() *RunnersList {
return &RunnersList{
runners: make([]*github.Runner, 0),
}
}
func (r *RunnersList) Add(runner *github.Runner) {
if !exists(r.runners, runner) {
r.runners = append(r.runners, runner)
}
}
func (r *RunnersList) GetServer() *httptest.Server {
router := mux.NewRouter()
router.Handle("/repos/{owner}/{repo}/actions/runners", r.handleList())
router.Handle("/repos/{owner}/{repo}/actions/runners/{id}", r.handleRemove())
router.Handle("/orgs/{org}/actions/runners", r.handleList())
router.Handle("/orgs/{org}/actions/runners/{id}", r.handleRemove())
return httptest.NewServer(router)
}
func (r *RunnersList) handleList() http.HandlerFunc {
return func(w http.ResponseWriter, res *http.Request) {
j, err := json.Marshal(github.Runners{
TotalCount: len(r.runners),
Runners: r.runners,
})
if err != nil {
panic(err)
}
w.WriteHeader(http.StatusOK)
w.Write(j)
}
}
func (r *RunnersList) handleRemove() http.HandlerFunc {
return func(w http.ResponseWriter, res *http.Request) {
vars := mux.Vars(res)
for i, runner := range r.runners {
if runner.ID != nil && vars["id"] == strconv.FormatInt(*runner.ID, 10) {
r.runners = append(r.runners[:i], r.runners[i+1:]...)
}
}
w.WriteHeader(http.StatusOK)
}
}
func exists(runners []*github.Runner, runner *github.Runner) bool {
for _, r := range runners {
if *r.Name == *runner.Name {
return true
}
}
return false
}

View File

@@ -9,7 +9,7 @@ import (
"time"
"github.com/bradleyfalzon/ghinstallation"
"github.com/google/go-github/v31/github"
"github.com/google/go-github/v32/github"
"golang.org/x/oauth2"
)
@@ -85,7 +85,7 @@ func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name strin
return rt, nil
}
// RemoveRunner removes a runner with specified runner ID from repocitory.
// RemoveRunner removes a runner with specified runner ID from repository.
func (c *Client) RemoveRunner(ctx context.Context, org, repo string, runnerID int64) error {
owner, repo, err := getOwnerAndRepo(org, repo)
@@ -121,7 +121,7 @@ func (c *Client) ListRunners(ctx context.Context, org, repo string) ([]*github.R
list, res, err := c.listRunners(ctx, owner, repo, &opts)
if err != nil {
return runners, fmt.Errorf("failed to remove runner: %v", err)
return runners, fmt.Errorf("failed to list runners: %v", err)
}
runners = append(runners, list.Runners...)

View File

@@ -10,7 +10,7 @@ import (
"net/url"
"reflect"
"github.com/google/go-github/v31/github"
"github.com/google/go-github/v32/github"
"github.com/google/go-querystring/query"
)

View File

@@ -7,7 +7,7 @@ import (
"testing"
"time"
"github.com/google/go-github/v31/github"
"github.com/google/go-github/v32/github"
"github.com/summerwind/actions-runner-controller/github/fake"
)
@@ -41,9 +41,9 @@ func TestGetRegistrationToken(t *testing.T) {
token string
err bool
}{
{org: "test", repo: "valid", token: fake.RegistrationToken, err: false},
{org: "test", repo: "invalid", token: "", err: true},
{org: "test", repo: "error", token: "", err: true},
{org: "", repo: "test/valid", token: fake.RegistrationToken, err: false},
{org: "", repo: "test/invalid", token: "", err: true},
{org: "", repo: "test/error", token: "", err: true},
{org: "test", repo: "", token: fake.RegistrationToken, err: false},
{org: "invalid", repo: "", token: "", err: true},
{org: "error", repo: "", token: "", err: true},
@@ -68,9 +68,9 @@ func TestListRunners(t *testing.T) {
length int
err bool
}{
{org: "test", repo: "valid", length: 2, err: false},
{org: "test", repo: "invalid", length: 0, err: true},
{org: "test", repo: "error", length: 0, err: true},
{org: "", repo: "test/valid", length: 2, err: false},
{org: "", repo: "test/invalid", length: 0, err: true},
{org: "", repo: "test/error", length: 0, err: true},
{org: "test", repo: "", length: 2, err: false},
{org: "invalid", repo: "", length: 0, err: true},
{org: "error", repo: "", length: 0, err: true},
@@ -94,9 +94,9 @@ func TestRemoveRunner(t *testing.T) {
repo string
err bool
}{
{org: "test", repo: "valid", err: false},
{org: "test", repo: "invalid", err: true},
{org: "test", repo: "error", err: true},
{org: "", repo: "test/valid", err: false},
{org: "", repo: "test/invalid", err: true},
{org: "", repo: "test/error", err: true},
{org: "test", repo: "", err: false},
{org: "invalid", repo: "", err: true},
{org: "error", repo: "", err: true},