diff --git a/config/external.go b/config/external.go index 93dcc7c6..fcfe4190 100644 --- a/config/external.go +++ b/config/external.go @@ -38,14 +38,22 @@ type External struct { // ProviderDir is the path on disk to a folder containing an executable // called "garm-external-provider". ProviderDir string `toml:"provider_dir" json:"provider-dir"` + // ProviderExecutable is the full path to the executable that implements + // 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"` } func (e *External) ExecutablePath() (string, error) { - execPath := filepath.Join(e.ProviderDir, "garm-external-provider") + execPath := e.ProviderExecutable + if execPath == "" { + execPath = filepath.Join(e.ProviderDir, "garm-external-provider") + } + if !filepath.IsAbs(execPath) { return "", fmt.Errorf("executable path must be an absolute path") } - return filepath.Join(e.ProviderDir, "garm-external-provider"), nil + return execPath, nil } func (e *External) Validate() error { @@ -58,14 +66,6 @@ func (e *External) Validate() error { } } - if e.ProviderDir == "" { - return fmt.Errorf("missing provider dir") - } - - if !filepath.IsAbs(e.ProviderDir) { - return fmt.Errorf("path to provider dir must be absolute") - } - execPath, err := e.ExecutablePath() if err != nil { return errors.Wrap(err, "fetching executable path") diff --git a/config/external_test.go b/config/external_test.go index 40b85688..a537b570 100644 --- a/config/external_test.go +++ b/config/external_test.go @@ -72,20 +72,20 @@ func TestExternal(t *testing.T) { errString: "failed to access config file /there/is/no/config/here", }, { - name: "Missing provider dir", - cfg: External{ - ConfigFile: "", - ProviderDir: "", - }, - errString: "missing provider dir", - }, - { - name: "Provider dir must not be relative", + name: "Provider dir path must be absolute", cfg: External{ ConfigFile: "", ProviderDir: "../test", }, - errString: "path to provider dir must be absolute", + errString: "fetching executable path: executable path must be an absolute path", + }, + { + name: "Provider executable path must be absolute", + cfg: External{ + ConfigFile: "", + ProviderExecutable: "../test", + }, + errString: "fetching executable path: executable path must be an absolute path", }, { name: "Provider executable not found", diff --git a/contrib/providers.d/openstack/README.md b/contrib/providers.d/openstack/README.md index 4642e6d9..4995e543 100644 --- a/contrib/providers.d/openstack/README.md +++ b/contrib/providers.d/openstack/README.md @@ -2,4 +2,11 @@ This is an example external provider, written for OpenStack. It is a simple bash script that implements the external provider interface, in order to supply ```garm``` with compute instances. This is just an example, complete with a sample config file. -Not all functions are implemented, just the bare minimum to get it to work with the current feature set of ```garm```. It is not meant for production, as it needs a lot more error checking, retries, and potentially more flexibility to be of any use in a real environment. \ No newline at end of file +Not all functions are implemented, just the bare minimum to get it to work with the current feature set of ```garm```. It is not meant for production, as it needs a lot more error checking, retries, and potentially more flexibility to be of any use in a real environment. + +Images that are used with garm require the following properties set on the image: + + * os_type (one of: windows, linux) + * os_distro + * os_version + * architecture (one of: x86_64, armv7l, mips64, mips64el, mips, mipsel) diff --git a/contrib/providers.d/openstack/garm-external-provider b/contrib/providers.d/openstack/garm-external-provider index ee91cfcc..cc6eda64 100755 --- a/contrib/providers.d/openstack/garm-external-provider +++ b/contrib/providers.d/openstack/garm-external-provider @@ -275,7 +275,11 @@ function CreateInstance() { checkValNotNull "${VERSION}" "os_version" || return $? ARCH=$(echo "${IMAGE_DETAILS}" | jq -c -r '.properties.architecture') checkValNotNull "${ARCH}" "architecture" || return $? + GH_ARCH=OS_TO_GH_ARCH_MAP[${ARCH}] + if [ -z "${GH_ARCH}" ];then + GH_ARCH=${ARCH} + fi SOURCE_ARGS="" @@ -327,7 +331,7 @@ function CreateInstance() { --arg OS_TYPE "${OS_TYPE}" \ --arg OS_NAME "${DISTRO}" \ --arg OS_VERSION "${VERSION}" \ - --arg ARCH "${ARCH}" \ + --arg ARCH "${GH_ARCH}" \ --arg STATUS "${STATUS_MAP[${STATUS}]}" \ --arg POOL_ID "${GARM_POOL_ID}" \ --arg FAULT "${FAULT_VAL}" \ diff --git a/testdata/config.toml b/testdata/config.toml index 88bdaa39..4822f709 100644 --- a/testdata/config.toml +++ b/testdata/config.toml @@ -170,9 +170,10 @@ provider_type = "external" [provider.external] # config file passed to the executable via GARM_PROVIDER_CONFIG_FILE environment variable config_file = "/etc/garm/providers.d/azure/config.sh" - # path on disk to a folder that contains a "garm-external-provider" executable. The executable - # can be anything (bash, a binary, python, etc) - provider_dir = "/etc/garm/providers.d/azure" + # Absolute path to an executable that implements the provider logic. This executable can be + # anything (bash, a binary, python, etc). See documentation in this repo on how to write an + # external provider. + provider_executable = "/etc/garm/providers.d/azure/garm-external-provider" # This is a list of credentials that you can define as part of the repository # or organization definitions. They are not saved inside the database, as there