diff --git a/execution/common/commands.go b/execution/common/commands.go index c4e3a60..c0e7980 100644 --- a/execution/common/commands.go +++ b/execution/common/commands.go @@ -42,9 +42,10 @@ const ( // V0.1.1 commands const ( - ValidatePoolInfoCommand ExecutionCommand = "ValidatePoolInfo" - GetConfigJSONSchemaCommand ExecutionCommand = "GetConfigJSONSchema" - GetExtraSpecsJSONSchemaCommand ExecutionCommand = "GetExtraSpecsJSONSchema" + GetSupportedInterfaceVersionsCommand ExecutionCommand = "GetSupportedInterfaceVersions" + ValidatePoolInfoCommand ExecutionCommand = "ValidatePoolInfo" + GetConfigJSONSchemaCommand ExecutionCommand = "GetConfigJSONSchema" + GetExtraSpecsJSONSchemaCommand ExecutionCommand = "GetExtraSpecsJSONSchema" ) const ( diff --git a/execution/execution.go b/execution/execution.go index a6da559..481ab84 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -24,11 +24,6 @@ import ( executionv011 "github.com/cloudbase/garm-provider-common/execution/v0.1.1" ) -type ExternalProvider interface { - executionv010.ExternalProvider - executionv011.ExternalProvider -} - type Environment struct { EnvironmentV010 executionv010.EnvironmentV010 EnvironmentV011 executionv011.EnvironmentV011 @@ -41,7 +36,7 @@ func GetEnvironment() (Environment, error) { interfaceVersion := os.Getenv("GARM_INTERFACE_VERSION") switch interfaceVersion { - case common.Version010: + case common.Version010, "": env, err := executionv010.GetEnvironment() if err != nil { return Environment{}, err @@ -68,13 +63,23 @@ func GetEnvironment() (Environment, error) { } } -func Run(ctx context.Context, provider ExternalProvider, env Environment) (string, error) { - switch env.InterfaceVersion { - case common.Version010: - return executionv010.Run(ctx, provider, env.EnvironmentV010) +func (e Environment) Run(ctx context.Context, provider interface{}) (string, error) { + switch e.InterfaceVersion { + case common.Version010, "": + prov, ok := provider.(executionv010.ExternalProvider) + if !ok { + return "", fmt.Errorf("provider does not implement %s ExternalProvider", e.InterfaceVersion) + } + return e.EnvironmentV010.Run(ctx, prov) + case common.Version011: - return executionv011.Run(ctx, provider, env.EnvironmentV011) + prov, ok := provider.(executionv011.ExternalProvider) + if !ok { + return "", fmt.Errorf("provider does not implement %s ExternalProvider", e.InterfaceVersion) + } + return e.EnvironmentV011.Run(ctx, prov) + default: - return "", fmt.Errorf("unsupported interface version: %s", env.InterfaceVersion) + return "", fmt.Errorf("unsupported interface version: %s", e.InterfaceVersion) } } diff --git a/execution/v0.1.0/execution.go b/execution/v0.1.0/execution.go index 60735f7..73957cc 100644 --- a/execution/v0.1.0/execution.go +++ b/execution/v0.1.0/execution.go @@ -20,8 +20,6 @@ import ( "fmt" "os" - "golang.org/x/mod/semver" - common "github.com/cloudbase/garm-provider-common/execution/common" "github.com/cloudbase/garm-provider-common/params" ) @@ -43,10 +41,6 @@ func GetEnvironment() (EnvironmentV010, error) { } env.BootstrapParams = boostrapParams - if env.InterfaceVersion == "" { - env.InterfaceVersion = common.Version010 - } - if err := env.Validate(); err != nil { return EnvironmentV010{}, fmt.Errorf("failed to validate execution environment: %w", err) } @@ -60,7 +54,6 @@ type EnvironmentV010 struct { PoolID string ProviderConfigFile string InstanceID string - InterfaceVersion string BootstrapParams params.BootstrapInstance } @@ -106,20 +99,18 @@ func (e EnvironmentV010) Validate() error { return fmt.Errorf("missing controller ID") } case common.GetVersionCommand: - if !semver.IsValid(e.InterfaceVersion) { - return fmt.Errorf("invalid interface version: %s", e.InterfaceVersion) - } + return nil default: return fmt.Errorf("unknown GARM_COMMAND: %s", e.Command) } return nil } -func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV010) (string, error) { +func (e EnvironmentV010) Run(ctx context.Context, provider ExternalProvider) (string, error) { var ret string - switch env.Command { + switch e.Command { case common.CreateInstanceCommand: - instance, err := provider.CreateInstance(ctx, env.BootstrapParams) + instance, err := provider.CreateInstance(ctx, e.BootstrapParams) if err != nil { return "", fmt.Errorf("failed to create instance in provider: %w", err) } @@ -130,7 +121,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV010) (s } ret = string(asJs) case common.GetInstanceCommand: - instance, err := provider.GetInstance(ctx, env.InstanceID) + instance, err := provider.GetInstance(ctx, e.InstanceID) if err != nil { return "", fmt.Errorf("failed to get instance from provider: %w", err) } @@ -140,7 +131,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV010) (s } ret = string(asJs) case common.ListInstancesCommand: - instances, err := provider.ListInstances(ctx, env.PoolID) + instances, err := provider.ListInstances(ctx, e.PoolID) if err != nil { return "", fmt.Errorf("failed to list instances from provider: %w", err) } @@ -150,7 +141,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV010) (s } ret = string(asJs) case common.DeleteInstanceCommand: - if err := provider.DeleteInstance(ctx, env.InstanceID); err != nil { + if err := provider.DeleteInstance(ctx, e.InstanceID); err != nil { return "", fmt.Errorf("failed to delete instance from provider: %w", err) } case common.RemoveAllInstancesCommand: @@ -158,18 +149,18 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV010) (s return "", fmt.Errorf("failed to destroy environment: %w", err) } case common.StartInstanceCommand: - if err := provider.Start(ctx, env.InstanceID); err != nil { + if err := provider.Start(ctx, e.InstanceID); err != nil { return "", fmt.Errorf("failed to start instance: %w", err) } case common.StopInstanceCommand: - if err := provider.Stop(ctx, env.InstanceID, true); err != nil { + if err := provider.Stop(ctx, e.InstanceID, true); err != nil { return "", fmt.Errorf("failed to stop instance: %w", err) } case common.GetVersionCommand: version := provider.GetVersion(ctx) ret = string(version) default: - return "", fmt.Errorf("invalid command: %s", env.Command) + return "", fmt.Errorf("invalid command: %s", e.Command) } return ret, nil } diff --git a/execution/v0.1.0/execution_test.go b/execution/v0.1.0/execution_test.go index e8b7bf9..fd86fc6 100644 --- a/execution/v0.1.0/execution_test.go +++ b/execution/v0.1.0/execution_test.go @@ -380,7 +380,7 @@ func TestRun(t *testing.T) { mockInstance: tc.providerInstance, } - out, err := Run(context.Background(), &testExternalProvider, tc.providerEnv) + out, err := tc.providerEnv.Run(context.Background(), &testExternalProvider) if tc.expectedErrMsg == "" { require.NoError(t, err) diff --git a/execution/v0.1.1/execution.go b/execution/v0.1.1/execution.go index ab643b0..f679000 100644 --- a/execution/v0.1.1/execution.go +++ b/execution/v0.1.1/execution.go @@ -20,8 +20,6 @@ import ( "fmt" "os" - "golang.org/x/mod/semver" - common "github.com/cloudbase/garm-provider-common/execution/common" "github.com/cloudbase/garm-provider-common/params" ) @@ -33,7 +31,6 @@ func GetEnvironment() (EnvironmentV011, error) { PoolID: os.Getenv("GARM_POOL_ID"), ProviderConfigFile: os.Getenv("GARM_PROVIDER_CONFIG_FILE"), InstanceID: os.Getenv("GARM_INSTANCE_ID"), - InterfaceVersion: os.Getenv("GARM_INTERFACE_VERSION"), ExtraSpecs: os.Getenv("GARM_POOL_EXTRASPECS"), } @@ -45,10 +42,6 @@ func GetEnvironment() (EnvironmentV011, error) { } env.BootstrapParams = boostrapParams - if env.InterfaceVersion == "" { - env.InterfaceVersion = common.Version010 - } - if err := env.Validate(); err != nil { return EnvironmentV011{}, fmt.Errorf("failed to validate execution environment: %w", err) } @@ -62,7 +55,6 @@ type EnvironmentV011 struct { PoolID string ProviderConfigFile string InstanceID string - InterfaceVersion string ExtraSpecs string BootstrapParams params.BootstrapInstance } @@ -111,26 +103,21 @@ func (e EnvironmentV011) Validate() error { if e.ControllerID == "" { return fmt.Errorf("missing controller ID") } - case common.GetVersionCommand: - if !semver.IsValid(e.InterfaceVersion) { - return fmt.Errorf("invalid interface version: %s", e.InterfaceVersion) - } - case common.ValidatePoolInfoCommand, common.GetConfigJSONSchemaCommand, + case common.GetVersionCommand, common.GetSupportedInterfaceVersionsCommand, + common.ValidatePoolInfoCommand, common.GetConfigJSONSchemaCommand, common.GetExtraSpecsJSONSchemaCommand: - if !semver.IsValid(e.InterfaceVersion) && e.InterfaceVersion == common.Version010 { - return fmt.Errorf("invalid interface version: %s", e.InterfaceVersion) - } + return nil default: return fmt.Errorf("unknown GARM_COMMAND: %s", e.Command) } return nil } -func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (string, error) { +func (e EnvironmentV011) Run(ctx context.Context, provider ExternalProvider) (string, error) { var ret string - switch env.Command { + switch e.Command { case common.CreateInstanceCommand: - instance, err := provider.CreateInstance(ctx, env.BootstrapParams) + instance, err := provider.CreateInstance(ctx, e.BootstrapParams) if err != nil { return "", fmt.Errorf("failed to create instance in provider: %w", err) } @@ -141,7 +128,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (s } ret = string(asJs) case common.GetInstanceCommand: - instance, err := provider.GetInstance(ctx, env.InstanceID) + instance, err := provider.GetInstance(ctx, e.InstanceID) if err != nil { return "", fmt.Errorf("failed to get instance from provider: %w", err) } @@ -151,7 +138,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (s } ret = string(asJs) case common.ListInstancesCommand: - instances, err := provider.ListInstances(ctx, env.PoolID) + instances, err := provider.ListInstances(ctx, e.PoolID) if err != nil { return "", fmt.Errorf("failed to list instances from provider: %w", err) } @@ -161,7 +148,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (s } ret = string(asJs) case common.DeleteInstanceCommand: - if err := provider.DeleteInstance(ctx, env.InstanceID); err != nil { + if err := provider.DeleteInstance(ctx, e.InstanceID); err != nil { return "", fmt.Errorf("failed to delete instance from provider: %w", err) } case common.RemoveAllInstancesCommand: @@ -169,18 +156,25 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (s return "", fmt.Errorf("failed to destroy environment: %w", err) } case common.StartInstanceCommand: - if err := provider.Start(ctx, env.InstanceID); err != nil { + if err := provider.Start(ctx, e.InstanceID); err != nil { return "", fmt.Errorf("failed to start instance: %w", err) } case common.StopInstanceCommand: - if err := provider.Stop(ctx, env.InstanceID, true); err != nil { + if err := provider.Stop(ctx, e.InstanceID, true); err != nil { return "", fmt.Errorf("failed to stop instance: %w", err) } case common.GetVersionCommand: version := provider.GetVersion(ctx) ret = string(version) + case common.GetSupportedInterfaceVersionsCommand: + versions := provider.GetSupportedInterfaceVersions(ctx) + asJs, err := json.Marshal(versions) + if err != nil { + return "", fmt.Errorf("failed to marshal response: %w", err) + } + ret = string(asJs) case common.ValidatePoolInfoCommand: - if err := provider.ValidatePoolInfo(ctx, env.BootstrapParams.Image, env.BootstrapParams.Flavor, env.ProviderConfigFile, env.ExtraSpecs); err != nil { + if err := provider.ValidatePoolInfo(ctx, e.BootstrapParams.Image, e.BootstrapParams.Flavor, e.ProviderConfigFile, e.ExtraSpecs); err != nil { return "", fmt.Errorf("failed to validate pool info: %w", err) } case common.GetConfigJSONSchemaCommand: @@ -196,7 +190,7 @@ func Run(ctx context.Context, provider ExternalProvider, env EnvironmentV011) (s } ret = schema default: - return "", fmt.Errorf("invalid command: %s", env.Command) + return "", fmt.Errorf("invalid command: %s", e.Command) } return ret, nil } diff --git a/execution/v0.1.1/execution_test.go b/execution/v0.1.1/execution_test.go index 2d0f5e6..691ecec 100644 --- a/execution/v0.1.1/execution_test.go +++ b/execution/v0.1.1/execution_test.go @@ -88,6 +88,11 @@ func (p *testExternalProvider) GetVersion(context.Context) string { return "v0.1.1" } +func (p *testExternalProvider) GetSupportedInterfaceVersions(context.Context) []string { + //TODO: implement + return []string{"v0.1.0", "v0.1.1"} +} + func (p *testExternalProvider) ValidatePoolInfo(context.Context, string, string, string, string) error { //TODO: implement return nil @@ -161,7 +166,6 @@ func TestValidateEnvironment(t *testing.T) { PoolID: "pool-id", ProviderConfigFile: tmpfile.Name(), InstanceID: "instance-id", - InterfaceVersion: "v0.1.1", BootstrapParams: params.BootstrapInstance{ Name: "instance-name", }, @@ -396,7 +400,7 @@ func TestRun(t *testing.T) { mockInstance: tc.providerInstance, } - out, err := Run(context.Background(), &testExternalProvider, tc.providerEnv) + out, err := tc.providerEnv.Run(context.Background(), &testExternalProvider) if tc.expectedErrMsg == "" { require.NoError(t, err) diff --git a/execution/v0.1.1/interface.go b/execution/v0.1.1/interface.go index 0bcc765..0fea60f 100644 --- a/execution/v0.1.1/interface.go +++ b/execution/v0.1.1/interface.go @@ -26,6 +26,8 @@ import ( type ExternalProvider interface { // The common ExternalProvider interface common.ExternalProvider + // GetSupportedInterfaceVersions will return the supported interface versions. + GetSupportedInterfaceVersions(ctx context.Context) []string // ValidatePoolInfo will validate the pool info and return an error if it's not valid. ValidatePoolInfo(ctx context.Context, image string, flavor string, providerConfig string, extraspecs string) error // GetConfigJSONSchema will return the JSON schema for the provider's configuration. diff --git a/go.mod b/go.mod index ecc8b56..0d00115 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/stretchr/testify v1.9.0 github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 golang.org/x/crypto v0.26.0 - golang.org/x/mod v0.20.0 golang.org/x/sys v0.24.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 460639a..efe5b28 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,6 @@ github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLq github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=