mirror of
https://github.com/actions-runner-controller/actions-runner-controller.git
synced 2026-10-04 04:01:40 +02:00
Remove network requests from actions.NewClient (#2219)
Co-authored-by: Nikola Jokic <jokicnikola07@gmail.com>
This commit is contained in:
co-authored by
Nikola Jokic
parent
cc26593a9b
commit
df12e00c9e
+190
-365
@@ -12,9 +12,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -62,17 +60,17 @@ type Client struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// TODO: Convert to unexported fields once refactor of Listener is complete
|
||||
ActionsServiceAdminToken *string
|
||||
ActionsServiceAdminTokenExpiresAt *time.Time
|
||||
ActionsServiceURL *string
|
||||
ActionsServiceAdminToken string
|
||||
ActionsServiceAdminTokenExpiresAt time.Time
|
||||
ActionsServiceURL string
|
||||
|
||||
retryMax int
|
||||
retryWaitMax time.Duration
|
||||
|
||||
creds *ActionsAuth
|
||||
githubConfigURL string
|
||||
logger logr.Logger
|
||||
userAgent string
|
||||
creds *ActionsAuth
|
||||
config *GitHubConfig
|
||||
logger logr.Logger
|
||||
userAgent string
|
||||
|
||||
rootCAs *x509.CertPool
|
||||
tlsInsecureSkipVerify bool
|
||||
@@ -116,11 +114,16 @@ func WithoutTLSVerify() ClientOption {
|
||||
}
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth, options ...ClientOption) (ActionsService, error) {
|
||||
func NewClient(githubConfigURL string, creds *ActionsAuth, options ...ClientOption) (*Client, error) {
|
||||
config, err := ParseGitHubConfigFromURL(githubConfigURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse githubConfigURL: %w", err)
|
||||
}
|
||||
|
||||
ac := &Client{
|
||||
creds: creds,
|
||||
githubConfigURL: githubConfigURL,
|
||||
logger: logr.Discard(),
|
||||
creds: creds,
|
||||
config: config,
|
||||
logger: logr.Discard(),
|
||||
|
||||
// retryablehttp defaults
|
||||
retryMax: 4,
|
||||
@@ -132,9 +135,6 @@ func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth,
|
||||
}
|
||||
|
||||
retryClient := retryablehttp.NewClient()
|
||||
|
||||
// TODO: this silences retryclient default logger, do we want to provide one
|
||||
// instead? by default retryablehttp logs all requests to stderr
|
||||
retryClient.Logger = log.New(io.Discard, "", log.LstdFlags)
|
||||
|
||||
retryClient.RetryMax = ac.retryMax
|
||||
@@ -161,48 +161,94 @@ func NewClient(ctx context.Context, githubConfigURL string, creds *ActionsAuth,
|
||||
retryClient.HTTPClient.Transport = transport
|
||||
ac.Client = retryClient.StandardClient()
|
||||
|
||||
rt, err := ac.getRunnerRegistrationToken(ctx, githubConfigURL, *creds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get runner registration token: %w", err)
|
||||
}
|
||||
|
||||
adminConnInfo, err := ac.getActionsServiceAdminConnection(ctx, rt, githubConfigURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get actions service admin connection: %w", err)
|
||||
}
|
||||
|
||||
ac.ActionsServiceURL = adminConnInfo.ActionsServiceUrl
|
||||
|
||||
ac.mu.Lock()
|
||||
defer ac.mu.Unlock()
|
||||
ac.ActionsServiceAdminToken = adminConnInfo.AdminToken
|
||||
ac.ActionsServiceAdminTokenExpiresAt, err = actionsServiceAdminTokenExpiresAt(*adminConnInfo.AdminToken)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get admin token expire at: %w", err)
|
||||
}
|
||||
|
||||
return ac, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
||||
u := fmt.Sprintf("%s/%s?name=%s&api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetName)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
resp, err := c.Client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body = trimByteOrderMark(body)
|
||||
resp.Body = io.NopCloser(bytes.NewReader(body))
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) NewGitHubAPIRequest(ctx context.Context, method, path string, body io.Reader) (*http.Request, error) {
|
||||
u := c.config.GitHubAPIURL(path)
|
||||
req, err := http.NewRequestWithContext(ctx, method, u.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) NewActionsServiceRequest(ctx context.Context, method, path string, body io.Reader) (*http.Request, error) {
|
||||
err := c.updateTokenIfNeeded(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parsedPath, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
urlString, err := url.JoinPath(c.ActionsServiceURL, parsedPath.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err := url.Parse(urlString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
for k, v := range parsedPath.Query() {
|
||||
q[k] = v
|
||||
}
|
||||
if q.Get("api-version") == "" {
|
||||
q.Set("api-version", "6.0-preview")
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, u.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.ActionsServiceAdminToken))
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
||||
path := fmt.Sprintf("/%s?name=%s", scaleSetEndpoint, runnerScaleSetName)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -211,8 +257,9 @@ func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName strin
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, ParseActionsErrorFromResponse(resp)
|
||||
}
|
||||
|
||||
var runnerScaleSetList *runnerScaleSetsResponse
|
||||
err = unmarshalBody(resp, &runnerScaleSetList)
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerScaleSetList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -227,24 +274,12 @@ func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName strin
|
||||
}
|
||||
|
||||
func (c *Client) GetRunnerScaleSetById(ctx context.Context, runnerScaleSetId int) (*RunnerScaleSet, error) {
|
||||
u := fmt.Sprintf("%s/%s/%d?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
path := fmt.Sprintf("/%s/%d", scaleSetEndpoint, runnerScaleSetId)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -255,7 +290,7 @@ func (c *Client) GetRunnerScaleSetById(ctx context.Context, runnerScaleSetId int
|
||||
}
|
||||
|
||||
var runnerScaleSet *RunnerScaleSet
|
||||
err = unmarshalBody(resp, &runnerScaleSet)
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerScaleSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -263,24 +298,12 @@ func (c *Client) GetRunnerScaleSetById(ctx context.Context, runnerScaleSetId int
|
||||
}
|
||||
|
||||
func (c *Client) GetRunnerGroupByName(ctx context.Context, runnerGroup string) (*RunnerGroup, error) {
|
||||
u := fmt.Sprintf("%s/_apis/runtime/runnergroups/?groupName=%s&api-version=6.0-preview", *c.ActionsServiceURL, runnerGroup)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
path := fmt.Sprintf("/_apis/runtime/runnergroups/?groupName=%s", runnerGroup)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -295,7 +318,7 @@ func (c *Client) GetRunnerGroupByName(ctx context.Context, runnerGroup string) (
|
||||
}
|
||||
|
||||
var runnerGroupList *RunnerGroupList
|
||||
err = unmarshalBody(resp, &runnerGroupList)
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerGroupList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -312,29 +335,16 @@ func (c *Client) GetRunnerGroupByName(ctx context.Context, runnerGroup string) (
|
||||
}
|
||||
|
||||
func (c *Client) CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *RunnerScaleSet) (*RunnerScaleSet, error) {
|
||||
u := fmt.Sprintf("%s/%s?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
body, err := json.Marshal(runnerScaleSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, bytes.NewBuffer(body))
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodPost, scaleSetEndpoint, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -344,7 +354,7 @@ func (c *Client) CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *Runne
|
||||
return nil, ParseActionsErrorFromResponse(resp)
|
||||
}
|
||||
var createdRunnerScaleSet *RunnerScaleSet
|
||||
err = unmarshalBody(resp, &createdRunnerScaleSet)
|
||||
err = json.NewDecoder(resp.Body).Decode(&createdRunnerScaleSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -352,29 +362,18 @@ func (c *Client) CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *Runne
|
||||
}
|
||||
|
||||
func (c *Client) UpdateRunnerScaleSet(ctx context.Context, runnerScaleSetId int, runnerScaleSet *RunnerScaleSet) (*RunnerScaleSet, error) {
|
||||
u := fmt.Sprintf("%s/%s/%d?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%d", scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
body, err := json.Marshal(runnerScaleSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, u, bytes.NewBuffer(body))
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodPatch, path, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -385,7 +384,7 @@ func (c *Client) UpdateRunnerScaleSet(ctx context.Context, runnerScaleSetId int,
|
||||
}
|
||||
|
||||
var updatedRunnerScaleSet *RunnerScaleSet
|
||||
err = unmarshalBody(resp, &updatedRunnerScaleSet)
|
||||
err = json.NewDecoder(resp.Body).Decode(&updatedRunnerScaleSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -393,24 +392,12 @@ func (c *Client) UpdateRunnerScaleSet(ctx context.Context, runnerScaleSetId int,
|
||||
}
|
||||
|
||||
func (c *Client) DeleteRunnerScaleSet(ctx context.Context, runnerScaleSetId int) error {
|
||||
u := fmt.Sprintf("%s/%s/%d?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u, nil)
|
||||
path := fmt.Sprintf("/%s/%d", scaleSetEndpoint, runnerScaleSetId)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -425,12 +412,18 @@ func (c *Client) DeleteRunnerScaleSet(ctx context.Context, runnerScaleSetId int)
|
||||
}
|
||||
|
||||
func (c *Client) GetMessage(ctx context.Context, messageQueueUrl, messageQueueAccessToken string, lastMessageId int64) (*RunnerScaleSetMessage, error) {
|
||||
u := messageQueueUrl
|
||||
if lastMessageId > 0 {
|
||||
u = fmt.Sprintf("%s&lassMessageId=%d", messageQueueUrl, lastMessageId)
|
||||
u, err := url.Parse(messageQueueUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
if lastMessageId > 0 {
|
||||
q := u.Query()
|
||||
q.Set("lastMessageId", strconv.FormatInt(lastMessageId, 10))
|
||||
u.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -466,7 +459,7 @@ func (c *Client) GetMessage(ctx context.Context, messageQueueUrl, messageQueueAc
|
||||
}
|
||||
|
||||
var message *RunnerScaleSetMessage
|
||||
err = unmarshalBody(resp, &message)
|
||||
err = json.NewDecoder(resp.Body).Decode(&message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -514,7 +507,7 @@ func (c *Client) DeleteMessage(ctx context.Context, messageQueueUrl, messageQueu
|
||||
}
|
||||
|
||||
func (c *Client) CreateMessageSession(ctx context.Context, runnerScaleSetId int, owner string) (*RunnerScaleSetSession, error) {
|
||||
u := fmt.Sprintf("%v/%v/%v/sessions?%v", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId, apiVersionQueryParam)
|
||||
path := fmt.Sprintf("/%s/%d/sessions", scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
newSession := &RunnerScaleSetSession{
|
||||
OwnerName: owner,
|
||||
@@ -527,49 +520,36 @@ func (c *Client) CreateMessageSession(ctx context.Context, runnerScaleSetId int,
|
||||
|
||||
createdSession := &RunnerScaleSetSession{}
|
||||
|
||||
err = c.doSessionRequest(ctx, http.MethodPost, u, bytes.NewBuffer(requestData), http.StatusOK, createdSession)
|
||||
err = c.doSessionRequest(ctx, http.MethodPost, path, bytes.NewBuffer(requestData), http.StatusOK, createdSession)
|
||||
|
||||
return createdSession, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteMessageSession(ctx context.Context, runnerScaleSetId int, sessionId *uuid.UUID) error {
|
||||
u := fmt.Sprintf("%v/%v/%v/sessions/%v?%v", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId, sessionId.String(), apiVersionQueryParam)
|
||||
|
||||
return c.doSessionRequest(ctx, http.MethodDelete, u, nil, http.StatusNoContent, nil)
|
||||
path := fmt.Sprintf("/%s/%d/sessions/%s", scaleSetEndpoint, runnerScaleSetId, sessionId.String())
|
||||
return c.doSessionRequest(ctx, http.MethodDelete, path, nil, http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func (c *Client) RefreshMessageSession(ctx context.Context, runnerScaleSetId int, sessionId *uuid.UUID) (*RunnerScaleSetSession, error) {
|
||||
u := fmt.Sprintf("%v/%v/%v/sessions/%v?%v", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId, sessionId.String(), apiVersionQueryParam)
|
||||
path := fmt.Sprintf("/%s/%d/sessions/%s", scaleSetEndpoint, runnerScaleSetId, sessionId.String())
|
||||
refreshedSession := &RunnerScaleSetSession{}
|
||||
err := c.doSessionRequest(ctx, http.MethodPatch, u, nil, http.StatusOK, refreshedSession)
|
||||
err := c.doSessionRequest(ctx, http.MethodPatch, path, nil, http.StatusOK, refreshedSession)
|
||||
return refreshedSession, err
|
||||
}
|
||||
|
||||
func (c *Client) doSessionRequest(ctx context.Context, method, url string, requestData io.Reader, expectedResponseStatusCode int, responseUnmarshalTarget any) error {
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, url, requestData)
|
||||
func (c *Client) doSessionRequest(ctx context.Context, method, path string, requestData io.Reader, expectedResponseStatusCode int, responseUnmarshalTarget any) error {
|
||||
req, err := c.NewActionsServiceRequest(ctx, method, path, requestData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode == expectedResponseStatusCode && responseUnmarshalTarget != nil {
|
||||
err = unmarshalBody(resp, &responseUnmarshalTarget)
|
||||
return err
|
||||
return json.NewDecoder(resp.Body).Decode(responseUnmarshalTarget)
|
||||
}
|
||||
|
||||
if resp.StatusCode >= 400 && resp.StatusCode < 500 {
|
||||
@@ -587,7 +567,7 @@ func (c *Client) doSessionRequest(ctx context.Context, method, url string, reque
|
||||
}
|
||||
|
||||
func (c *Client) AcquireJobs(ctx context.Context, runnerScaleSetId int, messageQueueAccessToken string, requestIds []int64) ([]int64, error) {
|
||||
u := fmt.Sprintf("%s/%s/%d/acquirejobs?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
u := fmt.Sprintf("%s/%s/%d/acquirejobs?api-version=6.0-preview", c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
body, err := json.Marshal(requestIds)
|
||||
if err != nil {
|
||||
@@ -614,8 +594,8 @@ func (c *Client) AcquireJobs(ctx context.Context, runnerScaleSetId int, messageQ
|
||||
return nil, ParseActionsErrorFromResponse(resp)
|
||||
}
|
||||
|
||||
var acquiredJobs Int64List
|
||||
err = unmarshalBody(resp, &acquiredJobs)
|
||||
var acquiredJobs *Int64List
|
||||
err = json.NewDecoder(resp.Body).Decode(&acquiredJobs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -624,24 +604,13 @@ func (c *Client) AcquireJobs(ctx context.Context, runnerScaleSetId int, messageQ
|
||||
}
|
||||
|
||||
func (c *Client) GetAcquirableJobs(ctx context.Context, runnerScaleSetId int) (*AcquirableJobList, error) {
|
||||
u := fmt.Sprintf("%s/%s/%d/acquirablejobs?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, runnerScaleSetId)
|
||||
path := fmt.Sprintf("/%s/%d/acquirablejobs", scaleSetEndpoint, runnerScaleSetId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -657,7 +626,7 @@ func (c *Client) GetAcquirableJobs(ctx context.Context, runnerScaleSetId int) (*
|
||||
}
|
||||
|
||||
var acquirableJobList *AcquirableJobList
|
||||
err = unmarshalBody(resp, &acquirableJobList)
|
||||
err = json.NewDecoder(resp.Body).Decode(&acquirableJobList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -666,28 +635,18 @@ func (c *Client) GetAcquirableJobs(ctx context.Context, runnerScaleSetId int) (*
|
||||
}
|
||||
|
||||
func (c *Client) GenerateJitRunnerConfig(ctx context.Context, jitRunnerSetting *RunnerScaleSetJitRunnerSetting, scaleSetId int) (*RunnerScaleSetJitRunnerConfig, error) {
|
||||
runnerJitConfigUrl := fmt.Sprintf("%s/%s/%d/generatejitconfig?api-version=6.0-preview", *c.ActionsServiceURL, scaleSetEndpoint, scaleSetId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
path := fmt.Sprintf("/%s/%d/generatejitconfig", scaleSetEndpoint, scaleSetId)
|
||||
|
||||
body, err := json.Marshal(jitRunnerSetting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, runnerJitConfigUrl, bytes.NewBuffer(body))
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodPost, path, bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -698,7 +657,7 @@ func (c *Client) GenerateJitRunnerConfig(ctx context.Context, jitRunnerSetting *
|
||||
}
|
||||
|
||||
var runnerJitConfig *RunnerScaleSetJitRunnerConfig
|
||||
err = unmarshalBody(resp, &runnerJitConfig)
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerJitConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -706,24 +665,13 @@ func (c *Client) GenerateJitRunnerConfig(ctx context.Context, jitRunnerSetting *
|
||||
}
|
||||
|
||||
func (c *Client) GetRunner(ctx context.Context, runnerId int64) (*RunnerReference, error) {
|
||||
url := fmt.Sprintf("%v/%v/%v?%v", *c.ActionsServiceURL, runnerEndpoint, runnerId, apiVersionQueryParam)
|
||||
path := fmt.Sprintf("/%s/%d", runnerEndpoint, runnerId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -734,7 +682,8 @@ func (c *Client) GetRunner(ctx context.Context, runnerId int64) (*RunnerReferenc
|
||||
}
|
||||
|
||||
var runnerReference *RunnerReference
|
||||
if err := unmarshalBody(resp, &runnerReference); err != nil {
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -742,24 +691,13 @@ func (c *Client) GetRunner(ctx context.Context, runnerId int64) (*RunnerReferenc
|
||||
}
|
||||
|
||||
func (c *Client) GetRunnerByName(ctx context.Context, runnerName string) (*RunnerReference, error) {
|
||||
url := fmt.Sprintf("%v/%v?agentName=%v&%v", *c.ActionsServiceURL, runnerEndpoint, runnerName, apiVersionQueryParam)
|
||||
path := fmt.Sprintf("/%s?agentName=%s", runnerEndpoint, runnerName)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -770,7 +708,7 @@ func (c *Client) GetRunnerByName(ctx context.Context, runnerName string) (*Runne
|
||||
}
|
||||
|
||||
var runnerList *RunnerReferenceList
|
||||
err = unmarshalBody(resp, &runnerList)
|
||||
err = json.NewDecoder(resp.Body).Decode(&runnerList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -787,24 +725,13 @@ func (c *Client) GetRunnerByName(ctx context.Context, runnerName string) (*Runne
|
||||
}
|
||||
|
||||
func (c *Client) RemoveRunner(ctx context.Context, runnerId int64) error {
|
||||
url := fmt.Sprintf("%v/%v/%v?%v", *c.ActionsServiceURL, runnerEndpoint, runnerId, apiVersionQueryParam)
|
||||
path := fmt.Sprintf("/%s/%d", runnerEndpoint, runnerId)
|
||||
|
||||
if err := c.refreshTokenIfNeeded(ctx); err != nil {
|
||||
return fmt.Errorf("failed to refresh admin token if needed: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil)
|
||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodDelete, path, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *c.ActionsServiceAdminToken))
|
||||
|
||||
if c.userAgent != "" {
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
}
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -823,25 +750,25 @@ type registrationToken struct {
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) getRunnerRegistrationToken(ctx context.Context, githubConfigUrl string, creds ActionsAuth) (*registrationToken, error) {
|
||||
registrationTokenURL, err := createRegistrationTokenURL(githubConfigUrl)
|
||||
func (c *Client) getRunnerRegistrationToken(ctx context.Context) (*registrationToken, error) {
|
||||
path, err := createRegistrationTokenPath(c.config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, registrationTokenURL, &buf)
|
||||
req, err := c.NewGitHubAPIRequest(ctx, http.MethodPost, path, &buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bearerToken := ""
|
||||
|
||||
if creds.Token != "" {
|
||||
encodedToken := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("github:%v", creds.Token)))
|
||||
if c.creds.Token != "" {
|
||||
encodedToken := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("github:%v", c.creds.Token)))
|
||||
bearerToken = fmt.Sprintf("Basic %v", encodedToken)
|
||||
} else {
|
||||
accessToken, err := c.fetchAccessToken(ctx, githubConfigUrl, creds.AppCreds)
|
||||
accessToken, err := c.fetchAccessToken(ctx, c.config.ConfigURL.String(), c.creds.AppCreds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -851,9 +778,8 @@ func (c *Client) getRunnerRegistrationToken(ctx context.Context, githubConfigUrl
|
||||
|
||||
req.Header.Set("Content-Type", "application/vnd.github.v3+json")
|
||||
req.Header.Set("Authorization", bearerToken)
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
|
||||
c.logger.Info("getting runner registration token", "registrationTokenURL", registrationTokenURL)
|
||||
c.logger.Info("getting runner registration token", "registrationTokenURL", req.URL.String())
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
@@ -869,8 +795,8 @@ func (c *Client) getRunnerRegistrationToken(ctx context.Context, githubConfigUrl
|
||||
return nil, fmt.Errorf("unexpected response from Actions service during registration token call: %v - %v", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
registrationToken := ®istrationToken{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(registrationToken); err != nil {
|
||||
var registrationToken *registrationToken
|
||||
if err := json.NewDecoder(resp.Body).Decode(®istrationToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -889,21 +815,16 @@ func (c *Client) fetchAccessToken(ctx context.Context, gitHubConfigURL string, c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, err := githubAPIURL(gitHubConfigURL, fmt.Sprintf("/app/installations/%v/access_tokens", creds.AppInstallationID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil)
|
||||
path := fmt.Sprintf("/app/installations/%v/access_tokens", creds.AppInstallationID)
|
||||
req, err := c.NewGitHubAPIRequest(ctx, http.MethodPost, path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/vnd.github+json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessTokenJWT))
|
||||
req.Header.Add("User-Agent", c.userAgent)
|
||||
|
||||
c.logger.Info("getting access token for GitHub App auth", "accessTokenURL", u)
|
||||
c.logger.Info("getting access token for GitHub App auth", "accessTokenURL", req.URL.String())
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
@@ -912,8 +833,8 @@ func (c *Client) fetchAccessToken(ctx context.Context, gitHubConfigURL string, c
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Format: https://docs.github.com/en/rest/apps/apps#create-an-installation-access-token-for-an-app
|
||||
accessToken := &accessToken{}
|
||||
err = json.NewDecoder(resp.Body).Decode(accessToken)
|
||||
var accessToken *accessToken
|
||||
err = json.NewDecoder(resp.Body).Decode(&accessToken)
|
||||
return accessToken, err
|
||||
}
|
||||
|
||||
@@ -922,27 +843,14 @@ type ActionsServiceAdminConnection struct {
|
||||
AdminToken *string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *registrationToken, githubConfigUrl string) (*ActionsServiceAdminConnection, error) {
|
||||
parsedGitHubConfigURL, err := url.Parse(githubConfigUrl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isHostedServer(*parsedGitHubConfigURL) {
|
||||
parsedGitHubConfigURL.Host = fmt.Sprintf("api.%v", parsedGitHubConfigURL.Host)
|
||||
}
|
||||
|
||||
ru := fmt.Sprintf("%v://%v/actions/runner-registration", parsedGitHubConfigURL.Scheme, parsedGitHubConfigURL.Host)
|
||||
registrationURL, err := url.Parse(ru)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *registrationToken) (*ActionsServiceAdminConnection, error) {
|
||||
path := "/actions/runner-registration"
|
||||
|
||||
body := struct {
|
||||
Url string `json:"url"`
|
||||
RunnerEvent string `json:"runner_event"`
|
||||
}{
|
||||
Url: githubConfigUrl,
|
||||
Url: c.config.ConfigURL.String(),
|
||||
RunnerEvent: "register",
|
||||
}
|
||||
|
||||
@@ -954,16 +862,15 @@ func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *regis
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, registrationURL.String(), buf)
|
||||
req, err := c.NewGitHubAPIRequest(ctx, http.MethodPost, path, buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("RemoteAuth %s", *rt.Token))
|
||||
req.Header.Set("User-Agent", c.userAgent)
|
||||
|
||||
c.logger.Info("getting Actions tenant URL and JWT", "registrationURL", registrationURL.String())
|
||||
c.logger.Info("getting Actions tenant URL and JWT", "registrationURL", req.URL.String())
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
@@ -971,65 +878,30 @@ func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *regis
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
actionsServiceAdminConnection := &ActionsServiceAdminConnection{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(actionsServiceAdminConnection); err != nil {
|
||||
var actionsServiceAdminConnection *ActionsServiceAdminConnection
|
||||
if err := json.NewDecoder(resp.Body).Decode(&actionsServiceAdminConnection); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return actionsServiceAdminConnection, nil
|
||||
}
|
||||
|
||||
func isHostedServer(gitHubURL url.URL) bool {
|
||||
return gitHubURL.Host == "github.com" ||
|
||||
gitHubURL.Host == "www.github.com" ||
|
||||
gitHubURL.Host == "github.localhost"
|
||||
}
|
||||
func createRegistrationTokenPath(config *GitHubConfig) (string, error) {
|
||||
switch config.Scope {
|
||||
case GitHubScopeOrganization:
|
||||
path := fmt.Sprintf("/orgs/%s/actions/runners/registration-token", config.Organization)
|
||||
return path, nil
|
||||
|
||||
func createRegistrationTokenURL(githubConfigUrl string) (string, error) {
|
||||
parsedGitHubConfigURL, err := url.Parse(githubConfigUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
case GitHubScopeEnterprise:
|
||||
path := fmt.Sprintf("/enterprises/%s/actions/runners/registration-token", config.Enterprise)
|
||||
return path, nil
|
||||
|
||||
// Check for empty path before split, because strings.Split will return a slice of length 1
|
||||
// when the split delimiter is not present.
|
||||
trimmedPath := strings.TrimLeft(parsedGitHubConfigURL.Path, "/")
|
||||
if len(trimmedPath) == 0 {
|
||||
return "", fmt.Errorf("%q should point to an enterprise, org, or repository", parsedGitHubConfigURL.String())
|
||||
}
|
||||
case GitHubScopeRepository:
|
||||
path := fmt.Sprintf("/repos/%s/%s/actions/runners/registration-token", config.Organization, config.Repository)
|
||||
return path, nil
|
||||
|
||||
pathParts := strings.Split(path.Clean(strings.TrimLeft(parsedGitHubConfigURL.Path, "/")), "/")
|
||||
|
||||
switch len(pathParts) {
|
||||
case 1: // Organization
|
||||
registrationTokenURL := fmt.Sprintf(
|
||||
"%v://%v/api/v3/orgs/%v/actions/runners/registration-token",
|
||||
parsedGitHubConfigURL.Scheme, parsedGitHubConfigURL.Host, pathParts[0])
|
||||
|
||||
if isHostedServer(*parsedGitHubConfigURL) {
|
||||
registrationTokenURL = fmt.Sprintf(
|
||||
"%v://api.%v/orgs/%v/actions/runners/registration-token",
|
||||
parsedGitHubConfigURL.Scheme, parsedGitHubConfigURL.Host, pathParts[0])
|
||||
}
|
||||
|
||||
return registrationTokenURL, nil
|
||||
case 2: // Repository or enterprise
|
||||
repoScope := "repos/"
|
||||
if strings.ToLower(pathParts[0]) == "enterprises" {
|
||||
repoScope = ""
|
||||
}
|
||||
|
||||
registrationTokenURL := fmt.Sprintf("%v://%v/api/v3/%v%v/%v/actions/runners/registration-token",
|
||||
parsedGitHubConfigURL.Scheme, parsedGitHubConfigURL.Host, repoScope, pathParts[0], pathParts[1])
|
||||
|
||||
if isHostedServer(*parsedGitHubConfigURL) {
|
||||
registrationTokenURL = fmt.Sprintf("%v://api.%v/%v%v/%v/actions/runners/registration-token",
|
||||
parsedGitHubConfigURL.Scheme, parsedGitHubConfigURL.Host, repoScope, pathParts[0], pathParts[1])
|
||||
}
|
||||
|
||||
return registrationTokenURL, nil
|
||||
default:
|
||||
return "", fmt.Errorf("%q should point to an enterprise, org, or repository", parsedGitHubConfigURL.String())
|
||||
return "", fmt.Errorf("unknown scope for config url: %s", config.ConfigURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,68 +929,50 @@ func createJWTForGitHubApp(appAuth *GitHubAppAuth) (string, error) {
|
||||
return token.SignedString(privateKey)
|
||||
}
|
||||
|
||||
func unmarshalBody(response *http.Response, v interface{}) (err error) {
|
||||
if response != nil && response.Body != nil {
|
||||
var err error
|
||||
defer func() {
|
||||
if closeError := response.Body.Close(); closeError != nil {
|
||||
err = closeError
|
||||
}
|
||||
}()
|
||||
body, err := io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body = trimByteOrderMark(body)
|
||||
return json.Unmarshal(body, &v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns slice of body without utf-8 byte order mark.
|
||||
// If BOM does not exist body is returned unchanged.
|
||||
func trimByteOrderMark(body []byte) []byte {
|
||||
return bytes.TrimPrefix(body, []byte("\xef\xbb\xbf"))
|
||||
}
|
||||
|
||||
func actionsServiceAdminTokenExpiresAt(jwtToken string) (*time.Time, error) {
|
||||
func actionsServiceAdminTokenExpiresAt(jwtToken string) (time.Time, error) {
|
||||
type JwtClaims struct {
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
token, _, err := jwt.NewParser().ParseUnverified(jwtToken, &JwtClaims{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse jwt token: %w", err)
|
||||
return time.Time{}, fmt.Errorf("failed to parse jwt token: %w", err)
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*JwtClaims); ok {
|
||||
return &claims.ExpiresAt.Time, nil
|
||||
return claims.ExpiresAt.Time, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to parse token claims to get expire at")
|
||||
return time.Time{}, fmt.Errorf("failed to parse token claims to get expire at")
|
||||
}
|
||||
|
||||
func (c *Client) refreshTokenIfNeeded(ctx context.Context) error {
|
||||
func (c *Client) updateTokenIfNeeded(ctx context.Context) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
aboutToExpire := time.Now().Add(60 * time.Second).After(*c.ActionsServiceAdminTokenExpiresAt)
|
||||
if !aboutToExpire {
|
||||
aboutToExpire := time.Now().Add(60 * time.Second).After(c.ActionsServiceAdminTokenExpiresAt)
|
||||
if !aboutToExpire && !c.ActionsServiceAdminTokenExpiresAt.IsZero() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.logger.Info("Admin token is about to expire, refreshing it", "githubConfigUrl", c.githubConfigURL)
|
||||
rt, err := c.getRunnerRegistrationToken(ctx, c.githubConfigURL, *c.creds)
|
||||
c.logger.Info("refreshing token", "githubConfigUrl", c.config.ConfigURL.String())
|
||||
rt, err := c.getRunnerRegistrationToken(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get runner registration token on fresh: %w", err)
|
||||
return fmt.Errorf("failed to get runner registration token on refresh: %w", err)
|
||||
}
|
||||
|
||||
adminConnInfo, err := c.getActionsServiceAdminConnection(ctx, rt, c.githubConfigURL)
|
||||
adminConnInfo, err := c.getActionsServiceAdminConnection(ctx, rt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get actions service admin connection on fresh: %w", err)
|
||||
return fmt.Errorf("failed to get actions service admin connection on refresh: %w", err)
|
||||
}
|
||||
|
||||
c.ActionsServiceURL = adminConnInfo.ActionsServiceUrl
|
||||
c.ActionsServiceAdminToken = adminConnInfo.AdminToken
|
||||
c.ActionsServiceURL = *adminConnInfo.ActionsServiceUrl
|
||||
c.ActionsServiceAdminToken = *adminConnInfo.AdminToken
|
||||
c.ActionsServiceAdminTokenExpiresAt, err = actionsServiceAdminTokenExpiresAt(*adminConnInfo.AdminToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get admin token expire at on refresh: %w", err)
|
||||
@@ -1126,32 +980,3 @@ func (c *Client) refreshTokenIfNeeded(ctx context.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func githubAPIURL(configURL, path string) (string, error) {
|
||||
u, err := url.Parse(configURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := &url.URL{
|
||||
Scheme: u.Scheme,
|
||||
}
|
||||
|
||||
switch u.Host {
|
||||
// Hosted
|
||||
case "github.com", "github.localhost":
|
||||
result.Host = fmt.Sprintf("api.%s", u.Host)
|
||||
// re-routing www.github.com to api.github.com
|
||||
case "www.github.com":
|
||||
result.Host = "api.github.com"
|
||||
|
||||
// Enterprise
|
||||
default:
|
||||
result.Host = u.Host
|
||||
result.Path = "/api/v3"
|
||||
}
|
||||
|
||||
result.Path += path
|
||||
|
||||
return result.String(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user