github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/build/sources/conveyorPacker_debootstrap.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  	"os"
    11  	"os/exec"
    12  	"runtime"
    13  	"strings"
    14  
    15  	"github.com/sylabs/singularity/internal/pkg/sylog"
    16  	"github.com/sylabs/singularity/pkg/build/types"
    17  )
    18  
    19  // DebootstrapConveyorPacker holds stuff that needs to be packed into the bundle
    20  type DebootstrapConveyorPacker struct {
    21  	b         *types.Bundle
    22  	mirrorurl string
    23  	osversion string
    24  	include   string
    25  }
    26  
    27  // Get downloads container information from the specified source
    28  func (cp *DebootstrapConveyorPacker) Get(b *types.Bundle) (err error) {
    29  	cp.b = b
    30  
    31  	// check for debootstrap on system(script using "singularity_which" not sure about its importance)
    32  	debootstrapPath, err := exec.LookPath("debootstrap")
    33  	if err != nil {
    34  		return fmt.Errorf("debootstrap is not in PATH... Perhaps 'apt-get install' it: %v", err)
    35  	}
    36  
    37  	if err = cp.getRecipeHeaderInfo(); err != nil {
    38  		return err
    39  	}
    40  
    41  	if os.Getuid() != 0 {
    42  		return fmt.Errorf("You must be root to build with debootstrap")
    43  	}
    44  
    45  	// run debootstrap command
    46  	cmd := exec.Command(debootstrapPath, `--variant=minbase`, `--exclude=openssl,udev,debconf-i18n,e2fsprogs`, `--include=apt,`+cp.include, `--arch=`+runtime.GOARCH, cp.osversion, cp.b.Rootfs(), cp.mirrorurl)
    47  	cmd.Stdout = os.Stdout
    48  	cmd.Stderr = os.Stderr
    49  
    50  	sylog.Debugf("\n\tDebootstrap Path: %s\n\tIncludes: apt(default),%s\n\tDetected Arch: %s\n\tOSVersion: %s\n\tMirrorURL: %s\n", debootstrapPath, cp.include, runtime.GOARCH, cp.osversion, cp.mirrorurl)
    51  
    52  	// run debootstrap
    53  	if err = cmd.Run(); err != nil {
    54  		return fmt.Errorf("While debootstrapping: %v", err)
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  // Pack puts relevant objects in a Bundle!
    61  func (cp *DebootstrapConveyorPacker) Pack() (*types.Bundle, error) {
    62  
    63  	//change root directory permissions to 0755
    64  	if err := os.Chmod(cp.b.Rootfs(), 0755); err != nil {
    65  		return nil, fmt.Errorf("While changing bundle rootfs perms: %v", err)
    66  	}
    67  
    68  	err := cp.insertBaseEnv(cp.b)
    69  	if err != nil {
    70  		return nil, fmt.Errorf("While inserting base environtment: %v", err)
    71  	}
    72  
    73  	err = cp.insertRunScript(cp.b)
    74  	if err != nil {
    75  		return nil, fmt.Errorf("While inserting runscript: %v", err)
    76  	}
    77  
    78  	return cp.b, nil
    79  }
    80  
    81  func (cp *DebootstrapConveyorPacker) getRecipeHeaderInfo() (err error) {
    82  	var ok bool
    83  
    84  	//get mirrorURL, OSVerison, and Includes components to definition
    85  	cp.mirrorurl, ok = cp.b.Recipe.Header["mirrorurl"]
    86  	if !ok {
    87  		return fmt.Errorf("Invalid debootstrap header, no MirrorURL specified")
    88  	}
    89  
    90  	cp.osversion, ok = cp.b.Recipe.Header["osversion"]
    91  	if !ok {
    92  		return fmt.Errorf("Invalid debootstrap header, no OSVersion specified")
    93  	}
    94  
    95  	include, _ := cp.b.Recipe.Header["include"]
    96  
    97  	//check for include environment variable and add it to requires string
    98  	include += ` ` + os.Getenv("INCLUDE")
    99  
   100  	//trim leading and trailing whitespace
   101  	include = strings.TrimSpace(include)
   102  
   103  	//convert Requires string to comma separated list
   104  	cp.include = strings.Replace(include, ` `, `,`, -1)
   105  
   106  	return nil
   107  }
   108  
   109  func (cp *DebootstrapConveyorPacker) insertBaseEnv(b *types.Bundle) (err error) {
   110  	if err = makeBaseEnv(b.Rootfs()); err != nil {
   111  		return
   112  	}
   113  	return nil
   114  }
   115  
   116  func (cp *DebootstrapConveyorPacker) insertRunScript(b *types.Bundle) (err error) {
   117  	f, err := os.Create(b.Rootfs() + "/.singularity.d/runscript")
   118  	if err != nil {
   119  		return
   120  	}
   121  
   122  	defer f.Close()
   123  
   124  	_, err = f.WriteString("#!/bin/sh\n")
   125  	if err != nil {
   126  		return
   127  	}
   128  
   129  	if err != nil {
   130  		return
   131  	}
   132  
   133  	f.Sync()
   134  
   135  	err = os.Chmod(b.Rootfs()+"/.singularity.d/runscript", 0755)
   136  	if err != nil {
   137  		return
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  // CleanUp removes any tmpfs owned by the conveyorPacker on the filesystem
   144  func (cp *DebootstrapConveyorPacker) CleanUp() {
   145  	os.RemoveAll(cp.b.Path)
   146  }