Files
Abiola IbrahimandGitHub f499e12c3f v0.6.0 refactor (#848)
* core: begin migration to ubuntu

* core: update cloud image link

* k3s: update version

* core: fix boot for ubuntu

* vm: add ability to set custom hostname

* core: checkpoint: remove qemu wrapper

* core: checkpoint: remove qemu wrapper

* cli: minor bug fix for terminal output

* cli: fix broken terminal output for deb download

* cli: improve terminal output for deb download

* vm: fix docker permission on initial create

* net: remove gvproxy, migrate to user-v2

* docker: fix host-gateway address

* vm: avoid re-installing packages

* k3s: fix broken coredns

* core: improve downloader

* vm: add binfmt for cross-platform containers

* containerd: fix for ubuntu

* containerd: fix broken working directory detection

* chore: remove obsolete env var

* chore: minor refactor for binfmt

* cli: fix ip address for colima list

* docker: add daemon support for proxy env vars

* vm: add more utilities

* ci: remove obsolete ubuntu layer

* ci: move to gh from hub

* core: use custom directory for Lima

* chore: minor factor, remove obsolete variable

* docker: workaround initial user permission issue

* chore: remove obsolete code

* vm: fix binfmt cache

* core: enforce Lima version requirement

* docker: workaround permission issue

* vm: enable inotify by default

* core: enable binfmt only on host arch

* docs: prepare for v0.6.0

* nix: update Go version in shell

* nix: update build

* build: add integration test script

* ci: remove aarch64, defer until proper m1 support

* build: fix colima path in integration test script
2023-11-12 11:28:30 +01:00

171 lines
5.1 KiB
Go

package cmd
import (
"bytes"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/abiosoft/colima/cli"
"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"
)
var nerdctlCmdArgs struct {
force bool
path string
usrBinWriteable bool
isColimaScript bool
}
// nerdctlCmd represents the nerdctl command
var nerdctlCmd = &cobra.Command{
Use: "nerdctl",
Aliases: []string{"nerd", "n"},
Short: "run nerdctl (requires containerd runtime)",
Long: `Run nerdctl to interact with containerd.
This requires containerd runtime.
It is recommended to specify '--' to differentiate from Colima flags.
`,
RunE: func(cmd *cobra.Command, args []string) error {
app := newApp()
r, err := app.Runtime()
if err != nil {
return err
}
if r != containerd.Name {
return fmt.Errorf("nerdctl only supports %s runtime", containerd.Name)
}
nerdctlArgs := append([]string{"sudo", "nerdctl"}, args...)
return app.SSH(nerdctlArgs...)
},
}
// nerdctlLinkFunc represents the nerdctl command
var nerdctlLinkFunc = func() *cobra.Command {
return &cobra.Command{
Use: "install",
Short: "install nerdctl alias script on the host",
Long: `Install nerdctl alias script on the host. The script will be installed at ` + nerdctlDefaultInstallPath + `.`,
Args: cobra.NoArgs,
PreRun: func(cmd *cobra.Command, args []string) {
// check if /usr/local/bin is writeable and no need for sudo
// if the path is user-specified, ignore.
if nerdctlCmdArgs.path != nerdctlDefaultInstallPath {
return
}
// attempt writing to the /usr/local/bin
tmpFile := filepath.Join(filepath.Dir(nerdctlDefaultInstallPath), "colima.tmp")
if err := os.WriteFile(tmpFile, []byte("tmp"), 0777); err == nil {
nerdctlCmdArgs.usrBinWriteable = true
_ = os.Remove(tmpFile)
}
// check if the current file (if exists) is generated by colima
// in such case no need for confirmation before overwrite
// TODO: this is too basic, should be better
if b, err := os.ReadFile(nerdctlCmdArgs.path); err == nil {
if strings.Contains(string(b), "colima nerdctl ") {
nerdctlCmdArgs.isColimaScript = true
}
}
},
RunE: func(cmd *cobra.Command, args []string) error {
exists := false
if _, err := os.Stat(nerdctlCmdArgs.path); err == nil && !nerdctlCmdArgs.force && !nerdctlCmdArgs.isColimaScript {
return fmt.Errorf("%s exists, use --force to replace", nerdctlCmdArgs.path)
} else if err == nil {
exists = true
}
t, err := template.New("").Parse(nerdctlScript)
if err != nil {
return fmt.Errorf("error parsing nerdctl script template: %w", err)
}
var values = struct {
ColimaApp string
Profile string
}{
ColimaApp: osutil.Executable(),
Profile: config.CurrentProfile().ShortName,
}
var buf bytes.Buffer
if err := t.Execute(&buf, values); err != nil {
return fmt.Errorf("error applying nerdctl script template: %w", err)
}
// /usr/local/bin writeable i.e. sudo not needed
// or user-specified install path, we assume user specified path is writeable
if nerdctlCmdArgs.usrBinWriteable || nerdctlCmdArgs.path != nerdctlDefaultInstallPath {
if exists {
if err := os.Rename(nerdctlCmdArgs.path, nerdctlCmdArgs.path+".moved"); err != nil {
return fmt.Errorf("error backing up existing file: %w", err)
}
}
if err := fsutil.MkdirAll("/usr/local/bin", 0755); err != nil {
return nil
}
return os.WriteFile(nerdctlCmdArgs.path, buf.Bytes(), 0755)
}
// sudo is needed for the default path
log.Println("/usr/local/bin not writable, sudo password required to install nerdctl binary")
if exists && !nerdctlCmdArgs.isColimaScript {
c := cli.CommandInteractive("sudo", "mv", nerdctlCmdArgs.path, nerdctlCmdArgs.path+".moved")
if err := c.Run(); err != nil {
return fmt.Errorf("error backing up existing file: %w", err)
}
}
// prepare dir
{
c := cli.CommandInteractive("sudo", "mkdir", "-p", "/usr/local/bin")
if err := c.Run(); err != nil {
return err
}
}
// install script
{
c := cli.CommandInteractive("sudo", "sh", "-c", "cat > "+nerdctlCmdArgs.path)
c.Stdin = &buf
if err := c.Run(); err != nil {
return err
}
}
// ensure it is executable
if err := cli.Command("sudo", "chmod", "+x", nerdctlCmdArgs.path).Run(); err != nil {
return err
}
return nil
},
}
}
const nerdctlDefaultInstallPath = "/usr/local/bin/nerdctl"
const nerdctlScript = `#!/usr/bin/env sh
{{.ColimaApp}} nerdctl --profile {{.Profile}} -- "$@"
`
func init() {
root.Cmd().AddCommand(nerdctlCmd)
nerdctlLink := nerdctlLinkFunc()
nerdctlCmd.AddCommand(nerdctlLink)
nerdctlLink.Flags().BoolVarP(&nerdctlCmdArgs.force, "force", "f", false, "replace "+nerdctlDefaultInstallPath+" (if exists)")
nerdctlLink.Flags().StringVar(&nerdctlCmdArgs.path, "path", nerdctlDefaultInstallPath, "path to install nerdctl binary")
}