github.com/Datadog/cnab-go@v0.3.3-beta1.0.20191007143216-bba4b7e723d0/packager/import.go (about)

     1  package packager
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/deislabs/cnab-go/bundle"
    10  	"github.com/deislabs/cnab-go/bundle/loader"
    11  	"github.com/docker/docker/pkg/archive"
    12  )
    13  
    14  // Importer is responsible for importing a file
    15  type Importer struct {
    16  	Source      string
    17  	Destination string
    18  	Loader      loader.BundleLoader
    19  }
    20  
    21  // NewImporter creates a new secure *Importer
    22  //
    23  // source is the filesystem path to the archive.
    24  // destination is the directory to unpack the contents.
    25  // load is a loader.BundleLoader preconfigured for loading bundles.
    26  func NewImporter(source, destination string, load loader.BundleLoader) *Importer {
    27  	return &Importer{
    28  		Source:      source,
    29  		Destination: destination,
    30  		Loader:      load,
    31  	}
    32  }
    33  
    34  // Import decompresses a bundle from Source (location of the compressed bundle) and properly places artifacts in the correct location(s)
    35  func (im *Importer) Import() error {
    36  	_, _, err := im.Unzip()
    37  
    38  	// TODO: https://github.com/deislabs/cnab-go/issues/136
    39  
    40  	return err
    41  }
    42  
    43  // Unzip decompresses a bundle from Source (location of the compressed bundle) and returns the path of the bundle and the bundle itself.
    44  func (im *Importer) Unzip() (string, *bundle.Bundle, error) {
    45  	baseDir := strings.TrimSuffix(filepath.Base(im.Source), ".tgz")
    46  	dest := filepath.Join(im.Destination, baseDir)
    47  	if err := os.MkdirAll(dest, 0755); err != nil {
    48  		return "", nil, err
    49  	}
    50  
    51  	reader, err := os.Open(im.Source)
    52  	if err != nil {
    53  		return "", nil, err
    54  	}
    55  	defer reader.Close()
    56  
    57  	tarOptions := &archive.TarOptions{
    58  		Compression:      archive.Gzip,
    59  		IncludeFiles:     []string{"."},
    60  		IncludeSourceDir: true,
    61  		NoLchown:         true,
    62  	}
    63  	if err := archive.Untar(reader, dest, tarOptions); err != nil {
    64  		return "", nil, fmt.Errorf("untar failed: %s", err)
    65  	}
    66  
    67  	// We try to load a bundle.cnab file first, and fall back to a bundle.json
    68  	ext := "cnab"
    69  	if _, err := os.Stat(filepath.Join(dest, "bundle.cnab")); os.IsNotExist(err) {
    70  		ext = "json"
    71  	}
    72  
    73  	bun, err := im.Loader.Load(filepath.Join(dest, "bundle."+ext))
    74  	if err != nil {
    75  		removeErr := os.RemoveAll(dest)
    76  		if removeErr != nil {
    77  			return "", nil, fmt.Errorf("failed to load and validate bundle.%s on import %s and failed to remove invalid bundle from filesystem %s", ext, err, removeErr)
    78  		}
    79  		return "", nil, fmt.Errorf("failed to load and validate bundle.%s: %s", ext, err)
    80  	}
    81  	return dest, bun, nil
    82  }