1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package sources
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"github.com/sylabs/singularity/v4/pkg/build/types"
"github.com/sylabs/singularity/v4/pkg/sylog"
)
// BusyBoxConveyor only needs to hold the conveyor to have the needed data to pack
type BusyBoxConveyor struct {
b *types.Bundle
}
// BusyBoxConveyorPacker only needs to hold the conveyor to have the needed data to pack
type BusyBoxConveyorPacker struct {
BusyBoxConveyor
}
// Get just stores the source
//
// FIXME: use context for cancellation.
func (c *BusyBoxConveyor) Get(_ context.Context, b *types.Bundle) (err error) {
c.b = b
// get mirrorURL, OSVerison, and Includes components to definition
mirrorurl, ok := b.Recipe.Header["mirrorurl"]
if !ok {
return fmt.Errorf("invalid busybox header, no mirrur url specified")
}
err = c.insertBaseEnv()
if err != nil {
return fmt.Errorf("while inserting base environment: %v", err)
}
err = c.insertBaseFiles()
if err != nil {
return fmt.Errorf("while inserting files: %v", err)
}
busyBoxPath, err := c.insertBusyBox(mirrorurl)
if err != nil {
return fmt.Errorf("while inserting busybox: %v", err)
}
cmd := exec.Command(busyBoxPath, `--install`, filepath.Join(c.b.RootfsPath, "/bin"))
sylog.Debugf("\n\tBusyBox Path: %s\n\tMirrorURL: %s\n", busyBoxPath, mirrorurl)
err = cmd.Run()
if err != nil {
return fmt.Errorf("while performing busybox install: %v", err)
}
return nil
}
// Pack puts relevant objects in a Bundle!
func (cp *BusyBoxConveyorPacker) Pack(context.Context) (b *types.Bundle, err error) {
err = cp.insertRunScript()
if err != nil {
return nil, fmt.Errorf("while inserting base environment: %v", err)
}
return cp.b, nil
}
func (c *BusyBoxConveyor) insertBaseFiles() error {
if err := os.WriteFile(filepath.Join(c.b.RootfsPath, "/etc/passwd"), []byte("root:!:0:0:root:/root:/bin/sh"), 0o664); err != nil {
return err
}
if err := os.WriteFile(filepath.Join(c.b.RootfsPath, "/etc/group"), []byte(" root:x:0:"), 0o664); err != nil {
return err
}
return os.WriteFile(filepath.Join(c.b.RootfsPath, "/etc/hosts"), []byte("127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4"), 0o664)
}
func (c *BusyBoxConveyor) insertBusyBox(mirrorurl string) (busyBoxPath string, err error) {
os.Mkdir(filepath.Join(c.b.RootfsPath, "/bin"), 0o755)
resp, err := http.Get(mirrorurl)
if err != nil {
return "", fmt.Errorf("while performing http request: %v", err)
}
defer resp.Body.Close()
f, err := os.Create(filepath.Join(c.b.RootfsPath, "/bin/busybox"))
if err != nil {
return "", err
}
defer f.Close()
bytesWritten, err := io.Copy(f, resp.Body)
if err != nil {
return "", err
}
// Simple check to make sure file received is the correct size
if bytesWritten != resp.ContentLength {
return "", fmt.Errorf("file received is not the right size. supposed to be: %v actually: %v", resp.ContentLength, bytesWritten)
}
err = os.Chmod(f.Name(), 0o755)
if err != nil {
return "", err
}
return filepath.Join(c.b.RootfsPath, "/bin/busybox"), nil
}
func (c *BusyBoxConveyor) insertBaseEnv() (err error) {
if err = makeBaseEnv(c.b.RootfsPath); err != nil {
return
}
return nil
}
func (cp *BusyBoxConveyorPacker) insertRunScript() error {
return os.WriteFile(filepath.Join(cp.b.RootfsPath, "/.singularity.d/runscript"), []byte("#!/bin/sh\n"), 0o755)
}
// CleanUp removes any tmpfs owned by the conveyorPacker on the filesystem
func (c *BusyBoxConveyor) CleanUp() {
c.b.Remove()
}
|