Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.

Commit

Permalink
Support copying image indexes
Browse files Browse the repository at this point in the history
Fixes #23
  • Loading branch information
glyn committed Sep 11, 2019
1 parent 23316cf commit 82d942d
Show file tree
Hide file tree
Showing 24 changed files with 1,172 additions and 263 deletions.
5 changes: 3 additions & 2 deletions Makefile
Expand Up @@ -13,9 +13,10 @@ check-counterfeiter:
@which counterfeiter > /dev/null || (echo counterfeiter not found: issue "GO111MODULE=off go get -u github.com/maxbrunsfeld/counterfeiter" && false)

gen-mocks: check-counterfeiter
counterfeiter -o pkg/registry/imagefakes/fake_image.go github.com/google/go-containerregistry/pkg/v1.Image
counterfeiter -o pkg/registry/imagefakes/fake_image_index.go github.com/google/go-containerregistry/pkg/v1.ImageIndex
counterfeiter -o pkg/registry/ggcrfakes/fake_image.go github.com/google/go-containerregistry/pkg/v1.Image
counterfeiter -o pkg/registry/ggcrfakes/fake_image_index.go github.com/google/go-containerregistry/pkg/v1.ImageIndex
counterfeiter pkg/registry LayoutPath
counterfeiter pkg/registry Image

irel: $(GO_SOURCES)
GO111MODULE=on go build -o $(OUTPUT) cmd/irel/main.go
Expand Down
2 changes: 1 addition & 1 deletion pkg/image/digest.go
Expand Up @@ -18,7 +18,7 @@ package image

import "github.com/opencontainers/go-digest"

