Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout wraps v1 image #243

Merged
merged 15 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 39 additions & 57 deletions cnb_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package imgutil
import (
"errors"
"fmt"
"io"
"strings"
"time"

Expand All @@ -18,26 +19,15 @@ import (
// The working image could be any v1.Image,
// but in practice will start off as a pointer to a locallayout.v1ImageFacade (or similar).
type CNBImageCore struct {
v1.Image // the working image
Store ImageStore
// required
repoName string
v1.Image // the working image
// optional
createdAt time.Time
preferredMediaTypes MediaTypes
preserveHistory bool
previousImage v1.Image
}

type ImageStore interface {
Contains(identifier string) bool
Delete(identifier string) error
Save(image IdentifiableV1Image, withName string, withAdditionalNames ...string) (string, error)
SaveFile(image IdentifiableV1Image, withName string) (string, error)

DownloadLayersFor(identifier string) error
Layers() []v1.Layer
}
Comment on lines -31 to -39
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally I thought this could be an interface that all packages could implement, but since most packages would override the methods that call this interface it's not so useful


type IdentifiableV1Image interface {
v1.Image
Identifier() (Identifier, error)
Expand All @@ -47,7 +37,7 @@ var _ v1.Image = &CNBImageCore{}

// FIXME: mark deprecated methods as deprecated on the interface when other packages (remote, layout) expose a v1.Image

// Deprecated: Architecture
// TBD Deprecated: Architecture
func (i *CNBImageCore) Architecture() (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -56,7 +46,7 @@ func (i *CNBImageCore) Architecture() (string, error) {
return configFile.Architecture, nil
}

// Deprecated: CreatedAt
// TBD Deprecated: CreatedAt
func (i *CNBImageCore) CreatedAt() (time.Time, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -65,7 +55,7 @@ func (i *CNBImageCore) CreatedAt() (time.Time, error) {
return configFile.Created.Time, nil
}

// Deprecated: Entrypoint
// TBD Deprecated: Entrypoint
func (i *CNBImageCore) Entrypoint() ([]string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand Down Expand Up @@ -96,25 +86,28 @@ func (i *CNBImageCore) GetAnnotateRefName() (string, error) {
return manifest.Annotations["org.opencontainers.image.ref.name"], nil
}

// Deprecated: History
func (i *CNBImageCore) History() ([]v1.History, error) {
configFile, err := getConfigFile(i.Image)
func (i *CNBImageCore) GetLayer(diffID string) (io.ReadCloser, error) {
hash, err := v1.NewHash(diffID)
if err != nil {
return nil, err
}
return configFile.History, nil
layer, err := i.LayerByDiffID(hash)
if err != nil {
return nil, err
}
return layer.Uncompressed()
}

func (i *CNBImageCore) Kind() string {
storeType := fmt.Sprintf("%T", i.Store)
parts := strings.Split(storeType, ".")
if len(parts) < 2 {
return storeType
// TBD Deprecated: History
func (i *CNBImageCore) History() ([]v1.History, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
return nil, err
}
return strings.TrimPrefix(parts[0], "*")
return configFile.History, nil
}

// Deprecated: Label
// TBD Deprecated: Label
func (i *CNBImageCore) Label(key string) (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -123,7 +116,7 @@ func (i *CNBImageCore) Label(key string) (string, error) {
return configFile.Config.Labels[key], nil
}

// Deprecated: Labels
// TBD Deprecated: Labels
func (i *CNBImageCore) Labels() (map[string]string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -132,16 +125,12 @@ func (i *CNBImageCore) Labels() (map[string]string, error) {
return configFile.Config.Labels, nil
}

// Deprecated: ManifestSize
// TBD Deprecated: ManifestSize
func (i *CNBImageCore) ManifestSize() (int64, error) {
return i.Image.Size()
}

func (i *CNBImageCore) Name() string {
return i.repoName
}

// Deprecated: OS
// TBD Deprecated: OS
func (i *CNBImageCore) OS() (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -150,7 +139,7 @@ func (i *CNBImageCore) OS() (string, error) {
return configFile.OS, nil
}

// Deprecated: OSVersion
// TBD Deprecated: OSVersion
func (i *CNBImageCore) OSVersion() (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -165,7 +154,7 @@ func (i *CNBImageCore) TopLayer() (string, error) {
return "", err
}
if len(layers) == 0 {
return "", fmt.Errorf("image %q has no layers", i.Name())
return "", errors.New("image has no layers")
}
topLayer := layers[len(layers)-1]
hex, err := topLayer.DiffID()
Expand All @@ -185,7 +174,7 @@ func (i *CNBImageCore) Valid() bool {
return err == nil
}

// Deprecated: Variant
// TBD Deprecated: Variant
func (i *CNBImageCore) Variant() (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -194,7 +183,7 @@ func (i *CNBImageCore) Variant() (string, error) {
return configFile.Variant, nil
}

// Deprecated: WorkingDir
// TBD Deprecated: WorkingDir
func (i *CNBImageCore) WorkingDir() (string, error) {
configFile, err := getConfigFile(i.Image)
if err != nil {
Expand All @@ -208,6 +197,9 @@ func (i *CNBImageCore) AnnotateRefName(refName string) error {
if err != nil {
return err
}
if manifest.Annotations == nil {
manifest.Annotations = make(map[string]string)
}
manifest.Annotations["org.opencontainers.image.ref.name"] = refName
mutated := mutate.Annotations(i.Image, manifest.Annotations)
image, ok := mutated.(v1.Image)
Expand All @@ -218,25 +210,21 @@ func (i *CNBImageCore) AnnotateRefName(refName string) error {
return nil
}

func (i *CNBImageCore) Rename(name string) {
i.repoName = name
}

// Deprecated: SetArchitecture
// TBD Deprecated: SetArchitecture
func (i *CNBImageCore) SetArchitecture(architecture string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.Architecture = architecture
})
}

// Deprecated: SetCmd
// TBD Deprecated: SetCmd
func (i *CNBImageCore) SetCmd(cmd ...string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.Config.Cmd = cmd
})
}

// Deprecated: SetEntrypoint
// TBD Deprecated: SetEntrypoint
func (i *CNBImageCore) SetEntrypoint(ep ...string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.Config.Entrypoint = ep
Expand Down Expand Up @@ -266,7 +254,7 @@ func (i *CNBImageCore) SetEnv(key, val string) error {
})
}

// Deprecated: SetHistory
// TBD Deprecated: SetHistory
func (i *CNBImageCore) SetHistory(histories []v1.History) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.History = histories
Expand All @@ -288,21 +276,21 @@ func (i *CNBImageCore) SetOS(osVal string) error {
})
}

// Deprecated: SetOSVersion
// TBD Deprecated: SetOSVersion
func (i *CNBImageCore) SetOSVersion(osVersion string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.OSVersion = osVersion
})
}

// Deprecated: SetVariant
// TBD Deprecated: SetVariant
func (i *CNBImageCore) SetVariant(variant string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.Variant = variant
})
}

// Deprecated: SetWorkingDir
// TBD Deprecated: SetWorkingDir
func (i *CNBImageCore) SetWorkingDir(dir string) error {
return i.MutateConfigFile(func(c *v1.ConfigFile) {
c.Config.WorkingDir = dir
Expand All @@ -329,11 +317,8 @@ func (i *CNBImageCore) AddLayerWithDiffIDAndHistory(path, _ string, history v1.H
if !i.preserveHistory {
history = emptyHistory
}
configFile, err := getConfigFile(i)
if err != nil {
return err
}
history.Created = configFile.Created
history.Created = v1.Time{Time: i.createdAt}

i.Image, err = mutate.Append(
i.Image,
mutate.Addendum{
Expand All @@ -346,9 +331,6 @@ func (i *CNBImageCore) AddLayerWithDiffIDAndHistory(path, _ string, history v1.H
}

func (i *CNBImageCore) Rebase(baseTopLayerDiffID string, withNewBase Image) error {
if i.Kind() != withNewBase.Kind() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If my underlying image i is a remote image, does it mean I can rebase it with a local or layout image?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, in theory - I haven't tested it, but probably you can

return fmt.Errorf("expected new base to be a %s image; got %s", i.Kind(), withNewBase.Kind())
}
newBase := withNewBase.UnderlyingImage() // FIXME: when all imgutil.Images are v1.Images, we can remove this part
var err error
i.Image, err = mutate.Rebase(i.Image, i.newV1ImageFacade(baseTopLayerDiffID), newBase)
Expand Down
Loading