[lxc-devel] [distrobuilder/master] Add Plamo Linux
monstermunchkin on Github
lxc-bot at linuxcontainers.org
Tue Mar 19 19:30:04 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 985 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190319/6889be34/attachment.bin>
-------------- next part --------------
From 5e2b51426d35fcc5fc299d6c2f99fa8901cd48d5 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Mon, 18 Mar 2019 16:05:27 +0100
Subject: [PATCH 1/5] shared: Add custom package manager
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
shared/definition.go | 82 ++++++++++++----
shared/definition_test.go | 199 ++++++++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+), 17 deletions(-)
diff --git a/shared/definition.go b/shared/definition.go
index b8d4ae7..a7da81e 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -30,13 +30,30 @@ type DefinitionPackagesRepository struct {
Releases []string `yaml:"release,omitmepty"` // Releases that this repo applies to
}
+// CustomManagerCmd represents a command for a custom manager.
+type CustomManagerCmd struct {
+ Command string `yaml:"cmd"`
+ Flags []string `yaml:"flags,omitempty"`
+}
+
+// DefinitionPackagesCustomManager represents a custom package manager.
+type DefinitionPackagesCustomManager struct {
+ Clean CustomManagerCmd `yaml:"clean"`
+ Install CustomManagerCmd `yaml:"install"`
+ Remove CustomManagerCmd `yaml:"remove"`
+ Refresh CustomManagerCmd `yaml:"refresh"`
+ Update CustomManagerCmd `yaml:"update"`
+ Flags []string `yaml:"flags,omitempty"`
+}
+
// A DefinitionPackages represents a package handler.
type DefinitionPackages struct {
- Manager string `yaml:"manager"`
- Update bool `yaml:"update,omitempty"`
- Cleanup bool `yaml:"cleanup,omitempty"`
- Sets []DefinitionPackagesSet `yaml:"sets,omitempty"`
- Repositories []DefinitionPackagesRepository `yaml:"repositories,omitempty"`
+ Manager string `yaml:"manager,omitempty"`
+ CustomManager *DefinitionPackagesCustomManager `yaml:"custom-manager,omitempty"`
+ Update bool `yaml:"update,omitempty"`
+ Cleanup bool `yaml:"cleanup,omitempty"`
+ Sets []DefinitionPackagesSet `yaml:"sets,omitempty"`
+ Repositories []DefinitionPackagesRepository `yaml:"repositories,omitempty"`
}
// A DefinitionImage represents the image.
@@ -241,23 +258,54 @@ func (d *Definition) Validate() error {
"docker-http",
"oraclelinux-http",
"opensuse-http",
+ "plamolinux-http",
}
if !shared.StringInSlice(strings.TrimSpace(d.Source.Downloader), validDownloaders) {
return fmt.Errorf("source.downloader must be one of %v", validDownloaders)
}
- validManagers := []string{
- "apk",
- "apt",
- "dnf",
- "pacman",
- "portage",
- "yum",
- "equo",
- "zypper",
- }
- if !shared.StringInSlice(strings.TrimSpace(d.Packages.Manager), validManagers) {
- return fmt.Errorf("packages.manager must be one of %v", validManagers)
+ if d.Packages.Manager != "" {
+ validManagers := []string{
+ "apk",
+ "apt",
+ "dnf",
+ "pacman",
+ "portage",
+ "yum",
+ "equo",
+ "zypper",
+ }
+ if !shared.StringInSlice(strings.TrimSpace(d.Packages.Manager), validManagers) {
+ return fmt.Errorf("packages.manager must be one of %v", validManagers)
+ }
+
+ if d.Packages.CustomManager != nil {
+ return fmt.Errorf("cannot have both packages.manager and packages.custom-manager set")
+ }
+ } else {
+ if d.Packages.CustomManager == nil {
+ return fmt.Errorf("packages.manager or packages.custom-manager needs to be set")
+ }
+
+ if d.Packages.CustomManager.Clean.Command == "" {
+ return fmt.Errorf("packages.custom-manager requires a clean command")
+ }
+
+ if d.Packages.CustomManager.Install.Command == "" {
+ return fmt.Errorf("packages.custom-manager requires an install command")
+ }
+
+ if d.Packages.CustomManager.Remove.Command == "" {
+ return fmt.Errorf("packages.custom-manager requires a remove command")
+ }
+
+ if d.Packages.CustomManager.Refresh.Command == "" {
+ return fmt.Errorf("packages.custom-manager requires a refresh command")
+ }
+
+ if d.Packages.CustomManager.Update.Command == "" {
+ return fmt.Errorf("packages.custom-manager requires an update command")
+ }
}
validGenerators := []string{
diff --git a/shared/definition_test.go b/shared/definition_test.go
index 49b6a6a..a4099d9 100644
--- a/shared/definition_test.go
+++ b/shared/definition_test.go
@@ -88,6 +88,39 @@ func TestValidateDefinition(t *testing.T) {
"",
false,
},
+ {
+ "valid Defintion with packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{
+ Install: CustomManagerCmd{
+ Command: "install",
+ },
+ Remove: CustomManagerCmd{
+ Command: "remove",
+ },
+ Clean: CustomManagerCmd{
+ Command: "clean",
+ },
+ Update: CustomManagerCmd{
+ Command: "update",
+ },
+ Refresh: CustomManagerCmd{
+ Command: "refresh",
+ },
+ },
+ },
+ },
+ "",
+ false,
+ },
{
"invalid ArchitectureMap",
Definition{
@@ -178,6 +211,172 @@ func TestValidateDefinition(t *testing.T) {
"packages.manager must be one of .+",
true,
},
+ {
+ "missing clean command in packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{},
+ },
+ },
+ "packages.custom-manager requires a clean command",
+ true,
+ },
+ {
+ "missing install command in packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{
+ Clean: CustomManagerCmd{
+ Command: "clean",
+ },
+ },
+ },
+ },
+ "packages.custom-manager requires an install command",
+ true,
+ },
+ {
+ "missing remove command in packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{
+ Clean: CustomManagerCmd{
+ Command: "clean",
+ },
+ Install: CustomManagerCmd{
+ Command: "install",
+ },
+ },
+ },
+ },
+ "packages.custom-manager requires a remove command",
+ true,
+ },
+ {
+ "missing refresh command in packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{
+ Clean: CustomManagerCmd{
+ Command: "clean",
+ },
+ Install: CustomManagerCmd{
+ Command: "install",
+ },
+ Remove: CustomManagerCmd{
+ Command: "remove",
+ },
+ },
+ },
+ },
+ "packages.custom-manager requires a refresh command",
+ true,
+ },
+ {
+ "missing update command in packages.custom-manager",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ CustomManager: &DefinitionPackagesCustomManager{
+ Clean: CustomManagerCmd{
+ Command: "clean",
+ },
+ Install: CustomManagerCmd{
+ Command: "install",
+ },
+ Remove: CustomManagerCmd{
+ Command: "remove",
+ },
+ Refresh: CustomManagerCmd{
+ Command: "refresh",
+ },
+ },
+ },
+ },
+ "packages.custom-manager requires an update command",
+ true,
+ },
+ {
+ "package.manager and package.custom-manager set",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{
+ Manager: "apt",
+ CustomManager: &DefinitionPackagesCustomManager{},
+ },
+ },
+ "cannot have both packages.manager and packages.custom-manager set",
+ true,
+ },
+ {
+ "package.manager and package.custom-manager unset",
+ Definition{
+ Image: DefinitionImage{
+ Distribution: "ubuntu",
+ Release: "artful",
+ },
+ Source: DefinitionSource{
+ Downloader: "debootstrap",
+ URL: "https://ubuntu.com",
+ Keys: []string{"0xCODE"},
+ },
+ Packages: DefinitionPackages{},
+ },
+ "packages.manager or packages.custom-manager needs to be set",
+ true,
+ },
{
"invalid action trigger",
Definition{
From de3d67bfedc024d92d416d69622273632dede151 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 Mar 2019 15:36:38 +0100
Subject: [PATCH 2/5] managers: Add custom package manager
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
managers/apk.go | 8 +++++++-
managers/apt.go | 8 +++++++-
managers/dnf.go | 8 +++++++-
managers/equo.go | 8 +++++++-
managers/manager.go | 42 ++++++++++++++++++++++++++++++++++++------
managers/pacman.go | 8 +++++++-
managers/portage.go | 8 +++++++-
managers/yum.go | 8 +++++++-
managers/zypper.go | 8 +++++++-
9 files changed, 92 insertions(+), 14 deletions(-)
diff --git a/managers/apk.go b/managers/apk.go
index b043289..7d77106 100644
--- a/managers/apk.go
+++ b/managers/apk.go
@@ -3,7 +3,13 @@ package managers
// NewApk creates a new Manager instance.
func NewApk() *Manager {
return &Manager{
- command: "apk",
+ commands: ManagerCommands{
+ clean: "apk",
+ install: "apk",
+ refresh: "apk",
+ remove: "apk",
+ update: "apk",
+ },
flags: ManagerFlags{
global: []string{
"--no-cache",
diff --git a/managers/apt.go b/managers/apt.go
index 8d63beb..22d7659 100644
--- a/managers/apt.go
+++ b/managers/apt.go
@@ -3,7 +3,13 @@ package managers
// NewApt creates a new Manager instance.
func NewApt() *Manager {
return &Manager{
- command: "apt-get",
+ commands: ManagerCommands{
+ clean: "apt-get",
+ install: "apt-get",
+ refresh: "apt-get",
+ remove: "apt-get",
+ update: "apt-get",
+ },
flags: ManagerFlags{
clean: []string{
"clean",
diff --git a/managers/dnf.go b/managers/dnf.go
index c575e8a..83d4e0a 100644
--- a/managers/dnf.go
+++ b/managers/dnf.go
@@ -3,7 +3,13 @@ package managers
// NewDnf creates a new Manager instance.
func NewDnf() *Manager {
return &Manager{
- command: "dnf",
+ commands: ManagerCommands{
+ clean: "dnf",
+ install: "dnf",
+ refresh: "dnf",
+ remove: "dnf",
+ update: "dnf",
+ },
flags: ManagerFlags{
global: []string{
"-y",
diff --git a/managers/equo.go b/managers/equo.go
index 1c9c6c1..2ae644c 100644
--- a/managers/equo.go
+++ b/managers/equo.go
@@ -40,7 +40,13 @@ func equoRepoCaller(repo shared.DefinitionPackagesRepository) error {
// NewEquo creates a new Manager instance
func NewEquo() *Manager {
return &Manager{
- command: "equo",
+ commands: ManagerCommands{
+ clean: "equo",
+ install: "equo",
+ refresh: "equo",
+ remove: "equo",
+ update: "equo",
+ },
flags: ManagerFlags{
global: []string{},
clean: []string{
diff --git a/managers/manager.go b/managers/manager.go
index 10f1d04..5823052 100644
--- a/managers/manager.go
+++ b/managers/manager.go
@@ -17,9 +17,18 @@ type ManagerHooks struct {
clean func() error
}
+// ManagerCommands represents all commands.
+type ManagerCommands struct {
+ clean string
+ install string
+ refresh string
+ remove string
+ update string
+}
+
// A Manager represents a package manager.
type Manager struct {
- command string
+ commands ManagerCommands
flags ManagerFlags
hooks ManagerHooks
RepoHandler func(repoAction shared.DefinitionPackagesRepository) error
@@ -49,6 +58,27 @@ func Get(name string) *Manager {
return nil
}
+// GetCustom returns a custom Manager specified by a Definition.
+func GetCustom(def shared.DefinitionPackagesCustomManager) *Manager {
+ return &Manager{
+ commands: ManagerCommands{
+ clean: def.Clean.Command,
+ install: def.Install.Command,
+ refresh: def.Refresh.Command,
+ remove: def.Remove.Command,
+ update: def.Update.Command,
+ },
+ flags: ManagerFlags{
+ clean: def.Clean.Flags,
+ install: def.Install.Flags,
+ refresh: def.Refresh.Flags,
+ remove: def.Remove.Flags,
+ update: def.Update.Flags,
+ global: def.Flags,
+ },
+ }
+}
+
// Install installs packages to the rootfs.
func (m Manager) Install(pkgs []string) error {
if len(m.flags.install) == 0 || pkgs == nil || len(pkgs) == 0 {
@@ -58,7 +88,7 @@ func (m Manager) Install(pkgs []string) error {
args := append(m.flags.global, m.flags.install...)
args = append(args, pkgs...)
- return shared.RunCommand(m.command, args...)
+ return shared.RunCommand(m.commands.install, args...)
}
// Remove removes packages from the rootfs.
@@ -70,7 +100,7 @@ func (m Manager) Remove(pkgs []string) error {
args := append(m.flags.global, m.flags.remove...)
args = append(args, pkgs...)
- return shared.RunCommand(m.command, args...)
+ return shared.RunCommand(m.commands.remove, args...)
}
// Clean cleans up cached files used by the package managers.
@@ -83,7 +113,7 @@ func (m Manager) Clean() error {
args := append(m.flags.global, m.flags.clean...)
- err = shared.RunCommand(m.command, args...)
+ err = shared.RunCommand(m.commands.clean, args...)
if err != nil {
return err
}
@@ -103,7 +133,7 @@ func (m Manager) Refresh() error {
args := append(m.flags.global, m.flags.refresh...)
- return shared.RunCommand(m.command, args...)
+ return shared.RunCommand(m.commands.refresh, args...)
}
// Update updates all packages.
@@ -114,7 +144,7 @@ func (m Manager) Update() error {
args := append(m.flags.global, m.flags.update...)
- return shared.RunCommand(m.command, args...)
+ return shared.RunCommand(m.commands.update, args...)
}
// SetInstallFlags overrides the default install flags.
diff --git a/managers/pacman.go b/managers/pacman.go
index 2b67c7d..6247386 100644
--- a/managers/pacman.go
+++ b/managers/pacman.go
@@ -26,7 +26,13 @@ func NewPacman() *Manager {
}
return &Manager{
- command: "pacman",
+ commands: ManagerCommands{
+ clean: "pacman",
+ install: "pacman",
+ refresh: "pacman",
+ remove: "pacman",
+ update: "pacman",
+ },
flags: ManagerFlags{
clean: []string{
"-Sc",
diff --git a/managers/portage.go b/managers/portage.go
index dd12dbb..d29bbe1 100644
--- a/managers/portage.go
+++ b/managers/portage.go
@@ -3,7 +3,13 @@ package managers
// NewPortage creates a new Manager instance.
func NewPortage() *Manager {
return &Manager{
- command: "emerge",
+ commands: ManagerCommands{
+ clean: "emerge",
+ install: "emerge",
+ refresh: "emerge",
+ remove: "emerge",
+ update: "emerge",
+ },
flags: ManagerFlags{
global: []string{},
clean: []string{},
diff --git a/managers/yum.go b/managers/yum.go
index 0016107..767fd32 100644
--- a/managers/yum.go
+++ b/managers/yum.go
@@ -3,7 +3,13 @@ package managers
// NewYum creates a new Manager instance.
func NewYum() *Manager {
return &Manager{
- command: "yum",
+ commands: ManagerCommands{
+ clean: "yum",
+ install: "yum",
+ refresh: "yum",
+ remove: "yum",
+ update: "yum",
+ },
flags: ManagerFlags{
clean: []string{
"clean", "all",
diff --git a/managers/zypper.go b/managers/zypper.go
index 6f54213..936d8d0 100644
--- a/managers/zypper.go
+++ b/managers/zypper.go
@@ -3,7 +3,13 @@ package managers
// NewZypper create a new Manager instance.
func NewZypper() *Manager {
return &Manager{
- command: "zypper",
+ commands: ManagerCommands{
+ clean: "zypper",
+ install: "zypper",
+ refresh: "zypper",
+ remove: "zypper",
+ update: "zypper",
+ },
flags: ManagerFlags{
global: []string{
"--non-interactive",
From 89461ddae71924a758783338c3dc187fdc08ab4f Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 Mar 2019 19:35:28 +0100
Subject: [PATCH 3/5] chroot: Support custom package manager
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
distrobuilder/chroot.go | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/distrobuilder/chroot.go b/distrobuilder/chroot.go
index 2485da8..cd3c45a 100644
--- a/distrobuilder/chroot.go
+++ b/distrobuilder/chroot.go
@@ -12,10 +12,15 @@ import (
func managePackages(def shared.DefinitionPackages, actions []shared.DefinitionAction,
release string, architecture string) error {
var err error
+ var manager *managers.Manager
- manager := managers.Get(def.Manager)
- if manager == nil {
- return fmt.Errorf("Couldn't get manager")
+ if def.Manager != "" {
+ manager = managers.Get(def.Manager)
+ if manager == nil {
+ return fmt.Errorf("Couldn't get manager")
+ }
+ } else {
+ manager = managers.GetCustom(*def.CustomManager)
}
// Handle repositories actions
From 75a050ad3c279f2adb4f75127c3ba1dbf83599bc Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 Mar 2019 19:38:07 +0100
Subject: [PATCH 4/5] sources: Add Plamo Linux
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
sources/plamolinux-http.go | 137 +++++++++++++++++++++++++++++++++++++
sources/source.go | 2 +
2 files changed, 139 insertions(+)
create mode 100644 sources/plamolinux-http.go
diff --git a/sources/plamolinux-http.go b/sources/plamolinux-http.go
new file mode 100644
index 0000000..a4751fa
--- /dev/null
+++ b/sources/plamolinux-http.go
@@ -0,0 +1,137 @@
+package sources
+
+import (
+ "fmt"
+ "net/url"
+ "path"
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "gopkg.in/antchfx/htmlquery.v1"
+
+ "github.com/lxc/distrobuilder/shared"
+)
+
+// PlamoLinuxHTTP represents the Plamo Linux downloader.
+type PlamoLinuxHTTP struct {
+}
+
+// NewPlamoLinuxHTTP creates a new PlamoLinuxHTTP instance.
+func NewPlamoLinuxHTTP() *PlamoLinuxHTTP {
+ return &PlamoLinuxHTTP{}
+}
+
+// Run downloads Plamo Linux.
+func (s *PlamoLinuxHTTP) Run(definition shared.Definition, rootfsDir string) error {
+ release, err := strconv.Atoi(definition.Image.Release)
+ if err != nil {
+ return fmt.Errorf("Failed to determine release: %v", err)
+ }
+
+ u, err := url.Parse(definition.Source.URL)
+ if err != nil {
+ return err
+ }
+
+ mirrorPath := path.Join(u.Path, fmt.Sprintf("Plamo-%s.x", definition.Image.Release),
+ definition.Image.ArchitectureMapped, "plamo")
+
+ paths := []string{
+ path.Join(mirrorPath, "00_base"),
+ }
+
+ if release < 7 {
+ paths = append(paths, path.Join(mirrorPath, "01_minimum"))
+
+ }
+
+ var pkgDir string
+
+ for _, p := range paths {
+ u.Path = p
+
+ pkgDir, err = s.downloadFiles(definition.Image, u.String())
+ if err != nil {
+ return fmt.Errorf("Failed to download packages: %v", err)
+ }
+ }
+
+ var pkgTool string
+
+ // Find package tool
+ if release < 7 {
+ pkgTool = "hdsetup"
+ } else {
+ pkgTool = "pkgtools"
+ }
+
+ matches, err := filepath.Glob(filepath.Join(pkgDir, fmt.Sprintf("%s-*.txz", pkgTool)))
+ if err != nil {
+ return err
+ }
+
+ if len(matches) == 0 {
+ return fmt.Errorf("Couldn't find any matching package")
+ } else if len(matches) > 1 {
+ return fmt.Errorf("Found more than one matching package")
+ }
+
+ err = shared.RunCommand("tar", "-pxJf", matches[0], "-C", rootfsDir, "sbin/")
+ if err != nil {
+ return err
+ }
+
+ return shared.RunScript(fmt.Sprintf(`#!/bin/sh
+
+dlcache=%s
+rootfs_dir=%s
+
+sed -i "/ldconfig/!s@/sbin@$rootfs_dir&@g" $rootfs_dir/sbin/installpkg*
+PATH=$rootfs_dir/sbin:$PATH
+export LC_ALL=C
+
+for p in $(ls -cr $dlcache/*.t?z) ; do
+ installpkg -root $rootfs_dir -priority ADD $p
+done
+`, pkgDir, rootfsDir))
+}
+
+func (s *PlamoLinuxHTTP) downloadFiles(def shared.DefinitionImage, URL string) (string, error) {
+ doc, err := htmlquery.LoadURL(URL)
+ if err != nil {
+ return "", err
+ }
+
+ if doc == nil {
+ return "", fmt.Errorf("Failed to load URL")
+ }
+
+ nodes := htmlquery.Find(doc, `//a/@href`)
+
+ var dir string
+
+ for _, n := range nodes {
+ target := htmlquery.InnerText(n)
+
+ if strings.HasSuffix(target, ".txz") {
+ // package
+ dir, err = shared.DownloadHash(def, fmt.Sprintf("%s/%s", URL, target), "", nil)
+ if err != nil {
+ return "", err
+ }
+ } else if strings.HasSuffix(target, ".txz/") {
+ // directory
+ u, err := url.Parse(URL)
+ if err != nil {
+ return "", err
+ }
+
+ u.Path = path.Join(u.Path, target)
+
+ return s.downloadFiles(def, u.String())
+ }
+ }
+
+ return dir, nil
+}
diff --git a/sources/source.go b/sources/source.go
index a284e68..2d4bc3b 100644
--- a/sources/source.go
+++ b/sources/source.go
@@ -32,6 +32,8 @@ func Get(name string) Downloader {
return NewOracleLinuxHTTP()
case "opensuse-http":
return NewOpenSUSEHTTP()
+ case "plamolinux-http":
+ return NewPlamoLinuxHTTP()
}
return nil
From e83298b7fa4e614ddf4ddd5052f078ede133b4d7 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 19 Mar 2019 19:40:07 +0100
Subject: [PATCH 5/5] doc: Add Plamo Linux example
Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
doc/examples/plamolinux | 62 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 doc/examples/plamolinux
diff --git a/doc/examples/plamolinux b/doc/examples/plamolinux
new file mode 100644
index 0000000..b782776
--- /dev/null
+++ b/doc/examples/plamolinux
@@ -0,0 +1,62 @@
+image:
+ distribution: plamolinux
+ release: 7
+ description: Plamo Linux
+ expiry: 30d
+ architecture: x86_64
+
+source:
+ downloader: plamolinux-http
+ url: https://repository.plamolinux.org/pub/linux/Plamo
+
+targets:
+ lxc:
+ create-message: |
+ You just created a Plamo Linux container (release={{ image.release }}, arch={{ image.architecture }})
+
+ config:
+ - type: all
+ before: 5
+ content: |-
+ lxc.include = LXC_TEMPLATE_CONFIG/plamolinux.common.conf
+
+ - type: user
+ before: 5
+ content: |-
+ lxc.include = LXC_TEMPLATE_CONFIG/plamolinux.userns.conf
+
+ - type: all
+ after: 4
+ content: |-
+ lxc.include = LXC_TEMPLATE_CONFIG/common.conf
+
+ - type: user
+ after: 4
+ content: |-
+ lxc.include = LXC_TEMPLATE_CONFIG/userns.conf
+
+ - type: all
+ content: |-
+ lxc.arch = {{ image.architecture_kernel }}
+
+files:
+ - name: hostname
+ path: /etc/hostname
+ generator: hostname
+
+ - name: hosts
+ path: /etc/hosts
+ generator: hosts
+
+packages:
+ custom-manager:
+ install:
+ cmd: installpkg
+ remove:
+ cmd: removepkg
+ update:
+ cmd: updatepkg
+ clean:
+ cmd: true
+ refresh:
+ cmd: true
More information about the lxc-devel
mailing list