diff --git a/go.mod b/go.mod index 94139848..d3351b75 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/antihax/optional v1.0.0 github.com/avast/retry-go/v4 v4.5.1 github.com/breml/rootcerts v0.2.16 - github.com/cirruslabs/cirrus-ci-agent v1.134.0 + github.com/cirruslabs/cirrus-ci-agent v1.134.1 github.com/cirruslabs/echelon v1.9.0 github.com/cirruslabs/go-java-glob v0.1.0 github.com/cirruslabs/podmanapi v0.3.1 diff --git a/go.sum b/go.sum index 843e47c7..bcb7edba 100644 --- a/go.sum +++ b/go.sum @@ -86,8 +86,8 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cirruslabs/cirrus-ci-agent v1.134.0 h1:C0UPJQ2sxQ74JNTG4ibqomYdtscmP1BwuA67hzNOQoU= -github.com/cirruslabs/cirrus-ci-agent v1.134.0/go.mod h1:jvoX8ANKh8bCvMTOMogTIIDxYyGGzoDOlyy8LPvhMrE= +github.com/cirruslabs/cirrus-ci-agent v1.134.1 h1:ix98bA/pxg08BAvY53QeLuc+eHvLcRxo1HHMiEaT7mI= +github.com/cirruslabs/cirrus-ci-agent v1.134.1/go.mod h1:jvoX8ANKh8bCvMTOMogTIIDxYyGGzoDOlyy8LPvhMrE= github.com/cirruslabs/echelon v1.9.0 h1:UtHAtoc+C7KZoYtbMCOL8JYA1Ndi6/4u0+gWxw9sB8I= github.com/cirruslabs/echelon v1.9.0/go.mod h1:Zk4IGe8upeefcwPGE143JCM7iwOkJnZ2ZFCbDWwoadA= github.com/cirruslabs/go-java-glob v0.1.0 h1:qC4Fzrq2sXKTLLsBb7ih7BNdCjCR6ZJAAK4nOZ6d/Ak= diff --git a/internal/executor/instance/instance.go b/internal/executor/instance/instance.go index 4792e9b7..5d62920d 100644 --- a/internal/executor/instance/instance.go +++ b/internal/executor/instance/instance.go @@ -111,8 +111,8 @@ func NewFromProto( }, }, security.NoSecurity(), logger) case *api.MacOSInstance: - return tart.New(instance.Image, instance.User, instance.Password, instance.Cpu, instance.Memory, - tart.WithLogger(logger)) + return tart.New(instance.Image, instance.User, instance.Password, 22, + instance.Cpu, instance.Memory, tart.WithLogger(logger)) default: return &UnsupportedInstance{ err: fmt.Errorf("%w: %T", ErrUnsupportedInstance, instance), diff --git a/internal/executor/instance/persistentworker/isolation/parallels/parallels.go b/internal/executor/instance/persistentworker/isolation/parallels/parallels.go index 0df6ca55..fdf3005c 100644 --- a/internal/executor/instance/persistentworker/isolation/parallels/parallels.go +++ b/internal/executor/instance/persistentworker/isolation/parallels/parallels.go @@ -75,7 +75,7 @@ func (parallels *Parallels) Run(ctx context.Context, config *runconfig.RunConfig return fmt.Errorf("%w: failed to retrieve VM %q IP-address: %v", ErrFailed, vm.name, err) } - return remoteagent.WaitForAgent(ctx, parallels.logger, ip, + return remoteagent.WaitForAgent(ctx, parallels.logger, ip, 22, parallels.sshUser, parallels.sshPassword, parallels.agentOS, "amd64", config, vm.ClonedFromSuspended(), nil, nil, "", map[string]string{"CIRRUS_VM_ID": vm.Ident()}) diff --git a/internal/executor/instance/persistentworker/isolation/tart/tart.go b/internal/executor/instance/persistentworker/isolation/tart/tart.go index fbbf6c92..d14941f6 100644 --- a/internal/executor/instance/persistentworker/isolation/tart/tart.go +++ b/internal/executor/instance/persistentworker/isolation/tart/tart.go @@ -42,6 +42,7 @@ type Tart struct { vmName string sshUser string sshPassword string + sshPort uint16 cpu uint32 memory uint32 diskSize uint32 @@ -56,6 +57,7 @@ func New( vmName string, sshUser string, sshPassword string, + sshPort uint16, cpu uint32, memory uint32, opts ...Option, @@ -64,6 +66,7 @@ func New( vmName: vmName, sshUser: sshUser, sshPassword: sshPassword, + sshPort: sshPort, cpu: cpu, memory: memory, } @@ -232,7 +235,7 @@ func (tart *Tart) Run(ctx context.Context, config *runconfig.RunConfig) (err err tart.logger.Debugf("IP %s retrieved from VM %s, running agent...", ip, tart.vm.Ident()) - err = remoteagent.WaitForAgent(ctx, tart.logger, ip, + err = remoteagent.WaitForAgent(ctx, tart.logger, ip, tart.sshPort, tart.sshUser, tart.sshPassword, "darwin", "arm64", config, true, initializeHooks, terminateHooks, "", map[string]string{"CIRRUS_VM_ID": tart.vm.Ident()}) diff --git a/internal/executor/instance/persistentworker/isolation/vetu/vetu.go b/internal/executor/instance/persistentworker/isolation/vetu/vetu.go index b64097a0..1a65b75a 100644 --- a/internal/executor/instance/persistentworker/isolation/vetu/vetu.go +++ b/internal/executor/instance/persistentworker/isolation/vetu/vetu.go @@ -33,6 +33,7 @@ type Vetu struct { vmName string sshUser string sshPassword string + sshPort uint16 cpu uint32 memory uint32 diskSize uint32 @@ -44,6 +45,7 @@ func New( vmName string, sshUser string, sshPassword string, + sshPort uint16, cpu uint32, memory uint32, opts ...Option, @@ -52,6 +54,7 @@ func New( vmName: vmName, sshUser: sshUser, sshPassword: sshPassword, + sshPort: sshPort, cpu: cpu, memory: memory, } @@ -138,7 +141,7 @@ func (vetu *Vetu) Run(ctx context.Context, config *runconfig.RunConfig) error { prepareInstanceSpan.End() - err = remoteagent.WaitForAgent(ctx, vetu.logger, ip, + err = remoteagent.WaitForAgent(ctx, vetu.logger, ip, vetu.sshPort, vetu.sshUser, vetu.sshPassword, "linux", runtime.GOARCH, config, true, vetu.initializeHooks(config), nil, "", map[string]string{"CIRRUS_VM_ID": vm.Ident()}) diff --git a/internal/executor/instance/persistentworker/persistentworker.go b/internal/executor/instance/persistentworker/persistentworker.go index b86380c1..53d6e21f 100644 --- a/internal/executor/instance/persistentworker/persistentworker.go +++ b/internal/executor/instance/persistentworker/persistentworker.go @@ -114,8 +114,8 @@ func newTart(iso *api.Isolation_Tart_, security *security.Security, logger logge opts = append(opts, tart.WithDiskSize(iso.Tart.DiskSize)) } - return tart.New(iso.Tart.Image, iso.Tart.User, iso.Tart.Password, iso.Tart.Cpu, iso.Tart.Memory, - opts...) + return tart.New(iso.Tart.Image, iso.Tart.User, iso.Tart.Password, uint16(iso.Tart.Port), + iso.Tart.Cpu, iso.Tart.Memory, opts...) } func newVetu(iso *api.Isolation_Vetu_, security *security.Security, logger logger.Lightweight) (*vetu.Vetu, error) { @@ -145,6 +145,6 @@ func newVetu(iso *api.Isolation_Vetu_, security *security.Security, logger logge opts = append(opts, vetu.WithDiskSize(iso.Vetu.DiskSize)) } - return vetu.New(iso.Vetu.Image, iso.Vetu.User, iso.Vetu.Password, iso.Vetu.Cpu, iso.Vetu.Memory, - opts...) + return vetu.New(iso.Vetu.Image, iso.Vetu.User, iso.Vetu.Password, uint16(iso.Vetu.Port), + iso.Vetu.Cpu, iso.Vetu.Memory, opts...) } diff --git a/internal/executor/instance/persistentworker/remoteagent/remoteagent.go b/internal/executor/instance/persistentworker/remoteagent/remoteagent.go index c77e2d7f..910f8e55 100644 --- a/internal/executor/instance/persistentworker/remoteagent/remoteagent.go +++ b/internal/executor/instance/persistentworker/remoteagent/remoteagent.go @@ -45,6 +45,7 @@ func WaitForAgent( ctx context.Context, logger logger.Lightweight, ip string, + port uint16, sshUser string, sshPassword string, agentOS string, @@ -59,7 +60,12 @@ func WaitForAgent( ctx, span := tracer.Start(ctx, "upload-and-wait-for-agent") defer span.End() - addr := ip + ":22" + // Default to 22 + if port == 0 { + port = 22 + } + + addr := fmt.Sprintf("%s:%d", ip, port) cli, err := connectViaSSH(ctx, logger, addr, sshUser, sshPassword) if err != nil { diff --git a/pkg/parser/instance/isolation/tart/tart.go b/pkg/parser/instance/isolation/tart/tart.go index 38d4a99d..084a4bee 100644 --- a/pkg/parser/instance/isolation/tart/tart.go +++ b/pkg/parser/instance/isolation/tart/tart.go @@ -61,6 +61,23 @@ func New(mergedEnv map[string]string, parserKit *parserkit.ParserKit) *Tart { return nil }) + portSchema := schema.Integer("SSH port.") + tart.OptionalField(nameable.NewSimpleNameable("port"), portSchema, func(node *node.Node) error { + rawPort, err := node.GetExpandedStringValue(mergedEnv) + if err != nil { + return err + } + + port, err := strconv.ParseUint(rawPort, 10, 16) + if err != nil { + return node.ParserError("failed to parse \"port:\" value: %v", err) + } + + tart.proto.Tart.Port = uint32(port) + + return nil + }) + cpuSchema := schema.Number("Number of VM CPUs.") tart.OptionalField(nameable.NewSimpleNameable("cpu"), cpuSchema, func(node *node.Node) error { cpu, err := node.GetExpandedStringValue(mergedEnv) diff --git a/pkg/parser/instance/isolation/vetu/vetu.go b/pkg/parser/instance/isolation/vetu/vetu.go index 74537b86..38f69024 100644 --- a/pkg/parser/instance/isolation/vetu/vetu.go +++ b/pkg/parser/instance/isolation/vetu/vetu.go @@ -61,6 +61,23 @@ func New(mergedEnv map[string]string, parserKit *parserkit.ParserKit) *Vetu { return nil }) + portSchema := schema.Integer("SSH port.") + vetu.OptionalField(nameable.NewSimpleNameable("port"), portSchema, func(node *node.Node) error { + rawPort, err := node.GetExpandedStringValue(mergedEnv) + if err != nil { + return err + } + + port, err := strconv.ParseUint(rawPort, 10, 16) + if err != nil { + return node.ParserError("failed to parse \"port:\" value: %v", err) + } + + vetu.proto.Vetu.Port = uint32(port) + + return nil + }) + cpuSchema := schema.Number("Number of VM CPUs.") vetu.OptionalField(nameable.NewSimpleNameable("cpu"), cpuSchema, func(node *node.Node) error { cpu, err := node.GetExpandedStringValue(mergedEnv) diff --git a/pkg/parser/parser_test.go b/pkg/parser/parser_test.go index e0aff1b1..7f86ff62 100644 --- a/pkg/parser/parser_test.go +++ b/pkg/parser/parser_test.go @@ -57,6 +57,8 @@ var validCases = []string{ "file-instruction-from-contents", "execution-behavior-on-timeout", "vetu-isolation", + "tart-ssh-options", + "vetu-ssh-options", } func absolutize(file string) string { diff --git a/pkg/parser/testdata/cirrus.json b/pkg/parser/testdata/cirrus.json index 270a6fb9..6580b942 100644 --- a/pkg/parser/testdata/cirrus.json +++ b/pkg/parser/testdata/cirrus.json @@ -3153,6 +3153,10 @@ "description": "SSH password.", "type": "string" }, + "port": { + "description": "SSH port.", + "type": "integer" + }, "user": { "description": "SSH username.", "type": "string" @@ -3210,6 +3214,10 @@ "description": "SSH password.", "type": "string" }, + "port": { + "description": "SSH port.", + "type": "integer" + }, "user": { "description": "SSH username.", "type": "string" @@ -3591,6 +3599,10 @@ "description": "SSH password.", "type": "string" }, + "port": { + "description": "SSH port.", + "type": "integer" + }, "user": { "description": "SSH username.", "type": "string" @@ -3648,6 +3660,10 @@ "description": "SSH password.", "type": "string" }, + "port": { + "description": "SSH port.", + "type": "integer" + }, "user": { "description": "SSH username.", "type": "string" diff --git a/pkg/parser/testdata/tart-ssh-options.json b/pkg/parser/testdata/tart-ssh-options.json new file mode 100644 index 00000000..1eb01917 --- /dev/null +++ b/pkg/parser/testdata/tart-ssh-options.json @@ -0,0 +1,41 @@ +[ + { + "commands": [ + { + "cloneInstruction": {}, + "name": "clone" + }, + { + "name": "main", + "scriptInstruction": { + "scripts": [ + "uname -a" + ] + } + } + ], + "environment": { + "CIRRUS_OS": "darwin" + }, + "instance": { + "@type": "type.googleapis.com/org.cirruslabs.ci.services.cirruscigrpc.PersistentWorkerInstance", + "isolation": { + "tart": { + "image": "ghcr.io/cirruslabs/macos-sonoma-base:latest", + "password": "doesn't matter", + "port": 2222 + } + } + }, + "metadata": { + "properties": { + "allow_failures": "false", + "experimental": "false", + "indexWithinBuild": "0", + "timeout_in": "3600", + "trigger_type": "AUTOMATIC" + } + }, + "name": "main" + } +] diff --git a/pkg/parser/testdata/tart-ssh-options.yml b/pkg/parser/testdata/tart-ssh-options.yml new file mode 100644 index 00000000..e7ba3cbf --- /dev/null +++ b/pkg/parser/testdata/tart-ssh-options.yml @@ -0,0 +1,10 @@ +task: + persistent_worker: + isolation: + tart: + image: ghcr.io/cirruslabs/macos-sonoma-base:latest + username: root + password: doesn't matter + port: 2222 + + script: uname -a diff --git a/pkg/parser/testdata/vetu-ssh-options.json b/pkg/parser/testdata/vetu-ssh-options.json new file mode 100644 index 00000000..5f74e6fc --- /dev/null +++ b/pkg/parser/testdata/vetu-ssh-options.json @@ -0,0 +1,38 @@ +[ + { + "commands": [ + { + "cloneInstruction": {}, + "name": "clone" + }, + { + "name": "main", + "scriptInstruction": { + "scripts": [ + "uname -a" + ] + } + } + ], + "instance": { + "@type": "type.googleapis.com/org.cirruslabs.ci.services.cirruscigrpc.PersistentWorkerInstance", + "isolation": { + "vetu": { + "image": "ghcr.io/cirruslabs/ubuntu:latest", + "password": "doesn't matter", + "port": 2222 + } + } + }, + "metadata": { + "properties": { + "allow_failures": "false", + "experimental": "false", + "indexWithinBuild": "0", + "timeout_in": "3600", + "trigger_type": "AUTOMATIC" + } + }, + "name": "main" + } +] diff --git a/pkg/parser/testdata/vetu-ssh-options.yml b/pkg/parser/testdata/vetu-ssh-options.yml new file mode 100644 index 00000000..82b03dfa --- /dev/null +++ b/pkg/parser/testdata/vetu-ssh-options.yml @@ -0,0 +1,10 @@ +task: + persistent_worker: + isolation: + vetu: + image: ghcr.io/cirruslabs/ubuntu:latest + username: root + password: doesn't matter + port: 2222 + + script: uname -a