Skip to content

Add support for multiple service deployers #1344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions internal/testrunner/runners/system/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,26 +446,34 @@ func (r *runner) runTest(config *testConfig, ctxt servicedeployer.ServiceContext

// Setup service.
logger.Debug("setting up service...")
serviceDeployer, err := servicedeployer.Factory(serviceOptions)
serviceDeployers, err := servicedeployer.Factory(serviceOptions)
if err != nil {
return result.WithError(fmt.Errorf("could not create service runner: %w", err))
}

if config.Service != "" {
ctxt.Name = config.Service
}
service, err := serviceDeployer.SetUp(ctxt)
if err != nil {
return result.WithError(fmt.Errorf("could not setup service: %w", err))
}
ctxt = service.Context()
r.shutdownServiceHandler = func() error {
logger.Debug("tearing down service...")
if err := service.TearDown(); err != nil {
return fmt.Errorf("error tearing down service: %w", err)

var services []servicedeployer.DeployedService

for _, serviceDeployer := range serviceDeployers {

service, err := serviceDeployer.SetUp(ctxt)
if err != nil {
return result.WithError(fmt.Errorf("could not setup service: %w", err))
}
ctxt = service.Context()
r.shutdownServiceHandler = func() error {
logger.Debug("tearing down service...")
if err := service.TearDown(); err != nil {
return fmt.Errorf("error tearing down service: %w", err)
}

return nil
return nil
}

services = append(services, service)
}

// Reload test config with ctx variable substitution.
Expand Down Expand Up @@ -606,8 +614,12 @@ func (r *runner) runTest(config *testConfig, ctxt servicedeployer.ServiceContext

// Signal to the service that the agent is ready (policy is assigned).
if config.ServiceNotifySignal != "" {
if err = service.Signal(config.ServiceNotifySignal); err != nil {
return result.WithError(fmt.Errorf("failed to notify test service: %w", err))
for _, service := range services {
if service.Context().Name == "docker" {
if err = service.Signal(config.ServiceNotifySignal); err != nil {
return result.WithError(fmt.Errorf("failed to notify test service: %w", err))
}
}
}
}

Expand Down
76 changes: 45 additions & 31 deletions internal/testrunner/runners/system/servicedeployer/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,46 +23,59 @@ type FactoryOptions struct {

// Factory chooses the appropriate service runner for the given data stream, depending
// on service configuration files defined in the package or data stream.
func Factory(options FactoryOptions) (ServiceDeployer, error) {
func Factory(options FactoryOptions) (map[string]ServiceDeployer, error) {
devDeployPath, err := FindDevDeployPath(options)
if err != nil {
return nil, fmt.Errorf("can't find \"%s\" directory: %w", devDeployDir, err)
}

serviceDeployerName, err := findServiceDeployer(devDeployPath)
serviceDeployers, err := findServiceDeployer(devDeployPath)
if err != nil {
return nil, fmt.Errorf("can't find any valid service deployer: %w", err)
}

serviceDeployerPath := filepath.Join(devDeployPath, serviceDeployerName)
serviceDeployerInstances := make(map[string]ServiceDeployer)

switch serviceDeployerName {
case "k8s":
if _, err := os.Stat(serviceDeployerPath); err == nil {
return NewKubernetesServiceDeployer(serviceDeployerPath)
}
case "docker":
dockerComposeYMLPath := filepath.Join(serviceDeployerPath, "docker-compose.yml")
if _, err := os.Stat(dockerComposeYMLPath); err == nil {
sv, err := useServiceVariant(devDeployPath, options.Variant)
if err != nil {
return nil, fmt.Errorf("can't use service variant: %w", err)
for _, serviceDeployerName := range serviceDeployers {
serviceDeployerPath := filepath.Join(devDeployPath, serviceDeployerName)

switch serviceDeployerName {
case "k8s":
if _, err := os.Stat(serviceDeployerPath); err == nil {
k8sDeployer, _ := NewKubernetesServiceDeployer(serviceDeployerPath)
serviceDeployerInstances["k8s"] = k8sDeployer
}

case "docker":
dockerComposeYMLPath := filepath.Join(serviceDeployerPath, "docker-compose.yml")
if _, err := os.Stat(dockerComposeYMLPath); err == nil {
sv, err := useServiceVariant(devDeployPath, options.Variant)
if err != nil {
return nil, fmt.Errorf("can't use service variant: %w", err)
}
dcDeployer, _ := NewDockerComposeServiceDeployer([]string{dockerComposeYMLPath}, sv)
serviceDeployerInstances["docker"] = dcDeployer
}

case "agent":
customAgentCfgYMLPath := filepath.Join(serviceDeployerPath, "custom-agent.yml")
if _, err := os.Stat(customAgentCfgYMLPath); err != nil {
return nil, fmt.Errorf("can't find expected file custom-agent.yml: %w", err)
}
agentDeployer, _ := NewCustomAgentDeployer(customAgentCfgYMLPath)
serviceDeployerInstances["agent"] = agentDeployer

case "tf":
if _, err := os.Stat(serviceDeployerPath); err == nil {
tfDeployer, _ := NewTerraformServiceDeployer(serviceDeployerPath)
serviceDeployerInstances["tf"] = tfDeployer
}
return NewDockerComposeServiceDeployer([]string{dockerComposeYMLPath}, sv)
}
case "agent":
customAgentCfgYMLPath := filepath.Join(serviceDeployerPath, "custom-agent.yml")
if _, err := os.Stat(customAgentCfgYMLPath); err != nil {
return nil, fmt.Errorf("can't find expected file custom-agent.yml: %w", err)
}
return NewCustomAgentDeployer(customAgentCfgYMLPath)

case "tf":
if _, err := os.Stat(serviceDeployerPath); err == nil {
return NewTerraformServiceDeployer(serviceDeployerPath)
default:
return nil, fmt.Errorf("unsupported service deployer (name: %s)", serviceDeployerName)
}
}
return nil, fmt.Errorf("unsupported service deployer (name: %s)", serviceDeployerName)
return serviceDeployerInstances, nil
}

// FindDevDeployPath function returns a path reference to the "_dev/deploy" directory.
Expand All @@ -85,10 +98,10 @@ func FindDevDeployPath(options FactoryOptions) (string, error) {
return "", fmt.Errorf("\"%s\" directory doesn't exist", devDeployDir)
}

func findServiceDeployer(devDeployPath string) (string, error) {
func findServiceDeployer(devDeployPath string) ([]string, error) {
fis, err := os.ReadDir(devDeployPath)
if err != nil {
return "", fmt.Errorf("can't read directory (path: %s): %w", devDeployDir, err)
return nil, fmt.Errorf("can't read directory (path: %s): %w", devDeployDir, err)
}

var folders []os.DirEntry
Expand All @@ -98,8 +111,9 @@ func findServiceDeployer(devDeployPath string) (string, error) {
}
}

if len(folders) != 1 {
return "", fmt.Errorf("expected to find only one service deployer in \"%s\"", devDeployPath)
var folderNames []string
for _, fname := range folders {
folderNames = append(folderNames, fname.Name())
}
return folders[0].Name(), nil
return folderNames, nil
}