Implement merge request review comments

This commit is contained in:
Maximilian Paß
2021-05-06 13:26:55 +02:00
parent 0dc4d28c1b
commit dba7160a41
10 changed files with 136 additions and 112 deletions

View File

@ -6,6 +6,7 @@ stages:
- lint - lint
- test - test
- docker - docker
- e2e
- deploy - deploy
- cleanup - cleanup
@ -48,7 +49,7 @@ test:
stage: test stage: test
needs: [] needs: []
script: script:
- go test $(go list ./... | grep -v /e2e | grep -v /poseidon$) -v -coverprofile coverage.cov - go test $(go list ./... | grep -v /e2e_tests) -v -coverprofile coverage.cov
- go tool cover -func=coverage.cov - go tool cover -func=coverage.cov
- go tool cover -html=coverage.cov -o coverage_unit.html - go tool cover -html=coverage.cov -o coverage_unit.html
artifacts: artifacts:
@ -57,24 +58,6 @@ test:
expire_in: 1 week expire_in: 1 week
expose_as: coverageReport expose_as: coverageReport
e2e_test:
image: drp.codemoon.xopic.de/nomad-ci:latest
stage: test
services:
- name: docker:dind
alias: docker
script:
# Avoid docker pull limit
- docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY
- docker pull $DOCKER_REGISTRY/openhpi/co_execenv_python:3.8
- docker tag $DOCKER_REGISTRY/openhpi/co_execenv_python:3.8 openhpi/co_execenv_python:3.8
# Setup own nomad cluster
- export NOMAD_ADDR=http://localhost:4646
- nomad agent -dev -log-level=WARN &
- sleep 15
# Start tests
- go test ./ ./e2e -v
dockerimage: dockerimage:
stage: docker stage: docker
image: docker:latest image: docker:latest
@ -111,6 +94,37 @@ nomadimage:
- docker push $NOMAD_CI_IMAGE_NAME_ENV - docker push $NOMAD_CI_IMAGE_NAME_ENV
- docker push $NOMAD_CI_IMAGE_NAME_GENERAL - docker push $NOMAD_CI_IMAGE_NAME_GENERAL
test_e2e:
image: $NOMAD_CI_IMAGE_NAME_ENV
stage: e2e
needs:
- compile
- job: nomadimage
services:
- name: docker:dind
alias: docker
variables:
DOCKER_HOST: "tcp://docker:2375"
script:
# Avoid docker pull limit
- docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD $DOCKER_REGISTRY
- docker pull $DOCKER_REGISTRY/openhpi/co_execenv_python:3.8
- docker tag $DOCKER_REGISTRY/openhpi/co_execenv_python:3.8 openhpi/co_execenv_python:3.8
# Setup own Nomad cluster and wait for startup
- export NOMAD_ADDR=http://localhost:4646
- nomad agent -dev -log-level=WARN &
- sleep 5
# Setup Nomad job and wait for it
- nomad run ci/python.nomad
- sleep 5
# Start Poseidon and wait for it
- ./poseidon &
- sleep 20
# Start tests
- go test ./e2e_tests -v
.start_deployment: &start_deployment .start_deployment: &start_deployment
image: $NOMAD_CI_IMAGE_NAME_ENV image: $NOMAD_CI_IMAGE_NAME_ENV
stage: deploy stage: deploy

View File

