github.com/cnabio/duffle@v0.0.0-20220503153733-cf7397b1463c/pkg/packager/export_test.go (about)

     1  package packager
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"reflect"
     8  	"sort"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/cnabio/cnab-go/bundle/loader"
    13  
    14  	"github.com/cnabio/duffle/pkg/imagestore"
    15  	"github.com/cnabio/duffle/pkg/imagestore/imagestoremocks"
    16  )
    17  
    18  func TestExport(t *testing.T) {
    19  	source, err := filepath.Abs(filepath.Join("testdata", "examplebun", "bundle.json"))
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	tempDir, tempPWD, pwd, err := setupExportTestEnvironment()
    24  	if err != nil {
    25  		t.Fatal(err)
    26  	}
    27  	defer func() {
    28  		os.RemoveAll(tempDir)
    29  		os.Chdir(pwd)
    30  		os.RemoveAll(tempPWD)
    31  	}()
    32  
    33  	imagesAdded := []string{}
    34  
    35  	is := &imagestoremocks.MockStore{
    36  		AddStub: func(im string) (string, error) {
    37  			imagesAdded = append(imagesAdded, im)
    38  			return "", nil
    39  		},
    40  	}
    41  
    42  	ex := Exporter{
    43  		source: source,
    44  		imageStoreConstructor: func(option ...imagestore.Option) (store imagestore.Store, e error) {
    45  			parms := imagestore.CreateParams(option...)
    46  			const expectedPrefix = "examplebun-0.1.0"
    47  			configArchiveDirBase := filepath.Base(parms.ArchiveDir)
    48  			if !strings.HasPrefix(configArchiveDirBase, expectedPrefix) {
    49  				t.Errorf("expected archive ending in %s, got %s", expectedPrefix, configArchiveDirBase)
    50  			}
    51  			return is, nil
    52  		},
    53  		logs:   filepath.Join(tempDir, "export-logs"),
    54  		loader: loader.NewLoader(),
    55  	}
    56  
    57  	if err := ex.Export(); err != nil {
    58  		t.Errorf("Expected no error, got error: %v", err)
    59  	}
    60  
    61  	expectedImagesAdded := []string{"mock/examplebun:0.1.0", "mock/image-a:58326809e0p19b79054015bdd4e93e84b71ae1ta", "mock/image-b:88426103e0p19b38554015bd34e93e84b71de2fc"}
    62  	sort.Strings(expectedImagesAdded)
    63  	sort.Strings(imagesAdded)
    64  	if !reflect.DeepEqual(imagesAdded, expectedImagesAdded) {
    65  		t.Errorf("ImageStore.add was called with %v; expected %v", imagesAdded, expectedImagesAdded)
    66  	}
    67  
    68  	expectedFile := "examplebun-0.1.0.tgz"
    69  	_, err = os.Stat(expectedFile)
    70  	if err != nil && os.IsNotExist(err) {
    71  		t.Errorf("Expected %s to exist but was not created", expectedFile)
    72  	} else if err != nil {
    73  		t.Errorf("Error with compressed bundle file: %v", err)
    74  	}
    75  }
    76  
    77  func TestExportCreatesFileProperly(t *testing.T) {
    78  	tempDir, err := setupTempDir()
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	defer os.RemoveAll(tempDir)
    83  
    84  	imagesAdded := []string{}
    85  
    86  	is := &imagestoremocks.MockStore{
    87  		AddStub: func(im string) (string, error) {
    88  			imagesAdded = append(imagesAdded, im)
    89  			return "", nil
    90  		},
    91  	}
    92  
    93  	ex := Exporter{
    94  		source:      "testdata/examplebun/bundle.json",
    95  		destination: filepath.Join(tempDir, "random-directory", "examplebun-whatev.tgz"),
    96  		imageStoreConstructor: func(option ...imagestore.Option) (store imagestore.Store, e error) {
    97  			parms := imagestore.CreateParams(option...)
    98  			const expectedPrefix = "examplebun-0.1.0"
    99  			configArchiveDirBase := filepath.Base(parms.ArchiveDir)
   100  			if !strings.HasPrefix(configArchiveDirBase, expectedPrefix) {
   101  				t.Errorf("expected archive ending in %s, got %s", expectedPrefix, configArchiveDirBase)
   102  			}
   103  			return is, nil
   104  		},
   105  		logs:   filepath.Join(tempDir, "export-logs"),
   106  		loader: loader.NewLoader(),
   107  	}
   108  
   109  	if err := ex.Export(); err == nil {
   110  		t.Error("Expected path does not exist error, got no error")
   111  	}
   112  
   113  	expectedImagesAdded := []string{"mock/examplebun:0.1.0", "mock/image-a:58326809e0p19b79054015bdd4e93e84b71ae1ta", "mock/image-b:88426103e0p19b38554015bd34e93e84b71de2fc"}
   114  	sort.Strings(expectedImagesAdded)
   115  	sort.Strings(imagesAdded)
   116  	if !reflect.DeepEqual(imagesAdded, expectedImagesAdded) {
   117  		t.Errorf("ImageStore.add was called with %v; expected %v", imagesAdded, expectedImagesAdded)
   118  	}
   119  
   120  	if err := os.MkdirAll(filepath.Join(tempDir, "random-directory"), 0755); err != nil {
   121  		t.Fatal(err)
   122  	}
   123  
   124  	if err := ex.Export(); err != nil {
   125  		t.Errorf("Expected no error, got error: %s", err)
   126  	}
   127  
   128  	expectedFile := filepath.Join(tempDir, "random-directory", "examplebun-whatev.tgz")
   129  	_, err = os.Stat(expectedFile)
   130  	if err != nil && os.IsNotExist(err) {
   131  		t.Errorf("Expected %s to exist but was not created", expectedFile)
   132  	} else if err != nil {
   133  		t.Errorf("Error with compressed bundle archive: %v", err)
   134  	}
   135  }
   136  
   137  func TestExportDigestMismatch(t *testing.T) {
   138  	source, err := filepath.Abs(filepath.Join("testdata", "examplebun", "bundle.json"))
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  	tempDir, tempPWD, pwd, err := setupExportTestEnvironment()
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	defer func() {
   147  		os.RemoveAll(tempDir)
   148  		os.Chdir(pwd)
   149  		os.RemoveAll(tempPWD)
   150  	}()
   151  
   152  	is := &imagestoremocks.MockStore{
   153  		AddStub: func(im string) (string, error) {
   154  			// return the same digest for all images, but only one of them has a digest in the bundle manifest so just
   155  			// that one will fail verification
   156  			return "sha256:222222228fb14266b7c0461ef1ef0b2f8c05f41cd544987a259a9d92cdad2540", nil
   157  		},
   158  	}
   159  
   160  	ex := Exporter{
   161  		source: source,
   162  		imageStoreConstructor: func(...imagestore.Option) (store imagestore.Store, e error) {
   163  			return is, nil
   164  		},
   165  		logs:   filepath.Join(tempDir, "export-logs"),
   166  		loader: loader.NewLoader(),
   167  	}
   168  
   169  	if err := ex.Export(); err.Error() != "Error preparing artifacts: content digest mismatch: image mock/image-a:"+
   170  		"58326809e0p19b79054015bdd4e93e84b71ae1ta has digest "+
   171  		"sha256:222222228fb14266b7c0461ef1ef0b2f8c05f41cd544987a259a9d92cdad2540 but the digest should be "+
   172  		"sha256:111111118fb14266b7c0461ef1ef0b2f8c05f41cd544987a259a9d92cdad2540 according to the bundle manifest" {
   173  		t.Errorf("Unexpected error: %v", err)
   174  	}
   175  }
   176  
   177  func setupTempDir() (string, error) {
   178  	tempDir, err := ioutil.TempDir("", "duffle-export-test")
   179  	if err != nil {
   180  		return "", err
   181  	}
   182  	return tempDir, nil
   183  }
   184  
   185  func setupPWD() (string, string, error) {
   186  	tempPWD, err := ioutil.TempDir("", "duffle-export-test")
   187  	if err != nil {
   188  		return "", "", err
   189  	}
   190  	pwd, err := os.Getwd()
   191  	if err != nil {
   192  		return "", "", err
   193  	}
   194  	if err := os.Chdir(tempPWD); err != nil {
   195  		return "", "", err
   196  	}
   197  
   198  	return tempPWD, pwd, nil
   199  }
   200  
   201  func setupExportTestEnvironment() (string, string, string, error) {
   202  	tempDir, err := setupTempDir()
   203  	if err != nil {
   204  		return "", "", "", err
   205  	}
   206  
   207  	tempPWD, pwd, err := setupPWD()
   208  	if err != nil {
   209  		return "", "", "", err
   210  	}
   211  
   212  	return tempDir, tempPWD, pwd, nil
   213  }