Skip to content
Snippets Groups Projects
Verified Commit 26a5f8c0 authored by Tomasz Maczukin's avatar Tomasz Maczukin :speech_balloon:
Browse files

Check compatibility using '/api/v4/runners/verify' endpoint

parent fff8685d
No related branches found
No related tags found
1 merge request!528Log error if API v4 is not present (GitLab CE/EE is older than 9.0)
Pipeline #
......@@ -38,12 +38,13 @@ var dialer = net.Dialer{
type client struct {
http.Client
url *url.URL
caFile string
caData []byte
skipVerify bool
updateTime time.Time
lastUpdate string
url *url.URL
caFile string
caData []byte
skipVerify bool
updateTime time.Time
lastUpdate string
compatibleWithGitLab bool
}
func (n *client) getLastUpdate() string {
......@@ -252,8 +253,9 @@ func newClient(requestCredentials requestCredentials) (c *client, err error) {
}
c = &client{
url: url,
caFile: requestCredentials.GetTLSCAFile(),
url: url,
caFile: requestCredentials.GetTLSCAFile(),
compatibleWithGitLab: true,
}
if CertificateDirectory != "" && c.caFile == "" {
......
......@@ -21,7 +21,7 @@ import (
const clientError = -100
var notSupportingGitLabPre90Message = "GitLab Runner >= 9.0 supports ONLY GitLab CE/EE >= 9.0"
var notSupportingGitLabPre90Message = "GitLab Runner >= 9.0 can be used ONLY with GitLab CE/EE >= 9.0"
type GitLabClient struct {
clients map[string]*client
......@@ -44,6 +44,7 @@ func (n *GitLabClient) getClient(credentials requestCredentials) (c *client, err
}
n.clients[key] = c
}
return
}
......@@ -94,6 +95,28 @@ func (n *GitLabClient) doJSON(credentials requestCredentials, method, uri string
return c.doJSON(uri, method, statusCode, request, response)
}
func (n *GitLabClient) checkGitLabVersionCompatibility(runner common.RunnerCredentials) {
request := common.VerifyRunnerRequest{
Token: "compatiblity-check",
}
result, statusText, _ := n.doJSON(&runner, "POST", "runners/verify", 200, &request, nil)
switch result {
case 403:
runner.Log().Println("Checking GitLab compatibility...", "OK")
default:
runner.Log().WithFields(logrus.Fields{
"result": result,
"statusText": statusText,
"reason": notSupportingGitLabPre90Message,
}).Errorln("Checking GitLab compatibility...", "not-compatible")
c, _ := n.getClient(&runner)
c.compatibleWithGitLab = false
}
}
func (n *GitLabClient) RegisterRunner(runner common.RunnerCredentials, description, tags string, runUntagged, locked bool) *common.RegisterRunnerResponse {
// TODO: pass executor
request := common.RegisterRunnerRequest{
......@@ -115,17 +138,12 @@ func (n *GitLabClient) RegisterRunner(runner common.RunnerCredentials, descripti
case 403:
runner.Log().Errorln("Registering runner...", "forbidden (check registration token)")
return nil
case 404:
runner.Log().WithFields(logrus.Fields{
"status": statusText,
"reason": notSupportingGitLabPre90Message,
}).Errorln("Registering runner...", "not-compatible")
return nil
case clientError:
runner.Log().WithField("status", statusText).Errorln("Registering runner...", "error")
return nil
default:
runner.Log().WithField("status", statusText).Errorln("Registering runner...", "failed")
n.checkGitLabVersionCompatibility(runner)
return nil
}
}
......@@ -145,17 +163,12 @@ func (n *GitLabClient) VerifyRunner(runner common.RunnerCredentials) bool {
case 403:
runner.Log().Errorln("Verifying runner...", "is removed")
return false
case 404:
runner.Log().WithFields(logrus.Fields{
"status": statusText,
"reason": notSupportingGitLabPre90Message,
}).Errorln("Verifying runner...", "not-compatible")
return false
case clientError:
runner.Log().WithField("status", statusText).Errorln("Verifying runner...", "error")
return false
return true
default:
runner.Log().WithField("status", statusText).Errorln("Verifying runner...", "failed")
n.checkGitLabVersionCompatibility(runner)
return true
}
}
......@@ -174,17 +187,12 @@ func (n *GitLabClient) UnregisterRunner(runner common.RunnerCredentials) bool {
case 403:
runner.Log().Errorln("Deleting runner...", "forbidden")
return false
case 404:
runner.Log().WithFields(logrus.Fields{
"status": statusText,
"reason": notSupportingGitLabPre90Message,
}).Errorln("Deleting runner...", "not-compatible")
return false
case clientError:
runner.Log().WithField("status", statusText).Errorln("Deleting runner...", "error")
return false
default:
runner.Log().WithField("status", statusText).Errorln("Deleting runner...", "failed")
n.checkGitLabVersionCompatibility(runner)
return false
}
}
......@@ -213,17 +221,12 @@ func (n *GitLabClient) RequestJob(config common.RunnerConfig) (*common.JobRespon
case 204:
config.Log().Debugln("Checking for jobs...", "nothing")
return nil, true
case 404:
config.Log().WithFields(logrus.Fields{
"status": statusText,
"reason": notSupportingGitLabPre90Message,
}).Errorln("checking for jobs...", "not-compatible")
return nil, false
case clientError:
config.Log().WithField("status", statusText).Errorln("Checking for jobs...", "error")
return nil, false
default:
config.Log().WithField("status", statusText).Warningln("Checking for jobs...", "failed")
n.checkGitLabVersionCompatibility(config.RunnerCredentials)
return nil, true
}
}
......
......@@ -272,7 +272,7 @@ func TestVerifyRunner(t *testing.T) {
assert.True(t, state, "in other cases where we can't explicitly say that runner is valid we say that it's")
state = c.VerifyRunner(brokenCredentials)
assert.False(t, state)
assert.True(t, state, "in other cases where we can't explicitly say that runner is valid we say that it's")
}
func getRequestJobResponse() (res map[string]interface{}) {
......@@ -861,10 +861,11 @@ func TestArtifactsDownload(t *testing.T) {
assert.Equal(t, DownloadNotFound, state, "Artifacts should be bit downloaded if it's not found")
}
func prepareAPIv4CompatibilityTestEnvironment(handler func(w http.ResponseWriter, r *http.Request)) (server *httptest.Server, runner RunnerConfig) {
func prepareAPIv4CompatibilityTestEnvironment(name string, handler func(w http.ResponseWriter, r *http.Request)) (server *httptest.Server, runner RunnerConfig) {
server = httptest.NewServer(http.HandlerFunc(handler))
runner = RunnerConfig{
Name: name,
RunnerCredentials: RunnerCredentials{
URL: server.URL,
Token: "valid",
......@@ -874,20 +875,45 @@ func prepareAPIv4CompatibilityTestEnvironment(handler func(w http.ResponseWriter
return
}
func execAPIv4CompatibilityTestRequest(t *testing.T, requestType string, runner RunnerConfig, isCompatible bool) {
t.Run(fmt.Sprintf("%s/%s", requestType, runner.Name), func(t *testing.T) {
c := NewGitLabClient()
switch requestType {
case "register runner":
c.RegisterRunner(runner.RunnerCredentials, "", "", false, false)
case "verify runner":
c.VerifyRunner(runner.RunnerCredentials)
case "unregister runner":
c.UnregisterRunner(runner.RunnerCredentials)
case "request job":
c.RequestJob(runner)
}
client, err := c.getClient(&runner.RunnerCredentials)
assert.NoError(t, err)
if isCompatible {
assert.True(t, client.compatibleWithGitLab, "Client should be marked as compatible with GitLab")
} else {
assert.False(t, client.compatibleWithGitLab, "Client should be marked as not compatible with GitLab")
}
})
}
func TestAPIv4Compatibility(t *testing.T) {
serverPre90, runnerPre90 := prepareAPIv4CompatibilityTestEnvironment(func(w http.ResponseWriter, r *http.Request) {
serverPre90, runnerPre90 := prepareAPIv4CompatibilityTestEnvironment("pre 9.0", func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/v4/runners":
w.WriteHeader(404)
w.WriteHeader(401)
case "/api/v4/runners/verify":
w.WriteHeader(404)
w.WriteHeader(401)
case "/api/v4/jobs/request":
w.WriteHeader(404)
}
})
defer serverPre90.Close()
server90, runner90 := prepareAPIv4CompatibilityTestEnvironment(func(w http.ResponseWriter, r *http.Request) {
server90, runner90 := prepareAPIv4CompatibilityTestEnvironment("9.0", func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/v4/runners":
switch r.Method {
......@@ -912,25 +938,12 @@ func TestAPIv4Compatibility(t *testing.T) {
})
defer server90.Close()
c := NewGitLabClient()
resp := c.RegisterRunner(runnerPre90.RunnerCredentials, "", "", false, false)
assert.Nil(t, resp, "Request against GitLab < 9.0 should not register Runner")
resp = c.RegisterRunner(runner90.RunnerCredentials, "", "", false, false)
assert.NotNil(t, resp, "Request against GitLab < 9.0 should register Runner")
ok := c.VerifyRunner(runnerPre90.RunnerCredentials)
assert.False(t, ok, "Request against GitLab < 9.0 should not verify Runner")
ok = c.VerifyRunner(runner90.RunnerCredentials)
assert.True(t, ok, "Request against GitLab < 9.0 should verify Runner")
ok = c.UnregisterRunner(runnerPre90.RunnerCredentials)
assert.False(t, ok, "Request against GitLab < 9.0 should not unregister Runner")
ok = c.UnregisterRunner(runner90.RunnerCredentials)
assert.True(t, ok, "Request against GitLab < 9.0 should unregister Runner")
_, healthy := c.RequestJob(runnerPre90)
assert.False(t, healthy, "Request against GitLab < 9.0 should mark Runner as unhealthy")
_, healthy = c.RequestJob(runner90)
assert.True(t, healthy, "Request against GitLab >= 9.0 should mark Runner as healthy")
execAPIv4CompatibilityTestRequest(t, "register runner", runnerPre90, false)
execAPIv4CompatibilityTestRequest(t, "register runner", runner90, true)
execAPIv4CompatibilityTestRequest(t, "verify runner", runnerPre90, false)
execAPIv4CompatibilityTestRequest(t, "verify runner", runner90, true)
execAPIv4CompatibilityTestRequest(t, "unregister runner", runnerPre90, false)
execAPIv4CompatibilityTestRequest(t, "unregister runner", runner90, true)
execAPIv4CompatibilityTestRequest(t, "request job", runnerPre90, false)
execAPIv4CompatibilityTestRequest(t, "request job", runner90, true)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment