Add route to create or update execution environments
This commit is contained in:

committed by
Tobias Kantusch

parent
3d395f0a38
commit
b990df7b9d
15
api/api.go
15
api/api.go
@ -12,9 +12,10 @@ import (
|
||||
var log = logging.GetLogger("api")
|
||||
|
||||
const (
|
||||
BasePath = "/api/v1"
|
||||
HealthPath = "/health"
|
||||
RunnersPath = "/runners"
|
||||
BasePath = "/api/v1"
|
||||
HealthPath = "/health"
|
||||
RunnersPath = "/runners"
|
||||
EnvironmentsPath = "/execution-environments"
|
||||
)
|
||||
|
||||
// NewRouter returns a *mux.Router which can be
|
||||
@ -37,6 +38,12 @@ func configureV1Router(router *mux.Router, runnerManager runner.Manager, environ
|
||||
v1.HandleFunc(HealthPath, Health).Methods(http.MethodGet)
|
||||
|
||||
runnerController := &RunnerController{manager: runnerManager}
|
||||
environmentController := &EnvironmentController{manager: environmentManager}
|
||||
|
||||
configureRoutes := func(router *mux.Router) {
|
||||
runnerController.ConfigureRoutes(router)
|
||||
environmentController.ConfigureRoutes(router)
|
||||
}
|
||||
|
||||
if auth.InitializeAuthentication() {
|
||||
// Create new authenticated subrouter.
|
||||
@ -45,6 +52,6 @@ func configureV1Router(router *mux.Router, runnerManager runner.Manager, environ
|
||||
authenticatedV1Router.Use(auth.HTTPAuthenticationMiddleware)
|
||||
runnerController.ConfigureRoutes(authenticatedV1Router)
|
||||
} else {
|
||||
runnerController.ConfigureRoutes(v1)
|
||||
configureRoutes(v1)
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,13 @@ func (er *ExecutionRequest) FullCommand() []string {
|
||||
}
|
||||
|
||||
// ExecutionEnvironmentRequest is the expected json structure of the request body for the create execution environment function.
|
||||
// nolint:unused,structcheck
|
||||
type ExecutionEnvironmentRequest struct {
|
||||
prewarmingPoolSize uint
|
||||
cpuLimit uint
|
||||
memoryLimit uint
|
||||
image string
|
||||
networkAccess bool
|
||||
exposedPorts []uint16
|
||||
PrewarmingPoolSize uint `json:"prewarmingPoolSize"`
|
||||
CPULimit uint `json:"cpuLimit"`
|
||||
MemoryLimit uint `json:"memoryLimit"`
|
||||
Image string `json:"image"`
|
||||
NetworkAccess bool `json:"networkAccess"`
|
||||
ExposedPorts []uint16 `json:"exposedPorts"`
|
||||
}
|
||||
|
||||
// RunnerResponse is the expected response when providing a runner.
|
||||
|
@ -1,17 +1,53 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/api/dto"
|
||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/environment"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
executionEnvironmentIDKey = "executionEnvironmentId"
|
||||
createOrUpdateRouteName = "createOrUpdate"
|
||||
)
|
||||
|
||||
type EnvironmentController struct {
|
||||
manager environment.Manager // nolint:unused,structcheck
|
||||
manager environment.Manager
|
||||
}
|
||||
|
||||
// create creates a new execution environment on the executor.
|
||||
func (e *EnvironmentController) create(writer http.ResponseWriter, request *http.Request) { // nolint:unused
|
||||
func (e *EnvironmentController) ConfigureRoutes(router *mux.Router) {
|
||||
environmentRouter := router.PathPrefix(EnvironmentsPath).Subrouter()
|
||||
specificEnvironmentRouter := environmentRouter.Path(fmt.Sprintf("/{%s:[0-9]+}", executionEnvironmentIDKey)).Subrouter()
|
||||
specificEnvironmentRouter.HandleFunc("", e.createOrUpdate).Methods(http.MethodPut).Name(createOrUpdateRouteName)
|
||||
}
|
||||
|
||||
// createOrUpdate creates/updates an execution environment on the executor.
|
||||
func (e *EnvironmentController) createOrUpdate(writer http.ResponseWriter, request *http.Request) {
|
||||
req := new(dto.ExecutionEnvironmentRequest)
|
||||
if err := json.NewDecoder(request.Body).Decode(req); err != nil {
|
||||
writeBadRequest(writer, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, ok := mux.Vars(request)[executionEnvironmentIDKey]
|
||||
if !ok {
|
||||
writeBadRequest(writer, fmt.Errorf("could not find %s", executionEnvironmentIDKey))
|
||||
return
|
||||
}
|
||||
|
||||
created, err := e.manager.CreateOrUpdate(id, *req)
|
||||
if err != nil {
|
||||
writeInternalServerError(writer, err, dto.ErrorUnknown)
|
||||
}
|
||||
|
||||
if created {
|
||||
writer.WriteHeader(http.StatusCreated)
|
||||
} else {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
// delete removes an execution environment from the executor
|
||||
|
100
api/environments_test.go
Normal file
100
api/environments_test.go
Normal file
@ -0,0 +1,100 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/api/dto"
|
||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/environment"
|
||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/tests"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type EnvironmentControllerTestSuite struct {
|
||||
suite.Suite
|
||||
manager *environment.ManagerMock
|
||||
router *mux.Router
|
||||
}
|
||||
|
||||
func TestEnvironmentControllerTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(EnvironmentControllerTestSuite))
|
||||
}
|
||||
|
||||
func (s *EnvironmentControllerTestSuite) SetupTest() {
|
||||
s.manager = &environment.ManagerMock{}
|
||||
s.router = NewRouter(nil, s.manager)
|
||||
}
|
||||
|
||||
type CreateOrUpdateEnvironmentTestSuite struct {
|
||||
EnvironmentControllerTestSuite
|
||||
path string
|
||||
id string
|
||||
body []byte
|
||||
}
|
||||
|
||||
func TestCreateOrUpdateEnvironmentTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(CreateOrUpdateEnvironmentTestSuite))
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) SetupTest() {
|
||||
s.EnvironmentControllerTestSuite.SetupTest()
|
||||
s.id = tests.DefaultEnvironmentIdAsString
|
||||
testURL, err := s.router.Get(createOrUpdateRouteName).URL(executionEnvironmentIDKey, s.id)
|
||||
if err != nil {
|
||||
s.T().Fatal(err)
|
||||
}
|
||||
s.path = testURL.String()
|
||||
s.body, err = json.Marshal(dto.ExecutionEnvironmentRequest{})
|
||||
if err != nil {
|
||||
s.T().Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) recordRequest() *httptest.ResponseRecorder {
|
||||
recorder := httptest.NewRecorder()
|
||||
request, err := http.NewRequest(http.MethodPut, s.path, bytes.NewReader(s.body))
|
||||
if err != nil {
|
||||
s.T().Fatal(err)
|
||||
}
|
||||
s.router.ServeHTTP(recorder, request)
|
||||
return recorder
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) TestReturnsBadRequestWhenBadBody() {
|
||||
s.body = []byte{}
|
||||
recorder := s.recordRequest()
|
||||
s.Equal(http.StatusBadRequest, recorder.Code)
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) TestReturnsInternalServerErrorWhenManagerReturnsError() {
|
||||
testError := tests.DefaultError
|
||||
s.manager.
|
||||
On("CreateOrUpdate", s.id, mock.AnythingOfType("dto.ExecutionEnvironmentRequest")).
|
||||
Return(false, testError)
|
||||
|
||||
recorder := s.recordRequest()
|
||||
s.Equal(http.StatusInternalServerError, recorder.Code)
|
||||
s.Contains(recorder.Body.String(), testError.Error())
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) TestReturnsCreatedIfNewEnvironment() {
|
||||
s.manager.
|
||||
On("CreateOrUpdate", s.id, mock.AnythingOfType("dto.ExecutionEnvironmentRequest")).
|
||||
Return(true, nil)
|
||||
|
||||
recorder := s.recordRequest()
|
||||
s.Equal(http.StatusCreated, recorder.Code)
|
||||
}
|
||||
|
||||
func (s *CreateOrUpdateEnvironmentTestSuite) TestReturnsNoContentIfNotNewEnvironment() {
|
||||
s.manager.
|
||||
On("CreateOrUpdate", s.id, mock.AnythingOfType("dto.ExecutionEnvironmentRequest")).
|
||||
Return(false, nil)
|
||||
|
||||
recorder := s.recordRequest()
|
||||
s.Equal(http.StatusNoContent, recorder.Code)
|
||||
}
|
Reference in New Issue
Block a user