Skip to content

Commit

Permalink
multiple misc updates (abiosoft#374)
Browse files Browse the repository at this point in the history
* chore: update nix shell

* chore: remove redundant code

* core: update iso images

* layer: ensure hostname sync

* cli: add clone command

* k8s: update default to v1.24.3+k3s1

* core: make docker/k8s context activation optional

* k8s: remove as active context on shutdown

* chore: fix typo
  • Loading branch information
abiosoft authored Jul 26, 2022
1 parent 0e092a6 commit 75025eb
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 79 deletions.
98 changes: 98 additions & 0 deletions cmd/clone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package cmd

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

"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/cmd/root"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment/vm/lima/limautil"
"github.com/abiosoft/colima/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// stopCmd represents the stop command
var cloneCmd = &cobra.Command{
Use: "clone <profile> <new-profile>",
Short: "clone Colima profile",
Long: `Clone the Colima profile.`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
from := config.Profile(args[0])
to := config.Profile(args[1])

limaHome, err := limautil.LimaHome()
if err != nil {
err = fmt.Errorf("error detecting Lima config directory: %w", err)
logrus.Warnln(err)
logrus.Warnln("falling back to default '$HOME/.lima'")
limaHome = filepath.Join(util.HomeDir(), ".lima")
}

limaDir := func(p config.ProfileInfo) string {
return filepath.Join(limaHome, p.ID)
}

configFile := func(p config.ProfileInfo) string {
return filepath.Join(filepath.Dir(config.Dir()), p.ShortName, config.ConfigFileName)
}

logrus.Infof("preparing to clone %s...", from.DisplayName)
{
// verify source profile exists
if stat, err := os.Stat(limaDir(from)); err != nil || !stat.IsDir() {
return fmt.Errorf("colima profile '%s' does not exist", from.ShortName)
}

// verify destination profile does not exists
if stat, err := os.Stat(limaDir(to)); err == nil && stat.IsDir() {
return fmt.Errorf("colima profile '%s' already exists, delete with `colima delete %s` and try again", to.ShortName, to.ShortName)
}

// copy source to destination
logrus.Info("cloning virtual machine...")
if err := cli.Command("mkdir", "-p", limaDir(to)).Run(); err != nil {
return fmt.Errorf("error preparing to copy VM: %w", err)
}

if err := cli.Command("cp",
filepath.Join(limaDir(from), "basedisk"),
filepath.Join(limaDir(from), "diffdisk"),
filepath.Join(limaDir(from), "cidata.iso"),
filepath.Join(limaDir(from), "lima.yaml"),
limaDir(to),
).Run(); err != nil {
return fmt.Errorf("error copying VM: %w", err)
}
}

{
logrus.Info("copying config...")
// verify source config exists
if _, err := os.Stat(configFile(from)); err != nil {
return fmt.Errorf("config missing for colima profile '%s': %w", from.ShortName, err)
}

// ensure destination config directory
if err := cli.Command("mkdir", "-p", filepath.Dir(configFile(to))).Run(); err != nil {
return fmt.Errorf("cannot copy config to new profile '%s': %w", to.ShortName, err)
}

if err := cli.Command("cp", configFile(from), configFile(to)).Run(); err != nil {
return fmt.Errorf("error copying VM config: %w", err)
}
}

logrus.Info("clone successful")
logrus.Infof("run `colima start %s` to start the newly cloned profile", to.ShortName)
return nil
},
}

func init() {
root.Cmd().AddCommand(cloneCmd)

}
8 changes: 8 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ var startCmdArgs struct {
LegacyKubernetes bool // for backward compatibility
Edit bool
Editor string
ActivateRuntime bool
}
}

