Add config option to enable (m)TLS between Poseidon and Nomad
This commit is contained in:

committed by
Jan-Eric Hellenberg

parent
e2d71a11ad
commit
6a60b6cd89
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ tests/e2e/configuration.yaml
|
|||||||
# TLS certificate/key
|
# TLS certificate/key
|
||||||
*.crt
|
*.crt
|
||||||
*.key
|
*.key
|
||||||
|
*.pem
|
||||||
|
|
||||||
# trivy artifacts
|
# trivy artifacts
|
||||||
.trivy
|
.trivy
|
||||||
|
@ -101,7 +101,7 @@ Once configured, all requests to the Nomad API automatically contain a `X-Nomad-
|
|||||||
|
|
||||||
### TLS
|
### TLS
|
||||||
|
|
||||||
We highly encourage the use of TLS in this API to increase the security. To enable TLS, set `server.tls` or the corresponding environment variable to true and specify the `server.certfile` and `server.keyfile` options.
|
We highly encourage the use of TLS in this API to increase the security. To enable TLS, set `server.tls.active` or the corresponding environment variable to true and specify the `server.tls.certfile` and `server.tls.keyfile` options.
|
||||||
|
|
||||||
You can create a self-signed certificate to use with this API using the following command.
|
You can create a self-signed certificate to use with this API using the following command.
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ var (
|
|||||||
func runServer(server *http.Server) {
|
func runServer(server *http.Server) {
|
||||||
log.WithField("address", server.Addr).Info("Starting server")
|
log.WithField("address", server.Addr).Info("Starting server")
|
||||||
var err error
|
var err error
|
||||||
if config.Config.Server.TLS {
|
if config.Config.Server.TLS.Active {
|
||||||
server.TLSConfig = config.TLSConfig
|
server.TLSConfig = config.TLSConfig
|
||||||
log.
|
log.
|
||||||
WithField("CertFile", config.Config.Server.CertFile).
|
WithField("CertFile", config.Config.Server.TLS.CertFile).
|
||||||
WithField("KeyFile", config.Config.Server.KeyFile).
|
WithField("KeyFile", config.Config.Server.TLS.KeyFile).
|
||||||
Debug("Using TLS")
|
Debug("Using TLS")
|
||||||
err = server.ListenAndServeTLS(config.Config.Server.CertFile, config.Config.Server.KeyFile)
|
err = server.ListenAndServeTLS(config.Config.Server.TLS.CertFile, config.Config.Server.TLS.KeyFile)
|
||||||
} else {
|
} else {
|
||||||
err = server.ListenAndServe()
|
err = server.ListenAndServe()
|
||||||
}
|
}
|
||||||
@ -45,20 +45,16 @@ func runServer(server *http.Server) {
|
|||||||
|
|
||||||
func initServer() *http.Server {
|
func initServer() *http.Server {
|
||||||
// API initialization
|
// API initialization
|
||||||
nomadAPIClient, err := nomad.NewExecutorAPI(
|
nomadAPIClient, err := nomad.NewExecutorAPI(&config.Config.Nomad)
|
||||||
config.Config.NomadAPIURL(),
|
|
||||||
config.Config.Nomad.Namespace,
|
|
||||||
config.Config.Nomad.Token,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).WithField("nomad url", config.Config.NomadAPIURL()).Fatal("Error parsing the nomad url")
|
log.WithError(err).WithField("nomad config", config.Config.Nomad).Fatal("Error creating Nomad API client")
|
||||||
}
|
}
|
||||||
|
|
||||||
runnerManager := runner.NewNomadRunnerManager(nomadAPIClient, context.Background())
|
runnerManager := runner.NewNomadRunnerManager(nomadAPIClient, context.Background())
|
||||||
environmentManager := environment.NewNomadEnvironmentManager(runnerManager, nomadAPIClient)
|
environmentManager := environment.NewNomadEnvironmentManager(runnerManager, nomadAPIClient)
|
||||||
|
|
||||||
return &http.Server{
|
return &http.Server{
|
||||||
Addr: config.Config.PoseidonAPIURL().Host,
|
Addr: config.Config.Server.URL().Host,
|
||||||
WriteTimeout: time.Second * 15,
|
WriteTimeout: time.Second * 15,
|
||||||
ReadTimeout: time.Second * 15,
|
ReadTimeout: time.Second * 15,
|
||||||
IdleTimeout: time.Second * 60,
|
IdleTimeout: time.Second * 60,
|
||||||
|
@ -6,12 +6,14 @@ server:
|
|||||||
port: 7200
|
port: 7200
|
||||||
# If set, this token is required in the X-Poseidon-Token header for each route except /health
|
# If set, this token is required in the X-Poseidon-Token header for each route except /health
|
||||||
token: SECRET
|
token: SECRET
|
||||||
# If set, the API uses TLS for all incoming connections
|
# Configuration of TLS between the web client and Poseidon.
|
||||||
tls: true
|
tls:
|
||||||
# The path to the certificate file used for TLS
|
# If set, the API uses TLS for all incoming connections.
|
||||||
certfile: ./poseidon.crt
|
active: true
|
||||||
# The path to the key file used for TLS
|
# The path to the certificate file used for TLS
|
||||||
keyfile: ./poseidon.key
|
certfile: ./poseidon.crt
|
||||||
|
# The path to the key file used for TLS
|
||||||
|
keyfile: ./poseidon.key
|
||||||
# If true, an additional WebSocket connection will be opened to split stdout and stderr when executing interactively
|
# If true, an additional WebSocket connection will be opened to split stdout and stderr when executing interactively
|
||||||
interactiveStderr: true
|
interactiveStderr: true
|
||||||
|
|
||||||
@ -23,8 +25,16 @@ nomad:
|
|||||||
port: 4646
|
port: 4646
|
||||||
# Authenticate requests to the Nomad server with this token
|
# Authenticate requests to the Nomad server with this token
|
||||||
token: SECRET
|
token: SECRET
|
||||||
# Specifies whether to use TLS when communicating with the Nomad server
|
# Configuration of TLS between the Poseidon and Nomad.
|
||||||
tls: false
|
tls:
|
||||||
|
# Specifies whether to use TLS when communicating with the Nomad server.
|
||||||
|
active: false
|
||||||
|
# The path to the certificate of the CA authority of the Nomad host.
|
||||||
|
cafile: ./ca.crt
|
||||||
|
# The path to the client certificate file used for TLS
|
||||||
|
certfile: ./poseidon.crt
|
||||||
|
# The path to the client key file used for TLS
|
||||||
|
keyfile: ./poseidon.key
|
||||||
# Nomad namespace to use. If unset, 'default' is used
|
# Nomad namespace to use. If unset, 'default' is used
|
||||||
namespace: poseidon
|
namespace: poseidon
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ func (r *RunnerController) execute(writer http.ResponseWriter, request *http.Req
|
|||||||
}
|
}
|
||||||
|
|
||||||
var scheme string
|
var scheme string
|
||||||
if config.Config.Server.TLS {
|
if config.Config.Server.TLS.Active {
|
||||||
scheme = "wss"
|
scheme = "wss"
|
||||||
} else {
|
} else {
|
||||||
scheme = "ws"
|
scheme = "ws"
|
||||||
|
@ -19,19 +19,26 @@ import (
|
|||||||
var (
|
var (
|
||||||
Config = &configuration{
|
Config = &configuration{
|
||||||
Server: server{
|
Server: server{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
Port: 7200,
|
Port: 7200,
|
||||||
Token: "",
|
Token: "",
|
||||||
TLS: false,
|
TLS: TLS{
|
||||||
CertFile: "",
|
Active: false,
|
||||||
KeyFile: "",
|
CertFile: "",
|
||||||
|
KeyFile: "",
|
||||||
|
},
|
||||||
InteractiveStderr: true,
|
InteractiveStderr: true,
|
||||||
},
|
},
|
||||||
Nomad: nomad{
|
Nomad: Nomad{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
Port: 4646,
|
Port: 4646,
|
||||||
Token: "",
|
Token: "",
|
||||||
TLS: false,
|
TLS: TLS{
|
||||||
|
Active: false,
|
||||||
|
CAFile: "",
|
||||||
|
CertFile: "",
|
||||||
|
KeyFile: "",
|
||||||
|
},
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
},
|
},
|
||||||
Logger: logger{
|
Logger: logger{
|
||||||
@ -54,21 +61,37 @@ type server struct {
|
|||||||
Address string
|
Address string
|
||||||
Port int
|
Port int
|
||||||
Token string
|
Token string
|
||||||
TLS bool
|
TLS TLS
|
||||||
CertFile string
|
|
||||||
KeyFile string
|
|
||||||
InteractiveStderr bool
|
InteractiveStderr bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// nomad configures the used Nomad cluster.
|
// URL returns the URL of the Poseidon webserver.
|
||||||
type nomad struct {
|
func (s *server) URL() *url.URL {
|
||||||
|
return parseURL(s.Address, s.Port, s.TLS.Active)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nomad configures the used Nomad cluster.
|
||||||
|
type Nomad struct {
|
||||||
Address string
|
Address string
|
||||||
Port int
|
Port int
|
||||||
Token string
|
Token string
|
||||||
TLS bool
|
TLS TLS
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URL returns the URL for the configured Nomad cluster.
|
||||||
|
func (n *Nomad) URL() *url.URL {
|
||||||
|
return parseURL(n.Address, n.Port, n.TLS.Active)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TLS configures TLS on a connection.
|
||||||
|
type TLS struct {
|
||||||
|
Active bool
|
||||||
|
CAFile string
|
||||||
|
CertFile string
|
||||||
|
KeyFile string
|
||||||
|
}
|
||||||
|
|
||||||
// logger configures the used logger.
|
// logger configures the used logger.
|
||||||
type logger struct {
|
type logger struct {
|
||||||
Level string
|
Level string
|
||||||
@ -77,7 +100,7 @@ type logger struct {
|
|||||||
// configuration contains the complete configuration of Poseidon.
|
// configuration contains the complete configuration of Poseidon.
|
||||||
type configuration struct {
|
type configuration struct {
|
||||||
Server server
|
Server server
|
||||||
Nomad nomad
|
Nomad Nomad
|
||||||
Logger logger
|
Logger logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,16 +119,6 @@ func InitConfig() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NomadAPIURL returns the URL for the configured Nomad cluster.
|
|
||||||
func (c *configuration) NomadAPIURL() *url.URL {
|
|
||||||
return parseURL(Config.Nomad.Address, Config.Nomad.Port, Config.Nomad.TLS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PoseidonAPIURL returns the URL of the Poseidon webserver.
|
|
||||||
func (c *configuration) PoseidonAPIURL() *url.URL {
|
|
||||||
return parseURL(Config.Server.Address, Config.Server.Port, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseURL(address string, port int, tlsEnabled bool) *url.URL {
|
func parseURL(address string, port int, tlsEnabled bool) *url.URL {
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
if tlsEnabled {
|
if tlsEnabled {
|
||||||
|
@ -13,9 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
getServerPort = func(c *configuration) interface{} { return c.Server.Port }
|
getServerPort = func(c *configuration) interface{} { return c.Server.Port }
|
||||||
getNomadToken = func(c *configuration) interface{} { return c.Nomad.Token }
|
getNomadToken = func(c *configuration) interface{} { return c.Nomad.Token }
|
||||||
getNomadTLS = func(c *configuration) interface{} { return c.Nomad.TLS }
|
getNomadTLSActive = func(c *configuration) interface{} { return c.Nomad.TLS.Active }
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestConfiguration() *configuration {
|
func newTestConfiguration() *configuration {
|
||||||
@ -24,11 +24,13 @@ func newTestConfiguration() *configuration {
|
|||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
Port: 3000,
|
Port: 3000,
|
||||||
},
|
},
|
||||||
Nomad: nomad{
|
Nomad: Nomad{
|
||||||
Address: "127.0.0.2",
|
Address: "127.0.0.2",
|
||||||
Port: 4646,
|
Port: 4646,
|
||||||
Token: "SECRET",
|
Token: "SECRET",
|
||||||
TLS: false,
|
TLS: TLS{
|
||||||
|
Active: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Logger: logger{
|
Logger: logger{
|
||||||
Level: "INFO",
|
Level: "INFO",
|
||||||
@ -87,8 +89,8 @@ func TestReadEnvironmentVariables(t *testing.T) {
|
|||||||
{"SERVER_PORT", "4000", 4000, getServerPort},
|
{"SERVER_PORT", "4000", 4000, getServerPort},
|
||||||
{"SERVER_PORT", "hello", 3000, getServerPort},
|
{"SERVER_PORT", "hello", 3000, getServerPort},
|
||||||
{"NOMAD_TOKEN", "ACCESS", "ACCESS", getNomadToken},
|
{"NOMAD_TOKEN", "ACCESS", "ACCESS", getNomadToken},
|
||||||
{"NOMAD_TLS", "true", true, getNomadTLS},
|
{"NOMAD_TLS_ACTIVE", "true", true, getNomadTLSActive},
|
||||||
{"NOMAD_TLS", "hello", false, getNomadTLS},
|
{"NOMAD_TLS_ACTIVE", "hello", false, getNomadTLSActive},
|
||||||
}
|
}
|
||||||
prefix := "POSEIDON_TEST"
|
prefix := "POSEIDON_TEST"
|
||||||
for _, testCase := range environmentTests {
|
for _, testCase := range environmentTests {
|
||||||
@ -131,8 +133,8 @@ func TestReadYamlConfigFile(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{[]byte("server:\n port: 5000\n"), 5000, getServerPort},
|
{[]byte("server:\n port: 5000\n"), 5000, getServerPort},
|
||||||
{[]byte("nomad:\n token: ACCESS\n"), "ACCESS", getNomadToken},
|
{[]byte("nomad:\n token: ACCESS\n"), "ACCESS", getNomadToken},
|
||||||
{[]byte("nomad:\n tls: true\n"), true, getNomadTLS},
|
{[]byte("nomad:\n tls:\n active: true\n"), true, getNomadTLSActive},
|
||||||
{[]byte(""), false, getNomadTLS},
|
{[]byte(""), false, getNomadTLSActive},
|
||||||
{[]byte("nomad:\n token:\n"), "SECRET", getNomadToken},
|
{[]byte("nomad:\n token:\n"), "SECRET", getNomadToken},
|
||||||
}
|
}
|
||||||
for _, testCase := range yamlTests {
|
for _, testCase := range yamlTests {
|
||||||
@ -197,12 +199,12 @@ func TestURLParsing(t *testing.T) {
|
|||||||
|
|
||||||
func TestNomadAPIURL(t *testing.T) {
|
func TestNomadAPIURL(t *testing.T) {
|
||||||
config := newTestConfiguration()
|
config := newTestConfiguration()
|
||||||
assert.Equal(t, "http", config.NomadAPIURL().Scheme)
|
assert.Equal(t, "http", config.Nomad.URL().Scheme)
|
||||||
assert.Equal(t, "127.0.0.2:4646", config.NomadAPIURL().Host)
|
assert.Equal(t, "127.0.0.2:4646", config.Nomad.URL().Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoseidonAPIURL(t *testing.T) {
|
func TestPoseidonAPIURL(t *testing.T) {
|
||||||
config := newTestConfiguration()
|
config := newTestConfiguration()
|
||||||
assert.Equal(t, "http", config.PoseidonAPIURL().Scheme)
|
assert.Equal(t, "http", config.Server.URL().Scheme)
|
||||||
assert.Equal(t, "127.0.0.1:3000", config.PoseidonAPIURL().Host)
|
assert.Equal(t, "127.0.0.1:3000", config.Server.URL().Host)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
nomadApi "github.com/hashicorp/nomad/api"
|
nomadApi "github.com/hashicorp/nomad/api"
|
||||||
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/internal/config"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -16,7 +16,7 @@ var (
|
|||||||
// apiQuerier provides access to the Nomad functionality.
|
// apiQuerier provides access to the Nomad functionality.
|
||||||
type apiQuerier interface {
|
type apiQuerier interface {
|
||||||
// init prepares an apiClient to be able to communicate to a provided Nomad API.
|
// init prepares an apiClient to be able to communicate to a provided Nomad API.
|
||||||
init(nomadURL *url.URL, nomadNamespace, nomadToken string) (err error)
|
init(nomadConfig *config.Nomad) (err error)
|
||||||
|
|
||||||
// LoadJobList loads the list of jobs from the Nomad API.
|
// LoadJobList loads the list of jobs from the Nomad API.
|
||||||
LoadJobList() (list []*nomadApi.JobListStub, err error)
|
LoadJobList() (list []*nomadApi.JobListStub, err error)
|
||||||
@ -61,17 +61,24 @@ type nomadAPIClient struct {
|
|||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nc *nomadAPIClient) init(nomadURL *url.URL, nomadNamespace, nomadToken string) (err error) {
|
func (nc *nomadAPIClient) init(nomadConfig *config.Nomad) (err error) {
|
||||||
|
nomadTLSConfig := &nomadApi.TLSConfig{}
|
||||||
|
if nomadConfig.TLS.Active {
|
||||||
|
nomadTLSConfig.CACert = nomadConfig.TLS.CAFile
|
||||||
|
nomadTLSConfig.ClientCert = nomadConfig.TLS.CertFile
|
||||||
|
nomadTLSConfig.ClientKey = nomadConfig.TLS.KeyFile
|
||||||
|
}
|
||||||
|
|
||||||
nc.client, err = nomadApi.NewClient(&nomadApi.Config{
|
nc.client, err = nomadApi.NewClient(&nomadApi.Config{
|
||||||
Address: nomadURL.String(),
|
Address: nomadConfig.URL().String(),
|
||||||
TLSConfig: &nomadApi.TLSConfig{},
|
TLSConfig: nomadTLSConfig,
|
||||||
Namespace: nomadNamespace,
|
Namespace: nomadConfig.Namespace,
|
||||||
SecretID: nomadToken,
|
SecretID: nomadConfig.Token,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating new Nomad client: %w", err)
|
return fmt.Errorf("error creating new Nomad client: %w", err)
|
||||||
}
|
}
|
||||||
nc.namespace = nomadNamespace
|
nc.namespace = nomadConfig.Namespace
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,11 @@ import (
|
|||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
api "github.com/hashicorp/nomad/api"
|
api "github.com/hashicorp/nomad/api"
|
||||||
|
config "gitlab.hpi.de/codeocean/codemoon/poseidon/internal/config"
|
||||||
|
|
||||||
io "io"
|
io "io"
|
||||||
|
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
url "net/url"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// apiQuerierMock is an autogenerated mock type for the apiQuerier type
|
// apiQuerierMock is an autogenerated mock type for the apiQuerier type
|
||||||
@ -202,13 +201,13 @@ func (_m *apiQuerierMock) allocation(jobID string) (*api.Allocation, error) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// init provides a mock function with given fields: nomadURL, nomadNamespace, nomadToken
|
// init provides a mock function with given fields: nomadConfig
|
||||||
func (_m *apiQuerierMock) init(nomadURL *url.URL, nomadNamespace string, nomadToken string) error {
|
func (_m *apiQuerierMock) init(nomadConfig *config.Nomad) error {
|
||||||
ret := _m.Called(nomadURL, nomadNamespace, nomadToken)
|
ret := _m.Called(nomadConfig)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(*url.URL, string, string) error); ok {
|
if rf, ok := ret.Get(0).(func(*config.Nomad) error); ok {
|
||||||
r0 = rf(nomadURL, nomadNamespace, nomadToken)
|
r0 = rf(nomadConfig)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,11 @@ import (
|
|||||||
context "context"
|
context "context"
|
||||||
|
|
||||||
api "github.com/hashicorp/nomad/api"
|
api "github.com/hashicorp/nomad/api"
|
||||||
|
config "gitlab.hpi.de/codeocean/codemoon/poseidon/internal/config"
|
||||||
|
|
||||||
io "io"
|
io "io"
|
||||||
|
|
||||||
mock "github.com/stretchr/testify/mock"
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
url "net/url"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExecutorAPIMock is an autogenerated mock type for the ExecutorAPI type
|
// ExecutorAPIMock is an autogenerated mock type for the ExecutorAPI type
|
||||||
@ -394,13 +393,13 @@ func (_m *ExecutorAPIMock) allocation(jobID string) (*api.Allocation, error) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// init provides a mock function with given fields: nomadURL, nomadNamespace, nomadToken
|
// init provides a mock function with given fields: nomadConfig
|
||||||
func (_m *ExecutorAPIMock) init(nomadURL *url.URL, nomadNamespace string, nomadToken string) error {
|
func (_m *ExecutorAPIMock) init(nomadConfig *config.Nomad) error {
|
||||||
ret := _m.Called(nomadURL, nomadNamespace, nomadToken)
|
ret := _m.Called(nomadConfig)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(*url.URL, string, string) error); ok {
|
if rf, ok := ret.Get(0).(func(*config.Nomad) error); ok {
|
||||||
r0 = rf(nomadURL, nomadNamespace, nomadToken)
|
r0 = rf(nomadConfig)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/pkg/logging"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/pkg/logging"
|
||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/pkg/nullio"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/pkg/nullio"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -81,15 +80,15 @@ type APIClient struct {
|
|||||||
|
|
||||||
// NewExecutorAPI creates a new api client.
|
// NewExecutorAPI creates a new api client.
|
||||||
// One client is usually sufficient for the complete runtime of the API.
|
// One client is usually sufficient for the complete runtime of the API.
|
||||||
func NewExecutorAPI(nomadURL *url.URL, nomadNamespace, nomadToken string) (ExecutorAPI, error) {
|
func NewExecutorAPI(nomadConfig *config.Nomad) (ExecutorAPI, error) {
|
||||||
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
||||||
err := client.init(nomadURL, nomadNamespace, nomadToken)
|
err := client.init(nomadConfig)
|
||||||
return client, err
|
return client, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// init prepares an apiClient to be able to communicate to a provided Nomad API.
|
// init prepares an apiClient to be able to communicate to a provided Nomad API.
|
||||||
func (a *APIClient) init(nomadURL *url.URL, nomadNamespace, nomadToken string) error {
|
func (a *APIClient) init(nomadConfig *config.Nomad) error {
|
||||||
if err := a.apiQuerier.init(nomadURL, nomadNamespace, nomadToken); err != nil {
|
if err := a.apiQuerier.init(nomadConfig); err != nil {
|
||||||
return fmt.Errorf("error initializing API querier: %w", err)
|
return fmt.Errorf("error initializing API querier: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -131,28 +131,38 @@ var (
|
|||||||
|
|
||||||
const TestNamespace = "unit-tests"
|
const TestNamespace = "unit-tests"
|
||||||
const TestNomadToken = "n0m4d-t0k3n"
|
const TestNomadToken = "n0m4d-t0k3n"
|
||||||
|
const TestDefaultAddress = "127.0.0.1"
|
||||||
|
|
||||||
|
func NomadTestConfig(address string) *config.Nomad {
|
||||||
|
return &config.Nomad{
|
||||||
|
Address: address,
|
||||||
|
Port: 4646,
|
||||||
|
Token: TestNomadToken,
|
||||||
|
TLS: config.TLS{
|
||||||
|
Active: false,
|
||||||
|
},
|
||||||
|
Namespace: TestNamespace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestApiClient_init(t *testing.T) {
|
func TestApiClient_init(t *testing.T) {
|
||||||
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
||||||
err := client.init(&TestURL, TestNamespace, TestNomadToken)
|
err := client.init(NomadTestConfig(TestDefaultAddress))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApiClientCanNotBeInitializedWithInvalidUrl(t *testing.T) {
|
func TestApiClientCanNotBeInitializedWithInvalidUrl(t *testing.T) {
|
||||||
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
client := &APIClient{apiQuerier: &nomadAPIClient{}}
|
||||||
err := client.init(&url.URL{
|
err := client.init(NomadTestConfig("http://" + TestDefaultAddress))
|
||||||
Scheme: "http",
|
|
||||||
Host: "http://127.0.0.1:4646",
|
|
||||||
}, TestNamespace, TestNomadToken)
|
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewExecutorApiCanBeCreatedWithoutError(t *testing.T) {
|
func TestNewExecutorApiCanBeCreatedWithoutError(t *testing.T) {
|
||||||
expectedClient := &APIClient{apiQuerier: &nomadAPIClient{}}
|
expectedClient := &APIClient{apiQuerier: &nomadAPIClient{}}
|
||||||
err := expectedClient.init(&TestURL, TestNamespace, TestNomadToken)
|
err := expectedClient.init(NomadTestConfig(TestDefaultAddress))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
_, err = NewExecutorAPI(&TestURL, TestNamespace, TestNomadToken)
|
_, err = NewExecutorAPI(NomadTestConfig(TestDefaultAddress))
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
nomadNamespace = config.Config.Nomad.Namespace
|
nomadNamespace = config.Config.Nomad.Namespace
|
||||||
nomadClient, err = nomadApi.NewClient(&nomadApi.Config{
|
nomadClient, err = nomadApi.NewClient(&nomadApi.Config{
|
||||||
Address: config.Config.NomadAPIURL().String(),
|
Address: config.Config.Nomad.URL().String(),
|
||||||
TLSConfig: &nomadApi.TLSConfig{},
|
TLSConfig: &nomadApi.TLSConfig{},
|
||||||
Namespace: nomadNamespace,
|
Namespace: nomadNamespace,
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
// BuildURL joins multiple route paths.
|
// BuildURL joins multiple route paths.
|
||||||
func BuildURL(parts ...string) string {
|
func BuildURL(parts ...string) string {
|
||||||
url := config.Config.PoseidonAPIURL().String()
|
url := config.Config.Server.URL().String()
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
if !strings.HasPrefix(part, "/") {
|
if !strings.HasPrefix(part, "/") {
|
||||||
url += "/"
|
url += "/"
|
||||||
|
Reference in New Issue
Block a user