added k8s stub adapter for execution environment

This commit is contained in:
Elmar Kresse
2024-09-18 10:43:38 +02:00
parent f9a6ba8f1c
commit 12ff205bd2
119 changed files with 1374 additions and 12549 deletions

View File

@ -13,6 +13,7 @@ import (
"github.com/openHPI/poseidon/pkg/logging"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"k8s.io/client-go/rest"
"net/url"
"os"
"reflect"
@ -66,6 +67,17 @@ var (
DNS: nil,
},
},
Kubernetes: Kubernetes{
Enabled: false,
KubeConfig: rest.Config{
Host: "",
TLSClientConfig: rest.TLSClientConfig{
Insecure: false,
ServerName: "",
},
BearerToken: "",
},
},
AWS: AWS{
Enabled: false,
Endpoint: "",
@ -134,6 +146,11 @@ type Nomad struct {
Network nomadApi.NetworkResource
}
type Kubernetes struct {
Enabled bool
KubeConfig rest.Config
}
// URL returns the URL for the configured Nomad cluster.
func (n *Nomad) URL() *url.URL {
return parseURL(n.Address, n.Port, n.TLS.Active)
@ -179,13 +196,14 @@ type InfluxDB struct {
// configuration contains the complete configuration of Poseidon.
type configuration struct {
Server server
Nomad Nomad
AWS AWS
Logger Logger
Profiling Profiling
Sentry sentry.ClientOptions
InfluxDB InfluxDB
Server server
Nomad Nomad
Kubernetes Kubernetes
AWS AWS
Logger Logger
Profiling Profiling
Sentry sentry.ClientOptions
InfluxDB InfluxDB
}
// InitConfig merges configuration options from environment variables and

View File

@ -1,223 +0,0 @@
package config
import (
"fmt"
"github.com/openHPI/poseidon/tests"
"github.com/sirupsen/logrus"
"github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"os"
"path/filepath"
"reflect"
"testing"
)
var (
getServerPort = func(c *configuration) interface{} { return c.Server.Port }
getNomadToken = func(c *configuration) interface{} { return c.Nomad.Token }
getNomadTLSActive = func(c *configuration) interface{} { return c.Nomad.TLS.Active }
getAWSFunctions = func(c *configuration) interface{} { return c.AWS.Functions }
)
func newTestConfiguration() *configuration {
return &configuration{
Server: server{
Address: "127.0.0.1",
Port: 3000,
},
Nomad: Nomad{
Address: "127.0.0.2",
Port: 4646,
Token: "SECRET",
TLS: TLS{
Active: false,
},
},
Logger: Logger{
Level: "INFO",
},
}
}
func (c *configuration) getReflectValue() reflect.Value {
return reflect.ValueOf(c).Elem()
}
// writeConfigurationFile creates a file on disk and returns the path to it.
func writeConfigurationFile(t *testing.T, name string, content []byte) string {
t.Helper()
directory := t.TempDir()
filePath := filepath.Join(directory, name)
file, err := os.Create(filePath)
if err != nil {
t.Fatal("Could not create config file")
}
defer file.Close()
_, err = file.Write(content)
require.NoError(t, err)
return filePath
}
type MainTestSuite struct {
tests.MemoryLeakTestSuite
}
func TestMainTestSuite(t *testing.T) {
suite.Run(t, new(MainTestSuite))
}
func (s *MainTestSuite) TestCallingInitConfigTwiceReturnsError() {
configurationInitialized = false
err := InitConfig()
s.NoError(err)
err = InitConfig()
s.Error(err)
}
func (s *MainTestSuite) TestCallingInitConfigTwiceDoesNotChangeConfig() {
configurationInitialized = false
err := InitConfig()
s.Require().NoError(err)
Config = newTestConfiguration()
filePath := writeConfigurationFile(s.T(), "test.yaml", []byte("server:\n port: 5000\n"))
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = append(os.Args, "-config", filePath)
err = InitConfig()
s.Require().Error(err)
s.Equal(3000, Config.Server.Port)
}
func (s *MainTestSuite) TestReadEnvironmentVariables() {
var environmentTests = []struct {
variableSuffix string
valueToSet string
expectedValue interface{}
getTargetField func(*configuration) interface{}
}{
{"SERVER_PORT", "4000", 4000, getServerPort},
{"SERVER_PORT", "hello", 3000, getServerPort},
{"NOMAD_TOKEN", "ACCESS", "ACCESS", getNomadToken},
{"NOMAD_TLS_ACTIVE", "true", true, getNomadTLSActive},
{"NOMAD_TLS_ACTIVE", "hello", false, getNomadTLSActive},
{"AWS_FUNCTIONS", "java11Exec go118Exec", []string{"java11Exec", "go118Exec"}, getAWSFunctions},
}
prefix := "POSEIDON_TEST"
for _, testCase := range environmentTests {
config := newTestConfiguration()
environmentVariable := fmt.Sprintf("%s_%s", prefix, testCase.variableSuffix)
_ = os.Setenv(environmentVariable, testCase.valueToSet)
readFromEnvironment(prefix, config.getReflectValue())
_ = os.Unsetenv(environmentVariable)
s.Equal(testCase.expectedValue, testCase.getTargetField(config))
}
}
func (s *MainTestSuite) TestReadEnvironmentIgnoresNonPointerValue() {
config := newTestConfiguration()
_ = os.Setenv("POSEIDON_TEST_SERVER_PORT", "4000")
readFromEnvironment("POSEIDON_TEST", reflect.ValueOf(config))
_ = os.Unsetenv("POSEIDON_TEST_SERVER_PORT")
s.Equal(3000, config.Server.Port)
}
func (s *MainTestSuite) TestReadEnvironmentIgnoresNotSupportedType() {
config := &struct{ Timeout float64 }{1.0}
_ = os.Setenv("POSEIDON_TEST_TIMEOUT", "2.5")
readFromEnvironment("POSEIDON_TEST", reflect.ValueOf(config).Elem())
_ = os.Unsetenv("POSEIDON_TEST_TIMEOUT")
s.Equal(1.0, config.Timeout)
}
func (s *MainTestSuite) TestUnsetEnvironmentVariableDoesNotChangeConfig() {
config := newTestConfiguration()
readFromEnvironment("POSEIDON_TEST", config.getReflectValue())
s.Equal("INFO", config.Logger.Level)
}
func (s *MainTestSuite) TestReadYamlConfigFile() {
var yamlTests = []struct {
content []byte
expectedValue interface{}
getTargetField func(*configuration) interface{}
}{
{[]byte("server:\n port: 5000\n"), 5000, getServerPort},
{[]byte("nomad:\n token: ACCESS\n"), "ACCESS", getNomadToken},
{[]byte("nomad:\n tls:\n active: true\n"), true, getNomadTLSActive},
{[]byte(""), false, getNomadTLSActive},
{[]byte("nomad:\n token:\n"), "SECRET", getNomadToken},
{[]byte("aws:\n functions:\n - java11Exec\n - go118Exec\n"),
[]string{"java11Exec", "go118Exec"}, getAWSFunctions},
}
for _, testCase := range yamlTests {
config := newTestConfiguration()
config.mergeYaml(testCase.content)
s.Equal(testCase.expectedValue, testCase.getTargetField(config))
}
}
func (s *MainTestSuite) TestInvalidYamlExitsProgram() {
logger, hook := test.NewNullLogger()
// this function is used when calling log.Fatal() and
// prevents the program from exiting during this test
logger.ExitFunc = func(code int) {}
log = logger.WithField("package", "config_test")
config := newTestConfiguration()
config.mergeYaml([]byte("logger: level: DEBUG"))
s.Equal(1, len(hook.Entries))
s.Equal(logrus.FatalLevel, hook.LastEntry().Level)
}
func (s *MainTestSuite) TestReadConfigFileOverwritesConfig() {
Config = newTestConfiguration()
filePath := writeConfigurationFile(s.T(), "test.yaml", []byte("server:\n port: 5000\n"))
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = append(os.Args, "-config", filePath)
configurationInitialized = false
err := InitConfig()
s.Require().NoError(err)
s.Equal(5000, Config.Server.Port)
}
func (s *MainTestSuite) TestReadNonExistingConfigFileDoesNotOverwriteConfig() {
Config = newTestConfiguration()
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
os.Args = append(os.Args, "-config", "file_does_not_exist.yaml")
configurationInitialized = false
err := InitConfig()
s.Require().NoError(err)
s.Equal(3000, Config.Server.Port)
}
func (s *MainTestSuite) TestURLParsing() {
var urlTests = []struct {
address string
port int
tls bool
expectedScheme string
expectedHost string
}{
{"localhost", 3000, false, "http", "localhost:3000"},
{"127.0.0.1", 4000, true, "https", "127.0.0.1:4000"},
}
for _, testCase := range urlTests {
url := parseURL(testCase.address, testCase.port, testCase.tls)
s.Equal(testCase.expectedScheme, url.Scheme)
s.Equal(testCase.expectedHost, url.Host)
}
}
func (s *MainTestSuite) TestNomadAPIURL() {
config := newTestConfiguration()
s.Equal("http", config.Nomad.URL().Scheme)
s.Equal("127.0.0.2:4646", config.Nomad.URL().Host)
}
func (s *MainTestSuite) TestPoseidonAPIURL() {
config := newTestConfiguration()
s.Equal("http", config.Server.URL().Scheme)
s.Equal("127.0.0.1:3000", config.Server.URL().Host)
}