// Digest provides a CAS address of an image.
// Digest provides a CAS address of an image (either an image manifest or a manifest list).
type Digest struct {
dig digest.Digest
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/image/name.go
Expand Up @@ -29,7 +29,7 @@ const (
fullDockerHubHost = "index.docker.io"
)

// Name is a named image reference
// Name is a named image reference. It can refer to an image manifest or a manifest list (e.g. a multi-arch image).
type Name struct {
ref reference.Named
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/irel/copy.go
Expand Up @@ -19,7 +19,7 @@ package irel
import (
"fmt"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)
Expand Down Expand Up @@ -47,7 +47,7 @@ func copy(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", dstStr, err)
}

regClient := registry.NewRegistryClient()
regClient := ggcr.NewRegistryClient()
dig, _, err := regClient.Copy(src, dst)
if err != nil {
log.Fatalf("copy failed: %v", err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/irel/digest.go
Expand Up @@ -19,7 +19,7 @@ package irel
import (
"fmt"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)
Expand All @@ -43,7 +43,7 @@ func digest(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := registry.NewRegistryClient()
regClient := ggcr.NewRegistryClient()
dig, err := regClient.Digest(ref)
if err != nil {
log.Fatalf("digest failed: %v", err)
Expand Down
6 changes: 3 additions & 3 deletions pkg/irel/layout_add.go
Expand Up @@ -19,7 +19,7 @@ package irel
import (
"fmt"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)
Expand All @@ -40,8 +40,8 @@ func layoutAdd(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := registry.NewRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
regClient := ggcr.NewRegistryClient()
layout, err := regClient.NewLayout(layoutPath)
if err != nil {
layout, err = regClient.NewLayout(layoutPath)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions pkg/irel/layout_find.go
Expand Up @@ -19,7 +19,7 @@ package irel
import (
"fmt"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)
Expand All @@ -40,7 +40,7 @@ func layoutFind(cmd *cobra.Command, args []string) {
log.Fatalf("invalid reference %q: %v", refStr, err)
}

regClient := registry.NewRegistryClient()
regClient := ggcr.NewRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
if err != nil {
log.Fatalf("failed to create OCI image layout: %v", err)
Expand Down
4 changes: 2 additions & 2 deletions pkg/irel/layout_push.go
Expand Up @@ -19,7 +19,7 @@ package irel
import (
"fmt"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
"github.com/pivotal/image-relocation/pkg/registry/ggcr"
"github.com/spf13/cobra"
"log"
)
Expand All @@ -45,7 +45,7 @@ func layoutPush(cmd *cobra.Command, args []string) {
log.Fatalf("invalid digest %q: %v", digStr, err)
}

regClient := registry.NewRegistryClient()
regClient := ggcr.NewRegistryClient()
layout, err := regClient.ReadLayout(layoutPath)
if err != nil {
log.Fatalf("failed to access OCI image layout: %v", err)
Expand Down
58 changes: 0 additions & 58 deletions pkg/registry/client.go
Expand Up @@ -17,9 +17,6 @@
package registry

import (
"fmt"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/pivotal/image-relocation/pkg/image"
)

Expand All @@ -41,58 +38,3 @@ type Client interface {
ReadLayout(path string) (Layout, error)
}

type client struct {
readRemoteImage func(n image.Name) (v1.Image, error)
writeRemoteImage func(i v1.Image, n image.Name) error
}

// NewRegistryClient returns a new Client.
func NewRegistryClient() Client {
return &client{
readRemoteImage: readRemoteImage,
writeRemoteImage: writeRemoteImage,
}
}

func (r *client) Digest(n image.Name) (image.Digest, error) {
img, err := r.readRemoteImage(n)
if err != nil {
return image.EmptyDigest, err
}

hash, err := img.Digest()
if err != nil {
return image.EmptyDigest, err
}

return image.NewDigest(hash.String())
}

func (r *client) Copy(source image.Name, target image.Name) (image.Digest, int64, error) {
img, err := r.readRemoteImage(source)
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to read image %v: %v", source, err)
}

hash, err := img.Digest()
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to read digest of image %v: %v", source, err)
}

err = r.writeRemoteImage(img, target)
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to write image %v: %v", target, err)
}

dig, err := image.NewDigest(hash.String())
if err != nil {
return image.EmptyDigest, 0, err
}

rawManifest, err := img.RawManifest()
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to get raw manifest of image %v: %v", source, err)
}

return dig, int64(len(rawManifest)), nil
}
77 changes: 77 additions & 0 deletions pkg/registry/ggcr/client.go
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2019-Present Pivotal Software, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ggcr

import (
"fmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/pivotal/image-relocation/pkg/image"
"github.com/pivotal/image-relocation/pkg/registry"
)

type manifestWriter func(i v1.Image, n image.Name) error
type indexWriter func(i v1.ImageIndex, n image.Name) error

type client struct {
readRemoteImage func(n image.Name) (registry.Image, error)
writeRemoteImage manifestWriter
writeRemoteIndex indexWriter
}

// NewRegistryClient returns a new Client.
func NewRegistryClient() registry.Client {
return &client{
readRemoteImage: readRemoteImage(writeRemoteImage, writeRemoteIndex),
writeRemoteImage: writeRemoteImage,
writeRemoteIndex: writeRemoteIndex,
}
}

func (r *client) Digest(n image.Name) (image.Digest, error) {
img, err := r.readRemoteImage(n)
if err != nil {
return image.EmptyDigest, err
}

hash, err := img.Digest()
if err != nil {
return image.EmptyDigest, err
}

return image.NewDigest(hash.String())
}

func (r *client) Copy(source image.Name, target image.Name) (image.Digest, int64, error) {
img, err := r.readRemoteImage(source)
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to read image %v: %v", source, err)
}

sourceDigest, err := img.Digest()
if err != nil {
return image.EmptyDigest, 0, fmt.Errorf("failed to read digest of image %v: %v", source, err)
}

targetDigest, s, err := img.Write(target)
if err != nil {
return image.EmptyDigest, 0 , fmt.Errorf("failed to write image %v: %v", target, err)
}
if sourceDigest != targetDigest {
return image.EmptyDigest, 0, fmt.Errorf("failed to preserve digest of image %v: source digest %v, target digest %v", source, sourceDigest, targetDigest)
}
return targetDigest, s, err
}

0 comments on commit 82d942d

Please sign in to comment.