diff --git a/components/activedirectory/params.go b/components/activedirectory/params.go index dad9b6cb6..a185b59df 100644 --- a/components/activedirectory/params.go +++ b/components/activedirectory/params.go @@ -3,7 +3,6 @@ package activedirectory import ( "github.com/DataDog/test-infra-definitions/common/utils" "github.com/DataDog/test-infra-definitions/components/command" - pulumiRemote "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" "github.com/pulumiverse/pulumi-time/sdk/go/time" ) @@ -49,7 +48,7 @@ func WithDomain(domainFqdn, domainAdmin, domainAdminPassword string) Option { } func (adCtx *activeDirectoryContext) joinActiveDirectoryDomain(params *JoinDomainConfiguration) error { - var joinCmd *pulumiRemote.Command + var joinCmd command.Command joinCmd, err := adCtx.comp.host.OS.Runner().Command(adCtx.comp.namer.ResourceName("join-domain"), &command.Args{ Create: pulumi.Sprintf(` Add-Computer -DomainName %s -Credential (New-Object System.Management.Automation.PSCredential -ArgumentList %s, %s) @@ -90,7 +89,7 @@ func WithDomainController(domainFqdn, adminPassword string) func(*Configuration) } func (adCtx *activeDirectoryContext) installDomainController(params *DomainControllerConfiguration) error { - var installCmd *pulumiRemote.Command + var installCmd command.Command installCmd, err := adCtx.comp.host.OS.Runner().Command(adCtx.comp.namer.ResourceName("install-forest"), &command.Args{ Create: pulumi.Sprintf(` Add-WindowsFeature -name ad-domain-services -IncludeManagementTools; diff --git a/components/command/filemanager.go b/components/command/filemanager.go index 580ad2b38..bee2c626c 100644 --- a/components/command/filemanager.go +++ b/components/command/filemanager.go @@ -10,19 +10,18 @@ import ( "runtime" "strings" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) type FileManager struct { - runner *Runner + runner Runner command OSCommand } -func NewFileManager(runner *Runner) *FileManager { +func NewFileManager(runner Runner) *FileManager { return &FileManager{ runner: runner, - command: runner.osCommand, + command: runner.OsCommand(), } } @@ -31,13 +30,13 @@ func (fm *FileManager) IsPathAbsolute(path string) bool { } // CreateDirectoryFromPulumiString if it does not exist from directory name as a Pulumi String -func (fm *FileManager) CreateDirectoryFromPulumiString(name string, remotePath pulumi.String, useSudo bool, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (fm *FileManager) CreateDirectoryFromPulumiString(name string, remotePath pulumi.String, useSudo bool, opts ...pulumi.ResourceOption) (Command, error) { return fm.command.CreateDirectory(fm.runner, name, remotePath, useSudo, opts...) } // CreateDirectoryForFile if the directory does not exist // To avoid pulumi.URN collisions if multiple files use the same directory, use the full filePath as URN and path.Split out the folderPath for creation -func (fm *FileManager) CreateDirectoryForFile(remotePath string, useSudo bool, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (fm *FileManager) CreateDirectoryForFile(remotePath string, useSudo bool, opts ...pulumi.ResourceOption) (Command, error) { // if given just a directory path, path.Split returns "" as file // eg. path.Split("/a/b/c/") -> "/a/b/c/", "" folderPath, _ := path.Split(remotePath) @@ -45,12 +44,12 @@ func (fm *FileManager) CreateDirectoryForFile(remotePath string, useSudo bool, o } // CreateDirectory if it does not exist -func (fm *FileManager) CreateDirectory(remotePath string, useSudo bool, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (fm *FileManager) CreateDirectory(remotePath string, useSudo bool, opts ...pulumi.ResourceOption) (Command, error) { return fm.command.CreateDirectory(fm.runner, "create-directory-"+remotePath, pulumi.String(remotePath), useSudo, opts...) } // TempDirectory creates a temporary directory -func (fm *FileManager) TempDirectory(folderName string, opts ...pulumi.ResourceOption) (*remote.Command, string, error) { +func (fm *FileManager) TempDirectory(folderName string, opts ...pulumi.ResourceOption) (Command, string, error) { tempDir := path.Join(fm.command.GetTemporaryDirectory(), folderName) folderCmd, err := fm.CreateDirectory(tempDir, false, opts...) return folderCmd, tempDir, err @@ -59,14 +58,14 @@ func (fm *FileManager) TempDirectory(folderName string, opts ...pulumi.ResourceO // HomeDirectory creates a directory in home directory, if it does not exist // A home directory is a file system directory on a multi-user operating system containing files for a given user of the system. // It does not require sudo, using sudo in home directory allows to change default ownership and it is discouraged. -func (fm *FileManager) HomeDirectory(folderName string, opts ...pulumi.ResourceOption) (*remote.Command, string, error) { +func (fm *FileManager) HomeDirectory(folderName string, opts ...pulumi.ResourceOption) (Command, string, error) { homeDir := path.Join(fm.command.GetHomeDirectory(), folderName) folderCmd, err := fm.CreateDirectory(homeDir, false, opts...) return folderCmd, homeDir, err } func (fm *FileManager) CopyFile(name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { - return fm.runner.NewCopyFile(name, localPath, remotePath, opts...) + return fm.runner.newCopyFile(name, localPath, remotePath, opts...) } func (fm *FileManager) CopyInlineFile(fileContent pulumi.StringInput, remotePath string, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { diff --git a/components/command/osCommand.go b/components/command/osCommand.go index b95136bfe..7b0983289 100644 --- a/components/command/osCommand.go +++ b/components/command/osCommand.go @@ -1,9 +1,9 @@ package command import ( + "runtime" "strings" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -13,11 +13,12 @@ type OSCommand interface { GetHomeDirectory() string CreateDirectory( - runner *Runner, + runner Runner, resourceName string, remotePath pulumi.StringInput, useSudo bool, - opts ...pulumi.ResourceOption) (*remote.Command, error) + opts ...pulumi.ResourceOption) (Command, error) + MoveFile(runner Runner, name string, source, destination pulumi.StringInput, sudo bool, opts ...pulumi.ResourceOption) (Command, error) BuildCommandString( command pulumi.StringInput, @@ -28,7 +29,9 @@ type OSCommand interface { IsPathAbsolute(path string) bool - NewCopyFile(runner *Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) + NewCopyFile(runner Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) + copyLocalFile(runner *LocalRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) + copyRemoteFile(runner *RemoteRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) } // ------------------------------ @@ -38,13 +41,13 @@ type OSCommand interface { const backupExtension = "pulumi.backup" func createDirectory( - runner *Runner, + runner Runner, name string, createCmd string, deleteCmd string, useSudo bool, opts ...pulumi.ResourceOption, -) (*remote.Command, error) { +) (Command, error) { // If the folder was previously created, make sure to delete it before creating it. opts = append(opts, pulumi.DeleteBeforeReplace(true)) return runner.Command(name, @@ -73,13 +76,13 @@ func buildCommandString( } func copyRemoteFile( - runner *Runner, + runner Runner, name string, createCommand pulumi.StringInput, deleteCommand pulumi.StringInput, useSudo bool, opts ...pulumi.ResourceOption, -) (*remote.Command, error) { +) (Command, error) { return runner.Command(name, &Args{ Create: createCommand, @@ -88,3 +91,11 @@ func copyRemoteFile( Triggers: pulumi.Array{createCommand, deleteCommand, pulumi.BoolPtr(useSudo)}, }, opts...) } + +func NewLocalOSCommand() OSCommand { + if runtime.GOOS == "windows" { + return NewWindowsOSCommand() + } + + return NewUnixOSCommand() +} diff --git a/components/command/package.go b/components/command/package.go index 6051aa19a..f9c48613c 100644 --- a/components/command/package.go +++ b/components/command/package.go @@ -5,14 +5,13 @@ import ( "github.com/DataDog/test-infra-definitions/common/namer" "github.com/DataDog/test-infra-definitions/common/utils" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) type GenericPackageManager struct { namer namer.Namer - updateDBCommand *remote.Command - runner *Runner + updateDBCommand Command + runner Runner opts []pulumi.ResourceOption installCmd string updateCmd string @@ -20,14 +19,14 @@ type GenericPackageManager struct { } func NewGenericPackageManager( - runner *Runner, + runner Runner, name string, installCmd string, updateCmd string, env pulumi.StringMap, ) *GenericPackageManager { packageManager := &GenericPackageManager{ - namer: namer.NewNamer(runner.e.Ctx(), name), + namer: namer.NewNamer(runner.Environment().Ctx(), name), runner: runner, installCmd: installCmd, updateCmd: updateCmd, @@ -37,7 +36,7 @@ func NewGenericPackageManager( return packageManager } -func (m *GenericPackageManager) Ensure(packageRef string, transform Transformer, checkBinary string, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (m *GenericPackageManager) Ensure(packageRef string, transform Transformer, checkBinary string, opts ...pulumi.ResourceOption) (Command, error) { opts = append(opts, m.opts...) if m.updateCmd != "" { updateDB, err := m.updateDB(opts) @@ -76,7 +75,7 @@ func (m *GenericPackageManager) Ensure(packageRef string, transform Transformer, return cmd, nil } -func (m *GenericPackageManager) updateDB(opts []pulumi.ResourceOption) (*remote.Command, error) { +func (m *GenericPackageManager) updateDB(opts []pulumi.ResourceOption) (Command, error) { if m.updateDBCommand != nil { return m.updateDBCommand, nil } diff --git a/components/command/runner.go b/components/command/runner.go index 9208a1c48..8ff4832d2 100644 --- a/components/command/runner.go +++ b/components/command/runner.go @@ -21,19 +21,32 @@ type Args struct { Environment pulumi.StringMap RequirePasswordFromStdin bool Sudo bool + // Only used for local commands + LocalAssetPaths pulumi.StringArrayInput + LocalDir pulumi.StringInput } -func (args *Args) toLocalCommandArgs(config runnerConfiguration, osCommand OSCommand) *local.CommandArgs { +func (args *Args) toLocalCommandArgs(config RunnerConfiguration, osCommand OSCommand) (*local.CommandArgs, error) { return &local.CommandArgs{ - Create: osCommand.BuildCommandString(args.Create, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), - Update: osCommand.BuildCommandString(args.Update, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), - Delete: osCommand.BuildCommandString(args.Delete, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), - Triggers: args.Triggers, - Stdin: args.Stdin, - } + Create: osCommand.BuildCommandString(args.Create, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), + Update: osCommand.BuildCommandString(args.Update, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), + Delete: osCommand.BuildCommandString(args.Delete, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), + Triggers: args.Triggers, + Stdin: args.Stdin, + AssetPaths: args.LocalAssetPaths, + Dir: args.LocalDir, + }, nil } -func (args *Args) toRemoteCommandArgs(config runnerConfiguration, osCommand OSCommand) *remote.CommandArgs { +func (args *Args) toRemoteCommandArgs(config RunnerConfiguration, osCommand OSCommand) (*remote.CommandArgs, error) { + // Ensure no local arguments are passed to remote commands + if args.LocalAssetPaths != nil { + return nil, fmt.Errorf("local asset paths are not supported in remote commands") + } + if args.LocalDir != nil { + return nil, fmt.Errorf("local dir is not supported in remote commands") + } + return &remote.CommandArgs{ Connection: config.connection, Create: osCommand.BuildCommandString(args.Create, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), @@ -41,28 +54,77 @@ func (args *Args) toRemoteCommandArgs(config runnerConfiguration, osCommand OSCo Delete: osCommand.BuildCommandString(args.Delete, args.Environment, args.Sudo, args.RequirePasswordFromStdin, config.user), Triggers: args.Triggers, Stdin: args.Stdin, - } + }, nil } // Transformer is a function that can be used to modify the command name and args. // Examples: swapping `args.Delete` with `args.Create`, or adding `args.Triggers`, or editing the name type Transformer func(name string, args Args) (string, Args) -type runnerConfiguration struct { +type RunnerConfiguration struct { user string connection remote.ConnectionInput } -type Runner struct { +type Command interface { + pulumi.Resource + + StdoutOutput() pulumi.StringOutput + StderrOutput() pulumi.StringOutput +} + +type LocalCommand struct { + *local.Command +} + +type RemoteCommand struct { + *remote.Command +} + +var _ Command = &RemoteCommand{} +var _ Command = &LocalCommand{} + +func (c *LocalCommand) StdoutOutput() pulumi.StringOutput { + return c.Command.Stdout +} + +func (c *LocalCommand) StderrOutput() pulumi.StringOutput { + return c.Command.Stderr +} + +func (c *RemoteCommand) StdoutOutput() pulumi.StringOutput { + return c.Command.Stdout +} + +func (c *RemoteCommand) StderrOutput() pulumi.StringOutput { + return c.Command.Stderr +} + +type Runner interface { + Environment() config.Env + Namer() namer.Namer + Config() RunnerConfiguration + OsCommand() OSCommand + PulumiOptions() []pulumi.ResourceOption + + Command(name string, args *Args, opts ...pulumi.ResourceOption) (Command, error) + + newCopyFile(name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) +} + +var _ Runner = &RemoteRunner{} +var _ Runner = &LocalRunner{} + +type RemoteRunner struct { e config.Env namer namer.Namer - waitCommand *remote.Command - config runnerConfiguration + waitCommand Command + config RunnerConfiguration osCommand OSCommand options []pulumi.ResourceOption } -type RunnerArgs struct { +type RemoteRunnerArgs struct { ParentResource pulumi.Resource ConnectionName string Connection remote.ConnectionInput @@ -71,11 +133,11 @@ type RunnerArgs struct { OSCommand OSCommand } -func NewRunner(e config.Env, args RunnerArgs) (*Runner, error) { - runner := &Runner{ +func NewRemoteRunner(e config.Env, args RemoteRunnerArgs) (*RemoteRunner, error) { + runner := &RemoteRunner{ e: e, namer: namer.NewNamer(e.Ctx(), "remote").WithPrefix(args.ConnectionName), - config: runnerConfiguration{ + config: RunnerConfiguration{ connection: args.Connection, user: args.User, }, @@ -101,22 +163,53 @@ func NewRunner(e config.Env, args RunnerArgs) (*Runner, error) { return runner, nil } -func (r *Runner) Command(name string, args *Args, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (r *RemoteRunner) Environment() config.Env { + return r.e +} + +func (r *RemoteRunner) Namer() namer.Namer { + return r.namer +} + +func (r *RemoteRunner) Config() RunnerConfiguration { + return r.config +} + +func (r *RemoteRunner) OsCommand() OSCommand { + return r.osCommand +} + +func (r *RemoteRunner) Command(name string, args *Args, opts ...pulumi.ResourceOption) (Command, error) { if args.Sudo && r.config.user != "" { r.e.Ctx().Log.Info(fmt.Sprintf("warning: running sudo command on a runner with user %s, discarding user", r.config.user), nil) } - return remote.NewCommand(r.e.Ctx(), r.namer.ResourceName("cmd", name), args.toRemoteCommandArgs(r.config, r.osCommand), utils.MergeOptions(r.options, opts...)...) + remoteArgs, err := args.toRemoteCommandArgs(r.config, r.osCommand) + if err != nil { + return nil, err + } + + cmd, err := remote.NewCommand(r.e.Ctx(), r.namer.ResourceName("cmd", name), remoteArgs, utils.MergeOptions(r.options, opts...)...) + + if err != nil { + return nil, err + } + + return &RemoteCommand{cmd}, nil } -func (r *Runner) NewCopyFile(name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { - return r.osCommand.NewCopyFile(r, name, localPath, remotePath, opts...) +func (r *RemoteRunner) newCopyFile(name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + return r.osCommand.copyRemoteFile(r, name, localPath, remotePath, opts...) +} + +func (r *RemoteRunner) PulumiOptions() []pulumi.ResourceOption { + return r.options } type LocalRunner struct { e config.Env namer namer.Namer - config runnerConfiguration + config RunnerConfiguration osCommand OSCommand } @@ -130,7 +223,7 @@ func NewLocalRunner(e config.Env, args LocalRunnerArgs) *LocalRunner { e: e, namer: namer.NewNamer(e.Ctx(), "local"), osCommand: args.OSCommand, - config: runnerConfiguration{ + config: RunnerConfiguration{ user: args.User, }, } @@ -138,7 +231,42 @@ func NewLocalRunner(e config.Env, args LocalRunnerArgs) *LocalRunner { return localRunner } -func (r *LocalRunner) Command(name string, args *Args, opts ...pulumi.ResourceOption) (*local.Command, error) { +func (r *LocalRunner) Environment() config.Env { + return r.e +} + +func (r *LocalRunner) Namer() namer.Namer { + return r.namer +} + +func (r *LocalRunner) Config() RunnerConfiguration { + return r.config +} + +func (r *LocalRunner) OsCommand() OSCommand { + return r.osCommand +} + +func (r *LocalRunner) Command(name string, args *Args, opts ...pulumi.ResourceOption) (Command, error) { opts = utils.MergeOptions[pulumi.ResourceOption](opts, r.e.WithProviders(config.ProviderCommand)) - return local.NewCommand(r.e.Ctx(), r.namer.ResourceName("cmd", name), args.toLocalCommandArgs(r.config, r.osCommand), opts...) + localArgs, err := args.toLocalCommandArgs(r.config, r.osCommand) + if err != nil { + return nil, err + } + + cmd, err := local.NewCommand(r.e.Ctx(), r.namer.ResourceName("cmd", name), localArgs, opts...) + + if err != nil { + return nil, err + } + + return &LocalCommand{cmd}, nil +} + +func (r *LocalRunner) newCopyFile(name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + return r.osCommand.copyLocalFile(r, name, localPath, remotePath, opts...) +} + +func (r *LocalRunner) PulumiOptions() []pulumi.ResourceOption { + return []pulumi.ResourceOption{} } diff --git a/components/command/unixOSCommand.go b/components/command/unixOSCommand.go index 21a94e376..35241eed6 100644 --- a/components/command/unixOSCommand.go +++ b/components/command/unixOSCommand.go @@ -27,12 +27,12 @@ func NewUnixOSCommand() OSCommand { // CreateDirectory if it does not exist func (unixOSCommand) CreateDirectory( - runner *Runner, + runner Runner, name string, remotePath pulumi.StringInput, useSudo bool, opts ...pulumi.ResourceOption, -) (*remote.Command, error) { +) (Command, error) { createCmd := fmt.Sprintf("mkdir -p %v", remotePath) deleteCmd := fmt.Sprintf(`bash -c 'if [ -z "$(ls -A %v)" ]; then rm -d %v; fi'`, remotePath, remotePath) // check if directory already exist @@ -60,7 +60,7 @@ func (fs unixOSCommand) BuildCommandString(command pulumi.StringInput, env pulum var envVars pulumi.StringArray for varName, varValue := range env { - envVars = append(envVars, pulumi.Sprintf(`%v="%v"`, varName, varValue)) + envVars = append(envVars, pulumi.Sprintf(`export %v="%v";`, varName, varValue)) } return buildCommandString(formattedCommand, envVars, func(envVarsStr pulumi.StringOutput) pulumi.StringInput { @@ -72,28 +72,8 @@ func (fs unixOSCommand) IsPathAbsolute(path string) bool { return strings.HasPrefix(path, "/") } -func (fs unixOSCommand) NewCopyFile(runner *Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { - tempRemotePath := localPath.ToStringOutput().ApplyT(func(path string) string { - return filepath.Join(runner.osCommand.GetTemporaryDirectory(), filepath.Base(path)) - }).(pulumi.StringOutput) - - tempCopyFile, err := remote.NewCopyFile(runner.e.Ctx(), runner.namer.ResourceName("copy", name), &remote.CopyFileArgs{ - Connection: runner.config.connection, - LocalPath: localPath, - RemotePath: tempRemotePath, - Triggers: pulumi.Array{localPath, tempRemotePath}, - }, utils.MergeOptions(runner.options, opts...)...) - - if err != nil { - return nil, err - } - - moveCommand, err := fs.moveRemoteFile(runner, name, tempRemotePath, remotePath, true, utils.MergeOptions(opts, utils.PulumiDependsOn(tempCopyFile))...) - if err != nil { - return nil, err - } - - return moveCommand, err +func (fs unixOSCommand) NewCopyFile(runner Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + return runner.newCopyFile(name, localPath, remotePath, opts...) } func formatCommandIfNeeded(command pulumi.StringInput, sudo bool, password bool, user string) pulumi.StringInput { @@ -117,10 +97,48 @@ func formatCommandIfNeeded(command pulumi.StringInput, sudo bool, password bool, return formattedCommand } -func (fs unixOSCommand) moveRemoteFile(runner *Runner, name string, source, destination pulumi.StringInput, sudo bool, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (fs unixOSCommand) MoveFile(runner Runner, name string, source, destination pulumi.StringInput, sudo bool, opts ...pulumi.ResourceOption) (Command, error) { backupPath := pulumi.Sprintf("%v.%s", destination, backupExtension) copyCommand := pulumi.Sprintf(`cp '%v' '%v'`, source, destination) createCommand := pulumi.Sprintf(`bash -c 'if [ -f '%v' ]; then mv -f '%v' '%v'; fi; %v'`, destination, destination, backupPath, copyCommand) deleteCommand := pulumi.Sprintf(`bash -c 'if [ -f '%v' ]; then mv -f '%v' '%v'; else rm -f '%v'; fi'`, backupPath, backupPath, destination, destination) return copyRemoteFile(runner, fmt.Sprintf("move-file-%s", name), createCommand, deleteCommand, sudo, utils.MergeOptions(opts, pulumi.ReplaceOnChanges([]string{"*"}), pulumi.DeleteBeforeReplace(true))...) } + +func (fs unixOSCommand) copyLocalFile(runner *LocalRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + createCmd := pulumi.Sprintf("cp '%v' '%v'", src, dst) + deleteCmd := pulumi.Sprintf("rm '%v'", dst) + useSudo := false + + return runner.Command(name, + &Args{ + Create: createCmd, + Delete: deleteCmd, + Sudo: useSudo, + Triggers: pulumi.Array{createCmd, deleteCmd, pulumi.BoolPtr(useSudo)}, + }, opts...) +} + +func (fs unixOSCommand) copyRemoteFile(runner *RemoteRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + tempRemotePath := src.ToStringOutput().ApplyT(func(path string) string { + return filepath.Join(runner.OsCommand().GetTemporaryDirectory(), filepath.Base(path)) + }).(pulumi.StringOutput) + + tempCopyFile, err := remote.NewCopyFile(runner.Environment().Ctx(), runner.Namer().ResourceName("copy", name), &remote.CopyFileArgs{ + Connection: runner.Config().connection, + LocalPath: src, + RemotePath: tempRemotePath, + Triggers: pulumi.Array{src, tempRemotePath}, + }, utils.MergeOptions(runner.PulumiOptions(), opts...)...) + + if err != nil { + return nil, err + } + + moveCommand, err := runner.OsCommand().MoveFile(runner, name, tempRemotePath, dst, true, utils.MergeOptions(opts, utils.PulumiDependsOn(tempCopyFile))...) + if err != nil { + return nil, err + } + + return moveCommand, err +} diff --git a/components/command/utils.go b/components/command/utils.go index 2dd361c8d..03fa532ed 100644 --- a/components/command/utils.go +++ b/components/command/utils.go @@ -1,13 +1,12 @@ package command import ( - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) -type ReadyFunc func(*Runner) (*remote.Command, error) +type ReadyFunc func(Runner) (Command, error) -func WaitForCloudInit(runner *Runner) (*remote.Command, error) { +func WaitForCloudInit(runner Runner) (Command, error) { return runner.Command( "wait-cloud-init", &Args{ @@ -17,7 +16,7 @@ func WaitForCloudInit(runner *Runner) (*remote.Command, error) { }) } -func WaitForSuccessfulConnection(runner *Runner) (*remote.Command, error) { +func WaitForSuccessfulConnection(runner Runner) (Command, error) { return runner.Command( "wait-successful-connection", &Args{ diff --git a/components/command/windowsOSCommand.go b/components/command/windowsOSCommand.go index c5fb0e3c5..440cdbaf5 100644 --- a/components/command/windowsOSCommand.go +++ b/components/command/windowsOSCommand.go @@ -20,12 +20,12 @@ func NewWindowsOSCommand() OSCommand { // CreateDirectory if it does not exist func (fs windowsOSCommand) CreateDirectory( - runner *Runner, + runner Runner, name string, remotePath pulumi.StringInput, _ bool, opts ...pulumi.ResourceOption, -) (*remote.Command, error) { +) (Command, error) { useSudo := false return createDirectory( runner, @@ -78,11 +78,37 @@ func (fs windowsOSCommand) IsPathAbsolute(path string) bool { return false } -func (fs windowsOSCommand) NewCopyFile(runner *Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { - return remote.NewCopyFile(runner.e.Ctx(), runner.namer.ResourceName("copy", name), &remote.CopyFileArgs{ - Connection: runner.config.connection, - LocalPath: localPath, - RemotePath: remotePath, - Triggers: pulumi.Array{localPath, remotePath}, - }, utils.MergeOptions(runner.options, opts...)...) +func (fs windowsOSCommand) NewCopyFile(runner Runner, name string, localPath, remotePath pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + return runner.newCopyFile(name, localPath, remotePath, opts...) +} + +func (fs windowsOSCommand) MoveFile(runner Runner, name string, source, destination pulumi.StringInput, sudo bool, opts ...pulumi.ResourceOption) (Command, error) { + backupPath := pulumi.Sprintf("%v.%s", destination, backupExtension) + copyCommand := pulumi.Sprintf(`Copy-Item -Path '%v' -Destination '%v'`, source, destination) + createCommand := pulumi.Sprintf(`if (Test-Path '%v') { Move-Item -Force -Path '%v' -Destination '%v' }; %v`, destination, destination, backupPath, copyCommand) + deleteCommand := pulumi.Sprintf(`if (Test-Path '%v') { Move-Item -Force -Path '%v' -Destination '%v' } else { Remove-Item -Force -Path %v }`, backupPath, backupPath, destination, destination) + return copyRemoteFile(runner, fmt.Sprintf("move-file-%s", name), createCommand, deleteCommand, sudo, utils.MergeOptions(opts, pulumi.ReplaceOnChanges([]string{"*"}), pulumi.DeleteBeforeReplace(true))...) +} + +func (fs windowsOSCommand) copyLocalFile(runner *LocalRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + createCmd := pulumi.Sprintf("Copy-Item -Path '%v' -Destination '%v'", src, dst) + deleteCmd := pulumi.Sprintf("Remove-Item -Path '%v'", dst) + useSudo := false + + return runner.Command(name, + &Args{ + Create: createCmd, + Delete: deleteCmd, + Sudo: useSudo, + Triggers: pulumi.Array{createCmd, deleteCmd, pulumi.BoolPtr(useSudo)}, + }, opts...) +} + +func (fs windowsOSCommand) copyRemoteFile(runner *RemoteRunner, name string, src, dst pulumi.StringInput, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { + return remote.NewCopyFile(runner.Environment().Ctx(), runner.Namer().ResourceName("copy", name), &remote.CopyFileArgs{ + Connection: runner.Config().connection, + LocalPath: src, + RemotePath: dst, + Triggers: pulumi.Array{src, dst}, + }, utils.MergeOptions(runner.PulumiOptions(), opts...)...) } diff --git a/components/datadog/agent/host_linuxos.go b/components/datadog/agent/host_linuxos.go index f72cdc84a..b163cd2e4 100644 --- a/components/datadog/agent/host_linuxos.go +++ b/components/datadog/agent/host_linuxos.go @@ -2,13 +2,13 @@ package agent import ( "fmt" + "strings" + "github.com/DataDog/test-infra-definitions/components/command" "github.com/DataDog/test-infra-definitions/components/datadog/agentparams" "github.com/DataDog/test-infra-definitions/components/os" remoteComp "github.com/DataDog/test-infra-definitions/components/remote" - "strings" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -62,6 +62,6 @@ func (am *agentLinuxManager) getAgentConfigFolder() string { return "/etc/datadog-agent" } -func (am *agentLinuxManager) restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (am *agentLinuxManager) restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { return am.targetOS.ServiceManger().EnsureRestarted("datadog-agent", transform, opts...) } diff --git a/components/datadog/agent/host_os.go b/components/datadog/agent/host_os.go index 05b498604..8d8de1d6d 100644 --- a/components/datadog/agent/host_os.go +++ b/components/datadog/agent/host_os.go @@ -2,13 +2,13 @@ package agent import ( "fmt" + "github.com/DataDog/test-infra-definitions/components/datadog/agentparams" "github.com/DataDog/test-infra-definitions/components/command" "github.com/DataDog/test-infra-definitions/components/os" remoteComp "github.com/DataDog/test-infra-definitions/components/remote" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -16,7 +16,7 @@ import ( type agentOSManager interface { getInstallCommand(version agentparams.PackageVersion, additionalInstallParameters []string) (string, error) getAgentConfigFolder() string - restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) + restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) } func getOSManager(host *remoteComp.Host) agentOSManager { diff --git a/components/datadog/agent/host_windowsos.go b/components/datadog/agent/host_windowsos.go index a4817dc16..63283b04c 100644 --- a/components/datadog/agent/host_windowsos.go +++ b/components/datadog/agent/host_windowsos.go @@ -20,7 +20,6 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" awsConfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -68,7 +67,7 @@ for ($i=0; $i -lt 3; $i++) { }; $exitCode = (Start-Process -Wait msiexec -PassThru -ArgumentList '/qn /i %s APIKEY=%%s %s').ExitCode Get-Content %s -Exit $exitCode +Exit $exitCode `, url, localFilename, localFilename, strings.Join(additionalInstallParameters, " "), logFilePath) return cmd, nil } @@ -77,7 +76,7 @@ func (am *agentWindowsManager) getAgentConfigFolder() string { return `C:\ProgramData\Datadog` } -func (am *agentWindowsManager) restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (am *agentWindowsManager) restartAgentServices(transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { // TODO: When we introduce Namer in components, we should use it here. cmdName := am.host.Name() + "-" + "restart-agent" // Retry restart several time, workaround to https://datadoghq.atlassian.net/browse/WINA-747 @@ -92,7 +91,7 @@ while ($tries -lt 5) { } Start-Sleep -Seconds $sleepTime $sleepTime = $sleepTime * 2 - $tries++ + $tries++ } Get-Content stderr.txt Exit $exitCode diff --git a/components/docker/component.go b/components/docker/component.go index 6db241712..72d9a1451 100644 --- a/components/docker/component.go +++ b/components/docker/component.go @@ -13,7 +13,6 @@ import ( "github.com/DataDog/test-infra-definitions/components/command" remoteComp "github.com/DataDog/test-infra-definitions/components/remote" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -64,7 +63,7 @@ func (d *Manager) Export(ctx *pulumi.Context, out *ManagerOutput) error { return components.Export(ctx, d, out) } -func (d *Manager) ComposeFileUp(composeFilePath string, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (d *Manager) ComposeFileUp(composeFilePath string, opts ...pulumi.ResourceOption) (command.Command, error) { opts = utils.MergeOptions(d.opts, opts...) composeHash, err := utils.FileHash(composeFilePath) @@ -93,7 +92,7 @@ func (d *Manager) ComposeFileUp(composeFilePath string, opts ...pulumi.ResourceO ) } -func (d *Manager) ComposeStrUp(name string, composeManifests []ComposeInlineManifest, envVars pulumi.StringMap, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (d *Manager) ComposeStrUp(name string, composeManifests []ComposeInlineManifest, envVars pulumi.StringMap, opts ...pulumi.ResourceOption) (command.Command, error) { opts = utils.MergeOptions(d.opts, opts...) homeCmd, composePath, err := d.Host.OS.FileManager().HomeDirectory(name+"-compose-tmp", opts...) @@ -140,7 +139,7 @@ func (d *Manager) ComposeStrUp(name string, composeManifests []ComposeInlineMani ) } -func (d *Manager) install() (*remote.Command, error) { +func (d *Manager) install() (command.Command, error) { opts := []pulumi.ResourceOption{pulumi.Parent(d)} opts = utils.MergeOptions(d.opts, opts...) dockerInstall, err := d.Host.OS.PackageManager().Ensure("docker.io", nil, "docker", opts...) @@ -178,7 +177,7 @@ func (d *Manager) install() (*remote.Command, error) { groupCmd, err := d.Host.OS.Runner().Command( d.namer.ResourceName("group"), &command.Args{ - Create: pulumi.Sprintf("usermod -a -G docker %s", whoami.Stdout), + Create: pulumi.Sprintf("usermod -a -G docker %s", whoami.StdoutOutput()), Sudo: true, }, utils.MergeOptions(opts, utils.PulumiDependsOn(whoami))..., @@ -190,7 +189,7 @@ func (d *Manager) install() (*remote.Command, error) { return groupCmd, err } -func (d *Manager) installCompose() (*remote.Command, error) { +func (d *Manager) installCompose() (command.Command, error) { opts := append(d.opts, pulumi.Parent(d)) installCompose := pulumi.Sprintf("bash -c '(docker-compose version | grep %s) || (curl --retry 10 -fsSLo /usr/local/bin/docker-compose https://github.com/docker/compose/releases/download/%s/docker-compose-linux-$(uname -p) && sudo chmod 755 /usr/local/bin/docker-compose)'", composeVersion, composeVersion) return d.Host.OS.Runner().Command( diff --git a/components/kubernetes/kind.go b/components/kubernetes/kind.go index b2b43757f..37b9a2706 100644 --- a/components/kubernetes/kind.go +++ b/components/kubernetes/kind.go @@ -100,7 +100,7 @@ func NewKindCluster(env config.Env, vm *remote.Host, name string, kubeVersion st // Patch Kubeconfig based on private IP output // Also add skip tls - clusterComp.KubeConfig = pulumi.All(kubeConfigCmd.Stdout, vm.Address).ApplyT(func(args []interface{}) string { + clusterComp.KubeConfig = pulumi.All(kubeConfigCmd.StdoutOutput(), vm.Address).ApplyT(func(args []interface{}) string { allowInsecure := regexp.MustCompile("certificate-authority-data:.+").ReplaceAllString(args[0].(string), "insecure-skip-tls-verify: true") return strings.ReplaceAll(allowInsecure, "0.0.0.0", args[1].(string)) }).(pulumi.StringOutput) @@ -161,7 +161,7 @@ func NewLocalKindCluster(env config.Env, name string, kubeVersion string, opts . return err } - clusterComp.KubeConfig = kubeConfigCmd.Stdout + clusterComp.KubeConfig = kubeConfigCmd.StdoutOutput() clusterComp.ClusterName = kindClusterName.ToStringOutput() return nil diff --git a/components/os/linux.go b/components/os/linux.go index b060193cb..f70a85d1b 100644 --- a/components/os/linux.go +++ b/components/os/linux.go @@ -7,7 +7,7 @@ import ( "github.com/DataDog/test-infra-definitions/components/command" ) -func newLinuxOS(e config.Env, desc Descriptor, runner *command.Runner) OS { +func newLinuxOS(e config.Env, desc Descriptor, runner command.Runner) OS { os := &os{ descriptor: desc, runner: runner, diff --git a/components/os/linux_packagemanagers.go b/components/os/linux_packagemanagers.go index d263f9cbe..b41344a92 100644 --- a/components/os/linux_packagemanagers.go +++ b/components/os/linux_packagemanagers.go @@ -5,19 +5,19 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) -func newAptManager(runner *command.Runner) PackageManager { +func newAptManager(runner command.Runner) PackageManager { return command.NewGenericPackageManager(runner, "apt", "apt-get install -y", "apt-get update -y", pulumi.StringMap{"DEBIAN_FRONTEND": pulumi.String("noninteractive")}) } -func newYumManager(runner *command.Runner) PackageManager { +func newYumManager(runner command.Runner) PackageManager { return command.NewGenericPackageManager(runner, "yum", "yum install -y", "", nil) } -func newDnfManager(runner *command.Runner) PackageManager { +func newDnfManager(runner command.Runner) PackageManager { return command.NewGenericPackageManager(runner, "dnf", "dnf install -y", "", nil) } -func newZypperManager(runner *command.Runner) PackageManager { +func newZypperManager(runner command.Runner) PackageManager { return command.NewGenericPackageManager(runner, "zypper", "zypper -n install", "zypper -n refresh", nil) } diff --git a/components/os/linux_servicemanagers.go b/components/os/linux_servicemanagers.go index ad4d9460b..b78da21c7 100644 --- a/components/os/linux_servicemanagers.go +++ b/components/os/linux_servicemanagers.go @@ -5,20 +5,19 @@ import ( "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/components/command" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) type systemdServiceManager struct { e config.Env - runner *command.Runner + runner command.Runner } -func newSystemdServiceManager(e config.Env, runner *command.Runner) ServiceManager { +func newSystemdServiceManager(e config.Env, runner command.Runner) ServiceManager { return &systemdServiceManager{e: e, runner: runner} } -func (s *systemdServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (s *systemdServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { cmdName := s.e.CommonNamer().ResourceName("running", serviceName) cmdArgs := command.Args{ Sudo: true, @@ -35,14 +34,14 @@ func (s *systemdServiceManager) EnsureRestarted(serviceName string, transform co type sysvinitServiceManager struct { e config.Env - runner *command.Runner + runner command.Runner } -func newSysvinitServiceManager(e config.Env, runner *command.Runner) ServiceManager { +func newSysvinitServiceManager(e config.Env, runner command.Runner) ServiceManager { return &sysvinitServiceManager{e: e, runner: runner} } -func (s *sysvinitServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (s *sysvinitServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { cmdName := s.e.CommonNamer().ResourceName("running", serviceName) // To the difference of systemctl the restart doesn't work if the service isn't already running // so instead we run a stop command that we allow to fail and then a start command diff --git a/components/os/macos.go b/components/os/macos.go index c66be16f8..b9f637b6f 100644 --- a/components/os/macos.go +++ b/components/os/macos.go @@ -5,7 +5,7 @@ import ( "github.com/DataDog/test-infra-definitions/components/command" ) -func newMacOS(e config.Env, desc Descriptor, runner *command.Runner) OS { +func newMacOS(e config.Env, desc Descriptor, runner command.Runner) OS { os := &os{ descriptor: desc, runner: runner, diff --git a/components/os/macos_packagemanagers.go b/components/os/macos_packagemanagers.go index 0cda0e3de..511a675f0 100644 --- a/components/os/macos_packagemanagers.go +++ b/components/os/macos_packagemanagers.go @@ -5,7 +5,7 @@ import ( "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) -func newBrewManager(runner *command.Runner) PackageManager { +func newBrewManager(runner command.Runner) PackageManager { return command.NewGenericPackageManager(runner, "brew", "brew install -y", "brew update -y", pulumi.StringMap{"NONINTERACTIVE": pulumi.String("1")}) } diff --git a/components/os/macos_servicemanagers.go b/components/os/macos_servicemanagers.go index a29d00f83..8ebd8a8d4 100644 --- a/components/os/macos_servicemanagers.go +++ b/components/os/macos_servicemanagers.go @@ -5,20 +5,19 @@ import ( "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/components/command" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) type macOSServiceManager struct { e config.Env - runner *command.Runner + runner command.Runner } -func newMacOSServiceManager(e config.Env, runner *command.Runner) ServiceManager { +func newMacOSServiceManager(e config.Env, runner command.Runner) ServiceManager { return &macOSServiceManager{e: e, runner: runner} } -func (s *macOSServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (s *macOSServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { cmdName := s.e.CommonNamer().ResourceName("running", serviceName) cmdArgs := command.Args{ Sudo: true, diff --git a/components/os/os.go b/components/os/os.go index a9570a2a3..0a3a8d130 100644 --- a/components/os/os.go +++ b/components/os/os.go @@ -6,7 +6,6 @@ import ( "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/components/command" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -15,12 +14,12 @@ type PackageManager interface { // Ensure ensures that a package is installed // checkBinary is a binary that should be checked before running the install command, if it is not empty it will first run the `command -v checkBinary` command and if it fails it will run the installCmd, // if it succeeds we consider the package is already installed - Ensure(packageRef string, transform command.Transformer, checkBinary string, opts ...pulumi.ResourceOption) (*remote.Command, error) + Ensure(packageRef string, transform command.Transformer, checkBinary string, opts ...pulumi.ResourceOption) (command.Command, error) } type ServiceManager interface { // EnsureStarted starts or restarts (may be stop+start depending on implementation) the service if already running - EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) + EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) } // FileManager needs to be added here as well instead of the command package @@ -29,7 +28,7 @@ type ServiceManager interface { type OS interface { Descriptor() Descriptor - Runner() *command.Runner + Runner() command.Runner FileManager() *command.FileManager PackageManager() PackageManager ServiceManger() ServiceManager @@ -40,7 +39,7 @@ var _ OS = &os{} // os is a generic implementation of OS interface type os struct { descriptor Descriptor - runner *command.Runner + runner command.Runner fileManager *command.FileManager packageManager PackageManager serviceManager ServiceManager @@ -50,7 +49,7 @@ func (o os) Descriptor() Descriptor { return o.descriptor } -func (o os) Runner() *command.Runner { +func (o os) Runner() command.Runner { return o.runner } @@ -69,7 +68,7 @@ func (o os) ServiceManger() ServiceManager { func NewOS( e config.Env, descriptor Descriptor, - runner *command.Runner, + runner command.Runner, ) OS { switch descriptor.Family() { case LinuxFamily: diff --git a/components/os/windows.go b/components/os/windows.go index a6e9dec78..304f1d0fa 100644 --- a/components/os/windows.go +++ b/components/os/windows.go @@ -5,7 +5,7 @@ import ( "github.com/DataDog/test-infra-definitions/components/command" ) -func newWindowsOS(e config.Env, desc Descriptor, runner *command.Runner) OS { +func newWindowsOS(e config.Env, desc Descriptor, runner command.Runner) OS { os := &os{ descriptor: desc, runner: runner, diff --git a/components/os/windows_servicemanagers.go b/components/os/windows_servicemanagers.go index b75015b23..fb2afdf9e 100644 --- a/components/os/windows_servicemanagers.go +++ b/components/os/windows_servicemanagers.go @@ -3,20 +3,19 @@ package os import ( "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/components/command" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) type windowsServiceManager struct { e config.Env - runner *command.Runner + runner command.Runner } -func newWindowsServiceManager(e config.Env, runner *command.Runner) ServiceManager { +func newWindowsServiceManager(e config.Env, runner command.Runner) ServiceManager { return &windowsServiceManager{e: e, runner: runner} } -func (s *windowsServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (*remote.Command, error) { +func (s *windowsServiceManager) EnsureRestarted(serviceName string, transform command.Transformer, opts ...pulumi.ResourceOption) (command.Command, error) { cmdName := s.e.CommonNamer().ResourceName("running", serviceName) cmdArgs := command.Args{ Create: pulumi.String("Restart-Service -Name " + serviceName), diff --git a/components/remote/os.go b/components/remote/os.go index 984e0d7c6..988db2746 100644 --- a/components/remote/os.go +++ b/components/remote/os.go @@ -20,7 +20,7 @@ func InitHost(e config.Env, conn remote.ConnectionOutput, osDesc os.Descriptor, } // Now we can create the runner - runner, err := command.NewRunner(e, command.RunnerArgs{ + runner, err := command.NewRemoteRunner(e, command.RemoteRunnerArgs{ ParentResource: host, ConnectionName: host.Name(), Connection: conn, diff --git a/main.go b/main.go index 4bfc97ce0..0c3df24bf 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "strings" "github.com/DataDog/test-infra-definitions/registry" - "github.com/pulumi/pulumi/sdk/v3/go/pulumi" "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config" ) diff --git a/resources/local/podman/vm.go b/resources/local/podman/vm.go index 6ec2bf8e2..242271106 100644 --- a/resources/local/podman/vm.go +++ b/resources/local/podman/vm.go @@ -4,13 +4,11 @@ import ( _ "embed" "os" "path" - "runtime" - "github.com/DataDog/test-infra-definitions/common/config" "github.com/DataDog/test-infra-definitions/common/utils" + "github.com/DataDog/test-infra-definitions/components/command" resourceslocal "github.com/DataDog/test-infra-definitions/resources/local" - "github.com/pulumi/pulumi-command/sdk/go/command/local" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -23,10 +21,8 @@ var dockerfileContent string var customDockerConfig = "{}" func NewInstance(e resourceslocal.Environment, args VMArgs, opts ...pulumi.ResourceOption) (address pulumi.StringOutput, user string, port int, err error) { - interpreter := []string{"/bin/bash", "-c"} - if runtime.GOOS == "windows" { - interpreter = []string{"powershell", "-Command"} - } + runner := command.NewLocalRunner(&e, command.LocalRunnerArgs{OSCommand: command.NewLocalOSCommand()}) + fileManager := command.NewFileManager(runner) publicKey, err := os.ReadFile(e.DefaultPublicKeyPath()) if err != nil { @@ -40,48 +36,45 @@ func NewInstance(e resourceslocal.Environment, args VMArgs, opts ...pulumi.Resou dataPath := path.Join(homeDir, ".localpodman") // TODO clean up the folder on stack destroy // Requires a Runner refactor to reuse crossplatform commands - err = os.MkdirAll(dataPath, 0700) + dataDir, err := fileManager.CreateDirectory(dataPath, false) if err != nil { return pulumi.StringOutput{}, "", -1, err } + dockerfilePath := path.Join(dataPath, "Dockerfile") - err = os.WriteFile(dockerfilePath, []byte(dockerfileContent), 0600) + dockerFile, err := fileManager.CopyInlineFile(pulumi.String(dockerfileContent), dockerfilePath, pulumi.DependsOn([]pulumi.Resource{dataDir})) if err != nil { return pulumi.StringOutput{}, "", -1, err } // Use a config to avoid docker hooks that can call vault or other services (credHelpers) - err = os.WriteFile(path.Join(dataPath, "config.json"), []byte(customDockerConfig), 0600) + dockerConfig, err := fileManager.CopyInlineFile(pulumi.String(customDockerConfig), path.Join(dataPath, "config.json"), pulumi.DependsOn([]pulumi.Resource{dataDir})) if err != nil { return pulumi.StringOutput{}, "", -1, err } podmanCommand := "podman --config " + dataPath - opts = utils.MergeOptions(opts, e.WithProviders(config.ProviderCommand)) - // TODO use NewLocalRunner - // requires a refactor to pass interpreter - buildPodman, err := local.NewCommand(e.Ctx(), e.CommonNamer().ResourceName("podman-build", args.Name), &local.CommandArgs{ - Interpreter: pulumi.ToStringArray(interpreter), - Environment: pulumi.StringMap{"DOCKER_HOST_SSH_PUBLIC_KEY": pulumi.String(string(publicKey))}, - Create: pulumi.Sprintf("%s build --format=docker --build-arg DOCKER_HOST_SSH_PUBLIC_KEY=\"$DOCKER_HOST_SSH_PUBLIC_KEY\" -t %s .", podmanCommand, args.Name), - Delete: pulumi.Sprintf("%s rmi %s", podmanCommand, args.Name), - Triggers: pulumi.Array{}, - AssetPaths: pulumi.StringArray{}, - Dir: pulumi.String(dataPath), + opts = utils.MergeOptions(opts, pulumi.DependsOn([]pulumi.Resource{dockerFile, dockerConfig})) + buildPodman, err := runner.Command("podman-build"+args.Name, &command.Args{ + Environment: pulumi.StringMap{"DOCKER_HOST_SSH_PUBLIC_KEY": pulumi.String(string(publicKey))}, + Create: pulumi.Sprintf("%s build --format=docker --build-arg DOCKER_HOST_SSH_PUBLIC_KEY=\"$DOCKER_HOST_SSH_PUBLIC_KEY\" -t %s .", podmanCommand, args.Name), + Delete: pulumi.Sprintf("%s rmi %s", podmanCommand, args.Name), + Triggers: pulumi.Array{}, + LocalAssetPaths: pulumi.StringArray{}, + LocalDir: pulumi.String(dataPath), }, opts...) if err != nil { return pulumi.StringOutput{}, "", -1, err } opts = utils.MergeOptions(opts, pulumi.DependsOn([]pulumi.Resource{buildPodman})) - runPodman, err := local.NewCommand(e.Ctx(), e.CommonNamer().ResourceName("podman-run", args.Name), &local.CommandArgs{ - Interpreter: pulumi.ToStringArray(interpreter), - Environment: pulumi.StringMap{"DOCKER_HOST_SSH_PUBLIC_KEY": pulumi.String(string(publicKey))}, - Create: pulumi.Sprintf("%s run -d --name=%[2]s_run -p 50022:22 %[2]s", podmanCommand, args.Name), - Delete: pulumi.Sprintf("%s stop %[2]s_run && podman rm %[2]s_run", podmanCommand, args.Name), - Triggers: pulumi.Array{}, - AssetPaths: pulumi.StringArray{}, - Dir: pulumi.String(dataPath), + runPodman, err := runner.Command("podman-run"+args.Name, &command.Args{ + Environment: pulumi.StringMap{"DOCKER_HOST_SSH_PUBLIC_KEY": pulumi.String(string(publicKey))}, + Create: pulumi.Sprintf("%s run -d --name=%[2]s_run -p 50022:22 %[2]s", podmanCommand, args.Name), + Delete: pulumi.Sprintf("%s stop %[2]s_run && podman rm %[2]s_run", podmanCommand, args.Name), + Triggers: pulumi.Array{}, + LocalAssetPaths: pulumi.StringArray{}, + LocalDir: pulumi.String(dataPath), }, opts...) if err != nil { return pulumi.StringOutput{}, "", -1, err @@ -90,7 +83,7 @@ func NewInstance(e resourceslocal.Environment, args VMArgs, opts ...pulumi.Resou e.Ctx().Log.Info("Running with container of type ubuntu", nil) // hack to wait for the container to be up - ipAddress := runPodman.Stdout.ApplyT(func(_ string) string { + ipAddress := runPodman.StdoutOutput().ApplyT(func(_ string) string { return "localhost" }).(pulumi.StringOutput) diff --git a/scenarios/aws/ec2/vm.go b/scenarios/aws/ec2/vm.go index e3568fffd..85fed7a3e 100644 --- a/scenarios/aws/ec2/vm.go +++ b/scenarios/aws/ec2/vm.go @@ -12,7 +12,6 @@ import ( "github.com/DataDog/test-infra-definitions/resources/aws" "github.com/DataDog/test-infra-definitions/resources/aws/ec2" - goremote "github.com/pulumi/pulumi-command/sdk/go/command/remote" "github.com/pulumi/pulumi-random/sdk/v4/go/random" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -110,7 +109,7 @@ func NewVM(e aws.Environment, name string, params ...VMOption) (*remote.Host, er }) } -func InstallECRCredentialsHelper(e aws.Environment, vm *remote.Host) (*goremote.Command, error) { +func InstallECRCredentialsHelper(e aws.Environment, vm *remote.Host) (command.Command, error) { ecrCredsHelperInstall, err := vm.OS.PackageManager().Ensure("amazon-ecr-credential-helper", nil, "") if err != nil { return nil, err diff --git a/scenarios/aws/microVMs/microvms/libvirt.go b/scenarios/aws/microVMs/microvms/libvirt.go index 3a0f22496..68105dc10 100644 --- a/scenarios/aws/microVMs/microvms/libvirt.go +++ b/scenarios/aws/microVMs/microvms/libvirt.go @@ -47,7 +47,7 @@ func newLibvirtFS(ctx *pulumi.Context, vmset *vmconfig.VMSet, pools map[vmconfig } } -func createDomainConsoleLog(runner *Runner, domainName string, resourceName string, depends []pulumi.Resource) (pulumi.Resource, error) { +func createDomainConsoleLog(runner command.Runner, domainName string, resourceName string, depends []pulumi.Resource) (pulumi.Resource, error) { args := command.Args{ Create: pulumi.Sprintf("truncate --size=0 %s", resources.GetConsolePath(domainName)), } diff --git a/scenarios/aws/microVMs/microvms/libvirt_fs.go b/scenarios/aws/microVMs/microvms/libvirt_fs.go index 2ac4ac685..e69725c59 100644 --- a/scenarios/aws/microVMs/microvms/libvirt_fs.go +++ b/scenarios/aws/microVMs/microvms/libvirt_fs.go @@ -211,7 +211,7 @@ func NewLibvirtFSCustomRecipe(ctx *pulumi.Context, vmset *vmconfig.VMSet, pools } } -func refreshFromBackingStore(volume LibvirtVolume, runner *Runner, urlPath string, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func refreshFromBackingStore(volume LibvirtVolume, runner command.Runner, urlPath string, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { var downloadCmd string var refreshCmd string @@ -246,7 +246,7 @@ func refreshFromBackingStore(volume LibvirtVolume, runner *Runner, urlPath strin return []pulumi.Resource{res}, err } -func downloadAndExtractRootfs(fs *LibvirtFilesystem, runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func downloadAndExtractRootfs(fs *LibvirtFilesystem, runner command.Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { var waitFor []pulumi.Resource var downloadSpecs []filesystemImageDownload var retrieveImage []pulumi.Resource @@ -334,7 +334,7 @@ func downloadAndExtractRootfs(fs *LibvirtFilesystem, runner *Runner, depends []p return waitFor, nil } -func extractImage(fsImage *filesystemImage, runner *Runner, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func extractImage(fsImage *filesystemImage, runner command.Runner, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { // Extract archive from the download path assuming it is xz compressed extractTopLevelArchive := command.Args{ Create: pulumi.Sprintf("rm %s || true; xz -d %s", fsImage.imagePath, fsImage.downloadPath()), @@ -347,7 +347,7 @@ func extractImage(fsImage *filesystemImage, runner *Runner, namer namer.Namer, d return []pulumi.Resource{res}, nil } -func (fs *LibvirtFilesystem) SetupLibvirtFilesystem(providerFn LibvirtProviderFn, runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func (fs *LibvirtFilesystem) SetupLibvirtFilesystem(providerFn LibvirtProviderFn, runner command.Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { // Downloading the base images for the volumes is the slowest part of the entire setup. // We want this step to start as soon as our remote VMs are ready. Therefore, we do not // make it depend on any other step. @@ -363,7 +363,7 @@ func (fs *LibvirtFilesystem) SetupLibvirtFilesystem(providerFn LibvirtProviderFn return setupLibvirtFilesystem(fs, runner, providerFn, depends) } -func setupLibvirtFilesystem(fs *LibvirtFilesystem, runner *Runner, providerFn LibvirtProviderFn, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func setupLibvirtFilesystem(fs *LibvirtFilesystem, runner command.Runner, providerFn LibvirtProviderFn, depends []pulumi.Resource) ([]pulumi.Resource, error) { var waitFor []pulumi.Resource for _, vol := range fs.volumes { setupLibvirtVMVolumeDone, err := vol.SetupLibvirtVMVolume(fs.ctx, runner, providerFn, fs.isLocal, depends) diff --git a/scenarios/aws/microVMs/microvms/network.go b/scenarios/aws/microVMs/microvms/network.go index f134f89b6..b1a682cc6 100644 --- a/scenarios/aws/microVMs/microvms/network.go +++ b/scenarios/aws/microVMs/microvms/network.go @@ -93,7 +93,7 @@ func getMicroVMGroupSubnet(taken []string) (string, error) { return "", fmt.Errorf("getMicroVMGroupSubnet: could not find subnet") } -func allowNFSPortsForBridge(ctx *pulumi.Context, isLocal bool, bridge pulumi.StringOutput, runner *Runner, resourceNamer namer.Namer, microVMGroupSubnet string) ([]pulumi.Resource, error) { +func allowNFSPortsForBridge(ctx *pulumi.Context, isLocal bool, bridge pulumi.StringOutput, runner command.Runner, resourceNamer namer.Namer, microVMGroupSubnet string) ([]pulumi.Resource, error) { sudoPassword := GetSudoPassword(ctx, isLocal) iptablesAllowTCPArgs := command.Args{ Create: pulumi.Sprintf(iptablesTCPRule, iptablesAddRuleFlag, bridge, microVMGroupSubnet, tcpRPCInfoPorts), diff --git a/scenarios/aws/microVMs/microvms/pool.go b/scenarios/aws/microVMs/microvms/pool.go index 6187b8f84..a8d7adefa 100644 --- a/scenarios/aws/microVMs/microvms/pool.go +++ b/scenarios/aws/microVMs/microvms/pool.go @@ -14,7 +14,7 @@ import ( ) type LibvirtPool interface { - SetupLibvirtPool(ctx *pulumi.Context, runner *Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) + SetupLibvirtPool(ctx *pulumi.Context, runner command.Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) Name() string Type() vmconfig.PoolType Path() string @@ -67,7 +67,7 @@ Setup for remote pool and local pool is different for a number of reasons: the target environment and the pulumi host are the same machine. It is simpler to use this API locally than have a complicated permissions setup. */ -func remoteGlobalPool(p *globalLibvirtPool, runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func remoteGlobalPool(p *globalLibvirtPool, runner command.Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { poolXMLWrittenArgs := command.Args{ Create: pulumi.Sprintf("echo \"%s\" > %s", p.poolXML, p.poolXMLPath), Delete: pulumi.Sprintf("rm -f %s", p.poolXMLPath), @@ -139,7 +139,7 @@ func localGlobalPool(ctx *pulumi.Context, p *globalLibvirtPool, providerFn Libvi return []pulumi.Resource{poolReady}, nil } -func (p *globalLibvirtPool) SetupLibvirtPool(ctx *pulumi.Context, runner *Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func (p *globalLibvirtPool) SetupLibvirtPool(ctx *pulumi.Context, runner command.Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { if isLocal { return localGlobalPool(ctx, p, providerFn, depends) } @@ -200,7 +200,7 @@ func NewRAMBackedLibvirtPool(ctx *pulumi.Context, disk *vmconfig.Disk) (LibvirtP }, nil } -func (p *rambackedLibvirtPool) SetupLibvirtPool(ctx *pulumi.Context, runner *Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func (p *rambackedLibvirtPool) SetupLibvirtPool(ctx *pulumi.Context, runner command.Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) ([]pulumi.Resource, error) { buildSharedDiskInRamfsArgs := command.Args{ Create: pulumi.Sprintf(sharedDiskCmd, p.poolPath, p.poolSize, p.baseImagePath), Delete: pulumi.Sprintf("umount %[1]s && rm -r %[1]s", p.poolPath), diff --git a/scenarios/aws/microVMs/microvms/provision.go b/scenarios/aws/microVMs/microvms/provision.go index 5fcd726e4..68a0fa102 100644 --- a/scenarios/aws/microVMs/microvms/provision.go +++ b/scenarios/aws/microVMs/microvms/provision.go @@ -64,15 +64,15 @@ func readMicroVMSSHKey(instance *Instance, depends []pulumi.Resource) (pulumi.St args := command.Args{ Create: pulumi.Sprintf("cat %s", filepath.Join(GetWorkingDirectory(instance.Arch), "ddvm_rsa")), } - done, err := instance.runner.RemoteCommand(instance.instanceNamer.ResourceName("read-microvm-ssh-key"), &args, pulumi.DependsOn(depends)) + done, err := instance.runner.Command(instance.instanceNamer.ResourceName("read-microvm-ssh-key"), &args, pulumi.DependsOn(depends)) if err != nil { return pulumi.StringOutput{}, nil, err } - s := pulumi.ToSecret(done.Stdout).(pulumi.StringOutput) + s := pulumi.ToSecret(done.StdoutOutput()).(pulumi.StringOutput) return s, []pulumi.Resource{done}, err } -func setupSSHAllowEnv(runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func setupSSHAllowEnv(runner command.Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { args := command.Args{ Create: pulumi.Sprintf("echo -e 'AcceptEnv DD_API_KEY\n' | sudo tee -a /etc/ssh/sshd_config"), } @@ -83,7 +83,7 @@ func setupSSHAllowEnv(runner *Runner, depends []pulumi.Resource) ([]pulumi.Resou return []pulumi.Resource{done}, nil } -func reloadSSHD(runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func reloadSSHD(runner command.Runner, depends []pulumi.Resource) ([]pulumi.Resource, error) { args := command.Args{ Create: pulumi.Sprintf("sudo systemctl reload sshd.service"), } @@ -94,7 +94,7 @@ func reloadSSHD(runner *Runner, depends []pulumi.Resource) ([]pulumi.Resource, e return []pulumi.Resource{done}, nil } -func mountMicroVMDisks(runner *Runner, disks []resources.DomainDisk, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func mountMicroVMDisks(runner command.Runner, disks []resources.DomainDisk, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { var waitFor []pulumi.Resource for _, d := range disks { @@ -117,7 +117,7 @@ func mountMicroVMDisks(runner *Runner, disks []resources.DomainDisk, namer namer return waitFor, nil } -func setDockerDataRoot(runner *Runner, disks []resources.DomainDisk, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func setDockerDataRoot(runner command.Runner, disks []resources.DomainDisk, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { var waitFor []pulumi.Resource for _, d := range disks { @@ -142,7 +142,7 @@ func setDockerDataRoot(runner *Runner, disks []resources.DomainDisk, namer namer return waitFor, nil } -func enableNFSConnKiller(runner *Runner, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func enableNFSConnKiller(runner command.Runner, namer namer.Namer, depends []pulumi.Resource) ([]pulumi.Resource, error) { args := command.Args{ Create: pulumi.Sprintf("systemctl enable --now kill-dead-nfs-connections.timer"), Sudo: true, @@ -173,7 +173,7 @@ func provisionMetalInstance(instance *Instance) ([]pulumi.Resource, error) { return reloadSSHDDone, nil } -func prepareLibvirtSSHKeys(runner *Runner, localRunner *command.LocalRunner, resourceNamer namer.Namer, pair sshKeyPair, depends []pulumi.Resource) ([]pulumi.Resource, error) { +func prepareLibvirtSSHKeys(runner command.Runner, localRunner *command.LocalRunner, resourceNamer namer.Namer, pair sshKeyPair, depends []pulumi.Resource) ([]pulumi.Resource, error) { sshGenArgs := command.Args{ Create: pulumi.Sprintf("rm -f %s && rm -f %s && ssh-keygen -t rsa -b 4096 -f %s -q -N \"\" && cat %s", pair.privateKey, pair.publicKey, pair.privateKey, pair.publicKey), Delete: pulumi.Sprintf("rm %s && rm %s", pair.privateKey, pair.publicKey), @@ -189,7 +189,7 @@ func prepareLibvirtSSHKeys(runner *Runner, localRunner *command.LocalRunner, res // We override the runner-level user here with root, and construct the path to the default users .ssh directory, // in order to write the public ssh key in the correct file. sshWriteArgs := command.Args{ - Create: pulumi.Sprintf("echo '%s' >> $(getent passwd 1000 | cut -d: -f6)/.ssh/authorized_keys", sshgenDone.Stdout), + Create: pulumi.Sprintf("echo '%s' >> $(getent passwd 1000 | cut -d: -f6)/.ssh/authorized_keys", sshgenDone.StdoutOutput()), Sudo: true, } @@ -237,9 +237,9 @@ func provisionRemoteMicroVMs(vmCollections []*VMCollection, instanceEnv *Instanc } pc := createProxyConnection(domain.ip, "root", microVMSSHKey, conn.ToConnectionOutput()) - remoteRunner, err := command.NewRunner( + remoteRunner, err := command.NewRemoteRunner( collection.instance.e, - command.RunnerArgs{ + command.RemoteRunnerArgs{ ParentResource: domain.lvDomain, Connection: pc, ConnectionName: collection.instance.instanceNamer.ResourceName("conn", domain.domainID), @@ -249,21 +249,20 @@ func provisionRemoteMicroVMs(vmCollections []*VMCollection, instanceEnv *Instanc if err != nil { return nil, err } - microRunner := NewRunner(WithRemoteRunner(remoteRunner)) - mountDisksDone, err := mountMicroVMDisks(microRunner, domain.Disks, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) + mountDisksDone, err := mountMicroVMDisks(remoteRunner, domain.Disks, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) if err != nil { return nil, err } - setDockerDataRootDone, err := setDockerDataRoot(microRunner, domain.Disks, domain.domainNamer, mountDisksDone) + setDockerDataRootDone, err := setDockerDataRoot(remoteRunner, domain.Disks, domain.domainNamer, mountDisksDone) if err != nil { return nil, err } deps := append(readKeyDone, setDockerDataRootDone...) deps = append(deps, domain.lvDomain) - reloadSSHDDone, err := reloadSSHD(microRunner, deps) + reloadSSHDDone, err := reloadSSHD(remoteRunner, deps) if err != nil { return nil, err } @@ -299,9 +298,9 @@ func provisionLocalMicroVMs(vmCollections []*VMCollection) ([]pulumi.Resource, e return nil, err } - remoteRunner, err := command.NewRunner( + remoteRunner, err := command.NewRemoteRunner( *collection.instance.e, - command.RunnerArgs{ + command.RemoteRunnerArgs{ ParentResource: domain.lvDomain, Connection: conn, ConnectionName: domain.domainNamer.ResourceName("provision-conn"), @@ -311,22 +310,21 @@ func provisionLocalMicroVMs(vmCollections []*VMCollection) ([]pulumi.Resource, e if err != nil { return nil, err } - microVMRunner := NewRunner(WithRemoteRunner(remoteRunner)) if collection.instance.IsMacOSHost() { - nfsConnKillerDone, err := enableNFSConnKiller(microVMRunner, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) + nfsConnKillerDone, err := enableNFSConnKiller(remoteRunner, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) if err != nil { return nil, err } waitFor = append(waitFor, nfsConnKillerDone...) } - mountDisksDone, err := mountMicroVMDisks(microVMRunner, domain.Disks, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) + mountDisksDone, err := mountMicroVMDisks(remoteRunner, domain.Disks, domain.domainNamer, []pulumi.Resource{domain.lvDomain}) if err != nil { return nil, err } - setDockerDataRootDone, err := setDockerDataRoot(microVMRunner, domain.Disks, domain.domainNamer, mountDisksDone) + setDockerDataRootDone, err := setDockerDataRoot(remoteRunner, domain.Disks, domain.domainNamer, mountDisksDone) if err != nil { return nil, err } diff --git a/scenarios/aws/microVMs/microvms/run.go b/scenarios/aws/microVMs/microvms/run.go index 0a5ce4d40..517669839 100644 --- a/scenarios/aws/microVMs/microvms/run.go +++ b/scenarios/aws/microVMs/microvms/run.go @@ -34,7 +34,7 @@ type Instance struct { instance *remoteComp.Host Arch string instanceNamer namer.Namer - runner *Runner + runner command.Runner libvirtURI pulumi.StringOutput } @@ -192,9 +192,9 @@ func configureInstance(instance *Instance, m *config.DDMicroVMConfig) ([]pulumi. OSCommand: osCommand, }) if instance.Arch != LocalVMSet { - instance.runner = NewRunner(WithRemoteRunner(instance.instance.OS.Runner())) + instance.runner = instance.instance.OS.Runner() } else { - instance.runner = NewRunner(WithLocalRunner(localRunner)) + instance.runner = localRunner } shouldProvision := m.GetBoolWithDefault(m.MicroVMConfig, config.DDMicroVMProvisionEC2Instance, true) diff --git a/scenarios/aws/microVMs/microvms/runner.go b/scenarios/aws/microVMs/microvms/runner.go deleted file mode 100644 index 7a71b6932..000000000 --- a/scenarios/aws/microVMs/microvms/runner.go +++ /dev/null @@ -1,77 +0,0 @@ -package microvms - -import ( - "errors" - - "github.com/DataDog/test-infra-definitions/components/command" - "github.com/pulumi/pulumi-command/sdk/go/command/local" - "github.com/pulumi/pulumi-command/sdk/go/command/remote" - "github.com/pulumi/pulumi/sdk/v3/go/pulumi" -) - -type Runner struct { - remoteRunner *command.Runner - localRunner *command.LocalRunner -} - -func NewRunner(options ...func(*Runner)) *Runner { - runner := Runner{} - - for _, opts := range options { - opts(&runner) - } - - return &runner -} - -func WithRemoteRunner(runner *command.Runner) func(*Runner) { - return func(a *Runner) { - a.remoteRunner = runner - } -} - -func WithLocalRunner(runner *command.LocalRunner) func(*Runner) { - return func(a *Runner) { - a.localRunner = runner - } -} - -func (a *Runner) Command(name string, args *command.Args, opts ...pulumi.ResourceOption) (pulumi.Resource, error) { - if a.remoteRunner != nil { - return a.remoteRunner.Command(name, args, opts...) - } - if a.localRunner != nil { - return a.localRunner.Command(name, args, opts...) - } - - panic("no runner initialized") -} - -func (a *Runner) RemoteCommand(name string, args *command.Args, opts ...pulumi.ResourceOption) (*remote.Command, error) { - if a.remoteRunner == nil { - return nil, errors.New("remote runner not initialized for Runner instance") - } - return a.remoteRunner.Command(name, args, opts...) -} - -func (a *Runner) LocalCommand(name string, args *command.Args, opts ...pulumi.ResourceOption) (*local.Command, error) { - if a.localRunner == nil { - return nil, errors.New("local runner not initialized for Runner instance") - } - return a.localRunner.Command(name, args, opts...) -} - -func (a *Runner) GetRemoteRunner() (*command.Runner, error) { - if a.remoteRunner == nil { - return nil, errors.New("remote runner not initialized") - } - - return a.remoteRunner, nil -} - -func (a *Runner) GetLocalRunner() (*command.LocalRunner, error) { - if a.localRunner == nil { - return nil, errors.New("local runner not initialized") - } - return a.localRunner, nil -} diff --git a/scenarios/aws/microVMs/microvms/volume.go b/scenarios/aws/microVMs/microvms/volume.go index cc2b32797..2e9df3ef4 100644 --- a/scenarios/aws/microVMs/microvms/volume.go +++ b/scenarios/aws/microVMs/microvms/volume.go @@ -12,7 +12,7 @@ import ( ) type LibvirtVolume interface { - SetupLibvirtVMVolume(ctx *pulumi.Context, runner *Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) (pulumi.Resource, error) + SetupLibvirtVMVolume(ctx *pulumi.Context, runner command.Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) (pulumi.Resource, error) UnderlyingImage() *filesystemImage FullResourceName(...string) string Key() string @@ -99,7 +99,7 @@ func NewLibvirtVolume( } } -func remoteLibvirtVolume(v *volume, runner *Runner, depends []pulumi.Resource) (pulumi.Resource, error) { +func remoteLibvirtVolume(v *volume, runner command.Runner, depends []pulumi.Resource) (pulumi.Resource, error) { var baseVolumeReady pulumi.Resource volumeXMLPath := fmt.Sprintf("/tmp/volume-%s.xml", v.filesystemImage.imageName) @@ -156,7 +156,7 @@ func localLibvirtVolume(v *volume, ctx *pulumi.Context, providerFn LibvirtProvid return stgvolReady, nil } -func (v *volume) SetupLibvirtVMVolume(ctx *pulumi.Context, runner *Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) (pulumi.Resource, error) { +func (v *volume) SetupLibvirtVMVolume(ctx *pulumi.Context, runner command.Runner, providerFn LibvirtProviderFn, isLocal bool, depends []pulumi.Resource) (pulumi.Resource, error) { if isLocal { return localLibvirtVolume(v, ctx, providerFn, depends) }