Implement merge request review comments
This commit is contained in:
@ -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
|
||||||
|
@ -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
50
ci/python.nomad
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
36
e2e_tests/e2e_test.go
Normal 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, "")
|
||||||
|
}
|
@ -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")
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package e2e
|
package e2e_tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
32
main_test.go
32
main_test.go
@ -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()
|
|
||||||
}
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Reference in New Issue
Block a user