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