Skip to content

Commit

Permalink
*: pluggable transports
Browse files Browse the repository at this point in the history
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
  • Loading branch information
runcom committed Jan 20, 2017
1 parent b5c6de3 commit 20454d9
Show file tree
Hide file tree
Showing 13 changed files with 83 additions and 36 deletions.
13 changes: 7 additions & 6 deletions copy/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import (
"github.com/Sirupsen/logrus"
"github.com/containers/image/image"
"github.com/containers/image/manifest"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/signature"
"github.com/containers/image/transports"
_ "github.com/containers/image/transports"
"github.com/containers/image/types"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
Expand Down Expand Up @@ -106,14 +107,14 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe

dest, err := destRef.NewImageDestination(options.DestinationCtx)
if err != nil {
return errors.Wrapf(err, "Error initializing destination %s", transports.ImageName(destRef))
return errors.Wrapf(err, "Error initializing destination %s", registeredtransports.ImageName(destRef))
}
defer dest.Close()
destSupportedManifestMIMETypes := dest.SupportedManifestMIMETypes()

rawSource, err := srcRef.NewImageSource(options.SourceCtx, destSupportedManifestMIMETypes)
if err != nil {
return errors.Wrapf(err, "Error initializing source %s", transports.ImageName(srcRef))
return errors.Wrapf(err, "Error initializing source %s", registeredtransports.ImageName(srcRef))
}
unparsedImage := image.UnparsedFromSource(rawSource)
defer func() {
Expand All @@ -128,13 +129,13 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
}
src, err := image.FromUnparsedImage(unparsedImage)
if err != nil {
return errors.Wrapf(err, "Error initializing image from source %s", transports.ImageName(srcRef))
return errors.Wrapf(err, "Error initializing image from source %s", registeredtransports.ImageName(srcRef))
}
unparsedImage = nil
defer src.Close()

if src.IsMultiImage() {
return errors.Errorf("can not copy %s: manifest contains multiple images", transports.ImageName(srcRef))
return errors.Errorf("can not copy %s: manifest contains multiple images", registeredtransports.ImageName(srcRef))
}

var sigs [][]byte
Expand Down Expand Up @@ -206,7 +207,7 @@ func Image(policyContext *signature.PolicyContext, destRef, srcRef types.ImageRe
}
dockerReference := dest.Reference().DockerReference()
if dockerReference == nil {
return errors.Errorf("Cannot determine canonical Docker reference for destination %s", transports.ImageName(dest.Reference()))
return errors.Errorf("Cannot determine canonical Docker reference for destination %s", registeredtransports.ImageName(dest.Reference()))
}

writeReport("Signing manifest\n")
Expand Down
5 changes: 5 additions & 0 deletions directory/directory_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,15 @@ import (
"github.com/containers/image/directory/explicitfilepath"
"github.com/containers/image/docker/reference"
"github.com/containers/image/image"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
"github.com/opencontainers/go-digest"
)

func init() {
registeredtransports.Register(Transport)
}

// Transport is an ImageTransport for directory paths.
var Transport = dirTransport{}

Expand Down
5 changes: 5 additions & 0 deletions docker/docker_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import (

"github.com/containers/image/docker/policyconfiguration"
"github.com/containers/image/docker/reference"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
"github.com/pkg/errors"
)

func init() {
registeredtransports.Register(Transport)
}

// Transport is an ImageTransport for Docker registry-hosted images.
var Transport = dockerTransport{}

Expand Down
5 changes: 5 additions & 0 deletions oci/layout/oci_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import (
"github.com/containers/image/directory/explicitfilepath"
"github.com/containers/image/docker/reference"
"github.com/containers/image/image"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)

func init() {
registeredtransports.Register(Transport)
}

// Transport is an ImageTransport for OCI directories.
var Transport = ociTransport{}

Expand Down
5 changes: 5 additions & 0 deletions openshift/openshift_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import (
"github.com/containers/image/docker/policyconfiguration"
"github.com/containers/image/docker/reference"
genericImage "github.com/containers/image/image"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
"github.com/pkg/errors"
)

func init() {
registeredtransports.Register(Transport)
}

// Transport is an ImageTransport for OpenShift registry-hosted images.
var Transport = openshiftTransport{}

Expand Down
34 changes: 34 additions & 0 deletions registeredtransports/registeredtransports.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package registeredtransports

import (
"fmt"

"github.com/containers/image/types"
)

// KnownTransports is a registry of known ImageTransport instances.
var KnownTransports map[string]types.ImageTransport

func init() {
KnownTransports = make(map[string]types.ImageTransport)
}

// Register TODO(runcom)
func Register(t types.ImageTransport) {
name := t.Name()
if _, ok := KnownTransports[name]; ok {
panic(fmt.Sprintf("Duplicate image transport name %s", name))
}
KnownTransports[name] = t
}

// ImageName converts a types.ImageReference into an URL-like image name, which MUST be such that
// ParseImageName(ImageName(reference)) returns an equivalent reference.
//
// This is the generally recommended way to refer to images in the UI.
//
// NOTE: The returned string is not promised to be equal to the original input to ParseImageName;
// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
func ImageName(ref types.ImageReference) string {
return ref.Transport().Name() + ":" + ref.StringWithinTransport()
}
4 changes: 2 additions & 2 deletions signature/policy_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/pkg/errors"

"github.com/containers/image/docker/reference"
"github.com/containers/image/transports"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
)

