github.com/apptainer/singularity@v3.1.1+incompatible/internal/pkg/build/sources/conveyorPacker_oci_test.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_test
     7  
     8  import (
     9  	"io"
    10  	"io/ioutil"
    11  	"log"
    12  	"net/http"
    13  	"os"
    14  	"os/exec"
    15  	"testing"
    16  
    17  	"github.com/sylabs/singularity/internal/pkg/build/sources"
    18  	"github.com/sylabs/singularity/internal/pkg/test"
    19  	"github.com/sylabs/singularity/pkg/build/types"
    20  	useragent "github.com/sylabs/singularity/pkg/util/user-agent"
    21  )
    22  
    23  const (
    24  	dockerURI         = "docker://alpine"
    25  	dockerArchiveURI  = "https://s3.amazonaws.com/singularity-ci-public/alpine-docker-save.tar"
    26  	ociArchiveURI     = "https://s3.amazonaws.com/singularity-ci-public/alpine-oci-archive.tar"
    27  	dockerDaemonImage = "alpine:latest"
    28  )
    29  
    30  func TestMain(m *testing.M) {
    31  	useragent.InitValue("singularity", "3.0.0-alpha.1-303-gaed8d30-dirty")
    32  
    33  	os.Exit(m.Run())
    34  }
    35  
    36  // TestOCIConveyorDocker tests if we can pull an alpine image from dockerhub
    37  func TestOCIConveyorDocker(t *testing.T) {
    38  	test.DropPrivilege(t)
    39  	defer test.ResetPrivilege(t)
    40  
    41  	b, err := types.NewBundle("", "sbuild-oci")
    42  	if err != nil {
    43  		return
    44  	}
    45  
    46  	b.Recipe, err = types.NewDefinitionFromURI(dockerURI)
    47  	if err != nil {
    48  		t.Fatalf("unable to parse URI %s: %v\n", dockerURI, err)
    49  	}
    50  
    51  	cp := &sources.OCIConveyorPacker{}
    52  
    53  	err = cp.Get(b)
    54  	// clean up tmpfs since assembler isnt called
    55  	defer cp.CleanUp()
    56  	if err != nil {
    57  		t.Fatalf("failed to Get from %s: %v\n", dockerURI, err)
    58  	}
    59  }
    60  
    61  // TestOCIConveyorDockerArchive tests if we can use a docker save archive
    62  // as a source
    63  func TestOCIConveyorDockerArchive(t *testing.T) {
    64  	test.DropPrivilege(t)
    65  	defer test.ResetPrivilege(t)
    66  
    67  	archive, err := getTestTar(dockerArchiveURI)
    68  	if err != nil {
    69  		t.Fatalf("Could not download docker archive test file: %v", err)
    70  	}
    71  	defer os.Remove(archive)
    72  
    73  	b, err := types.NewBundle("", "sbuild-oci")
    74  	if err != nil {
    75  		return
    76  	}
    77  
    78  	archiveURI := "docker-archive:" + archive
    79  	b.Recipe, err = types.NewDefinitionFromURI(archiveURI)
    80  	if err != nil {
    81  		t.Fatalf("unable to parse URI %s: %v\n", archiveURI, err)
    82  	}
    83  
    84  	cp := &sources.OCIConveyorPacker{}
    85  
    86  	err = cp.Get(b)
    87  	// clean up tmpfs since assembler isnt called
    88  	defer cp.CleanUp()
    89  	if err != nil {
    90  		t.Fatalf("failed to Get from %s: %v\n", archiveURI, err)
    91  	}
    92  }
    93  
    94  // TestOCIConveyerDockerDaemon tests if we can use an oci laytout dir
    95  // as a source
    96  func TestOCIConveyorDockerDaemon(t *testing.T) {
    97  	test.DropPrivilege(t)
    98  	defer test.ResetPrivilege(t)
    99  
   100  	cmd := exec.Command("docker", "ps")
   101  	err := cmd.Run()
   102  	if err != nil {
   103  		t.Logf("docker not available - skipping docker-daemon test")
   104  		return
   105  	}
   106  
   107  	cmd = exec.Command("docker", "pull", dockerDaemonImage)
   108  	err = cmd.Run()
   109  	if err != nil {
   110  		t.Fatalf("could not docker pull alpine:latest %v", err)
   111  		return
   112  	}
   113  
   114  	b, err := types.NewBundle("", "sbuild-oci")
   115  	if err != nil {
   116  		return
   117  	}
   118  
   119  	daemonURI := "docker-daemon:" + dockerDaemonImage
   120  	b.Recipe, err = types.NewDefinitionFromURI(daemonURI)
   121  	if err != nil {
   122  		t.Fatalf("unable to parse URI %s: %v\n", daemonURI, err)
   123  	}
   124  
   125  	cp := &sources.OCIConveyorPacker{}
   126  
   127  	err = cp.Get(b)
   128  	// clean up tmpfs since assembler isnt called
   129  	defer cp.CleanUp()
   130  	if err != nil {
   131  		t.Fatalf("failed to Get from %s: %v\n", daemonURI, err)
   132  	}
   133  }
   134  
   135  // TestOCIConveyorOCIArchive tests if we can use an oci archive
   136  // as a source
   137  func TestOCIConveyorOCIArchive(t *testing.T) {
   138  	test.DropPrivilege(t)
   139  	defer test.ResetPrivilege(t)
   140  
   141  	archive, err := getTestTar(ociArchiveURI)
   142  	if err != nil {
   143  		t.Fatalf("Could not download oci archive test file: %v", err)
   144  	}
   145  	defer os.Remove(archive)
   146  
   147  	b, err := types.NewBundle("", "sbuild-oci")
   148  	if err != nil {
   149  		return
   150  	}
   151  
   152  	archiveURI := "oci-archive:" + archive
   153  	b.Recipe, err = types.NewDefinitionFromURI(archiveURI)
   154  	if err != nil {
   155  		t.Fatalf("unable to parse URI %s: %v\n", archiveURI, err)
   156  	}
   157  
   158  	cp := &sources.OCIConveyorPacker{}
   159  
   160  	err = cp.Get(b)
   161  	// clean up tmpfs since assembler isnt called
   162  	defer cp.CleanUp()
   163  	if err != nil {
   164  		t.Fatalf("failed to Get from %s: %v\n", archiveURI, err)
   165  	}
   166  }
   167  
   168  // TestOCIConveyerOCILayout tests if we can use an oci layout dir
   169  // as a source
   170  func TestOCIConveyorOCILayout(t *testing.T) {
   171  	test.DropPrivilege(t)
   172  	defer test.ResetPrivilege(t)
   173  
   174  	archive, err := getTestTar(ociArchiveURI)
   175  	if err != nil {
   176  		t.Fatalf("Could not download oci archive test file: %v", err)
   177  	}
   178  	defer os.Remove(archive)
   179  
   180  	// We need to extract the oci archive to a directory
   181  	// Don't want to implement untar routines here, so use system tar
   182  	dir, err := ioutil.TempDir("", "oci-test")
   183  	if err != nil {
   184  		t.Fatalf("Could not create temporary directory: %v", err)
   185  	}
   186  	defer os.RemoveAll(dir)
   187  	cmd := exec.Command("tar", "-C", dir, "-xf", archive)
   188  	err = cmd.Run()
   189  	if err != nil {
   190  		t.Fatalf("Error extracting oci archive to layout: %v", err)
   191  	}
   192  
   193  	b, err := types.NewBundle("", "sbuild-oci")
   194  	if err != nil {
   195  		return
   196  	}
   197  
   198  	layoutURI := "oci:" + dir
   199  	b.Recipe, err = types.NewDefinitionFromURI(layoutURI)
   200  	if err != nil {
   201  		t.Fatalf("unable to parse URI %s: %v\n", layoutURI, err)
   202  	}
   203  
   204  	cp := &sources.OCIConveyorPacker{}
   205  
   206  	err = cp.Get(b)
   207  	// clean up tmpfs since assembler isnt called
   208  	defer cp.CleanUp()
   209  	if err != nil {
   210  		t.Fatalf("failed to Get from %s: %v\n", layoutURI, err)
   211  	}
   212  }
   213  
   214  // TestOCIPacker checks if we can create a Kitchen
   215  func TestOCIPacker(t *testing.T) {
   216  	test.DropPrivilege(t)
   217  	defer test.ResetPrivilege(t)
   218  
   219  	b, err := types.NewBundle("", "sbuild-oci")
   220  	if err != nil {
   221  		return
   222  	}
   223  
   224  	b.Recipe, err = types.NewDefinitionFromURI(dockerURI)
   225  	if err != nil {
   226  		t.Fatalf("unable to parse URI %s: %v\n", dockerURI, err)
   227  	}
   228  
   229  	ocp := &sources.OCIConveyorPacker{}
   230  
   231  	err = ocp.Get(b)
   232  	// clean up tmpfs since assembler isnt called
   233  	defer ocp.CleanUp()
   234  	if err != nil {
   235  		t.Fatalf("failed to Get from %s: %v\n", dockerURI, err)
   236  	}
   237  
   238  	_, err = ocp.Pack()
   239  
   240  	if err != nil {
   241  		t.Fatalf("failed to Pack from %s: %v\n", dockerURI, err)
   242  	}
   243  }
   244  
   245  func getTestTar(url string) (path string, err error) {
   246  	dl, err := ioutil.TempFile("", "oci-test")
   247  	if err != nil {
   248  		log.Fatal(err)
   249  	}
   250  	defer dl.Close()
   251  
   252  	r, err := http.Get(url)
   253  	if err != nil {
   254  		return "", err
   255  	}
   256  	defer r.Body.Close()
   257  
   258  	_, err = io.Copy(dl, r.Body)
   259  	if err != nil {
   260  		return "", err
   261  	}
   262  
   263  	return dl.Name(), nil
   264  }