github.com/buildpack/pack@v0.5.0/client.go (about)

     1  package pack
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  
     7  	"github.com/buildpack/imgutil"
     8  	imglocal "github.com/buildpack/imgutil/local"
     9  	"github.com/buildpack/imgutil/remote"
    10  	dockerClient "github.com/docker/docker/client"
    11  	"github.com/google/go-containerregistry/pkg/authn"
    12  	"github.com/pkg/errors"
    13  
    14  	"github.com/buildpack/pack/blob"
    15  	"github.com/buildpack/pack/build"
    16  	"github.com/buildpack/pack/config"
    17  	"github.com/buildpack/pack/image"
    18  	"github.com/buildpack/pack/logging"
    19  )
    20  
    21  type Client struct {
    22  	logger       logging.Logger
    23  	imageFetcher ImageFetcher
    24  	downloader   Downloader
    25  	lifecycle    Lifecycle
    26  	docker       *dockerClient.Client
    27  	imageFactory ImageFactory
    28  }
    29  
    30  type ClientOption func(c *Client)
    31  
    32  // WithLogger supply your own logger.
    33  func WithLogger(l logging.Logger) ClientOption {
    34  	return func(c *Client) {
    35  		c.logger = l
    36  	}
    37  }
    38  
    39  // WithImageFactory supply your own image factory.
    40  func WithImageFactory(f ImageFactory) ClientOption {
    41  	return func(c *Client) {
    42  		c.imageFactory = f
    43  	}
    44  }
    45  
    46  // WithFetcher supply your own fetcher.
    47  func WithFetcher(f ImageFetcher) ClientOption {
    48  	return func(c *Client) {
    49  		c.imageFetcher = f
    50  	}
    51  }
    52  
    53  // WithDownloader supply your own downloader.
    54  func WithDownloader(d Downloader) ClientOption {
    55  	return func(c *Client) {
    56  		c.downloader = d
    57  	}
    58  }
    59  
    60  // WithCacheDir supply your own cache directory.
    61  //
    62  // Deprecated: use WithDownloader instead.
    63  func WithCacheDir(path string) ClientOption {
    64  	return func(c *Client) {
    65  		c.downloader = blob.NewDownloader(c.logger, path)
    66  	}
    67  }
    68  
    69  // WithDockerClient supply your own docker client.
    70  func WithDockerClient(docker *dockerClient.Client) ClientOption {
    71  	return func(c *Client) {
    72  		c.docker = docker
    73  	}
    74  }
    75  
    76  func NewClient(opts ...ClientOption) (*Client, error) {
    77  	var client Client
    78  
    79  	for _, opt := range opts {
    80  		opt(&client)
    81  	}
    82  
    83  	if client.logger == nil {
    84  		client.logger = logging.New(os.Stderr)
    85  	}
    86  
    87  	if client.docker == nil {
    88  		var err error
    89  		client.docker, err = dockerClient.NewClientWithOpts(dockerClient.FromEnv, dockerClient.WithVersion("1.38"))
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  	}
    94  
    95  	if client.downloader == nil {
    96  		packHome, err := config.PackHome()
    97  		if err != nil {
    98  			return nil, errors.Wrap(err, "getting pack home")
    99  		}
   100  		client.downloader = blob.NewDownloader(client.logger, filepath.Join(packHome, "download-cache"))
   101  	}
   102  
   103  	if client.imageFetcher == nil {
   104  		client.imageFetcher = image.NewFetcher(client.logger, client.docker)
   105  	}
   106  
   107  	if client.imageFactory == nil {
   108  		client.imageFactory = &DefaultImageFactory{
   109  			dockerClient: client.docker,
   110  			keychain:     authn.DefaultKeychain,
   111  		}
   112  	}
   113  
   114  	client.lifecycle = build.NewLifecycle(client.docker, client.logger)
   115  
   116  	return &client, nil
   117  }
   118  
   119  type DefaultImageFactory struct {
   120  	dockerClient *dockerClient.Client
   121  	keychain     authn.Keychain
   122  }
   123  
   124  func (f *DefaultImageFactory) NewImage(repoName string, local bool) (imgutil.Image, error) {
   125  	if local {
   126  		return imglocal.NewImage(repoName, f.dockerClient)
   127  	}
   128  	return remote.NewImage(repoName, f.keychain)
   129  }