github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/internal/packager/packing.go (about)

     1  package packager
     2  
     3  import (
     4  	"archive/tar"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"path/filepath"
     9  
    10  	"github.com/docker/app/internal"
    11  	"github.com/docker/app/types"
    12  	"github.com/docker/cli/cli/command"
    13  	"github.com/pkg/errors"
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  const (
    18  	// DefaultCNABBaseImageName is the name of the default base invocation image.
    19  	DefaultCNABBaseImageName = "docker/cnab-app-base"
    20  
    21  	dockerIgnore = "Dockerfile"
    22  )
    23  
    24  func tarAdd(tarout *tar.Writer, path, file string) error {
    25  	payload, err := ioutil.ReadFile(file)
    26  	if err != nil {
    27  		return err
    28  	}
    29  	return tarAddBytes(tarout, path, payload)
    30  }
    31  
    32  func tarAddBytes(tarout *tar.Writer, path string, payload []byte) error {
    33  	h := &tar.Header{
    34  		Name:     path,
    35  		Size:     int64(len(payload)),
    36  		Mode:     0644,
    37  		Typeflag: tar.TypeReg,
    38  	}
    39  	err := tarout.WriteHeader(h)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	_, err = tarout.Write(payload)
    44  	return err
    45  }
    46  
    47  // PackInvocationImageContext creates a Docker build context for building a CNAB invocation image
    48  func PackInvocationImageContext(cli command.Cli, app *types.App, target io.Writer) error {
    49  	logrus.Debug("Packing invocation image context")
    50  	tarout := tar.NewWriter(target)
    51  	defer tarout.Close()
    52  	prefix := fmt.Sprintf("%s%s/", app.Metadata().Name, internal.AppExtension)
    53  	if len(app.Composes()) != 1 {
    54  		return errors.New("app should have one and only one compose file")
    55  	}
    56  	if len(app.ParametersRaw()) != 1 {
    57  		return errors.New("app should have one and only one parameters file")
    58  	}
    59  	if err := tarAddBytes(tarout, "Dockerfile", []byte(dockerFile(cli))); err != nil {
    60  		return errors.Wrap(err, "failed to add Dockerfile to the invocation image build context")
    61  	}
    62  	if err := tarAddBytes(tarout, ".dockerignore", []byte(dockerIgnore)); err != nil {
    63  		return errors.Wrap(err, "failed to add .dockerignore to the invocation image build context")
    64  	}
    65  	if err := tarAddBytes(tarout, prefix+internal.MetadataFileName, app.MetadataRaw()); err != nil {
    66  		return errors.Wrapf(err, "failed to add %q to the invocation image build context", prefix+internal.MetadataFileName)
    67  	}
    68  	if err := tarAddBytes(tarout, prefix+internal.ComposeFileName, app.Composes()[0]); err != nil {
    69  		return errors.Wrapf(err, "failed to add %q to the invocation image build context", prefix+internal.ComposeFileName)
    70  	}
    71  	if err := tarAddBytes(tarout, prefix+internal.ParametersFileName, app.ParametersRaw()[0]); err != nil {
    72  		return errors.Wrapf(err, "failed to add %q to the invocation image build context", prefix+internal.ParametersFileName)
    73  	}
    74  	for _, attachment := range app.Attachments() {
    75  		if err := tarAdd(tarout, prefix+attachment.Path(), filepath.Join(app.Path, attachment.Path())); err != nil {
    76  			return errors.Wrapf(err, "failed to add attachment %q to the invocation image build context", prefix+attachment.Path())
    77  		}
    78  	}
    79  	return nil
    80  }
    81  
    82  // BaseInvocationImage returns the name and tag of the CNAB base invocation image
    83  func BaseInvocationImage(cli command.Cli) string {
    84  	img := DefaultCNABBaseImageName + `:` + internal.Version
    85  	if cfg := cli.ConfigFile(); cfg != nil {
    86  		if v, ok := cfg.PluginConfig("app", "base-invocation-image"); ok {
    87  			return v
    88  		}
    89  	}
    90  	return img
    91  }
    92  
    93  func dockerFile(cli command.Cli) string {
    94  	return fmt.Sprintf("FROM %s\nCOPY . .", BaseInvocationImage(cli))
    95  }