@ -4,22 +4,25 @@ FROM golang:latest
# Install prerequisites, gettext contains envsubst used in the CI # Install prerequisites, gettext contains envsubst used in the CI
RUN apt-get update && \ RUN apt-get update && \
apt install -y unzip wget gettext && \ apt install -y \
apt-get clean && \ unzip \
rm -rf /var/lib/apt/lists && \ wget \
apt-get install -y \ gettext \
apt-transport-https \ apt-transport-https \
ca-certificates \ ca-certificates \
curl \ curl \
gnupg gnupg \
lsb-release && \
apt-get clean && \
rm -rf /var/lib/apt/lists
RUN apt-get update && apt-get install -y lsb-release && apt-get clean all
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
RUN echo \ RUN echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y docker-ce docker-ce-cli containerd.io apt-get install -y docker-ce docker-ce-cli containerd.io && \
rm -rf /var/lib/apt/lists
# Download Nomad # Download Nomad
RUN wget "https://releases.hashicorp.com/nomad/1.0.4/nomad_1.0.4_linux_amd64.zip" && \ RUN wget "https://releases.hashicorp.com/nomad/1.0.4/nomad_1.0.4_linux_amd64.zip" && \
@ -32,9 +35,3 @@ RUN mv nomad /usr/sbin/ && nomad -version
COPY nomad-run-and-wait /usr/sbin/ COPY nomad-run-and-wait /usr/sbin/
RUN chmod +x /usr/sbin/nomad-run-and-wait RUN chmod +x /usr/sbin/nomad-run-and-wait
RUN wget "https://raw.githubusercontent.com/docker-library/docker/f6a0c427f0354dcf5870c430c72c8f1d6b4e6d5e/20.10/docker-entrypoint.sh"
RUN mv ./docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["sh"]

50
ci/python.nomad Normal file
View File

@ -0,0 +1,50 @@
// ToDo: Delete when creating job on test startup #26.
job "python" {
datacenters = ["dc1"]
type = "batch"
group "python" {
ephemeral_disk {
migrate = false
size = 10
sticky = false
}
count = 1
scaling {
enabled = true
max = 300
}
spread {
// see https://www.nomadproject.io/docs/job-specification/spread#even-spread-across-data-center
// This spreads the load evenly amongst our nodes
attribute = "${node.unique.name}"
weight = 100
}
task "python" {
driver = "docker"
kill_timeout = "0s"
kill_signal = "SIGKILL"
config {
image = "openhpi/co_execenv_python:3.8"
command = "sleep"
args = ["infinity"]
}
logs {
max_files = 1
max_file_size = 1
}
resources {
cpu = 40
memory = 40
}
restart {
delay = "0s"
}
}
}
}

View File

@ -1,18 +0,0 @@
package e2e
import (
"gitlab.hpi.de/codeocean/codemoon/poseidon/api"
"gitlab.hpi.de/codeocean/codemoon/poseidon/config"
"strings"
)
/*
* # E2E Tests
*
* For the e2e tests a nomad cluster must be connected and poseidon must be running.
*/
func buildURL(parts ...string) (url string) {
parts = append([]string{config.Config.PoseidonAPIURL().String(), api.RouteBase}, parts...)
return strings.Join(parts, "")
}

36
e2e_tests/e2e_test.go Normal file
View File

@ -0,0 +1,36 @@
package e2e_tests
import (
"gitlab.hpi.de/codeocean/codemoon/poseidon/api"
"gitlab.hpi.de/codeocean/codemoon/poseidon/config"
"gitlab.hpi.de/codeocean/codemoon/poseidon/logging"
"os"
"strings"
"testing"
)
/*
* # E2E Tests
*
* For the e2e tests a nomad cluster must be connected and poseidon must be running.
*/
var log = logging.GetLogger("e2e_tests")
// Overwrite TestMain for custom setup.
func TestMain(m *testing.M) {
log.Info("Test Setup")
err := config.InitConfig()
if err != nil {
log.Warn("Could not initialize configuration")
}
// ToDo: Add Nomad job here when it is possible to create execution environments. See #26.
log.Info("Test Run")
code := m.Run()
os.Exit(code)
}
func buildURL(parts ...string) (url string) {
parts = append([]string{config.Config.PoseidonAPIURL().String(), api.RouteBase}, parts...)
return strings.Join(parts, "")
}

View File

