[lxc-devel] [distrobuilder/master] *: Switch to cobra CLI
monstermunchkin on Github
lxc-bot at linuxcontainers.org
Mon Mar 5 16:50:41 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 379 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180305/53ae0bd6/attachment.bin>
-------------- next part --------------
From 5f4b4b25c524c1c6bf57412d4a5f3815e9b6ff0a Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Fri, 2 Mar 2018 22:08:58 +0100
Subject: [PATCH] *: Switch to cobra CLI
Resolves #13
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
distrobuilder/main.go | 281 ++++++++++++++++++++--------------------
distrobuilder/main_build-dir.go | 20 +++
distrobuilder/main_lxc.go | 79 +++++++++++
distrobuilder/main_lxd.go | 91 +++++++++++++
generators/hostname_test.go | 4 +-
generators/hosts_test.go | 4 +-
image/lxc.go | 17 ++-
image/lxc_test.go | 4 +-
image/lxd.go | 20 ++-
image/lxd_test.go | 2 +-
10 files changed, 359 insertions(+), 163 deletions(-)
create mode 100644 distrobuilder/main_build-dir.go
create mode 100644 distrobuilder/main_lxc.go
create mode 100644 distrobuilder/main_lxd.go
diff --git a/distrobuilder/main.go b/distrobuilder/main.go
index dfb9e92..c893092 100644
--- a/distrobuilder/main.go
+++ b/distrobuilder/main.go
@@ -53,132 +53,129 @@ import (
"os"
"path/filepath"
- "github.com/lxc/distrobuilder/generators"
- "github.com/lxc/distrobuilder/image"
"github.com/lxc/distrobuilder/shared"
"github.com/lxc/distrobuilder/sources"
+ "github.com/spf13/cobra"
- lxd "github.com/lxc/lxd/shared"
- cli "gopkg.in/urfave/cli.v1"
yaml "gopkg.in/yaml.v2"
)
+type cmdGlobal struct {
+ flagCleanup bool
+ flagCacheDir string
+
+ definition *shared.Definition
+ sourceDir string
+ targetDir string
+}
+
func main() {
- app := cli.NewApp()
- app.Usage = "image generator"
- // INPUT can either be a file or '-' which reads from stdin
- app.ArgsUsage = "[file|-]"
- app.HideHelp = true
- app.Action = run
- app.Flags = []cli.Flag{
- cli.BoolFlag{
- Name: "lxc",
- Usage: "generate LXC image files",
- },
- cli.BoolFlag{
- Name: "lxd",
- Usage: "generate LXD image files",
- },
- cli.BoolFlag{
- Name: "plain",
- Usage: "generate plain chroot",
- },
- cli.BoolTFlag{
- Name: "unified",
- Usage: "output unified tarball for LXD images",
- },
- cli.BoolTFlag{
- Name: "cleanup",
- Usage: "clean up build directory",
- },
- cli.StringFlag{
- Name: "template-dir",
- Usage: "template directory",
- },
- cli.StringFlag{
- Name: "cache-dir",
- Usage: "cache directory",
- Value: "/var/cache/distrobuilder",
- },
- cli.StringFlag{
- Name: "compression",
- Usage: "compression algorithm",
- },
- cli.BoolFlag{
- Name: "help, h",
- Usage: "show help",
- },
+ // Sanity checks
+ if os.Geteuid() != 0 {
+ fmt.Fprintln(os.Stderr, "You must be root to run this tool")
+ os.Exit(1)
}
- err := app.Run(os.Args)
+ // Global flags
+ globalCmd := cmdGlobal{}
+
+ app := &cobra.Command{
+ Use: "distrobuilder",
+ Short: "System container image builder for LXC and LXD",
+ PersistentPostRunE: globalCmd.postRun,
+ }
+
+ app.PersistentFlags().BoolVar(&globalCmd.flagCleanup, "cleanup", true,
+ "Clean up cache directory")
+ app.PersistentFlags().StringVar(&globalCmd.flagCacheDir, "cache-dir",
+ "/var/cache/distrobuilder", "Cache directory")
+
+ // LXC sub-commands
+ LXCCmd := cmdLXC{global: &globalCmd}
+ app.AddCommand(LXCCmd.commandBuild())
+ app.AddCommand(LXCCmd.commandPack())
+
+ // LXD sub-commands
+ LXDCmd := cmdLXD{global: &globalCmd}
+ app.AddCommand(LXDCmd.commandBuild())
+ app.AddCommand(LXDCmd.commandPack())
+
+ // build-dir sub-command
+ buildDirCmd := cmdBuildDir{global: &globalCmd}
+ app.AddCommand(buildDirCmd.command())
+
+ // Run the main command and handle errors
+ err := app.Execute()
if err != nil {
- fmt.Fprintf(os.Stderr, "error: %s\n", err)
os.Exit(1)
}
}
-func run(c *cli.Context) error {
- // Sanity checks
- if os.Geteuid() != 0 {
- return fmt.Errorf("You must be root to run this tool")
+func (c *cmdGlobal) preRunBuild(cmd *cobra.Command, args []string) error {
+ c.sourceDir = c.flagCacheDir
+
+ if len(args) > 1 {
+ // Create and set target directory if provided
+ err := os.MkdirAll(args[1], 0755)
+ if err != nil {
+ return err
+ }
+ c.targetDir = args[1]
+ } else {
+ // Use current working directory as target
+ var err error
+ c.targetDir, err = os.Getwd()
+ if err != nil {
+ return err
+ }
}
- // Create our working directory
- os.RemoveAll(c.GlobalString("cache-dir"))
- os.MkdirAll(c.GlobalString("cache-dir"), 0755)
+ // Special case: Make cache directory the target directory. This will
+ // prevent us from having to move ${cacheDir}/rootfs to ${target}/rootfs.
+ if cmd.CalledAs() == "build-dir" {
+ c.flagCacheDir = c.targetDir
+ }
+
+ var err error
// Get the image definition
- def, err := getDefinition(c.Args().Get(0))
+ c.definition, err = getDefinition(args[0])
if err != nil {
- return fmt.Errorf("Error getting definition: %s", err)
+ return err
}
- // Get the downloader to use for this image
- downloader := sources.Get(def.Source.Downloader)
- if downloader == nil {
- return fmt.Errorf("Unsupported source downloader: %s", def.Source.Downloader)
+ // Get the mapped architecture
+ arch, err := getMappedArchitecture(c.definition)
+ if err != nil {
+ return err
}
- // Translate the requested architecture name
- var arch string
- if def.Mappings.ArchitectureMap != "" {
- // Translate the architecture using the requested map
- arch, err = shared.GetArch(def.Mappings.ArchitectureMap, def.Image.Arch)
- if err != nil {
- return fmt.Errorf("Failed to translate the architecture name: %s", err)
- }
- } else if len(def.Mappings.Architectures) > 0 {
- // Translate the architecture using a user specified mapping
- var ok bool
- arch, ok = def.Mappings.Architectures[def.Image.Arch]
- if !ok {
- // If no mapping exists, it means it doesn't need translating
- arch = def.Image.Arch
- }
- } else {
- // No map or mappings provided, just go with it as it is
- arch = def.Image.Arch
+ // Create cache directory
+ err = os.MkdirAll(c.flagCacheDir, 0755)
+ if err != nil {
+ return err
+ }
+
+ // Get the downloader to use for this image
+ downloader := sources.Get(c.definition.Source.Downloader)
+ if downloader == nil {
+ return fmt.Errorf("Unsupported source downloader: %s", c.definition.Source.Downloader)
}
// Download the root filesystem
- err = downloader.Run(def.Source, def.Image.Release, arch,
- c.GlobalString("cache-dir"))
+ err = downloader.Run(c.definition.Source, c.definition.Image.Release, arch, c.flagCacheDir)
if err != nil {
return fmt.Errorf("Error while downloading source: %s", err)
}
- if c.GlobalBoolT("cleanup") {
- defer os.RemoveAll(c.GlobalString("cache-dir"))
- }
-
// Setup the mounts and chroot into the rootfs
- exitChroot, err := setupChroot(filepath.Join(c.GlobalString("cache-dir"), "rootfs"))
+ exitChroot, err := setupChroot(filepath.Join(c.flagCacheDir, "rootfs"))
if err != nil {
return fmt.Errorf("Failed to setup chroot: %s", err)
}
// Install/remove/update packages
- err = managePackages(def.Packages)
+ err = managePackages(c.definition.Packages)
if err != nil {
exitChroot()
return fmt.Errorf("Failed to manage packages: %s", err)
@@ -187,67 +184,39 @@ func run(c *cli.Context) error {
// Unmount everything and exit the chroot
exitChroot()
- if c.GlobalBool("lxc") {
- img := image.NewLXCImage(c.GlobalString("cache-dir"), def.Image, def.Targets.LXC)
-
- for _, file := range def.Files {
- generator := generators.Get(file.Generator)
- if generator == nil {
- return fmt.Errorf("Unknown generator '%s'", file.Generator)
- }
-
- if len(file.Releases) > 0 && !lxd.StringInSlice(def.Image.Release, file.Releases) {
- continue
- }
+ return nil
+}
- err := generator.CreateLXCData(c.GlobalString("cache-dir"), file.Path, img)
- if err != nil {
- continue
- }
- }
+func (c *cmdGlobal) preRunPack(cmd *cobra.Command, args []string) error {
+ var err error
- err := img.Build()
- if err != nil {
- return fmt.Errorf("Failed to create LXC image: %s", err)
- }
+ c.sourceDir = args[1]
- // Clean up the chroot by restoring the orginal files.
- err = generators.RestoreFiles(c.GlobalString("cache-dir"))
- if err != nil {
- return fmt.Errorf("Failed to restore cached files: %s", err)
- }
+ c.targetDir = "."
+ if len(args) == 3 {
+ c.targetDir = args[2]
}
- if c.GlobalBool("lxd") {
- img := image.NewLXDImage(c.GlobalString("cache-dir"), def.Image)
-
- for _, file := range def.Files {
- if len(file.Releases) > 0 && !lxd.StringInSlice(def.Image.Release, file.Releases) {
- continue
- }
-
- generator := generators.Get(file.Generator)
- if generator == nil {
- return fmt.Errorf("Unknown generator '%s'", file.Generator)
- }
-
- err := generator.CreateLXDData(c.GlobalString("cache-dir"), file.Path, img)
- if err != nil {
- return fmt.Errorf("Failed to create LXD data: %s", err)
- }
- }
+ // Get the image definition
+ c.definition, err = getDefinition(args[0])
+ if err != nil {
+ return err
+ }
- err := img.Build(c.GlobalBool("unified"))
- if err != nil {
- return fmt.Errorf("Failed to create LXD image: %s", err)
- }
+ // Create cache directory
+ err = os.MkdirAll(c.flagCacheDir, 0755)
+ if err != nil {
+ return err
}
- if c.GlobalBool("plain") {
- err := shared.Pack("plain.tar.xz", filepath.Join(c.GlobalString("cache-dir"), "rootfs"), ".")
- if err != nil {
- return fmt.Errorf("Failed to create plain rootfs: %s", err)
- }
+ return nil
+}
+
+func (c *cmdGlobal) postRun(cmd *cobra.Command, args []string) error {
+ // Clean up cache directory if needed. Do not clean up if the build-dir
+ // sub-command is run since the directory is needed for further actions.
+ if c.flagCleanup && cmd.CalledAs() != "build-dir" {
+ return os.RemoveAll(c.flagCacheDir)
}
return nil
@@ -292,3 +261,29 @@ func getDefinition(fname string) (*shared.Definition, error) {
return &def, nil
}
+
+func getMappedArchitecture(def *shared.Definition) (string, error) {
+ var arch string
+
+ if def.Mappings.ArchitectureMap != "" {
+ // Translate the architecture using the requested map
+ var err error
+ arch, err = shared.GetArch(def.Mappings.ArchitectureMap, def.Image.Arch)
+ if err != nil {
+ return "", fmt.Errorf("Failed to translate the architecture name: %s", err)
+ }
+ } else if len(def.Mappings.Architectures) > 0 {
+ // Translate the architecture using a user specified mapping
+ var ok bool
+ arch, ok = def.Mappings.Architectures[def.Image.Arch]
+ if !ok {
+ // If no mapping exists, it means it doesn't need translating
+ arch = def.Image.Arch
+ }
+ } else {
+ // No map or mappings provided, just go with it as it is
+ arch = def.Image.Arch
+ }
+
+ return arch, nil
+}
diff --git a/distrobuilder/main_build-dir.go b/distrobuilder/main_build-dir.go
new file mode 100644
index 0000000..416914d
--- /dev/null
+++ b/distrobuilder/main_build-dir.go
@@ -0,0 +1,20 @@
+package main
+
+import "github.com/spf13/cobra"
+
+type cmdBuildDir struct {
+ cmd *cobra.Command
+ global *cmdGlobal
+}
+
+func (c *cmdBuildDir) command() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "build-dir <filename|-> <target dir>",
+ Short: "Build plain rootfs",
+ Args: cobra.ExactArgs(2),
+ RunE: c.global.preRunBuild,
+ }
+
+ c.cmd = cmd
+ return cmd
+}
diff --git a/distrobuilder/main_lxc.go b/distrobuilder/main_lxc.go
new file mode 100644
index 0000000..40a1cd9
--- /dev/null
+++ b/distrobuilder/main_lxc.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "fmt"
+
+ "github.com/lxc/distrobuilder/generators"
+ "github.com/lxc/distrobuilder/image"
+ lxd "github.com/lxc/lxd/shared"
+ "github.com/spf13/cobra"
+)
+
+type cmdLXC struct {
+ cmdBuild *cobra.Command
+ cmdPack *cobra.Command
+ global *cmdGlobal
+}
+
+type cmdBuildLXC struct {
+ cmd *cobra.Command
+ global *cmdGlobal
+}
+
+func (c *cmdLXC) commandBuild() *cobra.Command {
+ c.cmdBuild = &cobra.Command{
+ Use: "build-lxc <filename|-> [target dir]",
+ Short: "Build LXC image from scratch",
+ Args: cobra.RangeArgs(1, 2),
+ PreRunE: c.global.preRunBuild,
+ RunE: c.run,
+ }
+ return c.cmdBuild
+}
+
+func (c *cmdLXC) commandPack() *cobra.Command {
+ c.cmdPack = &cobra.Command{
+ Use: "pack-lxc <filename|-> <source dir> [target dir]",
+ Short: "Create LXC image from existing rootfs",
+ Args: cobra.RangeArgs(2, 3),
+ PreRunE: c.global.preRunPack,
+ RunE: c.run,
+ }
+ return c.cmdPack
+}
+
+func (c *cmdLXC) run(cmd *cobra.Command, args []string) error {
+ img := image.NewLXCImage(c.global.sourceDir, c.global.targetDir,
+ c.global.flagCacheDir, c.global.definition.Image,
+ c.global.definition.Targets.LXC)
+
+ for _, file := range c.global.definition.Files {
+ generator := generators.Get(file.Generator)
+ if generator == nil {
+ return fmt.Errorf("Unknown generator '%s'", file.Generator)
+ }
+
+ if len(file.Releases) > 0 && !lxd.StringInSlice(
+ c.global.definition.Image.Release, file.Releases) {
+ continue
+ }
+
+ err := generator.CreateLXCData(c.global.flagCacheDir, file.Path, img)
+ if err != nil {
+ continue
+ }
+ }
+
+ err := img.Build()
+ if err != nil {
+ return fmt.Errorf("Failed to create LXC image: %s", err)
+ }
+
+ // Clean up the chroot by restoring the orginal files.
+ err = generators.RestoreFiles(c.global.flagCacheDir)
+ if err != nil {
+ return fmt.Errorf("Failed to restore cached files: %s", err)
+ }
+
+ return nil
+}
diff --git a/distrobuilder/main_lxd.go b/distrobuilder/main_lxd.go
new file mode 100644
index 0000000..e357877
--- /dev/null
+++ b/distrobuilder/main_lxd.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/lxc/distrobuilder/generators"
+ "github.com/lxc/distrobuilder/image"
+ lxd "github.com/lxc/lxd/shared"
+ "github.com/spf13/cobra"
+)
+
+type cmdLXD struct {
+ cmdBuild *cobra.Command
+ cmdPack *cobra.Command
+ global *cmdGlobal
+
+ flagType string
+ flagCompression string
+}
+
+func (c *cmdLXD) commandBuild() *cobra.Command {
+ c.cmdBuild = &cobra.Command{
+ Use: "build-lxd <filename|-> [target dir] [--type=TYPE] [--compression=COMPRESSION]",
+ Short: "Build LXD image from scratch",
+ Args: cobra.RangeArgs(1, 2),
+ PreRunE: func(cmd *cobra.Command, args []string) error {
+ if !lxd.StringInSlice(c.flagType, []string{"split", "unified"}) {
+ return errors.New("--type needs to be one of ['split', 'unified']")
+ }
+
+ return c.global.preRunBuild(cmd, args)
+ },
+ RunE: c.run,
+ }
+
+ c.cmdBuild.Flags().StringVar(&c.flagType, "type", "split", "Type of tarball to create")
+ c.cmdBuild.Flags().StringVar(&c.flagCompression, "compression", "xz", "Type of compression to use")
+
+ return c.cmdBuild
+}
+
+func (c *cmdLXD) commandPack() *cobra.Command {
+ c.cmdPack = &cobra.Command{
+ Use: "pack-lxd <filename|-> <source dir> [target dir] [--type=TYPE] [--compression=COMPRESSION]",
+ Short: "Create LXD image from existing rootfs",
+ Args: cobra.RangeArgs(2, 3),
+ PreRunE: func(cmd *cobra.Command, args []string) error {
+ if !lxd.StringInSlice(c.flagType, []string{"split", "unified"}) {
+ return errors.New("--type needs to be one of ['split', 'unified']")
+ }
+
+ return c.global.preRunPack(cmd, args)
+ },
+ RunE: c.run,
+ }
+
+ c.cmdPack.Flags().StringVar(&c.flagType, "type", "split", "Type of tarball to create")
+ c.cmdPack.Flags().StringVar(&c.flagCompression, "compression", "xz", "Type of compression to use")
+
+ return c.cmdPack
+}
+
+func (c *cmdLXD) run(cmd *cobra.Command, args []string) error {
+ img := image.NewLXDImage(c.global.sourceDir, c.global.targetDir,
+ c.global.flagCacheDir, c.global.definition.Image)
+
+ for _, file := range c.global.definition.Files {
+ if len(file.Releases) > 0 && !lxd.StringInSlice(c.global.definition.Image.Release,
+ file.Releases) {
+ continue
+ }
+
+ generator := generators.Get(file.Generator)
+ if generator == nil {
+ return fmt.Errorf("Unknown generator '%s'", file.Generator)
+ }
+
+ err := generator.CreateLXDData(c.global.sourceDir, file.Path, img)
+ if err != nil {
+ return fmt.Errorf("Failed to create LXD data: %s", err)
+ }
+ }
+
+ err := img.Build(c.flagType == "unified")
+ if err != nil {
+ return fmt.Errorf("Failed to create LXD image: %s", err)
+ }
+
+ return nil
+}
diff --git a/generators/hostname_test.go b/generators/hostname_test.go
index be7f9fe..b2c00ed 100644
--- a/generators/hostname_test.go
+++ b/generators/hostname_test.go
@@ -25,7 +25,7 @@ func TestHostnameGeneratorCreateLXCData(t *testing.T) {
Release: "artful",
}
- image := image.NewLXCImage(cacheDir, definition, shared.DefinitionTargetLXC{})
+ image := image.NewLXCImage(cacheDir, "", cacheDir, definition, shared.DefinitionTargetLXC{})
err := os.MkdirAll(filepath.Join(cacheDir, "rootfs", "etc"), 0755)
if err != nil {
@@ -66,7 +66,7 @@ func TestHostnameGeneratorCreateLXDData(t *testing.T) {
Release: "artful",
}
- image := image.NewLXDImage(cacheDir, definition)
+ image := image.NewLXDImage(cacheDir, "", cacheDir, definition)
err := os.MkdirAll(filepath.Join(cacheDir, "rootfs", "etc"), 0755)
if err != nil {
diff --git a/generators/hosts_test.go b/generators/hosts_test.go
index 4571276..f29da90 100644
--- a/generators/hosts_test.go
+++ b/generators/hosts_test.go
@@ -25,7 +25,7 @@ func TestHostsGeneratorCreateLXCData(t *testing.T) {
Release: "artful",
}
- image := image.NewLXCImage(cacheDir, definition, shared.DefinitionTargetLXC{})
+ image := image.NewLXCImage(cacheDir, "", cacheDir, definition, shared.DefinitionTargetLXC{})
err := os.MkdirAll(filepath.Join(cacheDir, "rootfs", "etc"), 0755)
if err != nil {
@@ -70,7 +70,7 @@ func TestHostsGeneratorCreateLXDData(t *testing.T) {
Release: "artful",
}
- image := image.NewLXDImage(cacheDir, definition)
+ image := image.NewLXDImage(cacheDir, "", cacheDir, definition)
err := os.MkdirAll(filepath.Join(cacheDir, "rootfs", "etc"), 0755)
if err != nil {
diff --git a/image/lxc.go b/image/lxc.go
index 64d0ceb..e3e1513 100644
--- a/image/lxc.go
+++ b/image/lxc.go
@@ -15,15 +15,19 @@ import (
// LXCImage represents a LXC image.
type LXCImage struct {
+ sourceDir string
+ targetDir string
cacheDir string
definition shared.DefinitionImage
target shared.DefinitionTargetLXC
}
// NewLXCImage returns a LXCImage.
-func NewLXCImage(cacheDir string, definition shared.DefinitionImage,
+func NewLXCImage(sourceDir, targetDir, cacheDir string, definition shared.DefinitionImage,
target shared.DefinitionTargetLXC) *LXCImage {
img := LXCImage{
+ sourceDir,
+ targetDir,
cacheDir,
definition,
target,
@@ -69,7 +73,7 @@ func (l *LXCImage) Build() error {
return err
}
- err = shared.Pack("rootfs.tar.xz", l.cacheDir, "rootfs")
+ err = shared.Pack(filepath.Join(l.targetDir, "rootfs.tar.xz"), l.sourceDir, "rootfs")
if err != nil {
return err
}
@@ -103,8 +107,8 @@ func (l *LXCImage) createMetadata() error {
var excludesUser string
- if lxd.PathExists(filepath.Join(l.cacheDir, "rootfs", "dev")) {
- err := filepath.Walk(filepath.Join(l.cacheDir, "rootfs", "dev"),
+ if lxd.PathExists(filepath.Join(l.sourceDir, "rootfs", "dev")) {
+ err := filepath.Walk(filepath.Join(l.sourceDir, "rootfs", "dev"),
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@@ -112,7 +116,7 @@ func (l *LXCImage) createMetadata() error {
if info.Mode()&os.ModeDevice != 0 {
excludesUser += fmt.Sprintf("%s\n",
- strings.TrimPrefix(path, filepath.Join(l.cacheDir, "rootfs")))
+ strings.TrimPrefix(path, filepath.Join(l.sourceDir, "rootfs")))
}
return nil
@@ -138,7 +142,8 @@ func (l *LXCImage) packMetadata() error {
files = append(files, "templates")
}
- err := shared.Pack("meta.tar.xz", filepath.Join(l.cacheDir, "metadata"), files...)
+ err := shared.Pack(filepath.Join(l.targetDir, "meta.tar.xz"),
+ filepath.Join(l.cacheDir, "metadata"), files...)
if err != nil {
return fmt.Errorf("Failed to create metadata: %s", err)
}
diff --git a/image/lxc_test.go b/image/lxc_test.go
index 803d73b..9271176 100644
--- a/image/lxc_test.go
+++ b/image/lxc_test.go
@@ -38,7 +38,7 @@ func lxcCacheDir() string {
}
func setupLXC() *LXCImage {
- return NewLXCImage(lxcCacheDir(), lxcImageDef, lxcTarget)
+ return NewLXCImage(lxcCacheDir(), "", lxcCacheDir(), lxcImageDef, lxcTarget)
}
func teardownLXC() {
@@ -46,7 +46,7 @@ func teardownLXC() {
}
func TestNewLXCImage(t *testing.T) {
- image := NewLXCImage(lxcCacheDir(), lxcImageDef, lxcTarget)
+ image := NewLXCImage(lxcCacheDir(), "", lxcCacheDir(), lxcImageDef, lxcTarget)
defer teardownLXC()
if image.cacheDir != lxcCacheDir() {
diff --git a/image/lxd.go b/image/lxd.go
index f04b6c6..8449e7e 100644
--- a/image/lxd.go
+++ b/image/lxd.go
@@ -15,6 +15,8 @@ import (
// A LXDImage represents a LXD image.
type LXDImage struct {
+ sourceDir string
+ targetDir string
cacheDir string
creationDate time.Time
Metadata api.ImageMetadata
@@ -22,8 +24,11 @@ type LXDImage struct {
}
// NewLXDImage returns a LXDImage.
-func NewLXDImage(cacheDir string, imageDef shared.DefinitionImage) *LXDImage {
+func NewLXDImage(sourceDir, targetDir, cacheDir string,
+ imageDef shared.DefinitionImage) *LXDImage {
return &LXDImage{
+ sourceDir,
+ targetDir,
cacheDir,
time.Now(),
api.ImageMetadata{
@@ -41,7 +46,7 @@ func (l *LXDImage) Build(unified bool) error {
return nil
}
- file, err := os.Create(filepath.Join(l.cacheDir, "metadata.yaml"))
+ file, err := os.Create(filepath.Join(l.sourceDir, "metadata.yaml"))
if err != nil {
return err
}
@@ -60,7 +65,7 @@ func (l *LXDImage) Build(unified bool) error {
paths := []string{"metadata.yaml"}
// Only include templates directory in the tarball if it's present.
- info, err := os.Stat(filepath.Join(l.cacheDir, "templates"))
+ info, err := os.Stat(filepath.Join(l.sourceDir, "templates"))
if err == nil && info.IsDir() {
paths = append(paths, "templates")
}
@@ -81,20 +86,21 @@ func (l *LXDImage) Build(unified bool) error {
}
paths = append(paths, "rootfs")
- err = shared.Pack(fmt.Sprintf("%s.tar.xz", fname), l.cacheDir, paths...)
+ err = shared.Pack(filepath.Join(l.targetDir, fmt.Sprintf("%s.tar.xz", fname)),
+ l.sourceDir, paths...)
if err != nil {
return err
}
} else {
// Create rootfs as squashfs.
- err = shared.RunCommand("mksquashfs", filepath.Join(l.cacheDir, "rootfs"),
- "rootfs.squashfs", "-noappend")
+ err = shared.RunCommand("mksquashfs", filepath.Join(l.sourceDir, "rootfs"),
+ filepath.Join(l.targetDir, "rootfs.squashfs"), "-noappend")
if err != nil {
return err
}
// Create metadata tarball.
- err = shared.Pack("lxd.tar.xz", l.cacheDir, paths...)
+ err = shared.Pack(filepath.Join(l.targetDir, "lxd.tar.xz"), l.sourceDir, paths...)
if err != nil {
return err
}
diff --git a/image/lxd_test.go b/image/lxd_test.go
index a855de1..a10237b 100644
--- a/image/lxd_test.go
+++ b/image/lxd_test.go
@@ -36,7 +36,7 @@ func setupLXD(t *testing.T) *LXDImage {
t.Fatalf("Failed to create templates directory: %s", err)
}
- image := NewLXDImage(cacheDir, lxdImageDef)
+ image := NewLXDImage(cacheDir, "", cacheDir, lxdImageDef)
// Override creation date
image.creationDate = time.Date(2006, 1, 2, 3, 4, 5, 0, time.UTC)
More information about the lxc-devel
mailing list