Expand Down Expand Up @@ -123,7 +123,7 @@ func (m *policyTransportsMap) UnmarshalJSON(data []byte) error {
// So, use a temporary map of pointers-to-slices and convert.
tmpMap := map[string]*PolicyTransportScopes{}
if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} {
transport, ok := transports.KnownTransports[key]
transport, ok := registeredtransports.KnownTransports[key]
if !ok {
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions signature/policy_eval_simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package signature
import (
"fmt"

"github.com/containers/image/transports"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
)

Expand All @@ -20,9 +20,9 @@ func (pr *prInsecureAcceptAnything) isRunningImageAllowed(image types.UnparsedIm
}

func (pr *prReject) isSignatureAuthorAccepted(image types.UnparsedImage, sig []byte) (signatureAcceptanceResult, *Signature, error) {
return sarRejected, nil, PolicyRequirementError(fmt.Sprintf("Any signatures for image %s are rejected by policy.", transports.ImageName(image.Reference())))
return sarRejected, nil, PolicyRequirementError(fmt.Sprintf("Any signatures for image %s are rejected by policy.", registeredtransports.ImageName(image.Reference())))
}

func (pr *prReject) isRunningImageAllowed(image types.UnparsedImage) (bool, error) {
return false, PolicyRequirementError(fmt.Sprintf("Running image %s is rejected by policy.", transports.ImageName(image.Reference())))
return false, PolicyRequirementError(fmt.Sprintf("Running image %s is rejected by policy.", registeredtransports.ImageName(image.Reference())))
}
4 changes: 2 additions & 2 deletions signature/policy_reference_match.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"

"github.com/containers/image/docker/reference"
"github.com/containers/image/transports"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
)

Expand All @@ -15,7 +15,7 @@ func parseImageAndDockerReference(image types.UnparsedImage, s2 string) (referen
r1 := image.Reference().DockerReference()
if r1 == nil {
return nil, nil, PolicyRequirementError(fmt.Sprintf("Docker reference match attempted on image %s with no known Docker reference identity",
transports.ImageName(image.Reference())))
registeredtransports.ImageName(image.Reference())))
}
r2, err := reference.ParseNamed(s2)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions signature/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"testing"

_ "github.com/containers/image/openshift"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
Expand Down
5 changes: 5 additions & 0 deletions storage/storage_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ import (

"github.com/Sirupsen/logrus"
"github.com/containers/image/docker/reference"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/types"
"github.com/containers/storage/storage"
"github.com/opencontainers/go-digest"
ddigest "github.com/opencontainers/go-digest"
)

func init() {
registeredtransports.Register(Transport)
}

var (
// Transport is an ImageTransport that uses either a default
// storage.Store or one that's it's explicitly told to use.
Expand Down
25 changes: 5 additions & 20 deletions transports/transports.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
package transports

import (
"fmt"
"strings"

"github.com/containers/image/directory"
"github.com/containers/image/docker"
"github.com/containers/image/docker/daemon"
ociLayout "github.com/containers/image/oci/layout"
"github.com/containers/image/openshift"
"github.com/containers/image/registeredtransports"
"github.com/containers/image/storage"
"github.com/containers/image/types"
"github.com/pkg/errors"
)

// KnownTransports is a registry of known ImageTransport instances.
var KnownTransports map[string]types.ImageTransport

func init() {
KnownTransports = make(map[string]types.ImageTransport)
// NOTE: Make sure docs/policy.json.md is updated when adding or updating
// a transport.
for _, t := range []types.ImageTransport{
Expand All @@ -30,10 +26,10 @@ func init() {
storage.Transport,
} {
name := t.Name()
if _, ok := KnownTransports[name]; ok {
panic(fmt.Sprintf("Duplicate image transport name %s", name))
if _, ok := registeredtransports.KnownTransports[name]; ok {
continue
}
KnownTransports[name] = t
registeredtransports.Register(t)
}
}

Expand All @@ -43,20 +39,9 @@ func ParseImageName(imgName string) (types.ImageReference, error) {
if len(parts) != 2 {
return nil, errors.Errorf(`Invalid image name "%s", expected colon-separated transport:reference`, imgName)
}
transport, ok := KnownTransports[parts[0]]
transport, ok := registeredtransports.KnownTransports[parts[0]]
if !ok {
return nil, errors.Errorf(`Invalid image name "%s", unknown transport "%s"`, imgName, parts[0])
}
return transport.ParseReference(parts[1])
}

// ImageName converts a types.ImageReference into an URL-like image name, which MUST be such that
// ParseImageName(ImageName(reference)) returns an equivalent reference.
//
// This is the generally recommended way to refer to images in the UI.
//
// NOTE: The returned string is not promised to be equal to the original input to ParseImageName;
// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
func ImageName(ref types.ImageReference) string {
return ref.Transport().Name() + ":" + ref.StringWithinTransport()
}
7 changes: 4 additions & 3 deletions transports/transports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package transports
import (
"testing"

"github.com/containers/image/registeredtransports"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestKnownTransports(t *testing.T) {
assert.NotNil(t, KnownTransports) // Ensure that the initialization has actually been run
assert.True(t, len(KnownTransports) > 1)
assert.NotNil(t, registeredtransports.KnownTransports) // Ensure that the initialization has actually been run
assert.True(t, len(registeredtransports.KnownTransports) > 1)
}

func TestParseImageName(t *testing.T) {
Expand Down Expand Up @@ -40,7 +41,7 @@ func TestImageNameHandling(t *testing.T) {
fullInput := c.transport + ":" + c.input
ref, err := ParseImageName(fullInput)
require.NoError(t, err, fullInput)
s := ImageName(ref)
s := registeredtransports.ImageName(ref)
assert.Equal(t, c.transport+":"+c.roundtrip, s, fullInput)
}
}

0 comments on commit 20454d9

Please sign in to comment.