Merge pull request #24 from stevvooe/breakup-common

Breakup common package
This commit is contained in:
Stephen Day 2015-01-06 10:08:10 -08:00
commit fdea60af05
18 changed files with 53 additions and 51 deletions

View file

@ -4,7 +4,6 @@ import (
"net/http" "net/http"
"regexp" "regexp"
"github.com/docker/distribution/common"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
) )
@ -12,7 +11,7 @@ var (
nameParameterDescriptor = ParameterDescriptor{ nameParameterDescriptor = ParameterDescriptor{
Name: "name", Name: "name",
Type: "string", Type: "string",
Format: common.RepositoryNameRegexp.String(), Format: RepositoryNameRegexp.String(),
Required: true, Required: true,
Description: `Name of the target repository.`, Description: `Name of the target repository.`,
} }
@ -20,7 +19,7 @@ var (
tagParameterDescriptor = ParameterDescriptor{ tagParameterDescriptor = ParameterDescriptor{
Name: "tag", Name: "tag",
Type: "string", Type: "string",
Format: common.TagNameRegexp.String(), Format: TagNameRegexp.String(),
Required: true, Required: true,
Description: `Tag of the target manifiest.`, Description: `Tag of the target manifiest.`,
} }
@ -377,7 +376,7 @@ var routeDescriptors = []RouteDescriptor{
}, },
{ {
Name: RouteNameTags, Name: RouteNameTags,
Path: "/v2/{name:" + common.RepositoryNameRegexp.String() + "}/tags/list", Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/tags/list",
Entity: "Tags", Entity: "Tags",
Description: "Retrieve information about tags.", Description: "Retrieve information about tags.",
Methods: []MethodDescriptor{ Methods: []MethodDescriptor{
@ -448,7 +447,7 @@ var routeDescriptors = []RouteDescriptor{
}, },
{ {
Name: RouteNameManifest, Name: RouteNameManifest,
Path: "/v2/{name:" + common.RepositoryNameRegexp.String() + "}/manifests/{tag:" + common.TagNameRegexp.String() + "}", Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/manifests/{tag:" + TagNameRegexp.String() + "}",
Entity: "Manifest", Entity: "Manifest",
Description: "Create, update and retrieve manifests.", Description: "Create, update and retrieve manifests.",
Methods: []MethodDescriptor{ Methods: []MethodDescriptor{
@ -693,7 +692,7 @@ var routeDescriptors = []RouteDescriptor{
{ {
Name: RouteNameBlob, Name: RouteNameBlob,
Path: "/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blobs/{digest:" + digest.DigestRegexp.String() + "}", Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/blobs/{digest:" + digest.DigestRegexp.String() + "}",
Entity: "Blob", Entity: "Blob",
Description: "Fetch the blob identified by `name` and `digest`. Used to fetch layers by tarsum digest.", Description: "Fetch the blob identified by `name` and `digest`. Used to fetch layers by tarsum digest.",
Methods: []MethodDescriptor{ Methods: []MethodDescriptor{
@ -852,7 +851,7 @@ var routeDescriptors = []RouteDescriptor{
{ {
Name: RouteNameBlobUpload, Name: RouteNameBlobUpload,
Path: "/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blobs/uploads/", Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/blobs/uploads/",
Entity: "Intiate Blob Upload", Entity: "Intiate Blob Upload",
Description: "Initiate a blob upload. This endpoint can be used to create resumable uploads or monolithic uploads.", Description: "Initiate a blob upload. This endpoint can be used to create resumable uploads or monolithic uploads.",
Methods: []MethodDescriptor{ Methods: []MethodDescriptor{
@ -964,7 +963,7 @@ var routeDescriptors = []RouteDescriptor{
{ {
Name: RouteNameBlobUploadChunk, Name: RouteNameBlobUploadChunk,
Path: "/v2/{name:" + common.RepositoryNameRegexp.String() + "}/blobs/uploads/{uuid}", Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/blobs/uploads/{uuid}",
Entity: "Blob Upload", Entity: "Blob Upload",
Description: "Interact with blob uploads. Clients should never assemble URLs for this endpoint and should only take it through the `Location` header on related API requests. The `Location` header and its parameters should be preserved by clients, using the latest value returned via upload related API calls.", Description: "Interact with blob uploads. Clients should never assemble URLs for this endpoint and should only take it through the `Location` header on related API requests. The `Location` header and its parameters should be preserved by clients, using the latest value returned via upload related API calls.",
Methods: []MethodDescriptor{ Methods: []MethodDescriptor{

View file

@ -1,4 +1,4 @@
package common package v2
import ( import (
"fmt" "fmt"

View file

@ -1,4 +1,4 @@
package common package v2
import ( import (
"testing" "testing"

View file

@ -14,11 +14,11 @@ import (
"testing" "testing"
"github.com/docker/distribution/api/v2" "github.com/docker/distribution/api/v2"
"github.com/docker/distribution/common/testutil"
"github.com/docker/distribution/configuration" "github.com/docker/distribution/configuration"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
_ "github.com/docker/distribution/storagedriver/inmemory" _ "github.com/docker/distribution/storagedriver/inmemory"
"github.com/docker/distribution/testutil"
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/gorilla/handlers" "github.com/gorilla/handlers"
) )

View file

@ -14,7 +14,6 @@ import (
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/docker/distribution/auth" "github.com/docker/distribution/auth"
"github.com/docker/distribution/common"
) )
// accessSet maps a typed, named resource to // accessSet maps a typed, named resource to
@ -38,7 +37,7 @@ func newAccessSet(accessItems ...auth.Access) accessSet {
accessSet[resource] = set accessSet[resource] = set
} }
set.Add(access.Action) set.add(access.Action)
} }
return accessSet return accessSet
@ -48,7 +47,7 @@ func newAccessSet(accessItems ...auth.Access) accessSet {
func (s accessSet) contains(access auth.Access) bool { func (s accessSet) contains(access auth.Access) bool {
actionSet, ok := s[access.Resource] actionSet, ok := s[access.Resource]
if ok { if ok {
return actionSet.Contains(access.Action) return actionSet.contains(access.Action)
} }
return false return false
@ -61,7 +60,7 @@ func (s accessSet) scopeParam() string {
scopes := make([]string, 0, len(s)) scopes := make([]string, 0, len(s))
for resource, actionSet := range s { for resource, actionSet := range s {
actions := strings.Join(actionSet.Keys(), ",") actions := strings.Join(actionSet.keys(), ",")
scopes = append(scopes, fmt.Sprintf("%s:%s:%s", resource.Type, resource.Name, actions)) scopes = append(scopes, fmt.Sprintf("%s:%s:%s", resource.Type, resource.Name, actions))
} }
@ -241,8 +240,8 @@ func (ac *accessController) Authorized(req *http.Request, accessItems ...auth.Ac
} }
verifyOpts := VerifyOptions{ verifyOpts := VerifyOptions{
TrustedIssuers: common.NewStringSet(ac.issuer), TrustedIssuers: []string{ac.issuer},
AcceptedAudiences: common.NewStringSet(ac.service), AcceptedAudiences: []string{ac.service},
Roots: ac.rootCerts, Roots: ac.rootCerts,
TrustedKeys: ac.trustedKeys, TrustedKeys: ac.trustedKeys,
} }

View file

@ -1,30 +1,30 @@
package common package token
// StringSet is a useful type for looking up strings. // StringSet is a useful type for looking up strings.
type StringSet map[string]struct{} type stringSet map[string]struct{}
// NewStringSet creates a new StringSet with the given strings. // NewStringSet creates a new StringSet with the given strings.
func NewStringSet(keys ...string) StringSet { func newStringSet(keys ...string) stringSet {
ss := make(StringSet, len(keys)) ss := make(stringSet, len(keys))
ss.Add(keys...) ss.add(keys...)
return ss return ss
} }
// Add inserts the given keys into this StringSet. // Add inserts the given keys into this StringSet.
func (ss StringSet) Add(keys ...string) { func (ss stringSet) add(keys ...string) {
for _, key := range keys { for _, key := range keys {
ss[key] = struct{}{} ss[key] = struct{}{}
} }
} }
// Contains returns whether the given key is in this StringSet. // Contains returns whether the given key is in this StringSet.
func (ss StringSet) Contains(key string) bool { func (ss stringSet) contains(key string) bool {
_, ok := ss[key] _, ok := ss[key]
return ok return ok
} }
// Keys returns a slice of all keys in this StringSet. // Keys returns a slice of all keys in this StringSet.
func (ss StringSet) Keys() []string { func (ss stringSet) keys() []string {
keys := make([]string, 0, len(ss)) keys := make([]string, 0, len(ss))
for key := range ss { for key := range ss {

View file

@ -14,7 +14,6 @@ import (
"github.com/docker/libtrust" "github.com/docker/libtrust"
"github.com/docker/distribution/auth" "github.com/docker/distribution/auth"
"github.com/docker/distribution/common"
) )
const ( const (
@ -71,8 +70,8 @@ type Token struct {
// VerifyOptions is used to specify // VerifyOptions is used to specify
// options when verifying a JSON Web Token. // options when verifying a JSON Web Token.
type VerifyOptions struct { type VerifyOptions struct {
TrustedIssuers common.StringSet TrustedIssuers []string
AcceptedAudiences common.StringSet AcceptedAudiences []string
Roots *x509.CertPool Roots *x509.CertPool
TrustedKeys map[string]libtrust.PublicKey TrustedKeys map[string]libtrust.PublicKey
} }
@ -132,13 +131,13 @@ func NewToken(rawToken string) (*Token, error) {
// Returns a nil error if the token is valid. // Returns a nil error if the token is valid.
func (t *Token) Verify(verifyOpts VerifyOptions) error { func (t *Token) Verify(verifyOpts VerifyOptions) error {
// Verify that the Issuer claim is a trusted authority. // Verify that the Issuer claim is a trusted authority.
if !verifyOpts.TrustedIssuers.Contains(t.Claims.Issuer) { if !contains(verifyOpts.TrustedIssuers, t.Claims.Issuer) {
log.Errorf("token from untrusted issuer: %q", t.Claims.Issuer) log.Errorf("token from untrusted issuer: %q", t.Claims.Issuer)
return ErrInvalidToken return ErrInvalidToken
} }
// Verify that the Audience claim is allowed. // Verify that the Audience claim is allowed.
if !verifyOpts.AcceptedAudiences.Contains(t.Claims.Audience) { if !contains(verifyOpts.AcceptedAudiences, t.Claims.Audience) {
log.Errorf("token intended for another audience: %q", t.Claims.Audience) log.Errorf("token intended for another audience: %q", t.Claims.Audience)
return ErrInvalidToken return ErrInvalidToken
} }
@ -332,7 +331,7 @@ func (t *Token) accessSet() accessSet {
} }
for _, action := range resourceActions.Actions { for _, action := range resourceActions.Actions {
set.Add(action) set.add(action)
} }
} }

View file

@ -15,10 +15,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/libtrust"
"github.com/docker/distribution/auth" "github.com/docker/distribution/auth"
"github.com/docker/distribution/common" "github.com/docker/libtrust"
) )
func makeRootKeys(numKeys int) ([]libtrust.PrivateKey, error) { func makeRootKeys(numKeys int) ([]libtrust.PrivateKey, error) {
@ -196,8 +194,8 @@ func TestTokenVerify(t *testing.T) {
} }
verifyOps := VerifyOptions{ verifyOps := VerifyOptions{
TrustedIssuers: common.NewStringSet(issuer), TrustedIssuers: []string{issuer},
AcceptedAudiences: common.NewStringSet(audience), AcceptedAudiences: []string{audience},
Roots: rootPool, Roots: rootPool,
TrustedKeys: trustedKeys, TrustedKeys: trustedKeys,
} }

View file

@ -4,8 +4,6 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"strings" "strings"
"github.com/docker/distribution/common"
) )
// joseBase64UrlEncode encodes the given data using the standard base64 url // joseBase64UrlEncode encodes the given data using the standard base64 url
@ -35,15 +33,26 @@ func joseBase64UrlDecode(s string) ([]byte, error) {
// actionSet is a special type of stringSet. // actionSet is a special type of stringSet.
type actionSet struct { type actionSet struct {
common.StringSet stringSet
} }
func newActionSet(actions ...string) actionSet { func newActionSet(actions ...string) actionSet {
return actionSet{common.NewStringSet(actions...)} return actionSet{newStringSet(actions...)}
} }
// Contains calls StringSet.Contains() for // Contains calls StringSet.Contains() for
// either "*" or the given action string. // either "*" or the given action string.
func (s actionSet) Contains(action string) bool { func (s actionSet) contains(action string) bool {
return s.StringSet.Contains("*") || s.StringSet.Contains(action) return s.stringSet.contains("*") || s.stringSet.contains(action)
}
// contains returns true if q is found in ss.
func contains(ss []string, q string) bool {
for _, s := range ss {
if s == q {
return true
}
}
return false
} }

View file

@ -9,9 +9,9 @@ import (
"sync" "sync"
"testing" "testing"
"github.com/docker/distribution/common/testutil"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
"github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest"
"github.com/docker/distribution/testutil"
) )
type testBlob struct { type testBlob struct {

View file

@ -10,7 +10,6 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/docker/distribution/common"
"github.com/docker/docker/pkg/tarsum" "github.com/docker/docker/pkg/tarsum"
) )
@ -105,7 +104,7 @@ func FromBytes(p []byte) (Digest, error) {
func (d Digest) Validate() error { func (d Digest) Validate() error {
s := string(d) s := string(d)
// Common case will be tarsum // Common case will be tarsum
_, err := common.ParseTarSum(s) _, err := ParseTarSum(s)
if err == nil { if err == nil {
return nil return nil
} }

View file

@ -1,4 +1,4 @@
package common package digest
import ( import (
"fmt" "fmt"

View file

@ -1,4 +1,4 @@
package common package digest
import ( import (
"reflect" "reflect"

View file

@ -7,7 +7,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/docker/distribution/common/testutil" "github.com/docker/distribution/testutil"
) )
func TestDigestVerifier(t *testing.T) { func TestDigestVerifier(t *testing.T) {

View file

@ -9,10 +9,10 @@ import (
"os" "os"
"testing" "testing"
"github.com/docker/distribution/common/testutil"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
"github.com/docker/distribution/storagedriver" "github.com/docker/distribution/storagedriver"
"github.com/docker/distribution/storagedriver/inmemory" "github.com/docker/distribution/storagedriver/inmemory"
"github.com/docker/distribution/testutil"
) )
// TestSimpleLayerUpload covers the layer upload process, exercising common // TestSimpleLayerUpload covers the layer upload process, exercising common

View file

@ -5,7 +5,6 @@ import (
"path" "path"
"strings" "strings"
"github.com/docker/distribution/common"
"github.com/docker/distribution/digest" "github.com/docker/distribution/digest"
) )
@ -189,7 +188,7 @@ func digestPathComoponents(dgst digest.Digest) ([]string, error) {
hex, hex,
} }
if tsi, err := common.ParseTarSum(dgst.String()); err == nil { if tsi, err := digest.ParseTarSum(dgst.String()); err == nil {
// We have a tarsum! // We have a tarsum!
version := tsi.Version version := tsi.Version
if version == "" { if version == "" {