diff --git a/layout/layout_test.go b/layout/layout_test.go index 63e4832b..d12dd986 100644 --- a/layout/layout_test.go +++ b/layout/layout_test.go @@ -146,7 +146,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { }) }) - when("#FromBaseImage", func() { + when("#FromBaseImageInstance", func() { when("no platform is specified", func() { when("base image is provided", func() { it.Before(func() { @@ -157,7 +157,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { it("sets the initial state from a linux/arm base image", func() { existingLayerSha := "sha256:5a0b973aa300cd2650869fd76d8546b361fcd6dfc77bd37b9d4f082cca9874e4" - img, err := layout.NewImage(imagePath, layout.FromBaseImage(testImage), layout.WithMediaTypes(imgutil.OCITypes)) + img, err := layout.NewImage(imagePath, layout.FromBaseImageInstance(testImage), layout.WithMediaTypes(imgutil.OCITypes)) h.AssertNil(t, err) h.AssertOCIMediaTypes(t, img) @@ -181,7 +181,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { when("base image does not exist", func() { it("returns an empty image", func() { - img, err := layout.NewImage(imagePath, layout.FromBaseImage(nil)) + img, err := layout.NewImage(imagePath, layout.FromBaseImageInstance(nil)) h.AssertNil(t, err) h.AssertOCIMediaTypes(t, img) @@ -584,7 +584,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { testImgPath := filepath.Join(tmpDir, "new-test-image") testImg, err := layout.NewImage( testImgPath, - layout.FromBaseImage(img), + layout.FromBaseImageInstance(img), ) h.AssertNil(t, err) @@ -609,7 +609,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { var baseImageNamePath = filepath.Join(tmpDir, "my-base-image") it.Before(func() { - baseImage, err := layout.NewImage(baseImageNamePath, layout.FromBaseImage(testImage)) + baseImage, err := layout.NewImage(baseImageNamePath, layout.FromBaseImageInstance(testImage)) h.AssertNil(t, err) h.AssertNil(t, baseImage.SetLabel("custom.label", "new-val")) h.AssertNil(t, baseImage.Save()) @@ -641,7 +641,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { testImgPath := filepath.Join(tmpDir, "new-test-image") testImg, err := layout.NewImage( testImgPath, - layout.FromBaseImage(img), + layout.FromBaseImageInstance(img), ) h.AssertNil(t, err) @@ -707,14 +707,14 @@ func testImage(t *testing.T, when spec.G, it spec.S) { os.RemoveAll(imagePath) }) - when("#FromBaseImage with full image", func() { + when("#FromBaseImageInstance with full image", func() { it.Before(func() { imagePath = filepath.Join(tmpDir, "save-from-base-image") }) when("additional names are provided", func() { it("creates an image and save it to both path provided", func() { - image, err := layout.NewImage(imagePath, layout.FromBaseImage(testImage)) + image, err := layout.NewImage(imagePath, layout.FromBaseImageInstance(testImage)) h.AssertNil(t, err) anotherPath := filepath.Join(tmpDir, "another-save-from-base-image") @@ -736,7 +736,7 @@ func testImage(t *testing.T, when spec.G, it spec.S) { when("no additional names are provided", func() { it("creates an image with all the layers from the underlying image", func() { - image, err := layout.NewImage(imagePath, layout.FromBaseImage(testImage)) + image, err := layout.NewImage(imagePath, layout.FromBaseImageInstance(testImage)) h.AssertNil(t, err) // save on disk in OCI diff --git a/layout/new.go b/layout/new.go index 8f3fdc25..240a930d 100644 --- a/layout/new.go +++ b/layout/new.go @@ -8,7 +8,7 @@ import ( "github.com/buildpacks/imgutil" ) -func NewImage(path string, ops ...ImageOption) (*Image, error) { +func NewImage(path string, ops ...imgutil.ImageOption) (*Image, error) { options := &imgutil.ImageOptions{} for _, op := range ops { op(options) diff --git a/layout/options.go b/layout/options.go index 6853a3cc..76da8f5e 100644 --- a/layout/options.go +++ b/layout/options.go @@ -8,75 +8,50 @@ import ( "github.com/buildpacks/imgutil" ) -type ImageOption func(*imgutil.ImageOptions) - -// FromBaseImage loads the provided image as the manifest, config, and layers for the working image. +// FromBaseImageInstance loads the provided image as the manifest, config, and layers for the working image. // If the image is not found, it does nothing. -func FromBaseImage(image v1.Image) func(*imgutil.ImageOptions) { +func FromBaseImageInstance(image v1.Image) func(*imgutil.ImageOptions) { return func(o *imgutil.ImageOptions) { o.BaseImage = image } } -// FromBaseImagePath (layout only) loads the image at the provided path as the manifest, config, and layers for the working image. -// If the image is not found, it does nothing. -func FromBaseImagePath(name string) func(*imgutil.ImageOptions) { +// WithoutLayersWhenSaved (layout only) if provided will cause the image to be written without layers in the `blobs` directory. +func WithoutLayersWhenSaved() func(*imgutil.ImageOptions) { return func(o *imgutil.ImageOptions) { - o.BaseImageRepoName = name + o.WithoutLayers = true } } -// WithConfig lets a caller provided a `config` object for the working image. +// FIXME: the following functions are defined in this package for backwards compatibility, +// and should eventually be deprecated. + +// FromBaseImagePath loads the image at the provided path as the manifest, config, and layers for the working image. +// If the image is not found, it does nothing. +func FromBaseImagePath(name string) func(*imgutil.ImageOptions) { + return imgutil.FromBaseImage(name) +} + func WithConfig(c *v1.Config) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.Config = c - } + return imgutil.WithConfig(c) } -// WithCreatedAt lets a caller set the "created at" timestamp for the working image when saved. -// If not provided, the default is imgutil.NormalizedDateTime. func WithCreatedAt(t time.Time) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.CreatedAt = t - } + return imgutil.WithCreatedAt(t) } -// WithDefaultPlatform provides the default Architecture/OS/OSVersion if no base image is provided, -// or if the provided image inputs (base and previous) are manifest lists. func WithDefaultPlatform(p imgutil.Platform) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.Platform = p - } + return imgutil.WithDefaultPlatform(p) } -// WithHistory if provided will configure the image to preserve history when saved -// (including any history from the base image if valid). func WithHistory() func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.PreserveHistory = true - } + return imgutil.WithHistory() } -// WithMediaTypes lets a caller set the desired media types for the manifest and config (including layers referenced in the manifest) -// to be either OCI media types or Docker media types. func WithMediaTypes(m imgutil.MediaTypes) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.MediaTypes = m - } + return imgutil.WithMediaTypes(m) } -// WithPreviousImage loads an existing image as the source for reusable layers. -// Use with ReuseLayer(). -// If the image is not found, it does nothing. func WithPreviousImage(name string) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.PreviousImageRepoName = name - } -} - -// WithoutLayersWhenSaved (layout only) if provided will cause the image to be written without layers in the `blobs` directory. -func WithoutLayersWhenSaved() func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.WithoutLayers = true - } + return imgutil.WithPreviousImage(name) } diff --git a/layout/sparse/new.go b/layout/sparse/new.go index 29c4d0c2..20bec079 100644 --- a/layout/sparse/new.go +++ b/layout/sparse/new.go @@ -8,12 +8,12 @@ import ( ) // NewImage returns a new Image saved on disk that can be modified -func NewImage(path string, from v1.Image, ops ...layout.ImageOption) (*layout.Image, error) { +func NewImage(path string, from v1.Image, ops ...imgutil.ImageOption) (*layout.Image, error) { preserveDigest := func(opts *imgutil.ImageOptions) { opts.PreserveDigest = true } - ops = append([]layout.ImageOption{ - layout.FromBaseImage(from), + ops = append([]imgutil.ImageOption{ + layout.FromBaseImageInstance(from), layout.WithoutLayersWhenSaved(), preserveDigest, }, ops...) diff --git a/local/new.go b/local/new.go index ebbc84f3..72c636fd 100644 --- a/local/new.go +++ b/local/new.go @@ -14,7 +14,7 @@ import ( // NewImage returns a new image that can be modified and saved to a docker daemon // via a tarball in legacy format. -func NewImage(repoName string, dockerClient DockerClient, ops ...func(*imgutil.ImageOptions)) (*Image, error) { +func NewImage(repoName string, dockerClient DockerClient, ops ...imgutil.ImageOption) (*Image, error) { options := &imgutil.ImageOptions{} for _, op := range ops { op(options) diff --git a/local/options.go b/local/options.go index 5dc52f14..82740066 100644 --- a/local/options.go +++ b/local/options.go @@ -8,58 +8,33 @@ import ( "github.com/buildpacks/imgutil" ) -// FromBaseImage loads the provided image as the manifest, config, and layers for the working image. -// If the image is not found, it does nothing. +// FIXME: the following functions are defined in this package for backwards compatibility, +// and should eventually be deprecated. + func FromBaseImage(name string) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.BaseImageRepoName = name - } + return imgutil.FromBaseImage(name) } -// WithConfig lets a caller provided a `config` object for the working image. func WithConfig(c *v1.Config) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.Config = c - } + return imgutil.WithConfig(c) } -// WithCreatedAt lets a caller set the "created at" timestamp for the working image when saved. -// If not provided, the default is imgutil.NormalizedDateTime. func WithCreatedAt(t time.Time) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.CreatedAt = t - } + return imgutil.WithCreatedAt(t) } -// WithDefaultPlatform provides the default Architecture/OS/OSVersion if no base image is provided, -// or if the provided image inputs (base and previous) are manifest lists. func WithDefaultPlatform(p imgutil.Platform) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.Platform = p - } + return imgutil.WithDefaultPlatform(p) } -// WithHistory if provided will configure the image to preserve history when saved -// (including any history from the base image if valid). func WithHistory() func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.PreserveHistory = true - } + return imgutil.WithHistory() } -// WithMediaTypes lets a caller set the desired media types for the manifest and config (including layers referenced in the manifest) -// to be either OCI media types or Docker media types. func WithMediaTypes(m imgutil.MediaTypes) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.MediaTypes = m - } + return imgutil.WithMediaTypes(m) } -// WithPreviousImage loads an existing image as the source for reusable layers. -// Use with ReuseLayer(). -// If the image is not found, it does nothing. func WithPreviousImage(name string) func(*imgutil.ImageOptions) { - return func(o *imgutil.ImageOptions) { - o.PreviousImageRepoName = name - } + return imgutil.WithPreviousImage(name) } diff --git a/options.go b/options.go index 33706eb1..e50e1eb4 100644 --- a/options.go +++ b/options.go @@ -6,6 +6,8 @@ import ( v1 "github.com/google/go-containerregistry/pkg/v1" ) +type ImageOption func(*ImageOptions) + type ImageOptions struct { BaseImageRepoName string PreviousImageRepoName string @@ -35,3 +37,59 @@ type RemoteOptions struct { type RegistrySetting struct { Insecure bool } + +// FromBaseImage loads the provided image as the manifest, config, and layers for the working image. +// If the image is not found, it does nothing. +func FromBaseImage(name string) func(*ImageOptions) { + return func(o *ImageOptions) { + o.BaseImageRepoName = name + } +} + +// WithConfig lets a caller provided a `config` object for the working image. +func WithConfig(c *v1.Config) func(*ImageOptions) { + return func(o *ImageOptions) { + o.Config = c + } +} + +// WithCreatedAt lets a caller set the "created at" timestamp for the working image when saved. +// If not provided, the default is NormalizedDateTime. +func WithCreatedAt(t time.Time) func(*ImageOptions) { + return func(o *ImageOptions) { + o.CreatedAt = t + } +} + +// WithDefaultPlatform provides the default Architecture/OS/OSVersion if no base image is provided, +// or if the provided image inputs (base and previous) are manifest lists. +func WithDefaultPlatform(p Platform) func(*ImageOptions) { + return func(o *ImageOptions) { + o.Platform = p + } +} + +// WithHistory if provided will configure the image to preserve history when saved +// (including any history from the base image if valid). +func WithHistory() func(*ImageOptions) { + return func(o *ImageOptions) { + o.PreserveHistory = true + } +} + +// WithMediaTypes lets a caller set the desired media types for the manifest and config (including layers referenced in the manifest) +// to be either OCI media types or Docker media types. +func WithMediaTypes(m MediaTypes) func(*ImageOptions) { + return func(o *ImageOptions) { + o.MediaTypes = m + } +} + +// WithPreviousImage loads an existing image as the source for reusable layers. +// Use with ReuseLayer(). +// If the image is not found, it does nothing. +func WithPreviousImage(name string) func(*ImageOptions) { + return func(o *ImageOptions) { + o.PreviousImageRepoName = name + } +} diff --git a/remote/new.go b/remote/new.go index 56c08ee2..dc3dd017 100644 --- a/remote/new.go +++ b/remote/new.go @@ -20,7 +20,7 @@ import ( ) // NewImage returns a new image that can be modified and saved to an OCI image registry. -func NewImage(repoName string, keychain authn.Keychain, ops ...func(*imgutil.ImageOptions)) (*Image, error) { +func NewImage(repoName string, keychain authn.Keychain, ops ...imgutil.ImageOption) (*Image, error) { options := &imgutil.ImageOptions{} for _, op := range ops { op(options) diff --git a/remote/options.go b/remote/options.go index cb6b2b4d..75b0e11d 100644 --- a/remote/options.go +++ b/remote/options.go @@ -8,85 +8,57 @@ import ( "github.com/buildpacks/imgutil" ) -type ImageOption func(o *imgutil.ImageOptions) - // AddEmptyLayerOnSave adds an empty layer before saving if the image has no layers at all. // This option is useful when exporting to registries that do not allow saving an image without layers, // for example: gcr.io. -func AddEmptyLayerOnSave() ImageOption { +func AddEmptyLayerOnSave() func(*imgutil.ImageOptions) { return func(o *imgutil.ImageOptions) { o.AddEmptyLayerOnSave = true } } -// FromBaseImage loads the provided image as the manifest, config, and layers for the working image. -// If the image is not found, it does nothing. -func FromBaseImage(name string) ImageOption { +// WithRegistrySetting registers options to use when accessing images in a registry +// in order to construct the image. +// The referenced images could include the base image, a previous image, or the image itself. +// The insecure parameter allows image references to be fetched without TLS. +func WithRegistrySetting(repository string, insecure bool) func(*imgutil.ImageOptions) { return func(o *imgutil.ImageOptions) { - o.BaseImageRepoName = name + if o.RegistrySettings == nil { + o.RegistrySettings = make(map[string]imgutil.RegistrySetting) + } + o.RegistrySettings[repository] = imgutil.RegistrySetting{ + Insecure: insecure, + } } } -// WithConfig lets a caller provided a `config` object for the working image. -func WithConfig(c *v1.Config) ImageOption { - return func(o *imgutil.ImageOptions) { - o.Config = c - } +// FIXME: the following functions are defined in this package for backwards compatibility, +// and should eventually be deprecated. + +func FromBaseImage(name string) func(*imgutil.ImageOptions) { + return imgutil.FromBaseImage(name) } -// WithCreatedAt lets a caller set the "created at" timestamp for the working image when saved. -// If not provided, the default is imgutil.NormalizedDateTime. -func WithCreatedAt(t time.Time) ImageOption { - return func(o *imgutil.ImageOptions) { - o.CreatedAt = t - } +func WithConfig(c *v1.Config) func(*imgutil.ImageOptions) { + return imgutil.WithConfig(c) } -// WithDefaultPlatform provides the default Architecture/OS/OSVersion if no base image is provided, -// or if the provided image inputs (base and previous) are manifest lists. -func WithDefaultPlatform(p imgutil.Platform) ImageOption { - return func(o *imgutil.ImageOptions) { - o.Platform = p - } +func WithCreatedAt(t time.Time) func(*imgutil.ImageOptions) { + return imgutil.WithCreatedAt(t) } -// WithHistory if provided will configure the image to preserve history when saved -// (including any history from the base image if valid). -func WithHistory() ImageOption { - return func(o *imgutil.ImageOptions) { - o.PreserveHistory = true - } +func WithDefaultPlatform(p imgutil.Platform) func(*imgutil.ImageOptions) { + return imgutil.WithDefaultPlatform(p) } -// WithMediaTypes lets a caller set the desired media types for the manifest and config (including layers referenced in the manifest) -// to be either OCI media types or Docker media types. -func WithMediaTypes(m imgutil.MediaTypes) ImageOption { - return func(o *imgutil.ImageOptions) { - o.MediaTypes = m - } +func WithHistory() func(*imgutil.ImageOptions) { + return imgutil.WithHistory() } -// WithPreviousImage loads an existing image as the source for reusable layers. -// Use with ReuseLayer(). -// If the image is not found, it does nothing. -func WithPreviousImage(name string) ImageOption { - return func(o *imgutil.ImageOptions) { - o.PreviousImageRepoName = name - } +func WithMediaTypes(m imgutil.MediaTypes) func(*imgutil.ImageOptions) { + return imgutil.WithMediaTypes(m) } -// WithRegistrySetting (remote only) registers options to use -// when accessing images in a registry -// in order to construct the image. -// The referenced images could include the base image, a previous image, or the image itself. -// The insecure parameter allows image references to be fetched without TLS. -func WithRegistrySetting(repository string, insecure bool) ImageOption { - return func(o *imgutil.ImageOptions) { - if o.RegistrySettings == nil { - o.RegistrySettings = make(map[string]imgutil.RegistrySetting) - } - o.RegistrySettings[repository] = imgutil.RegistrySetting{ - Insecure: insecure, - } - } +func WithPreviousImage(name string) func(*imgutil.ImageOptions) { + return imgutil.WithPreviousImage(name) }