Expand All @@ -111,6 +112,7 @@ func init() {

root.Cmd().AddCommand(startCmd)
startCmd.Flags().StringVarP(&startCmdArgs.Runtime, "runtime", "r", docker.Name, "container runtime ("+runtimes+")")
startCmd.Flags().BoolVar(&startCmdArgs.Flags.ActivateRuntime, "activate", true, "set as active Docker/Kubernetes context on startup")
startCmd.Flags().IntVarP(&startCmdArgs.CPU, "cpu", "c", defaultCPU, "number of CPUs")
startCmd.Flags().StringVar(&startCmdArgs.CPUType, "cpu-type", "", "the CPU type, options can be checked with 'qemu-system-"+defaultArch+" -cpu help'")
startCmd.Flags().IntVarP(&startCmdArgs.Memory, "memory", "m", defaultMemory, "memory in GiB")
Expand Down Expand Up @@ -179,6 +181,7 @@ func prepareConfig(cmd *cobra.Command) {

// convert cli to config file format
startCmdArgs.Mounts = mountsFromFlag(startCmdArgs.Flags.Mounts)
startCmdArgs.ActivateRuntime = &startCmdArgs.Flags.ActivateRuntime

// if there is no existing settings
if current.Empty() {
Expand Down Expand Up @@ -235,6 +238,11 @@ func prepareConfig(cmd *cobra.Command) {
if !cmd.Flag("layer").Changed {
startCmdArgs.Layer = current.Layer
}
if !cmd.Flag("activate").Changed {
if current.ActivateRuntime != nil { // backward compatibility for `activate`
startCmdArgs.ActivateRuntime = current.ActivateRuntime
}
}
if util.MacOS() {
if !cmd.Flag("network-address").Changed {
startCmdArgs.Network.Address = current.Network.Address
Expand Down
11 changes: 10 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ type Config struct {
MountType string `yaml:"mountType,omitempty"`

// Runtime is one of docker, containerd.
Runtime string `yaml:"runtime,omitempty"`
Runtime string `yaml:"runtime,omitempty"`
ActivateRuntime *bool `yaml:"autoActivate,omitempty"`

// Kubernetes configuration
Kubernetes Kubernetes `yaml:"kubernetes,omitempty"`
Expand Down Expand Up @@ -143,6 +144,14 @@ func (c Config) MountsOrDefault() []Mount {
}
}

// AutoActivate returns if auto-activation of host client config is enabled.
func (c Config) AutoActivate() bool {
if c.ActivateRuntime == nil {
return true
}
return *c.ActivateRuntime
}

// Empty checks if the configuration is empty.
func (c Config) Empty() bool { return c.Runtime == "" } // this may be better but not really needed.

Expand Down
4 changes: 2 additions & 2 deletions config/dirs.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ func TemplatesDir() string { return templatesDir.Dir() }
// WrapperDir returns the qemu wrapper directory.
func WrapperDir() string { return wrapperDir.Dir() }

const configFileName = "colima.yaml"
const ConfigFileName = "colima.yaml"

func configFile() string { return filepath.Join(configDir.Dir(), configFileName) }
func configFile() string { return filepath.Join(configDir.Dir(), ConfigFileName) }
9 changes: 8 additions & 1 deletion embedded/defaults/colima.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,19 @@ kubernetes:
# Kubernetes version to use.
# This needs to exactly match a k3s version https://github.com/k3s-io/k3s/releases
# Default: latest stable release
version: v1.23.6+k3s1
version: v1.24.3+k3s1

# Enable the traefik ingress controller
# Default: false
ingress: false

# Auto-activate on the Host for client access.
# Setting to true does the following on startup
# - sets as active Docker context (for Docker runtime).
# - sets as active Kubernetes context (if Kubernetes is enabled).
# Default: true
autoActivate: true

# Network configurations for the virtual machine.
network:
# Assign reachable IP address to the virtual machine.
Expand Down
1 change: 0 additions & 1 deletion environment/container/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func (c containerdRuntime) Name() string {
}

func (c containerdRuntime) Provision(context.Context) error {
// already provisioned as part of Lima
return c.guest.Write(buildKitConfFile, buildKitConf)
}

Expand Down
4 changes: 3 additions & 1 deletion environment/container/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ func (d dockerRuntime) Provision(ctx context.Context) error {

// docker context
a.Add(d.setupContext)
a.Add(d.useContext)
if conf.AutoActivate() {
a.Add(d.useContext)
}

return a.Exec()
}
Expand Down
26 changes: 18 additions & 8 deletions environment/container/kubernetes/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,17 @@ func (c kubernetesRuntime) provisionKubeconfig(ctx context.Context) error {
})

// set new context
a.Add(func() error {
out, err := c.host.RunOutput("kubectl", "config", "use-context", profile)
if err != nil {
return err
}
log.Println(out)
return nil
})
conf, _ := ctx.Value(config.CtxKey()).(config.Config)
if conf.AutoActivate() {
a.Add(func() error {
out, err := c.host.RunOutput("kubectl", "config", "use-context", profile)
if err != nil {
return err
}
log.Println(out)
return nil
})
}

// save settings
a.Add(func() error {
Expand All @@ -119,6 +122,13 @@ func (c kubernetesRuntime) unsetKubeconfig(a *cli.ActiveCommandChain) {
a.Add(func() error {
return c.host.Run("kubectl", "config", "unset", "clusters."+profile)
})
// kubectl config unset current-context
a.Add(func() error {
if c, _ := c.host.RunOutput("kubectl", "config", "current-context"); c != config.CurrentProfile().ID {
return nil
}
return c.host.Run("kubectl", "config", "unset", "current-context")
})
}

func (c kubernetesRuntime) teardownKubeconfig(a *cli.ActiveCommandChain) {
Expand Down
2 changes: 1 addition & 1 deletion environment/container/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

const (
Name = "kubernetes"
DefaultVersion = "v1.23.6+k3s1"
DefaultVersion = "v1.24.3+k3s1"

configKey = "kubernetes_config"
)
Expand Down
25 changes: 16 additions & 9 deletions environment/container/ubuntu/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,6 @@ func (u ubuntuRuntime) buildArgs() (b buildArgs, err error) {
return
}

func (u ubuntuRuntime) imageBasename() string {
return "ubuntu-layer-" + string(u.guest.Arch().Value())
}

func (u ubuntuRuntime) imageArchive() string {
name := "ubuntu-layer-" + string(u.guest.Arch().Value()) + ".tar.gz"
return filepath.Join("/usr/share/colima", name)
}

func (u ubuntuRuntime) imageCreated() bool {
args := nerdctl("image", "inspect", imageName)
return u.guest.RunQuiet(args...) == nil
Expand Down Expand Up @@ -170,3 +161,19 @@ func (u ubuntuRuntime) createContainer(conf config.Config) error {
args = append(args, imageName)
return u.guest.Run(args...)
}

func (u ubuntuRuntime) syncHostname() error {
currentHostname := func() string {
args := nerdctl("exec", containerName, "hostname")
hostname, _ := u.guest.RunOutput(args...)
return hostname
}()

hostname := config.CurrentProfile().ID
if currentHostname == hostname {
return nil
}

args := nerdctl("exec", containerName, "sudo", "hostname", hostname)
return u.guest.RunQuiet(args...)
}
17 changes: 14 additions & 3 deletions environment/container/ubuntu/ubuntu.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/environment"
"github.com/abiosoft/colima/environment/container/containerd"
"github.com/sirupsen/logrus"
)

// Name is container runtime name
Expand Down Expand Up @@ -82,16 +83,26 @@ func (u ubuntuRuntime) Provision(ctx context.Context) error {
return a.Exec()
}

func (u ubuntuRuntime) Start(context.Context) error {
return u.guest.Run(nerdctl("start", containerName)...)
func (u ubuntuRuntime) Start(ctx context.Context) error {
a := u.Init(ctx)

a.Add(func() error {
return u.guest.Run(nerdctl("start", containerName)...)
})
a.Add(u.syncHostname)

return a.Exec()
}

func (u ubuntuRuntime) Stop(context.Context) error {
return u.guest.Run(nerdctl("stop", containerName)...)
}

func (u ubuntuRuntime) Teardown(context.Context) error {
return u.guest.Run(nerdctl("rm", containerName)...)
if err := u.guest.Run(nerdctl("stop", containerName)...); err != nil {
logrus.Warn(fmt.Errorf("error stopping container: %w", err))
}
return u.guest.Run(nerdctl("rm", "-f", containerName)...)
}

func (u ubuntuRuntime) Version(ctx context.Context) string {
Expand Down
8 changes: 0 additions & 8 deletions environment/vm/lima/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package lima
import (
"context"
"fmt"
"net"
"path/filepath"
"strconv"

"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/util"
Expand Down Expand Up @@ -45,9 +43,3 @@ func (l limaVM) copyCerts() error {
}
return nil
}

func (l limaVM) addHost(host string, ip net.IP) error {
line := fmt.Sprintf("%s\t%s", ip.String(), host)
line = fmt.Sprintf("echo -e %s >> /etc/hosts", strconv.Quote(line))
return l.Run("sudo", "sh", "-c", line)
}
Loading

0 comments on commit 75025eb

Please sign in to comment.