@ -1,8 +1,7 @@
package e2e package e2e_tests
import ( import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gitlab.hpi.de/codeocean/codemoon/poseidon/api" "gitlab.hpi.de/codeocean/codemoon/poseidon/api"
"net/http" "net/http"
"testing" "testing"
@ -10,6 +9,7 @@ import (
func TestHealthRoute(t *testing.T) { func TestHealthRoute(t *testing.T) {
resp, err := http.Get(buildURL(api.RouteHealth)) resp, err := http.Get(buildURL(api.RouteHealth))
require.NoError(t, err) if assert.NoError(t, err) {
assert.Equal(t, http.StatusNoContent, resp.StatusCode, "The response code should be NoContent") assert.Equal(t, http.StatusNoContent, resp.StatusCode, "The response code should be NoContent")
}
} }

View File

@ -1,4 +1,4 @@
package e2e package e2e_tests
import ( import (
"encoding/json" "encoding/json"

View File

@ -1,32 +0,0 @@
package main
import (
"gitlab.hpi.de/codeocean/codemoon/poseidon/config"
"gitlab.hpi.de/codeocean/codemoon/poseidon/nomad"
"os"
"testing"
"time"
)
// overwrite TestMain for custom setup
func TestMain(m *testing.M) {
log.Print("Test Setup")
setup()
log.Print("Test Run")
code := m.Run()
os.Exit(code)
}
func setup() {
createNomadJob()
go main()
time.Sleep(15 * time.Second)
}
func createNomadJob() {
nomadAPIClient, err := nomad.New(config.Config.NomadAPIURL())
if err != nil {
log.WithError(err).Fatal("[Test] Can not parse nomad config")
}
nomadAPIClient.CreateDebugJob()
}

View File

@ -12,8 +12,8 @@ type ExecutorApi struct {
mock.Mock mock.Mock
} }
// CreateDebugJob provides a mock function with given fields: // CreateJob provides a mock function with given fields:
func (_m *ExecutorApi) CreateDebugJob() { func (_m *ExecutorApi) CreateJob() {
_m.Called() _m.Called()
} }

View File

@ -2,19 +2,15 @@ package nomad
import ( import (
nomadApi "github.com/hashicorp/nomad/api" nomadApi "github.com/hashicorp/nomad/api"
"gitlab.hpi.de/codeocean/codemoon/poseidon/logging"
"net/url" "net/url"
) )
var log = logging.GetLogger("nomad")
// ExecutorApi provides access to an container orchestration solution // ExecutorApi provides access to an container orchestration solution
type ExecutorApi interface { type ExecutorApi interface {
LoadJobList() (list []*nomadApi.JobListStub, err error) LoadJobList() (list []*nomadApi.JobListStub, err error)
GetJobScale(jobId string) (jobScale int, err error) GetJobScale(jobId string) (jobScale int, err error)
SetJobScaling(jobId string, count int, reason string) (err error) SetJobScaling(jobId string, count int, reason string) (err error)
LoadRunners(jobId string) (runnerIds []string, err error) LoadRunners(jobId string) (runnerIds []string, err error)
CreateDebugJob()
} }
// ApiClient provides access to the Nomad functionality // ApiClient provides access to the Nomad functionality
@ -45,25 +41,6 @@ func (apiClient *ApiClient) LoadJobList() (list []*nomadApi.JobListStub, err err
return return
} }
// CreateDebugJob creates a simple python job in the nomad cluster
func (apiClient *ApiClient) CreateDebugJob() {
job := nomadApi.NewBatchJob("python", "python", "global", 50)
job.AddDatacenter("dc1")
group := nomadApi.NewTaskGroup("python", 5)
task := nomadApi.NewTask("python", "docker")
task.SetConfig("image", "openhpi/co_execenv_python:3.8")
task.SetConfig("command", "sleep")
task.SetConfig("args", []string{"infinity"})
group.AddTask(task)
job.AddTaskGroup(group)
register, w, err := apiClient.client.Jobs().Register(job, nil)
log.Printf("response: %+v", register)
log.Printf("meta: %+v", w)
if err != nil {
log.WithError(err).Fatal("Error creating nomad job")
}
}
// GetJobScale returns the scale of the passed job. // GetJobScale returns the scale of the passed job.
func (apiClient *ApiClient) GetJobScale(jobId string) (jobScale int, err error) { func (apiClient *ApiClient) GetJobScale(jobId string) (jobScale int, err error) {
status, _, err := apiClient.client.Jobs().ScaleStatus(jobId, nil) status, _, err := apiClient.client.Jobs().ScaleStatus(jobId, nil)