github.com/docker/cnab-to-oci@v0.3.0-beta4/remotes/fixupoptions.go (about)

     1  package remotes
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  
     8  	"github.com/cnabio/cnab-go/bundle"
     9  	"github.com/containerd/containerd/platforms"
    10  	"github.com/containerd/containerd/remotes"
    11  	"github.com/docker/cnab-to-oci/internal"
    12  	"github.com/docker/cnab-to-oci/relocation"
    13  	"github.com/docker/distribution/reference"
    14  	ocischemav1 "github.com/opencontainers/image-spec/specs-go/v1"
    15  )
    16  
    17  const (
    18  	defaultMaxConcurrentJobs = 4
    19  	defaultJobsBufferLength  = 50
    20  )
    21  
    22  func noopEventCallback(FixupEvent) {}
    23  
    24  // fixupConfig defines the input required for a Fixup operation
    25  type fixupConfig struct {
    26  	bundle                        *bundle.Bundle
    27  	relocationMap                 relocation.ImageRelocationMap
    28  	targetRef                     reference.Named
    29  	eventCallback                 func(FixupEvent)
    30  	maxConcurrentJobs             int
    31  	jobsBufferLength              int
    32  	resolver                      remotes.Resolver
    33  	invocationImagePlatformFilter platforms.Matcher
    34  	componentImagePlatformFilter  platforms.Matcher
    35  	autoBundleUpdate              bool
    36  	pushImages                    bool
    37  	imageClient                   internal.ImageClient
    38  	pushOut                       io.Writer
    39  }
    40  
    41  // FixupOption is a helper for configuring a FixupBundle
    42  type FixupOption func(*fixupConfig) error
    43  
    44  func newFixupConfig(b *bundle.Bundle, ref reference.Named, resolver remotes.Resolver, options ...FixupOption) (fixupConfig, error) {
    45  	cfg := fixupConfig{
    46  		bundle:            b,
    47  		relocationMap:     relocation.ImageRelocationMap{},
    48  		targetRef:         ref,
    49  		resolver:          resolver,
    50  		eventCallback:     noopEventCallback,
    51  		jobsBufferLength:  defaultJobsBufferLength,
    52  		maxConcurrentJobs: defaultMaxConcurrentJobs,
    53  	}
    54  	for _, opt := range options {
    55  		if err := opt(&cfg); err != nil {
    56  			return fixupConfig{}, err
    57  		}
    58  	}
    59  	return cfg, nil
    60  }
    61  
    62  // WithInvocationImagePlatforms use filters platforms for an invocation image
    63  func WithInvocationImagePlatforms(supportedPlatforms []string) FixupOption {
    64  	return func(cfg *fixupConfig) error {
    65  		if len(supportedPlatforms) == 0 {
    66  			return nil
    67  		}
    68  		plats, err := toPlatforms(supportedPlatforms)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		cfg.invocationImagePlatformFilter = platforms.Any(plats...)
    73  		return nil
    74  	}
    75  }
    76  
    77  // WithComponentImagePlatforms use filters platforms for an invocation image
    78  func WithComponentImagePlatforms(supportedPlatforms []string) FixupOption {
    79  	return func(cfg *fixupConfig) error {
    80  		if len(supportedPlatforms) == 0 {
    81  			return nil
    82  		}
    83  		plats, err := toPlatforms(supportedPlatforms)
    84  		if err != nil {
    85  			return err
    86  		}
    87  		cfg.componentImagePlatformFilter = platforms.Any(plats...)
    88  		return nil
    89  	}
    90  }
    91  
    92  func toPlatforms(supportedPlatforms []string) ([]ocischemav1.Platform, error) {
    93  	result := make([]ocischemav1.Platform, len(supportedPlatforms))
    94  	for ix, p := range supportedPlatforms {
    95  		plat, err := platforms.Parse(p)
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  		result[ix] = plat
   100  	}
   101  	return result, nil
   102  }
   103  
   104  // WithEventCallback specifies a callback to execute for each Fixup event
   105  func WithEventCallback(callback func(FixupEvent)) FixupOption {
   106  	return func(cfg *fixupConfig) error {
   107  		cfg.eventCallback = callback
   108  		return nil
   109  	}
   110  }
   111  
   112  // WithParallelism provides a way to change the max concurrent jobs and the max number of jobs queued up
   113  func WithParallelism(maxConcurrentJobs int, jobsBufferLength int) FixupOption {
   114  	return func(cfg *fixupConfig) error {
   115  		cfg.maxConcurrentJobs = maxConcurrentJobs
   116  		cfg.jobsBufferLength = jobsBufferLength
   117  		return nil
   118  	}
   119  }
   120  
   121  // WithAutoBundleUpdate updates the bundle with content digests and size provided by the registry
   122  func WithAutoBundleUpdate() FixupOption {
   123  	return func(cfg *fixupConfig) error {
   124  		cfg.autoBundleUpdate = true
   125  		return nil
   126  	}
   127  }
   128  
   129  // WithPushImages authorizes the fixup command to push missing images.
   130  // By default the fixup will look at images defined in the bundle.
   131  // Existing images in the target registry or accessible from an other registry will be copied or mounted under the
   132  // target tag.
   133  // But local only images (for example after a local build of components of the bundle) must be pushed.
   134  // This option will allow to push images that are only available in the docker daemon image store to the defined target.
   135  func WithPushImages(imageClient internal.ImageClient, out io.Writer) FixupOption {
   136  	return func(cfg *fixupConfig) error {
   137  		cfg.pushImages = true
   138  		if imageClient == nil {
   139  			return fmt.Errorf("could not configure fixup, 'imageClient' cannot be nil to push images")
   140  		}
   141  		cfg.imageClient = imageClient
   142  		if out == nil {
   143  			cfg.pushOut = ioutil.Discard
   144  		} else {
   145  			cfg.pushOut = out
   146  		}
   147  		return nil
   148  	}
   149  }
   150  
   151  // WithRelocationMap stores a previously generated relocation map. This map will be used to copy or mount images
   152  // based on local images but already pushed on a registry.
   153  // This way if a bundle is pulled on a machine that doesn't contain the images, when the bundle is pushed and images
   154  // are not found the fixup will try to resolve the corresponding images from the relocation map.
   155  func WithRelocationMap(relocationMap relocation.ImageRelocationMap) FixupOption {
   156  	return func(cfg *fixupConfig) error {
   157  		cfg.relocationMap = relocationMap
   158  		return nil
   159  	}
   160  }