Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Support Linux #97

Merged
merged 4 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions internal/commands/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ func runConfig(cmd *cobra.Command, args []string) error {
// to be absolute[1].
//
// 2. GitLab Runner uses relative paths internally which results in improper directory traversal[2],
// this is why we use "/private/tmp" instead of just "/tmp" here as a workaround.
// so instead of "/tmp" we need to use "/private/tmp" here as a workaround.
//
// 3. However, there's no "/private/tmp" on Linux. So we use the lowest common denominator
// in the form of "/var/tmp". It's both (1) not a symbolic link and (2) is present on both platforms.
//
// [1]: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section
// [2]: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/31003
BuildsDir: "/private/tmp/builds",
CacheDir: "/private/tmp/cache",
BuildsDir: "/var/tmp/builds",
CacheDir: "/var/tmp/cache",
JobEnv: map[string]string{},
}

Expand Down Expand Up @@ -95,15 +98,14 @@ func runConfig(cmd *cobra.Command, args []string) error {
// Figure out the builds directory override to use
switch {
case tartConfig.HostDir:
gitlabRunnerConfig.BuildsDir = fmt.Sprintf("/Users/%s/hostdir", tartConfig.SSHUsername)
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalBuildsDirOnHost] = gitLabEnv.HostDirPath()

if err := os.MkdirAll(gitLabEnv.HostDirPath(), 0700); err != nil {
return err
}
case buildsDir != "":
gitlabRunnerConfig.BuildsDir = fmt.Sprintf("/Users/%s/buildsdir", tartConfig.SSHUsername)
buildsDir = os.ExpandEnv(buildsDir)
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalBuildsDir] = buildsDir
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalBuildsDirOnHost] = buildsDir

if err := os.MkdirAll(buildsDir, 0700); err != nil {
return err
Expand All @@ -115,9 +117,8 @@ func runConfig(cmd *cobra.Command, args []string) error {
// Figure out the cache directory override to use
switch {
case cacheDir != "":
gitlabRunnerConfig.CacheDir = fmt.Sprintf("/Users/%s/cachedir", tartConfig.SSHUsername)
cacheDir = os.ExpandEnv(cacheDir)
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalCacheDir] = cacheDir
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalCacheDirOnHost] = cacheDir

if err := os.MkdirAll(cacheDir, 0700); err != nil {
return err
Expand All @@ -126,6 +127,11 @@ func runConfig(cmd *cobra.Command, args []string) error {
gitlabRunnerConfig.CacheDir = guestCacheDir
}

// Propagate builds and cache directory locations in the guest
// because GitLab Runner won't do this for us
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalBuildsDir] = gitlabRunnerConfig.BuildsDir
gitlabRunnerConfig.JobEnv[tart.EnvTartExecutorInternalCacheDir] = gitlabRunnerConfig.CacheDir

jsonBytes, err := json.MarshalIndent(&gitlabRunnerConfig, "", " ")
if err != nil {
return err
Expand Down
13 changes: 12 additions & 1 deletion internal/commands/prepare/install-gitlab-runner-auto.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@
#
set -euo pipefail

GITLAB_RUNNER_URL="https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-arm64"
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case $ARCH in
aarch64)
ARCH="arm64"
;;
x86_64)
ARCH="amd64"
;;
esac

GITLAB_RUNNER_URL="https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-${OS}-${ARCH}"
GITLAB_RUNNER_PATH="/usr/local/bin/gitlab-runner"

# Is GitLab Runner already installed?
Expand Down
13 changes: 12 additions & 1 deletion internal/commands/prepare/install-gitlab-runner-curl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@
#
set -euo pipefail

OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
case $ARCH in
aarch64)
ARCH="arm64"
;;
x86_64)
ARCH="amd64"
;;
esac

GITLAB_RUNNER_VERSION="latest"
GITLAB_RUNNER_URL="https://gitlab-runner-downloads.s3.amazonaws.com/${GITLAB_RUNNER_VERSION}/binaries/gitlab-runner-darwin-arm64"
GITLAB_RUNNER_URL="https://gitlab-runner-downloads.s3.amazonaws.com/${GITLAB_RUNNER_VERSION}/binaries/gitlab-runner-${OS}-${ARCH}"
GITLAB_RUNNER_PATH="/usr/local/bin/gitlab-runner"

# Is GitLab Runner already installed?
Expand Down
46 changes: 34 additions & 12 deletions internal/commands/prepare/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,29 +191,51 @@ func runPrepareVM(cmd *cobra.Command, args []string) error {
log.Printf("Timezone was set to %s!\n", tz)
}

