Skip to content

Commit

Permalink
net: fix #344 qemu process missing gvproxy config (#352)
Browse files Browse the repository at this point in the history
* chore: move CGO_ENABLE arg to makefile

* chore: use actual current executable path

* chore: fix generated binary on M1 mac

* net: fix #344 qemu process missing gvproxy config

* chore: update gitignore

* chore: refactor, mock filesystem in tests

* chore: update nix environment

* chore: refactor Makefile (#354)

* refactor: extract build logic from build.sh to Makefile

* chore: add test rule to Makefile

* apply review suggestion

Co-authored-by: Abiola Ibrahim <[email protected]>

* fix: use defined `OUTPUT_DIR` variable

* chore: remove -race flag from test as it needs CGO_ENABLED=1

* chore: generate sha in binaries directory

* chore: propagate Go build environment variables

Co-authored-by: Abiola Ibrahim <[email protected]>

* chore: disable CGO

* chore: remove empty file

Co-authored-by: tricktron <[email protected]>
  • Loading branch information
abiosoft and tricktron authored Jun 29, 2022
1 parent 656ae6d commit 3a85204
Show file tree
Hide file tree
Showing 17 changed files with 212 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
_output/
_build/
bin/
result
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fmt:

.PHONY: build
build:
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags="$(LDFLAGS)" -o $(OUTPUT_DIR)/$(OUTPUT_BIN) ./cmd/colima
GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 go build -ldflags="$(LDFLAGS)" -o $(OUTPUT_DIR)/$(OUTPUT_BIN) ./cmd/colima
cd $(OUTPUT_DIR) && openssl sha256 -r -out $(OUTPUT_BIN).sha256sum $(OUTPUT_BIN)

.PHONY: test
Expand All @@ -59,3 +59,9 @@ install:
.PHONY: lint
lint: ## Assumes that golangci-lint is installed and in the path. To install: https://golangci-lint.run/usage/install/
golangci-lint --timeout 3m run

.PHONY: nix-derivation-shell
nix-derivation-shell:
$(eval DERIVATION=$(shell nix-build))
echo $(DERIVATION) | grep ^/nix
nix-shell -p $(DERIVATION)
3 changes: 2 additions & 1 deletion cmd/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/daemon/process"
"github.com/abiosoft/colima/util/fsutil"
godaemon "github.com/sevlyar/go-daemon"
"github.com/sirupsen/logrus"
)
Expand All @@ -22,7 +23,7 @@ var dir = process.Dir
// daemonize creates the daemon and returns if this is a child process
func daemonize() (ctx *godaemon.Context, child bool, err error) {
dir := dir()
if err := os.MkdirAll(dir, 0755); err != nil {
if err := fsutil.MkdirAll(dir, 0755); err != nil {
return nil, false, fmt.Errorf("cannot make dir: %w", err)
}

Expand Down
6 changes: 4 additions & 2 deletions cmd/nerdctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/abiosoft/colima/cmd/root"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment/container/containerd"
"github.com/abiosoft/colima/util/fsutil"
"github.com/abiosoft/colima/util/osutil"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -96,7 +98,7 @@ var nerdctlLinkFunc = func() *cobra.Command {
ColimaApp string
Profile string
}{
ColimaApp: os.Args[0],
ColimaApp: osutil.Executable(),
Profile: config.CurrentProfile().ShortName,
}
var buf bytes.Buffer
Expand All @@ -112,7 +114,7 @@ var nerdctlLinkFunc = func() *cobra.Command {
return fmt.Errorf("error backing up existing file: %w", err)
}
}
if err := os.MkdirAll("/usr/local/bin", 0755); err != nil {
if err := fsutil.MkdirAll("/usr/local/bin", 0755); err != nil {
return nil
}
return os.WriteFile(nerdctlCmdArgs.path, buf.Bytes(), 0755)
Expand Down
9 changes: 7 additions & 2 deletions config/dirs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import (
"path/filepath"
"sync"

"github.com/abiosoft/colima/util/fsutil"
"github.com/abiosoft/colima/util/osutil"
"github.com/abiosoft/colima/util/shautil"
"github.com/sirupsen/logrus"
)

Expand All @@ -28,7 +31,7 @@ func (r *requiredDir) Dir() string {
}

r.once.Do(func() {
if err := os.MkdirAll(dir, 0755); err != nil {
if err := fsutil.MkdirAll(dir, 0755); err != nil {
logrus.Fatal(fmt.Errorf("cannot make required directory: %w", err))
}
})
Expand Down Expand Up @@ -73,7 +76,9 @@ var (
if err != nil {
return "", err
}
return filepath.Join(dir, ".colima", "_wrapper"), nil
// generate unique directory for the current binary
uniqueDir := shautil.SHA1(osutil.Executable())
return filepath.Join(dir, ".colima", "_wrapper", uniqueDir.String()), nil
},
}
)
Expand Down
11 changes: 6 additions & 5 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package daemon
import (
"context"
"fmt"
"os"

"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/daemon/process"
"github.com/abiosoft/colima/daemon/process/gvproxy"
"github.com/abiosoft/colima/daemon/process/vmnet"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util/fsutil"
"github.com/abiosoft/colima/util/osutil"
)

// Manager handles running background processes.
Expand Down Expand Up @@ -55,14 +56,14 @@ func (l processManager) Dependencies(ctx context.Context) (deps process.Dependen

func (l processManager) init() error {
// dependencies for network
if err := os.MkdirAll(process.Dir(), 0755); err != nil {
if err := fsutil.MkdirAll(process.Dir(), 0755); err != nil {
return fmt.Errorf("error preparing vmnet: %w", err)
}
return nil
}

func (l processManager) Running(ctx context.Context) (s Status, err error) {
err = l.host.RunQuiet(os.Args[0], "daemon", "status", config.CurrentProfile().ShortName)
err = l.host.RunQuiet(osutil.Executable(), "daemon", "status", config.CurrentProfile().ShortName)
if err != nil {
return
}
Expand All @@ -86,7 +87,7 @@ func (l processManager) Start(ctx context.Context) error {
return fmt.Errorf("error preparing network directory: %w", err)
}

args := []string{os.Args[0], "daemon", "start", config.CurrentProfile().ShortName}
args := []string{osutil.Executable(), "daemon", "start", config.CurrentProfile().ShortName}
opts := optsFromCtx(ctx)
if opts.Vmnet {
args = append(args, "--vmnet")
Expand All @@ -108,7 +109,7 @@ func (l processManager) Stop(ctx context.Context) error {
if s, err := l.Running(ctx); err != nil || !s.Running {
return nil
}
return l.host.RunQuiet(os.Args[0], "daemon", "stop", config.CurrentProfile().ShortName)
return l.host.RunQuiet(osutil.Executable(), "daemon", "stop", config.CurrentProfile().ShortName)
}

func optsFromCtx(ctx context.Context) struct {
Expand Down
5 changes: 3 additions & 2 deletions daemon/process/gvproxy/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/daemon/process"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util/fsutil"
)

var _ process.Dependency = qemuBinsSymlinks{}
Expand All @@ -34,7 +35,7 @@ func (q qemuBinsSymlinks) Installed() bool {

func (q qemuBinsSymlinks) Install(host environment.HostActions) error {
dir := q.dir()
if err := os.MkdirAll(dir, 0755); err != nil {
if err := fsutil.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("error preparing qemu wrapper bin directory: %w", err)
}
this, err := os.Executable()
Expand Down Expand Up @@ -69,7 +70,7 @@ func (q qemuShareDirSymlink) Installed() bool {
func (q qemuShareDirSymlink) Install(host environment.HostActions) error {
dir := q.dir()
parent := filepath.Dir(dir)
if err := os.MkdirAll(parent, 0755); err != nil {
if err := fsutil.MkdirAll(parent, 0755); err != nil {
return fmt.Errorf("error preparing qemu wrapper shared directory: %w", err)
}

Expand Down
6 changes: 3 additions & 3 deletions daemon/process/gvproxy/gvproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/daemon/process"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/shautil"
"github.com/containers/gvisor-tap-vsock/pkg/transport"
"github.com/containers/gvisor-tap-vsock/pkg/types"
"github.com/containers/gvisor-tap-vsock/pkg/virtualnetwork"
Expand Down Expand Up @@ -88,9 +88,9 @@ func MacAddress() string {
// there is not much concern about the precision of the uniqueness.
// this can be revisited
if macAddress == nil {
sum := util.SHA256Hash(process.Dir())
sum := shautil.SHA256(process.Dir())
macAddress = append(macAddress, baseHWAddr...)
macAddress = append(macAddress, sum[0:3]...)
macAddress = append(macAddress, sum.Bytes()[0:3]...)
}
return macAddress.String()
}
Expand Down
34 changes: 34 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
let
pkgs = import <nixpkgs> { };
in
let
# override Lima to remove wrapper for qemu
# https://github.com/NixOS/nixpkgs/blob/f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5/pkgs/applications/virtualization/lima/default.nix#L35
lima = pkgs.lima.overrideAttrs (old: {
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r _output/* $out
runHook postInstall
'';
});
in
pkgs.buildGo118Module rec {
name = "colima";
pname = "colima";
src = ./.;
nativeBuildInputs = with pkgs; [ installShellFiles makeWrapper git coreutils ];
vendorSha256 = "sha256-jDzDwK7qA9lKP8CfkKzfooPDrHuHI4OpiLXmX9vOpOg=";
preConfigure = ''
ldflags="-X github.com/abiosoft/colima/config.appVersion=$(git describe --tags --always)
-X github.com/abiosoft/colima/config.revision=$(git rev-parse HEAD)"
'';
postInstall = ''
wrapProgram $out/bin/colima \
--prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.qemu lima ]}
installShellCompletion --cmd colima \
--bash <($out/bin/colima completion bash) \
--fish <($out/bin/colima completion fish) \
--zsh <($out/bin/colima completion zsh)
'';
}
6 changes: 5 additions & 1 deletion environment/vm/lima/lima.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@ import (
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/osutil"
"github.com/abiosoft/colima/util/yamlutil"
"github.com/sirupsen/logrus"
)

// New creates a new virtual machine.
func New(host environment.HostActions) environment.VM {
// environment variables for the subprocesses
var envs []string
envLimaInstance := limaInstanceEnvVar + "=" + config.CurrentProfile().ID
envSubprocess := config.SubprocessProfileEnvVar + "=" + config.CurrentProfile().ShortName
envs = append(envs, envLimaInstance, envSubprocess)
envBinary := osutil.EnvColimaBinary + "=" + osutil.Executable()
envs = append(envs, envLimaInstance, envSubprocess, envBinary)

// modify the PATH for qemu wrapper
binDir := filepath.Join(config.WrapperDir(), "bin")
envs = append(envs, "PATH="+util.AppendToPath(os.Getenv("PATH"), binDir))

Expand Down
2 changes: 2 additions & 0 deletions environment/vm/lima/yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/fsutil"
)

func Test_checkOverlappingMounts(t *testing.T) {
Expand Down Expand Up @@ -43,6 +44,7 @@ func Test_checkOverlappingMounts(t *testing.T) {
}

func Test_config_Mounts(t *testing.T) {
fsutil.FS = fsutil.FakeFS
tests := []struct {
mounts []string
isDefault bool
Expand Down
3 changes: 2 additions & 1 deletion shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ pkgs.mkShell {
go_1_18
git
coreutils
lima
];
shellHook = ''
export CGO_ENABLED=0
echo Nix Shell with $(go version)
'';
}
4 changes: 2 additions & 2 deletions util/downloader/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/shautil"
"github.com/abiosoft/colima/util/terminal"
)

Expand Down Expand Up @@ -37,7 +37,7 @@ type downloader struct {
}

func (d downloader) cacheFileName(url string) string {
return filepath.Join(config.CacheDir(), "caches", util.SHA256Hash(url).String())
return filepath.Join(config.CacheDir(), "caches", shautil.SHA256(url).String())
}

func (d downloader) cacheDownloadingFileName(url string) string {
Expand Down
50 changes: 50 additions & 0 deletions util/fsutil/fs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package fsutil

import (
"io/fs"
"os"
"testing/fstest"
)

// FS is the host filesystem implementation.
var FS FileSystem = DefaultFS{}

// MkdirAll calls FS.MakedirAll
func MkdirAll(path string, perm os.FileMode) error { return FS.MkdirAll(path, perm) }

// Open calls FS.Open
func Open(name string) (fs.File, error) { return FS.Open(name) }

// FS is abstraction for filesystem.
type FileSystem interface {
MkdirAll(path string, perm os.FileMode) error
fs.FS
}

var _ FileSystem = DefaultFS{}
var _ FileSystem = fakeFS{}

// DefaultFS is the default OS implementation of FileSystem.
type DefaultFS struct{}

// Open implements FS
func (DefaultFS) Open(name string) (fs.File, error) { return os.Open(name) }

// MkdirAll implements FS
func (DefaultFS) MkdirAll(path string, perm fs.FileMode) error { return os.MkdirAll(path, perm) }

// FakeFS is a mock FS. The following can be done in a test before usage.
// osutil.FS = osutil.FakeFS
var FakeFS FileSystem = fakeFS{}

type fakeFS struct{}

// Open implements FileSystem
func (fakeFS) Open(name string) (fs.File, error) {
return fstest.MapFS{name: &fstest.MapFile{
Data: []byte("fake file - " + name),
}}.Open(name)
}

// MkdirAll implements FileSystem
func (fakeFS) MkdirAll(path string, perm fs.FileMode) error { return nil }
48 changes: 48 additions & 0 deletions util/osutil/os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package osutil

import (
"fmt"
"os"
"os/exec"
"path/filepath"

"github.com/sirupsen/logrus"
)

const EnvColimaBinary = "COLIMA_BINARY"

// Executable returns the path name for the executable that started
// the current process.
func Executable() string {
e, err := func(s string) (string, error) {
// prioritize env var in case this is a nested process
if e := os.Getenv(EnvColimaBinary); e != "" {
return e, nil
}

if filepath.IsAbs(s) {
return s, nil
}

e, err := exec.LookPath(s)
if err != nil {
return "", fmt.Errorf("error looking up '%s' in PATH: %w", s, err)
}

abs, err := filepath.Abs(e)
if err != nil {
return "", fmt.Errorf("error computing absolute path of '%s': %w", e, err)
}

return abs, nil
}(os.Args[0])

if err != nil {
// this should never happen, thereby it is safe to do
logrus.Warnln(fmt.Errorf("cannot detect current running executable: %w", err))
logrus.Warnln("falling back to first CLI argument")
return os.Args[0]
}

return e
}
Loading

0 comments on commit 3a85204

Please sign in to comment.