-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
385 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
package machine | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
"github.com/c3os-io/c3os/internal/utils" | ||
"github.com/hashicorp/go-multierror" | ||
) | ||
|
||
type BundleConfig struct { | ||
Target string | ||
Repository string | ||
DBPath string | ||
RootPath string | ||
} | ||
|
||
// bundles needs to ship only /config/... (etc) and /bin/... (will go to /usr/local/bin) | ||
type BundleOption func(bc *BundleConfig) error | ||
|
||
func (bc *BundleConfig) Apply(opts ...BundleOption) error { | ||
for _, o := range opts { | ||
if err := o(bc); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func WithDBHPath(r string) BundleOption { | ||
return func(bc *BundleConfig) error { | ||
bc.DBPath = r | ||
return nil | ||
} | ||
} | ||
|
||
func WithRootFS(r string) BundleOption { | ||
return func(bc *BundleConfig) error { | ||
bc.RootPath = r | ||
return nil | ||
} | ||
} | ||
|
||
func WithRepository(r string) BundleOption { | ||
return func(bc *BundleConfig) error { | ||
bc.Repository = r | ||
return nil | ||
} | ||
} | ||
|
||
func WithTarget(p string) BundleOption { | ||
return func(bc *BundleConfig) error { | ||
bc.Target = p | ||
return nil | ||
} | ||
} | ||
|
||
func (bc *BundleConfig) extractRepo() (string, string) { | ||
s := strings.Split(bc.Repository, ":") | ||
return s[0], s[1] | ||
} | ||
|
||
// XXX: directly to rootfs ? or maybe better to /usr/local/.c3os/rootfs and handle symlinks? | ||
func defaultConfig() *BundleConfig { | ||
return &BundleConfig{ | ||
DBPath: "/usr/local/.c3os/db", | ||
RootPath: "/", | ||
Repository: "quay.io/c3os/packages", | ||
} | ||
} | ||
|
||
type BundleInstaller interface { | ||
Install(*BundleConfig) error | ||
} | ||
|
||
// TODO: | ||
// - Make provider consume bundles when bins are not detected in the rootfs | ||
// - Default bundles preset in case of no binaries detected and version specified via config. | ||
|
||
func RunBundles(bundles ...[]BundleOption) error { | ||
var resErr error | ||
for _, b := range bundles { | ||
config := defaultConfig() | ||
config.Apply(b...) | ||
|
||
installer, err := NewBundleInstaller(*config) | ||
if err != nil { | ||
resErr = multierror.Append(err) | ||
continue | ||
} | ||
dat := strings.Split(config.Target, ":") | ||
if len(dat) != 2 { | ||
resErr = multierror.Append(fmt.Errorf("invalid target")) | ||
|
||
continue | ||
} | ||
config.Target = dat[1] | ||
|
||
err = installer.Install(config) | ||
if err != nil { | ||
resErr = multierror.Append(err) | ||
continue | ||
} | ||
} | ||
|
||
return resErr | ||
} | ||
|
||
func NewBundleInstaller(bc BundleConfig) (BundleInstaller, error) { | ||
|
||
dat := strings.Split(bc.Target, ":") | ||
if len(dat) != 2 { | ||
return nil, fmt.Errorf("could not decode scheme") | ||
} | ||
switch strings.ToLower(dat[0]) { | ||
case "container": | ||
return &ContainerInstaller{}, nil | ||
case "run": | ||
return &ContainerRunner{}, nil | ||
case "package": | ||
return &LuetInstaller{}, nil | ||
|
||
} | ||
|
||
return &LuetInstaller{}, nil | ||
} | ||
|
||
// BundleInstall installs a bundle from a luet repo or a container image | ||
type ContainerRunner struct{} | ||
|
||
func (l *ContainerRunner) Install(config *BundleConfig) error { | ||
|
||
tempDir, err := ioutil.TempDir("", "containerrunner") | ||
if err != nil { | ||
return err | ||
} | ||
defer os.RemoveAll(tempDir) | ||
|
||
out, err := utils.SH( | ||
fmt.Sprintf( | ||
`luet util unpack %s %s`, | ||
config.Target, | ||
tempDir, | ||
), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("could not unpack container: %w - %s", err, out) | ||
} | ||
|
||
out, err = utils.SH(fmt.Sprintf("CONTAINERDIR=%s %s/run.sh", tempDir, tempDir)) | ||
if err != nil { | ||
return fmt.Errorf("could not execute container: %w - %s", err, out) | ||
} | ||
return nil | ||
} | ||
|
||
type ContainerInstaller struct{} | ||
|
||
func (l *ContainerInstaller) Install(config *BundleConfig) error { | ||
|
||
//mkdir -p test/etc/luet/repos.conf.d | ||
_, err := utils.SH( | ||
fmt.Sprintf( | ||
`luet util unpack %s %s`, | ||
config.Target, | ||
config.RootPath, | ||
), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("could not add repository: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type LuetInstaller struct{} | ||
|
||
func (l *LuetInstaller) Install(config *BundleConfig) error { | ||
|
||
t, repo := config.extractRepo() | ||
//mkdir -p test/etc/luet/repos.conf.d | ||
_, err := utils.SH( | ||
fmt.Sprintf( | ||
`LUET_CONFIG_FROM_HOST=false luet repo add --system-dbpath %s --system-target %s c3os-system -y --description "Automatically generated c3os-system" --url "%s" --type "%s"`, | ||
config.DBPath, | ||
config.RootPath, | ||
repo, | ||
t, | ||
), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("could not add repository: %w", err) | ||
} | ||
_, err = utils.SH( | ||
fmt.Sprintf( | ||
`LUET_CONFIG_FROM_HOST=false luet repo update -f --system-dbpath %s --system-target %s`, | ||
config.DBPath, | ||
config.RootPath, | ||
), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("could not sync repository: %w", err) | ||
} | ||
_, err = utils.SH( | ||
fmt.Sprintf( | ||
`LUET_CONFIG_FROM_HOST=false luet install -y --system-dbpath %s --system-target %s %s`, | ||
config.DBPath, | ||
config.RootPath, | ||
config.Target, | ||
), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("could not sync repository: %w", err) | ||
} | ||
|
||
// copy bins to /usr/local/bin | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.