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

Add cross origin blob mounting functionality. #1322

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion pkg/v1/remote/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func CheckPushPermission(ref name.Reference, kc authn.Keychain, t http.RoundTrip
client: &http.Client{Transport: tr},
context: context.Background(),
}
loc, _, err := w.initiateUpload("", "")
loc, _, err := w.initiateUpload("", "", "")
if loc != "" {
// Since we're only initiating the upload to check whether we
// can, we should attempt to cancel it, in case initiating
Expand Down
13 changes: 7 additions & 6 deletions pkg/v1/remote/write.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,15 @@ func (w *writer) checkExistingManifest(h v1.Hash, mt types.MediaType) (bool, err
// On success, the layer was either mounted (nothing more to do) or a blob
// upload was initiated and the body of that blob should be sent to the returned
// location.
func (w *writer) initiateUpload(from, mount string) (location string, mounted bool, err error) {
func (w *writer) initiateUpload(from, mount, origin string) (location string, mounted bool, err error) {
u := w.url(fmt.Sprintf("/v2/%s/blobs/uploads/", w.repo.RepositoryStr()))
uv := url.Values{}

if mount != "" && from != "" {
// Quay will fail if we specify a "mount" without a "from".
uv["mount"] = []string{mount}
uv["from"] = []string{from}
uv["origin"] = []string{origin}
}
u.RawQuery = uv.Encode()

Expand Down Expand Up @@ -411,7 +413,7 @@ func (w *writer) incrProgress(written int64) {
// uploadOne performs a complete upload of a single layer.
func (w *writer) uploadOne(ctx context.Context, l v1.Layer) error {
tryUpload := func() error {
var from, mount string
var from, mount, origin string
if h, err := l.Digest(); err == nil {
// If we know the digest, this isn't a streaming layer. Do an existence
// check so we can skip uploading the layer if possible.
Expand All @@ -432,12 +434,11 @@ func (w *writer) uploadOne(ctx context.Context, l v1.Layer) error {
mount = h.String()
}
if ml, ok := l.(*MountableLayer); ok {
if w.repo.RegistryStr() == ml.Reference.Context().RegistryStr() {
from = ml.Reference.Context().RepositoryStr()
}
from = ml.Reference.Context().RepositoryStr()
origin = ml.Reference.Context().RegistryStr()
}

location, mounted, err := w.initiateUpload(from, mount)
location, mounted, err := w.initiateUpload(from, mount, origin)
if err != nil {
return err
} else if mounted {
Expand Down
78 changes: 63 additions & 15 deletions pkg/v1/remote/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,9 @@ func TestInitiateUploadNoMountsExists(t *testing.T) {
expectedRepo := "foo/bar"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"origin": []string{""},
}.Encode()

w, closer, err := setupWriter(expectedRepo, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -257,7 +258,7 @@ func TestInitiateUploadNoMountsExists(t *testing.T) {
}
defer closer.Close()

_, mounted, err := w.initiateUpload("baz/bar", h.String())
_, mounted, err := w.initiateUpload("baz/bar", h.String(), "")
if err != nil {
t.Errorf("intiateUpload() = %v", err)
}
Expand All @@ -272,8 +273,9 @@ func TestInitiateUploadNoMountsInitiated(t *testing.T) {
expectedRepo := "baz/blah"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"origin": []string{""},
}.Encode()
expectedLocation := "https://somewhere.io/upload?foo=bar"

Expand All @@ -295,7 +297,7 @@ func TestInitiateUploadNoMountsInitiated(t *testing.T) {
}
defer closer.Close()

location, mounted, err := w.initiateUpload("baz/bar", h.String())
location, mounted, err := w.initiateUpload("baz/bar", h.String(), "")
if err != nil {
t.Errorf("intiateUpload() = %v", err)
}
Expand All @@ -313,8 +315,9 @@ func TestInitiateUploadNoMountsBadStatus(t *testing.T) {
expectedRepo := "ugh/another"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"origin": []string{""},
}.Encode()

w, closer, err := setupWriter(expectedRepo, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -334,7 +337,7 @@ func TestInitiateUploadNoMountsBadStatus(t *testing.T) {
}
defer closer.Close()

location, mounted, err := w.initiateUpload("baz/bar", h.String())
location, mounted, err := w.initiateUpload("baz/bar", h.String(), "")
if err == nil {
t.Errorf("intiateUpload() = %v, %v; wanted error", location, mounted)
}
Expand All @@ -346,8 +349,9 @@ func TestInitiateUploadMountsWithMountFromDifferentRegistry(t *testing.T) {
expectedRepo := "yet/again"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"mount": []string{h.String()},
"from": []string{"baz/bar"},
"origin": []string{""},
}.Encode()

w, closer, err := setupWriter(expectedRepo, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -367,7 +371,7 @@ func TestInitiateUploadMountsWithMountFromDifferentRegistry(t *testing.T) {
}
defer closer.Close()

_, mounted, err := w.initiateUpload("baz/bar", h.String())
_, mounted, err := w.initiateUpload("baz/bar", h.String(), "")
if err != nil {
t.Errorf("intiateUpload() = %v", err)
}
Expand All @@ -383,8 +387,9 @@ func TestInitiateUploadMountsWithMountFromTheSameRegistry(t *testing.T) {
expectedRepo := "yet/again"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{expectedMountRepo},
"mount": []string{h.String()},
"from": []string{expectedMountRepo},
"origin": []string{""},
}.Encode()

serverHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -407,7 +412,50 @@ func TestInitiateUploadMountsWithMountFromTheSameRegistry(t *testing.T) {
}
defer closer.Close()

_, mounted, err := w.initiateUpload(expectedMountRepo, h.String())
_, mounted, err := w.initiateUpload(expectedMountRepo, h.String(), "")
if err != nil {
t.Errorf("intiateUpload() = %v", err)
}
if !mounted {
t.Error("initiateUpload() = !mounted, want mounted")
}
}

// My new test
func TestInitiateUploadMountsWithOrigin(t *testing.T) {
img := setupImage(t)
h := mustConfigName(t, img)
expectedMountRepo := "a/different/repo"
expectedRepo := "yet/again"
expectedPath := fmt.Sprintf("/v2/%s/blobs/uploads/", expectedRepo)
expectedOrigin := "fakeOrigin"
expectedQuery := url.Values{
"mount": []string{h.String()},
"from": []string{expectedMountRepo},
"origin": []string{expectedOrigin},
}.Encode()

serverHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
t.Errorf("Method; got %v, want %v", r.Method, http.MethodPost)
}
if r.URL.Path != expectedPath {
t.Errorf("URL; got %v, want %v", r.URL.Path, expectedPath)
}
if r.URL.RawQuery != expectedQuery {
t.Errorf("RawQuery; got %v, want %v", r.URL.RawQuery, expectedQuery)
}
http.Error(w, "Mounted", http.StatusCreated)
})
server := httptest.NewServer(serverHandler)

w, closer, err := setupWriterWithServer(server, expectedRepo)
if err != nil {
t.Fatalf("setupWriterWithServer() = %v", err)
}
defer closer.Close()

_, mounted, err := w.initiateUpload(expectedMountRepo, h.String(), "fakeOrigin")
if err != nil {
t.Errorf("intiateUpload() = %v", err)
}
Expand Down