diff --git a/controllers/runner_controller.go b/controllers/runner_controller.go index 7904be83..96d4463b 100644 --- a/controllers/runner_controller.go +++ b/controllers/runner_controller.go @@ -20,10 +20,8 @@ import ( "context" "fmt" "reflect" - "time" "github.com/go-logr/logr" - "github.com/google/go-github/v29/github" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" @@ -34,6 +32,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/summerwind/actions-runner-controller/api/v1alpha1" + "github.com/summerwind/actions-runner-controller/github" ) const ( @@ -41,23 +40,6 @@ const ( finalizerName = "runner.actions.summerwind.dev" ) -type GitHubRunnerList struct { - TotalCount int `json:"total_count"` - Runners []GitHubRunner `json:"runners,omitempty"` -} - -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"` - ExpiresAt string `json:"expires_at"` -} - // RunnerReconciler reconciles a Runner object type RunnerReconciler struct { client.Client @@ -126,7 +108,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } if !runner.IsRegisterable() { - reg, err := r.newRegistration(ctx, runner.Spec.Repository) + rt, err := r.GitHubClient.GetRegistrationToken(ctx, runner.Spec.Repository, runner.Name) if err != nil { r.Recorder.Event(&runner, corev1.EventTypeWarning, "FailedUpdateRegistrationToken", "Updating registration token failed") log.Error(err, "Failed to get new registration token") @@ -134,7 +116,11 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } updated := runner.DeepCopy() - updated.Status.Registration = reg + updated.Status.Registration = v1alpha1.RunnerStatusRegistration{ + Repository: runner.Spec.Repository, + Token: rt.GetToken(), + ExpiresAt: metav1.NewTime(rt.GetExpiresAt().Time), + } if err := r.Status().Update(ctx, updated); err != nil { log.Error(err, "Failed to update runner status") @@ -226,109 +212,31 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, nil } -func (r *RunnerReconciler) newRegistration(ctx context.Context, repo string) (v1alpha1.RunnerStatusRegistration, error) { - var reg v1alpha1.RunnerStatusRegistration - - rt, err := r.getRegistrationToken(ctx, repo) - if err != nil { - return reg, err - } - - expiresAt, err := time.Parse(time.RFC3339, rt.ExpiresAt) - if err != nil { - return reg, err - } - - reg.Repository = repo - reg.Token = rt.Token - reg.ExpiresAt = metav1.NewTime(expiresAt) - - return reg, err -} - -func (r *RunnerReconciler) getRegistrationToken(ctx context.Context, repo string) (GitHubRegistrationToken, error) { - var regToken GitHubRegistrationToken - - req, err := r.GitHubClient.NewRequest("POST", fmt.Sprintf("/repos/%s/actions/runners/registration-token", repo), nil) - if err != nil { - return regToken, err - } - - res, err := r.GitHubClient.Do(ctx, req, ®Token) - if err != nil { - return regToken, err - } - - if res.StatusCode != 201 { - return regToken, fmt.Errorf("unexpected status: %d", res.StatusCode) - } - - return regToken, nil -} - func (r *RunnerReconciler) unregisterRunner(ctx context.Context, repo, name string) (bool, error) { - runners, err := r.listRunners(ctx, repo) + runners, err := r.GitHubClient.ListRunners(ctx, repo) if err != nil { return false, err } - id := 0 - for _, runner := range runners.Runners { - if runner.Name == name { - id = runner.ID + id := int64(0) + for _, runner := range runners { + if runner.GetName() == name { + id = runner.GetID() break } } - if id == 0 { + if id == int64(0) { return false, nil } - if err := r.removeRunner(ctx, repo, id); err != nil { + if err := r.GitHubClient.RemoveRunner(ctx, repo, id); err != nil { return false, err } return true, nil } -func (r *RunnerReconciler) listRunners(ctx context.Context, repo string) (GitHubRunnerList, error) { - runners := GitHubRunnerList{} - - 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) { var ( privileged bool = true diff --git a/go.mod b/go.mod index 62843417..342f99a2 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,14 @@ module github.com/summerwind/actions-runner-controller go 1.13 require ( - github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect - github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect github.com/bradleyfalzon/ghinstallation v1.1.1 github.com/davecgh/go-spew v1.1.1 github.com/go-logr/logr v0.1.0 - github.com/google/go-github v17.0.0+incompatible - github.com/google/go-github/v29 v29.0.3 + github.com/google/go-github/v31 v31.0.0 github.com/onsi/ginkgo v1.8.0 github.com/onsi/gomega v1.5.0 - github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 + github.com/stretchr/testify v1.4.0 // indirect golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 - gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect k8s.io/api v0.0.0-20190918155943-95b840bb6a1f k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655 k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90 diff --git a/go.sum b/go.sum index 4f99be54..9c79b86d 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,6 @@ github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -120,12 +116,10 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts= github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= -github.com/google/go-github/v29 v29.0.3 h1:IktKCTwU//aFHnpA+2SLIi7Oo9uhAzgsdZNbcAqhgdc= -github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= +github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo= +github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -237,6 +231,7 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -343,8 +338,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= diff --git a/main.go b/main.go index d4ba7647..8a58de3d 100644 --- a/main.go +++ b/main.go @@ -17,18 +17,14 @@ limitations under the License. package main import ( - "context" "flag" "fmt" - "net/http" "os" "strconv" - "github.com/bradleyfalzon/ghinstallation" - "github.com/google/go-github/v29/github" actionsv1alpha1 "github.com/summerwind/actions-runner-controller/api/v1alpha1" "github.com/summerwind/actions-runner-controller/controllers" - "golang.org/x/oauth2" + "github.com/summerwind/actions-runner-controller/github" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" @@ -56,6 +52,9 @@ func init() { func main() { var ( + err error + ghClient *github.Client + metricsAddr string enableLeaderElection bool @@ -66,8 +65,6 @@ func main() { ghAppID int64 ghAppInstallationID int64 ghAppPrivateKey string - - ghClient *github.Client ) flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") @@ -111,17 +108,17 @@ func main() { os.Exit(1) } - tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, ghAppID, ghAppInstallationID, ghAppPrivateKey) + ghClient, err = github.NewClient(ghAppID, ghAppInstallationID, ghAppPrivateKey) if err != nil { - fmt.Fprintf(os.Stderr, "Error: Invalid GitHub App credentials: %v\n", err) + fmt.Fprintf(os.Stderr, "Error: Failed to create GitHub client: %v\n", err) os.Exit(1) } - ghClient = github.NewClient(&http.Client{Transport: tr}) } else if ghToken != "" { - tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: ghToken}, - )) - ghClient = github.NewClient(tc) + ghClient, err = github.NewClientWithAccessToken(ghToken) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to create GitHub client: %v\n", err) + os.Exit(1) + } } else { fmt.Fprintln(os.Stderr, "Error: GitHub App credentials or personal access token must be specified.") os.Exit(1)