cmd API

cmd

package

API reference for the cmd package.

F
function

NewCompileCommand

Create and return a new compile command for the Cobra CLI

Returns

cmd/compile.go:14-29
func NewCompileCommand() *cobra.Command

{
	cmd := &cobra.Command{
		Use:   "compile",
		Short: "Compile the given recipe",
		Long:  "Compile the given Vib recipe into a working container image, using the specified runtime (docker/podman)",
		Example: `  vib compile // using the recipe in the current directory and the system's default runtime
  vib compile --runtime podman // using the recipe in the current directory and Podman as the runtime
  vib compile /path/to/recipe.yml --runtime podman // using the recipe at the specified path and Podman as the runtime
  Both docker and podman are supported as runtimes. If none is specified, the detected runtime will be used, giving priority to Docker.`,
		RunE: compileCommand,
	}
	cmd.Flags().StringP("runtime", "r", "", "The runtime to use (docker/podman)")
	cmd.Flags().SetInterspersed(false)

	return cmd
}
F
function

compileCommand

Execute the compile command: compile the given recipe into a container image

Parameters

args
[]string

Returns

error
cmd/compile.go:32-74
func compileCommand(cmd *cobra.Command, args []string) error

{
	commonNames := []string{
		"recipe.yml",
		"recipe.yaml",
		"vib.yml",
		"vib.yaml",
	}
	var recipePath string
	var arch string
	var containerRuntime string

	arch = runtime.GOARCH
	containerRuntime, _ = cmd.Flags().GetString("runtime")

	if len(args) == 0 {
		for _, name := range commonNames {
			if _, err := os.Stat(name); err == nil {
				recipePath = name
				break
			}
		}
	} else {
		recipePath = args[0]
	}

	if recipePath == "" {
		return fmt.Errorf("missing recipe path")
	}

	detectedRuntime := detectRuntime()
	if containerRuntime == "" && detectedRuntime == "" {
		return fmt.Errorf("missing runtime, and no one was detected")
	} else if containerRuntime == "" {
		containerRuntime = detectedRuntime
	}

	err := core.CompileRecipe(recipePath, arch, containerRuntime, IsRoot, OrigGID, OrigUID)
	if err != nil {
		return err
	}

	return nil
}
F
function

detectRuntime

Detect the container runtime by checking the system path

Returns

string
cmd/compile.go:79-91
func detectRuntime() string

{
	path, _ := exec.LookPath("docker")
	if path != "" {
		return "docker"
	}

	path, _ = exec.LookPath("podman")
	if path != "" {
		return "podman"
	}

	return ""
}
F
function

init

Initialize the root command with build, test, and compile commands

cmd/root.go:28-32
func init()

{
	rootCmd.AddCommand(NewBuildCommand())
	rootCmd.AddCommand(NewTestCommand())
	rootCmd.AddCommand(NewCompileCommand())
}
F
function

Execute

Execute the root command, handling root user environment setup and privilege dropping

Returns

error
cmd/root.go:35-64
func Execute() error

{
	if os.Getuid() == 0 {
		IsRoot = true
		gid, err := strconv.Atoi(os.Getenv("SUDO_GID"))
		if err != nil {
			return fmt.Errorf("failed to get user gid through SUDO_GID: %s", err.Error())
		}
		OrigGID = gid // go moment??

		uid, err := strconv.Atoi(os.Getenv("SUDO_UID"))
		if err != nil {
			return fmt.Errorf("failed to get user uid through SUDO_UID: %s", err.Error())
		}
		OrigUID = uid

		user := os.Getenv("SUDO_USER")
		os.Setenv("HOME", filepath.Join("/home", user))

		err = syscall.Setegid(OrigGID)
		if err != nil {
			fmt.Println("WARN: Failed to drop GID root privileges ", OrigGID)

		}
		err = syscall.Seteuid(OrigUID)
		if err != nil {
			fmt.Println("WARN: Failed to drop UID root privileges ", OrigUID)
		}
	}
	return rootCmd.Execute()
}
F
function

NewTestCommand

Create and return a new test command for the Cobra CLI

Returns

cmd/test.go:11-21
func NewTestCommand() *cobra.Command

{
	cmd := &cobra.Command{
		Use:   "test",
		Short: "Test the given recipe",
		Long:  "Test the given Vib recipe to check if it's valid",
		RunE:  testCommand,
	}
	cmd.Flags().SetInterspersed(false)

	return cmd
}
F
function

testCommand

Validate the provided recipe by testing it

Parameters

args
[]string

Returns

error
cmd/test.go:24-35
func testCommand(cmd *cobra.Command, args []string) error

{
	if len(args) == 0 {
		return fmt.Errorf("no recipe path specified")
	}

	recipePath := args[0]
	_, err := core.TestRecipe(recipePath)
	if err != nil {
		return err
	}
	return nil
}
F
function

NewBuildCommand

Create a new build command for the Cobra CLI

Returns

cmd/build.go:18-34
func NewBuildCommand() *cobra.Command

{
	cmd := &cobra.Command{
		Use:   "build",
		Short: "Build the given recipe",
		Long:  "Build the given Vib recipe into a Containerfile",
		Example: `  Using the recipe.yml/yaml or vib.yml/yaml file in the current directory:
    vib build

  To specify a recipe file, use:
    vib build /path/to/recipe.yml`,
		RunE: buildCommand,
	}
	cmd.Flags().StringP("arch", "a", runtime.GOARCH, "target architecture")
	cmd.Flags().SetInterspersed(false)

	return cmd
}
F
function

buildCommand

Handle the build command for the Cobra CLI

Parameters

args
[]string

Returns

error
cmd/build.go:37-95
func buildCommand(cmd *cobra.Command, args []string) error

{
	commonNames := []string{
		"recipe.yml",
		"recipe.yaml",
		"vib.yml",
		"vib.yaml",
	}
	var recipePath string
	var arch string

	arch, _ = cmd.Flags().GetString("arch")

	if len(args) == 0 {
		for _, name := range commonNames {
			if _, err := os.Stat(name); err == nil {
				recipePath = name
				break
			}
		}
	} else {
		recipePath = args[0]

		/*
			Check whether the provided file has either yml or yaml extension,
			if not, then return an error

			Operations on recipePath:
			1. Get the recipePath extension, then
			2. Trim the left dot(.) and
			3. Convert the extension to lower case.

			Covers the following:
			1. filename.txt - Invalid extension
			2. filename. - No extension
			3. filename - No extension
			4. filename.YAML or filename.YML - uppercase extension
		*/
		extension := strings.ToLower(strings.TrimLeft(filepath.Ext(recipePath), "."))
		if len(extension) == 0 || (extension != "yml" && extension != "yaml") {
			return fmt.Errorf("%s is an invalid recipe file", recipePath)
		}

		// Check whether the provided file exists, if not, then return an error
		if _, err := os.Stat(recipePath); errors.Is(err, os.ErrNotExist) {
			return fmt.Errorf("%s does not exist", recipePath)
		}
	}

	if recipePath == "" {
		return fmt.Errorf("missing recipe path")
	}

	_, err := core.BuildRecipe(recipePath, arch)
	if err != nil {
		return err
	}

	return nil
}