feat: passthrough additional env vars to provider
as some provider binaries probably need additional environment variables set (e.g kubernetes as client-go depends on KUBERNETES_SERVICE_ vars) it should be possible to define a list of environment variables which should get bypassed into the provider binary execution
This commit is contained in:
parent
05e179604d
commit
215bd71855
4 changed files with 145 additions and 8 deletions
|
|
@ -39,6 +39,9 @@ const (
|
|||
MySQLBackend DBBackendType = "mysql"
|
||||
// SQLiteBackend represents the SQLite3 DB backend
|
||||
SQLiteBackend DBBackendType = "sqlite3"
|
||||
// EnvironmentVariablePrefix is the prefix for all environment variables
|
||||
// that can not be used to get overwritten via the external provider
|
||||
EnvironmentVariablePrefix = "GARM"
|
||||
)
|
||||
|
||||
// NewConfig returns a new Config
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudbase/garm-provider-common/util/exec"
|
||||
|
||||
|
|
@ -42,6 +43,25 @@ type External struct {
|
|||
// the provider. If specified, it will take precedence over the "garm-external-provider"
|
||||
// executable in the ProviderDir.
|
||||
ProviderExecutable string `toml:"provider_executable" json:"provider-executable"`
|
||||
// EnvironmentVariables is a list of environment variable names that will be
|
||||
// passed to the external binary together with their values.
|
||||
EnvironmentVariables []string `toml:"environment_variables" json:"environment-variables"`
|
||||
}
|
||||
|
||||
func (e *External) GetEnvironmentVariables() []string {
|
||||
envVars := []string{}
|
||||
|
||||
for _, configuredEnvVars := range e.EnvironmentVariables {
|
||||
// discover environment variables
|
||||
for _, k := range os.Environ() {
|
||||
variable := strings.SplitN(k, "=", 2)
|
||||
if strings.HasPrefix(variable[0], configuredEnvVars) &&
|
||||
!strings.HasPrefix(variable[0], EnvironmentVariablePrefix) {
|
||||
envVars = append(envVars, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return envVars
|
||||
}
|
||||
|
||||
func (e *External) ExecutablePath() (string, error) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -121,3 +122,101 @@ func TestProviderExecutableIsExecutable(t *testing.T) {
|
|||
require.NotNil(t, err)
|
||||
require.EqualError(t, err, fmt.Sprintf("external provider binary %s is not executable", execPath))
|
||||
}
|
||||
|
||||
func TestExternalEnvironmentVariables(t *testing.T) {
|
||||
cfg := getDefaultExternalConfig(t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg External
|
||||
expectedEnvironmentVariables []string
|
||||
environmentVariables map[string]string
|
||||
}{
|
||||
{
|
||||
name: "Provider with no additional environment variables",
|
||||
cfg: cfg,
|
||||
expectedEnvironmentVariables: []string{},
|
||||
environmentVariables: map[string]string{
|
||||
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"PROVIDER_LOG_LEVEL": "debug",
|
||||
"PROVIDER_TIMEOUT": "30",
|
||||
"PROVIDER_RETRY_COUNT": "3",
|
||||
"INFRA_REGION": "us-east-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Provider with additional environment variables",
|
||||
cfg: External{
|
||||
ConfigFile: "",
|
||||
ProviderDir: "../test",
|
||||
EnvironmentVariables: []string{
|
||||
"PROVIDER_",
|
||||
"INFRA_REGION",
|
||||
},
|
||||
},
|
||||
environmentVariables: map[string]string{
|
||||
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"PROVIDER_LOG_LEVEL": "debug",
|
||||
"PROVIDER_TIMEOUT": "30",
|
||||
"PROVIDER_RETRY_COUNT": "3",
|
||||
"INFRA_REGION": "us-east-1",
|
||||
"GARM_POOL_ID": "f3b21376-e189-43ae-a1bd-7a3ffee57a58",
|
||||
},
|
||||
expectedEnvironmentVariables: []string{
|
||||
"PROVIDER_LOG_LEVEL=debug",
|
||||
"PROVIDER_TIMEOUT=30",
|
||||
"PROVIDER_RETRY_COUNT=3",
|
||||
"INFRA_REGION=us-east-1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "GARM variables are getting ignored",
|
||||
cfg: External{
|
||||
ConfigFile: "",
|
||||
ProviderDir: "../test",
|
||||
EnvironmentVariables: []string{
|
||||
"PROVIDER_",
|
||||
"INFRA_REGION",
|
||||
"GARM_SERVER",
|
||||
},
|
||||
},
|
||||
environmentVariables: map[string]string{
|
||||
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"PROVIDER_LOG_LEVEL": "debug",
|
||||
"PROVIDER_TIMEOUT": "30",
|
||||
"PROVIDER_RETRY_COUNT": "3",
|
||||
"INFRA_REGION": "us-east-1",
|
||||
"GARM_POOL_ID": "f3b21376-e189-43ae-a1bd-7a3ffee57a58",
|
||||
"GARM_SERVER_SHUTDOWN": "true",
|
||||
"GARM_SERVER_INSECURE": "true",
|
||||
},
|
||||
expectedEnvironmentVariables: []string{
|
||||
"PROVIDER_LOG_LEVEL=debug",
|
||||
"PROVIDER_TIMEOUT=30",
|
||||
"PROVIDER_RETRY_COUNT=3",
|
||||
"INFRA_REGION=us-east-1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// set environment variables
|
||||
for k, v := range tc.environmentVariables {
|
||||
err := os.Setenv(k, v)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to set environment variable: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
envVars := tc.cfg.GetEnvironmentVariables()
|
||||
|
||||
// sort slices to make them comparable
|
||||
slices.Sort(envVars)
|
||||
slices.Sort(tc.expectedEnvironmentVariables)
|
||||
|
||||
// compare slices
|
||||
require.Equal(t, tc.expectedEnvironmentVariables, envVars)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue