Skip to content

Commit fe156f2

Browse files
authored
Merge pull request #25 from veertuinc/release/v1.2.0
[CLOUD-1516] [CLOUD-1515] release/v1.2.0
2 parents 389109d + b5a95fa commit fe156f2

File tree

6 files changed

+129
-68
lines changed

6 files changed

+129
-68
lines changed

.goreleaser.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ before:
88
builds:
99
- main: cmd/anka-cloud-gitlab-executor/main.go
1010
ldflags: >
11-
-X github.com/veertuinc/anka-cloud-gitlab-executor/internal/version.Version={{.Version}}
12-
-X github.com/veertuinc/anka-cloud-gitlab-executor/internal/version.Commit={{.ShortCommit}}
11+
-X github.com/veertuinc/anka-cloud-gitlab-executor/internal/version.version={{.Version}}
12+
-X github.com/veertuinc/anka-cloud-gitlab-executor/internal/version.commit={{.ShortCommit}}
1313
env:
1414
- CGO_ENABLED=0
1515
goos:

README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ A [Gitlab Runner Custom Executor](https://docs.gitlab.com/runner/executors/custo
1111
1. Download the binary to the same machine your Gitlab Runner is running on.
1212
2. Add the following `[runners.custom]` block to Gitlab Runner configuration:
1313
> By default, runner config is at `~/.gitlab-runner/config.toml`
14+
15+
> Any environment variables can be specified in the `environment` block and apply to all jobs. However, they are also available in the job's environment, so avoid placing SSH credentials and other sensitive variables in the `environment` block.
1416
```
17+
environment = [
18+
"ANKA_CLOUD_CONTROLLER_URL=https://anka.contoller:8090",
19+
"ANKA_CLOUD_TEMPLATE_ID=8c592f53-65a4-444e-9342-79d3ff07837c",
20+
]
1521
[runners.custom]
1622
config_exec = "/path/to/anka-cloud-gitlab-executor"
1723
config_args = ["config"]
@@ -48,16 +54,34 @@ Accepted values for booleans are: "1", "t", "T", "true", "TRUE", "True", "0", "f
4854
| ANKA_CLOUD_CA_CERT_PATH | ❌ | String | If Controller is using a self-signed cert, CA file can be passed in for the runner to use when communicating with Controller. **_The path is accessed locally by the Runner_** |
4955
| ANKA_CLOUD_CLIENT_CERT_PATH | ❌ | String | If Client Cert Authentication is enabled, this is the path for the Certificate. **_The path is accessed locally by the Runner_** |
5056
| ANKA_CLOUD_CLIENT_CERT_KEY_PATH | ❌ | String | If Client Cert Authentication is enabled, this is the path for the Key. **_The path is accessed locally by the Runner_** |
51-
| ANKA_CLOUD_SSH_USER_NAME | ❌ | String | SSH user name to use inside VM. Defaults to "anka" |
52-
| ANKA_CLOUD_SSH_PASSWORD | ❌ | String | SSH password to use inside VM. Defaults to "admin" |
5357
| ANKA_CLOUD_CUSTOM_HTTP_HEADERS | ❌ | Object | key-value JSON object for custom headers to set when communicatin with Controller. Both keys and values must be strings |
5458
| ANKA_CLOUD_KEEP_ALIVE_ON_ERROR | ❌ | Boolean | Do not terminate Instance if job failed. This will leave the VM running until manually cleaned. Usually, this is used to inspect the VM post failing. If job was canceled, VM will be cleaned regardless of this variable. **There will be no indication for this behavior on the Job's output unless Gitlab Debug is enabled** |
5559
| ANKA_CLOUD_VM_VCPU | ❌ | Number | Set number of CPU num for the VM. Only works on `stopped` templates. Minimum value of 1 |
5660
| ANKA_CLOUD_VM_VRAM_MB | ❌ | Number | Set RAM in MiB for the VM. Only works on `stopped` templates. Minimum value of 1 |
5761
| ANKA_CLOUD_BUILDS_DIR | ❌ | String | Absolute path to a directory where builds are stored in the VM. If not supplied, "/tmp/builds" is used. |
5862
| ANKA_CLOUD_CACHE_DIR | ❌ | String | Absolute path to a directory where build caches are stored in the VM. If not supplied, "/tmp/cache" is used. |
63+
| ANKA_CLOUD_SSH_CONNECTION_ATTEMPTS | ❌ | Number | The attempts to make when sshing to the VM. Useful when VMs take a long time to start under stressful situations or slow disks (like EBS). Defaults to `4` -- Minimum value of 1 |
64+
| ANKA_CLOUD_SSH_CONNECTION_ATTEMPT_DELAY | ❌ | Number | The delay between ssh connection attempts in seconds. Defaults to `5` |
65+
| ANKA_CLOUD_SSH_USER_NAME | ❌ | String | SSH user name to use inside VM. Defaults to "anka". This can also be set via a command line flags to prevent this value from being exposed to the job. See example below. |
66+
| ANKA_CLOUD_SSH_PASSWORD | ❌ | String | SSH password to use inside VM. Defaults to "admin". This can also be set via a command line flags to prevent this value from being exposed to the job. See example below. |
67+
68+
To prevent SSH credentials from being exposed to the job log, they can instead be specified via command line arguments in the config.toml > runner.custom:
69+
70+
> Note: values specified via job environment variables will override those provided via command line arguments.
71+
```
72+
[runners.custom]
73+
config_exec = "/path/to/anka-cloud-gitlab-executor"
74+
config_args = ["config"]
75+
prepare_exec = "/path/to/anka-cloud-gitlab-executor"
76+
prepare_args = ["prepare"]
77+
run_exec = "/path/to/anka-cloud-gitlab-executor"
78+
run_args = ["run", "--ssh-username", "anka", "--ssh-password", "admin"]
79+
cleanup_exec = "/path/to/anka-cloud-gitlab-executor"
80+
cleanup_args = ["cleanup"]
81+
```
5982
6083
### Examples
84+
6185
Example basic pipeline:
6286
```
6387
variables:
@@ -153,3 +177,4 @@ This project produces a single binary, that accepts the current Gitlab stage as
153177
2. Prepare (Creates the Instance on the Anka Cloud, waiting for it to get scheduled)
154178
3. Run (Creates a remote shell on the VM, and pushes Gitlab provided script with stdin)
155179
4. Cleanup (Performs Termination request to the Anka Cloud Controller)
180+

go.mod

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ go 1.20
44

55
require (
66
github.com/spf13/cobra v1.7.0
7-
golang.org/x/crypto v0.17.0
7+
github.com/spf13/pflag v1.0.5
8+
golang.org/x/crypto v0.21.0
89
)
910

1011
require (
1112
github.com/inconshreveable/mousetrap v1.1.0 // indirect
12-
github.com/spf13/pflag v1.0.5 // indirect
13-
golang.org/x/net v0.17.0 // indirect
14-
golang.org/x/sys v0.15.0 // indirect
13+
golang.org/x/sys v0.18.0 // indirect
1514
)

go.sum

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,10 @@ github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
66
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
77
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
88
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
9-
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
10-
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
11-
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
12-
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
13-
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
14-
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
15-
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
16-
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
17-
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
18-
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
19-
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
20-
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
9+
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
10+
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
11+
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
12+
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
13+
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
2114
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2215
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/command/run.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,21 @@ func executeRun(ctx context.Context, env gitlab.Environment, args []string) erro
102102
var sshClient *ssh.Client
103103

104104
// retry logic mimics what is done by the official Gitlab Runner (true for gitlab runner v16.7.0)
105-
for i := 0; i < 3; i++ {
106-
log.Printf("attempt #%d to establish ssh connection to %q\n", i, addr)
105+
maxAttempts := env.SSHAttempts
106+
if maxAttempts < 1 {
107+
maxAttempts = 4
108+
}
109+
sshConnectionAttemptDelay := env.SSHConnectionAttemptDelay
110+
if sshConnectionAttemptDelay < 1 {
111+
sshConnectionAttemptDelay = 5
112+
}
113+
for i := 0; i < maxAttempts; i++ {
114+
log.Printf("attempt #%d to establish ssh connection to %q\n", i+1, addr)
107115
sshClient, err = ssh.Dial("tcp", addr, sshClientConfig)
108116
if err == nil {
109117
break
110118
}
111-
time.Sleep(3 * time.Second)
119+
time.Sleep(time.Duration(sshConnectionAttemptDelay) * time.Second)
112120
}
113121
if err != nil {
114122
return fmt.Errorf("failed to create new ssh client connection to %q: %w", addr, err)

internal/gitlab/vars.go

Lines changed: 81 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ package gitlab
33
import (
44
"encoding/json"
55
"fmt"
6+
67
"os"
78
"strconv"
89
"strings"
10+
11+
flag "github.com/spf13/pflag"
912
)
1013

1114
const (
@@ -15,55 +18,59 @@ const (
1518

1619
var (
1720
// Custom Executor vars
18-
varDebug = ankaVar("DEBUG")
19-
varControllerURL = ankaVar("CONTROLLER_URL")
20-
varTemplateId = ankaVar("TEMPLATE_ID")
21-
varTemplateTag = ankaVar("TEMPLATE_TAG")
22-
varNodeId = ankaVar("NODE_ID")
23-
varPriority = ankaVar("PRIORITY")
24-
varNodeGroupId = ankaVar("NODE_GROUP_ID")
25-
varCaCertPath = ankaVar("CA_CERT_PATH")
26-
varSkipTLSVerify = ankaVar("SKIP_TLS_VERIFY")
27-
varClientCertPath = ankaVar("CLIENT_CERT_PATH")
28-
varClientCertKeyPath = ankaVar("CLIENT_CERT_KEY_PATH")
29-
varSshUserName = ankaVar("SSH_USER_NAME")
30-
varSshPassword = ankaVar("SSH_PASSWORD")
31-
varCustomHTTPHeaders = ankaVar("CUSTOM_HTTP_HEADERS")
32-
varKeepAliveOnError = ankaVar("KEEP_ALIVE_ON_ERROR")
33-
varTemplateName = ankaVar("TEMPLATE_NAME")
34-
varBuildsDir = ankaVar("BUILDS_DIR")
35-
varCacheDir = ankaVar("CACHE_DIR")
36-
varVmVramMb = ankaVar("VM_VRAM_MB")
37-
varVmVcpu = ankaVar("VM_VCPU")
21+
varDebug = ankaVar("DEBUG")
22+
varControllerURL = ankaVar("CONTROLLER_URL")
23+
varTemplateId = ankaVar("TEMPLATE_ID")
24+
varTemplateTag = ankaVar("TEMPLATE_TAG")
25+
varNodeId = ankaVar("NODE_ID")
26+
varPriority = ankaVar("PRIORITY")
27+
varNodeGroupId = ankaVar("NODE_GROUP_ID")
28+
varCaCertPath = ankaVar("CA_CERT_PATH")
29+
varSkipTLSVerify = ankaVar("SKIP_TLS_VERIFY")
30+
varClientCertPath = ankaVar("CLIENT_CERT_PATH")
31+
varClientCertKeyPath = ankaVar("CLIENT_CERT_KEY_PATH")
32+
varSshUserName = ankaVar("SSH_USER_NAME")
33+
varSshPassword = ankaVar("SSH_PASSWORD")
34+
varSshAttempts = ankaVar("SSH_CONNECTION_ATTEMPTS")
35+
varSshConnectionAttemptDelay = ankaVar("SSH_CONNECTION_ATTEMPT_DELAY")
36+
varCustomHTTPHeaders = ankaVar("CUSTOM_HTTP_HEADERS")
37+
varKeepAliveOnError = ankaVar("KEEP_ALIVE_ON_ERROR")
38+
varTemplateName = ankaVar("TEMPLATE_NAME")
39+
varBuildsDir = ankaVar("BUILDS_DIR")
40+
varCacheDir = ankaVar("CACHE_DIR")
41+
varVmVramMb = ankaVar("VM_VRAM_MB")
42+
varVmVcpu = ankaVar("VM_VCPU")
3843

3944
// Gitlab vars
4045
varGitlabJobId = gitlabVar("CI_JOB_ID")
4146
varGitlabJobStatus = gitlabVar("CI_JOB_STATUS")
4247
)
4348

4449
type Environment struct {
45-
ControllerURL string
46-
Debug bool
47-
TemplateId string
48-
TemplateTag string
49-
NodeId string
50-
Priority int
51-
NodeGroupId string
52-
CaCertPath string
53-
SkipTLSVerify bool
54-
ClientCertPath string
55-
ClientCertKeyPath string
56-
SSHUserName string
57-
SSHPassword string
58-
GitlabJobId string
59-
CustomHttpHeaders map[string]string
60-
KeepAliveOnError bool
61-
GitlabJobStatus jobStatus
62-
TemplateName string
63-
BuildsDir string
64-
CacheDir string
65-
VmVramMb int
66-
VmVcpu int
50+
ControllerURL string
51+
Debug bool
52+
TemplateId string
53+
TemplateTag string
54+
NodeId string
55+
Priority int
56+
NodeGroupId string
57+
CaCertPath string
58+
SkipTLSVerify bool
59+
ClientCertPath string
60+
ClientCertKeyPath string
61+
SSHUserName string
62+
SSHPassword string
63+
SSHAttempts int
64+
SSHConnectionAttemptDelay int
65+
GitlabJobId string
66+
CustomHttpHeaders map[string]string
67+
KeepAliveOnError bool
68+
GitlabJobStatus jobStatus
69+
TemplateName string
70+
BuildsDir string
71+
CacheDir string
72+
VmVramMb int
73+
VmVcpu int
6774
}
6875

6976
type jobStatus string
@@ -75,8 +82,18 @@ var (
7582
JobStatusRunning jobStatus = "running"
7683
)
7784

85+
var sshPassword = flag.String("ssh-password", "", "the password used to SSH into the VM")
86+
var sshUserName = flag.String("ssh-username", "", "the username used to SSH into the VM")
87+
7888
func InitEnv() (Environment, error) {
79-
e := Environment{}
89+
// parse command line flags defined above
90+
flag.Parse()
91+
e := Environment{
92+
// load initial values from command line flags
93+
SSHPassword: *sshPassword,
94+
SSHUserName: *sshUserName,
95+
}
96+
8097
var ok bool
8198
if e.ControllerURL, ok = os.LookupEnv(varControllerURL); !ok {
8299
return e, fmt.Errorf("%w: %s", ErrMissingVar, varControllerURL)
@@ -90,8 +107,13 @@ func InitEnv() (Environment, error) {
90107
return e, fmt.Errorf("%w: %s", ErrMissingVar, varGitlabJobId)
91108
}
92109

93-
e.SSHUserName = os.Getenv(varSshUserName)
94-
e.SSHPassword = os.Getenv(varSshPassword)
110+
if os.Getenv(varSshUserName) != "" {
111+
e.SSHUserName = os.Getenv(varSshUserName)
112+
}
113+
if os.Getenv(varSshPassword) != "" {
114+
e.SSHPassword = os.Getenv(varSshPassword)
115+
}
116+
95117
e.TemplateId = os.Getenv(varTemplateId)
96118
e.TemplateName = os.Getenv(varTemplateName)
97119
e.TemplateTag = os.Getenv(varTemplateTag)
@@ -159,6 +181,20 @@ func InitEnv() (Environment, error) {
159181
e.VmVcpu = vcpu
160182
}
161183

184+
if sshAttempts, ok, err := GetIntEnvVar(varSshAttempts); ok {
185+
if err != nil {
186+
return e, fmt.Errorf("%w %q: %w", ErrInvalidVar, varSshAttempts, err)
187+
}
188+
e.SSHAttempts = sshAttempts
189+
}
190+
191+
if sshConnectionAttemptDelay, ok, err := GetIntEnvVar(varSshConnectionAttemptDelay); ok {
192+
if err != nil {
193+
return e, fmt.Errorf("%w %q: %w", ErrInvalidVar, varSshConnectionAttemptDelay, err)
194+
}
195+
e.SSHConnectionAttemptDelay = sshConnectionAttemptDelay
196+
}
197+
162198
return e, nil
163199
}
164200

0 commit comments

Comments
 (0)