Merge pull request #288 from runcom/pluggable-transports

vendor c/image for pluggable transports
This commit is contained in:
Antonio Murdaca 2017-03-02 15:39:52 +01:00 committed by GitHub
commit ab4912a5a1
13 changed files with 120 additions and 52 deletions

View File

@ -6,7 +6,7 @@ import (
"os" "os"
"github.com/containers/image/copy" "github.com/containers/image/copy"
"github.com/containers/image/transports" "github.com/containers/image/transports/alltransports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -37,11 +37,11 @@ func copyHandler(context *cli.Context) error {
} }
defer policyContext.Destroy() defer policyContext.Destroy()
srcRef, err := transports.ParseImageName(context.Args()[0]) srcRef, err := alltransports.ParseImageName(context.Args()[0])
if err != nil { if err != nil {
return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err) return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err)
} }
destRef, err := transports.ParseImageName(context.Args()[1]) destRef, err := alltransports.ParseImageName(context.Args()[1])
if err != nil { if err != nil {
return fmt.Errorf("Invalid destination name %s: %v", context.Args()[1], err) return fmt.Errorf("Invalid destination name %s: %v", context.Args()[1], err)
} }

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/containers/image/transports" "github.com/containers/image/transports/alltransports"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -13,7 +13,7 @@ func deleteHandler(context *cli.Context) error {
return errors.New("Usage: delete imageReference") return errors.New("Usage: delete imageReference")
} }
ref, err := transports.ParseImageName(context.Args()[0]) ref, err := alltransports.ParseImageName(context.Args()[0])
if err != nil { if err != nil {
return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err) return fmt.Errorf("Invalid source name %s: %v", context.Args()[0], err)
} }

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"strings" "strings"
"github.com/containers/image/transports" "github.com/containers/image/transports/alltransports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
@ -59,7 +59,7 @@ func getDockerAuth(creds string) (*types.DockerAuthConfig, error) {
// The caller must call .Close() on the returned Image. // The caller must call .Close() on the returned Image.
func parseImage(c *cli.Context) (types.Image, error) { func parseImage(c *cli.Context) (types.Image, error) {
imgName := c.Args().First() imgName := c.Args().First()
ref, err := transports.ParseImageName(imgName) ref, err := alltransports.ParseImageName(imgName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -74,7 +74,7 @@ func parseImage(c *cli.Context) (types.Image, error) {
// requestedManifestMIMETypes is as in types.ImageReference.NewImageSource. // requestedManifestMIMETypes is as in types.ImageReference.NewImageSource.
// The caller must call .Close() on the returned ImageSource. // The caller must call .Close() on the returned ImageSource.
func parseImageSource(c *cli.Context, name string, requestedManifestMIMETypes []string) (types.ImageSource, error) { func parseImageSource(c *cli.Context, name string, requestedManifestMIMETypes []string) (types.ImageSource, error) {
ref, err := transports.ParseImageName(name) ref, err := alltransports.ParseImageName(name)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -10,10 +10,15 @@ import (
"github.com/containers/image/directory/explicitfilepath" "github.com/containers/image/directory/explicitfilepath"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
"github.com/containers/image/image" "github.com/containers/image/image"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
func init() {
transports.Register(Transport)
}
// Transport is an ImageTransport for directory paths. // Transport is an ImageTransport for directory paths.
var Transport = dirTransport{} var Transport = dirTransport{}

View File

@ -5,10 +5,15 @@ import (
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
"github.com/containers/image/image" "github.com/containers/image/image"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
) )
func init() {
transports.Register(Transport)
}
// Transport is an ImageTransport for images managed by a local Docker daemon. // Transport is an ImageTransport for images managed by a local Docker daemon.
var Transport = daemonTransport{} var Transport = daemonTransport{}

View File

@ -6,10 +6,15 @@ import (
"github.com/containers/image/docker/policyconfiguration" "github.com/containers/image/docker/policyconfiguration"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func init() {
transports.Register(Transport)
}
// Transport is an ImageTransport for Docker registry-hosted images. // Transport is an ImageTransport for Docker registry-hosted images.
var Transport = dockerTransport{} var Transport = dockerTransport{}

View File

@ -54,7 +54,7 @@ func GuessMIMEType(manifest []byte) string {
} }
switch meta.MediaType { switch meta.MediaType {
case DockerV2Schema2MediaType, DockerV2ListMediaType, imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeImageManifestList: // A recognized type. case DockerV2Schema2MediaType, DockerV2ListMediaType: // A recognized type.
return meta.MediaType return meta.MediaType
} }
// this is the only way the function can return DockerV2Schema1MediaType, and recognizing that is essential for stripping the JWS signatures = computing the correct manifest digest. // this is the only way the function can return DockerV2Schema1MediaType, and recognizing that is essential for stripping the JWS signatures = computing the correct manifest digest.

View File

@ -9,11 +9,16 @@ import (
"github.com/containers/image/directory/explicitfilepath" "github.com/containers/image/directory/explicitfilepath"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
"github.com/containers/image/image" "github.com/containers/image/image"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func init() {
transports.Register(Transport)
}
// Transport is an ImageTransport for OCI directories. // Transport is an ImageTransport for OCI directories.
var Transport = ociTransport{} var Transport = ociTransport{}

View File

@ -8,10 +8,15 @@ import (
"github.com/containers/image/docker/policyconfiguration" "github.com/containers/image/docker/policyconfiguration"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
genericImage "github.com/containers/image/image" genericImage "github.com/containers/image/image"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func init() {
transports.Register(Transport)
}
// Transport is an ImageTransport for OpenShift registry-hosted images. // Transport is an ImageTransport for OpenShift registry-hosted images.
var Transport = openshiftTransport{} var Transport = openshiftTransport{}

View File

@ -122,10 +122,8 @@ func (m *policyTransportsMap) UnmarshalJSON(data []byte) error {
// So, use a temporary map of pointers-to-slices and convert. // So, use a temporary map of pointers-to-slices and convert.
tmpMap := map[string]*PolicyTransportScopes{} tmpMap := map[string]*PolicyTransportScopes{}
if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} {
transport, ok := transports.KnownTransports[key] // transport can be nil
if !ok { transport := transports.Get(key)
return nil
}
// paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe. // paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe.
if _, ok := tmpMap[key]; ok { if _, ok := tmpMap[key]; ok {
return nil return nil
@ -155,7 +153,7 @@ func (m *PolicyTransportScopes) UnmarshalJSON(data []byte) error {
} }
// policyTransportScopesWithTransport is a way to unmarshal a PolicyTransportScopes // policyTransportScopesWithTransport is a way to unmarshal a PolicyTransportScopes
// while validating using a specific ImageTransport. // while validating using a specific ImageTransport if not nil.
type policyTransportScopesWithTransport struct { type policyTransportScopesWithTransport struct {
transport types.ImageTransport transport types.ImageTransport
dest *PolicyTransportScopes dest *PolicyTransportScopes
@ -174,7 +172,7 @@ func (m *policyTransportScopesWithTransport) UnmarshalJSON(data []byte) error {
if _, ok := tmpMap[key]; ok { if _, ok := tmpMap[key]; ok {
return nil return nil
} }
if key != "" { if key != "" && m.transport != nil {
if err := m.transport.ValidatePolicyConfigurationScope(key); err != nil { if err := m.transport.ValidatePolicyConfigurationScope(key); err != nil {
return nil return nil
} }

View File

@ -9,12 +9,17 @@ import (
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/containers/image/docker/reference" "github.com/containers/image/docker/reference"
"github.com/containers/image/transports"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/containers/storage/storage" "github.com/containers/storage/storage"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
ddigest "github.com/opencontainers/go-digest" ddigest "github.com/opencontainers/go-digest"
) )
func init() {
transports.Register(Transport)
}
var ( var (
// Transport is an ImageTransport that uses either a default // Transport is an ImageTransport that uses either a default
// storage.Store or one that's it's explicitly told to use. // storage.Store or one that's it's explicitly told to use.

View File

@ -0,0 +1,31 @@
package alltransports
import (
"strings"
// register all known transports
// NOTE: Make sure docs/policy.json.md is updated when adding or updating
// a transport.
_ "github.com/containers/image/directory"
_ "github.com/containers/image/docker"
_ "github.com/containers/image/docker/daemon"
_ "github.com/containers/image/oci/layout"
_ "github.com/containers/image/openshift"
_ "github.com/containers/image/storage"
"github.com/containers/image/transports"
"github.com/containers/image/types"
"github.com/pkg/errors"
)
// ParseImageName converts a URL-like image name to a types.ImageReference.
func ParseImageName(imgName string) (types.ImageReference, error) {
parts := strings.SplitN(imgName, ":", 2)
if len(parts) != 2 {
return nil, errors.Errorf(`Invalid image name "%s", expected colon-separated transport:reference`, imgName)
}
transport := transports.Get(parts[0])
if transport == nil {
return nil, errors.Errorf(`Invalid image name "%s", unknown transport "%s"`, imgName, parts[0])
}
return transport.ParseReference(parts[1])
}

View File

@ -2,52 +2,61 @@ package transports
import ( import (
"fmt" "fmt"
"strings" "sync"
"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/storage"
"github.com/containers/image/types" "github.com/containers/image/types"
"github.com/pkg/errors"
) )
// KnownTransports is a registry of known ImageTransport instances. // knownTransports is a registry of known ImageTransport instances.
var KnownTransports map[string]types.ImageTransport type knownTransports struct {
transports map[string]types.ImageTransport
mu sync.Mutex
}
func init() { func (kt *knownTransports) Get(k string) types.ImageTransport {
KnownTransports = make(map[string]types.ImageTransport) kt.mu.Lock()
// NOTE: Make sure docs/policy.json.md is updated when adding or updating t := kt.transports[k]
// a transport. kt.mu.Unlock()
for _, t := range []types.ImageTransport{ return t
directory.Transport, }
docker.Transport,
daemon.Transport, func (kt *knownTransports) Remove(k string) {
ociLayout.Transport, kt.mu.Lock()
openshift.Transport, delete(kt.transports, k)
storage.Transport, kt.mu.Unlock()
} { }
func (kt *knownTransports) Add(t types.ImageTransport) {
kt.mu.Lock()
defer kt.mu.Unlock()
name := t.Name() name := t.Name()
if _, ok := KnownTransports[name]; ok { if t := kt.transports[name]; t != nil {
panic(fmt.Sprintf("Duplicate image transport name %s", name)) panic(fmt.Sprintf("Duplicate image transport name %s", name))
} }
KnownTransports[name] = t kt.transports[name] = t
}
var kt *knownTransports
func init() {
kt = &knownTransports{
transports: make(map[string]types.ImageTransport),
} }
} }
// ParseImageName converts a URL-like image name to a types.ImageReference. // Get returns the transport specified by name or nil when unavailable.
func ParseImageName(imgName string) (types.ImageReference, error) { func Get(name string) types.ImageTransport {
parts := strings.SplitN(imgName, ":", 2) return kt.Get(name)
if len(parts) != 2 { }
return nil, errors.Errorf(`Invalid image name "%s", expected colon-separated transport:reference`, imgName)
} // Delete deletes a transport from the registered transports.
transport, ok := KnownTransports[parts[0]] func Delete(name string) {
if !ok { kt.Remove(name)
return nil, errors.Errorf(`Invalid image name "%s", unknown transport "%s"`, imgName, parts[0]) }
}
return transport.ParseReference(parts[1]) // Register registers a transport.
func Register(t types.ImageTransport) {
kt.Add(t)
} }
// ImageName converts a types.ImageReference into an URL-like image name, which MUST be such that // ImageName converts a types.ImageReference into an URL-like image name, which MUST be such that