Skip to content

Commit

Permalink
Merge pull request #263 from buildpacks/fix/local-options
Browse files Browse the repository at this point in the history
Consolidate image options in imgutil package
  • Loading branch information
natalieparellano authored Apr 11, 2024
2 parents a57a66c + 41cd6e4 commit 9478f0a
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 152 deletions.
18 changes: 9 additions & 9 deletions layout/layout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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)

Expand All @@ -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())
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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")
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion layout/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
65 changes: 20 additions & 45 deletions layout/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
6 changes: 3 additions & 3 deletions layout/sparse/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)
Expand Down
2 changes: 1 addition & 1 deletion local/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
45 changes: 10 additions & 35 deletions local/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
58 changes: 58 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
v1 "github.com/google/go-containerregistry/pkg/v1"
)

type ImageOption func(*ImageOptions)

type ImageOptions struct {
BaseImageRepoName string
PreviousImageRepoName string
Expand Down Expand Up @@ -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
}
}
2 changes: 1 addition & 1 deletion remote/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 9478f0a

Please sign in to comment.