dirsToMount := []string{}
if config.HostDir {
dirsToMount = append(dirsToMount, "hostdir")
type MountPoint struct {
Name string
Path string
}
if _, ok := os.LookupEnv(tart.EnvTartExecutorInternalBuildsDir); ok {
dirsToMount = append(dirsToMount, "buildsdir")

vmInfo, err := vm.Info(cmd.Context())
if err != nil {
return err
}
if _, ok := os.LookupEnv(tart.EnvTartExecutorInternalCacheDir); ok {
dirsToMount = append(dirsToMount, "cachedir")

var mountPoints []MountPoint

if _, ok := os.LookupEnv(tart.EnvTartExecutorInternalBuildsDirOnHost); ok {
mountPoints = append(mountPoints, MountPoint{
Name: "buildsdir",
Path: os.Getenv(tart.EnvTartExecutorInternalBuildsDir),
})
}
if _, ok := os.LookupEnv(tart.EnvTartExecutorInternalCacheDirOnHost); ok {
mountPoints = append(mountPoints, MountPoint{
Name: "cachedir",
Path: os.Getenv(tart.EnvTartExecutorInternalCacheDir),
})
}

for _, dirToMount := range dirsToMount {
log.Printf("Mounting %s...\n", dirToMount)
for _, mountPoint := range mountPoints {
log.Printf("Mounting %s on %s...\n", mountPoint.Name, mountPoint.Path)

session, err := ssh.NewSession()
if err != nil {
return err
}
defer session.Close()

mountPoint := fmt.Sprintf("/Users/%s/%s", config.SSHUsername, dirToMount)
mkdirScript := fmt.Sprintf("mkdir -p %s", mountPoint)
mountScript := fmt.Sprintf("mount_virtiofs tart.virtiofs.%s.%s %s", dirToMount, gitLabEnv.JobID, mountPoint)
var command string

if vmInfo.OS == "darwin" {
command = "mount_virtiofs"
} else {
command = "sudo mount -t virtiofs"
}

mkdirScript := fmt.Sprintf("mkdir -p %s", mountPoint.Path)
mountScript := fmt.Sprintf("%s tart.virtiofs.%s.%s %s", command, mountPoint.Name,
gitLabEnv.JobID, mountPoint.Path)
session.Stdin = bytes.NewBufferString(strings.Join([]string{mkdirScript, mountScript, ""}, "\n"))
session.Stdout = os.Stdout
session.Stderr = os.Stderr
Expand Down
10 changes: 10 additions & 0 deletions internal/tart/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,20 @@ const (
// by the user.
EnvTartExecutorInternalBuildsDir = "TART_EXECUTOR_INTERNAL_BUILDS_DIR"

// EnvTartExecutorInternalBuildsDirOnHost is an internal environment variable
// that does not use the "CUSTOM_ENV_" prefix, thus preventing the override
// by the user.
EnvTartExecutorInternalBuildsDirOnHost = "TART_EXECUTOR_INTERNAL_BUILDS_DIR_ON_HOST"

// EnvTartExecutorInternalCacheDir is an internal environment variable
// that does not use the "CUSTOM_ENV_" prefix, thus preventing the override
// by the user.
EnvTartExecutorInternalCacheDir = "TART_EXECUTOR_INTERNAL_CACHE_DIR"

// EnvTartExecutorInternalCacheDirOnHost is an internal environment variable
// that does not use the "CUSTOM_ENV_" prefix, thus preventing the override
// by the user.
EnvTartExecutorInternalCacheDirOnHost = "TART_EXECUTOR_INTERNAL_CACHE_DIR_ON_HOST"
)

type Config struct {
Expand Down
33 changes: 26 additions & 7 deletions internal/tart/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tart
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -35,6 +36,10 @@ type VM struct {
id string
}

type VMInfo struct {
OS string `json:"os"`
}

func ExistingVM(gitLabEnv gitlab.Env) *VM {
return &VM{
id: gitLabEnv.VirtualMachineID(),
Expand Down Expand Up @@ -143,15 +148,14 @@ func (vm *VM) Start(
runArgs = append(runArgs, "--disk", customDiskMount)
}

if config.HostDir {
hostDir := gitLabEnv.HostDirPath()
runArgs = append(runArgs, "--dir", fmt.Sprintf("%s:tag=tart.virtiofs.hostdir.%s", hostDir, gitLabEnv.JobID))
} else if buildsDir, ok := os.LookupEnv(EnvTartExecutorInternalBuildsDir); ok {
runArgs = append(runArgs, "--dir", fmt.Sprintf("%s:tag=tart.virtiofs.buildsdir.%s", buildsDir, gitLabEnv.JobID))
if buildsDir, ok := os.LookupEnv(EnvTartExecutorInternalBuildsDirOnHost); ok {
runArgs = append(runArgs, "--dir", fmt.Sprintf("%s:tag=tart.virtiofs.buildsdir.%s",
buildsDir, gitLabEnv.JobID))
}

if cacheDir, ok := os.LookupEnv(EnvTartExecutorInternalCacheDir); ok {
runArgs = append(runArgs, "--dir", fmt.Sprintf("%s:tag=tart.virtiofs.cachedir.%s", cacheDir, gitLabEnv.JobID))
if cacheDir, ok := os.LookupEnv(EnvTartExecutorInternalCacheDirOnHost); ok {
runArgs = append(runArgs, "--dir", fmt.Sprintf("%s:tag=tart.virtiofs.cachedir.%s",
cacheDir, gitLabEnv.JobID))
}

runArgs = append(runArgs, vm.id)
Expand Down Expand Up @@ -278,6 +282,21 @@ func (vm *VM) IP(ctx context.Context, config Config) (string, error) {
return strings.TrimSpace(stdout), nil
}

func (vm *VM) Info(ctx context.Context) (*VMInfo, error) {
stdout, _, err := TartExec(ctx, "get", "--format", "json", vm.id)
if err != nil {
return nil, err
}

var vmInfo VMInfo

if err := json.Unmarshal([]byte(stdout), &vmInfo); err != nil {
return nil, err
}

return &vmInfo, nil
}

func (vm *VM) Stop() error {
_, _, err := TartExec(context.Background(), "stop", vm.id)

Expand Down