github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/build/sources/conveyorPacker_busybox.go (about)

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