Add tags implementation
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)master
							parent
							
								
									2eb9b286ed
								
							
						
					
					
						commit
						7d630192dd
					
				| 
						 | 
				
			
			@ -112,3 +112,10 @@ func parseHTTPErrorResponse(response *http.Response) error {
 | 
			
		|||
	}
 | 
			
		||||
	return &errors
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func handleErrorResponse(resp *http.Response) error {
 | 
			
		||||
	if resp.StatusCode >= 400 && resp.StatusCode < 500 {
 | 
			
		||||
		return parseHTTPErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
	return &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,14 +26,10 @@ type httpLayerUpload struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (hlu *httpLayerUpload) handleErrorResponse(resp *http.Response) error {
 | 
			
		||||
	switch {
 | 
			
		||||
	case resp.StatusCode == http.StatusNotFound:
 | 
			
		||||
	if resp.StatusCode == http.StatusNotFound {
 | 
			
		||||
		return &BlobUploadNotFoundError{Location: hlu.location}
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
	}
 | 
			
		||||
	return handleErrorResponse(resp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hlu *httpLayerUpload) ReadFrom(r io.Reader) (n int64, err error) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +91,36 @@ type manifests struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (ms *manifests) Tags() ([]string, error) {
 | 
			
		||||
	panic("not implemented")
 | 
			
		||||
	u, err := ms.ub.BuildTagsURL(ms.name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := ms.client.Get(u)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch {
 | 
			
		||||
	case resp.StatusCode == http.StatusOK:
 | 
			
		||||
		b, err := ioutil.ReadAll(resp.Body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		tagsResponse := struct {
 | 
			
		||||
			Tags []string `json:"tags"`
 | 
			
		||||
		}{}
 | 
			
		||||
		if err := json.Unmarshal(b, &tagsResponse); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return tagsResponse.Tags, nil
 | 
			
		||||
	case resp.StatusCode == http.StatusNotFound:
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ms *manifests) Exists(dgst digest.Digest) (bool, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,10 +143,8 @@ func (ms *manifests) ExistsByTag(tag string) (bool, error) {
 | 
			
		|||
		return true, nil
 | 
			
		||||
	case resp.StatusCode == http.StatusNotFound:
 | 
			
		||||
		return false, nil
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return false, parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return false, &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return false, handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,10 +174,8 @@ func (ms *manifests) GetByTag(tag string) (*manifest.SignedManifest, error) {
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		return &sm, nil
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return nil, parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return nil, handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -174,10 +200,8 @@ func (ms *manifests) Put(m *manifest.SignedManifest) error {
 | 
			
		|||
	case resp.StatusCode == http.StatusAccepted:
 | 
			
		||||
		// TODO(dmcgowan): Use or check digest header
 | 
			
		||||
		return nil
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -200,10 +224,8 @@ func (ms *manifests) Delete(dgst digest.Digest) error {
 | 
			
		|||
	switch {
 | 
			
		||||
	case resp.StatusCode == http.StatusOK:
 | 
			
		||||
		return nil
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -275,10 +297,8 @@ func (ls *layers) Upload() (distribution.LayerUpload, error) {
 | 
			
		|||
			startedAt: time.Now(),
 | 
			
		||||
			location:  location,
 | 
			
		||||
		}, nil
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return nil, parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return nil, handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -327,9 +347,7 @@ func (ls *layers) fetchLayer(dgst digest.Digest) (distribution.Layer, error) {
 | 
			
		|||
				BlobSum: dgst,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	case resp.StatusCode >= 400 && resp.StatusCode < 500:
 | 
			
		||||
		return nil, parseHTTPErrorResponse(resp)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, &UnexpectedHTTPStatusError{Status: resp.Status}
 | 
			
		||||
		return nil, handleErrorResponse(resp)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -602,3 +603,54 @@ func TestManifestPut(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// TODO(dmcgowan): Check for error cases
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestManifestTags(t *testing.T) {
 | 
			
		||||
	repo := "test.example.com/repo/tags/list"
 | 
			
		||||
	tagsList := []byte(strings.TrimSpace(`
 | 
			
		||||
{
 | 
			
		||||
	"name": "test.example.com/repo/tags/list",
 | 
			
		||||
	"tags": [
 | 
			
		||||
		"tag1",
 | 
			
		||||
		"tag2",
 | 
			
		||||
		"funtag"
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
	`))
 | 
			
		||||
	var m testutil.RequestResponseMap
 | 
			
		||||
	addPing(&m)
 | 
			
		||||
	m = append(m, testutil.RequestResponseMapping{
 | 
			
		||||
		Request: testutil.Request{
 | 
			
		||||
			Method: "GET",
 | 
			
		||||
			Route:  "/v2/" + repo + "/tags/list",
 | 
			
		||||
		},
 | 
			
		||||
		Response: testutil.Response{
 | 
			
		||||
			StatusCode: http.StatusOK,
 | 
			
		||||
			Body:       tagsList,
 | 
			
		||||
			Headers: http.Header(map[string][]string{
 | 
			
		||||
				"Content-Length": {fmt.Sprint(len(tagsList))},
 | 
			
		||||
				"Last-Modified":  {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
 | 
			
		||||
			}),
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	e, c := testServer(m)
 | 
			
		||||
	defer c()
 | 
			
		||||
 | 
			
		||||
	r, err := NewRepository(context.Background(), repo, e, &RepositoryConfig{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ms := r.Manifests()
 | 
			
		||||
	tags, err := ms.Tags()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(tags) != 3 {
 | 
			
		||||
		t.Fatalf("Wrong number of tags returned: %d, expected 3", len(tags))
 | 
			
		||||
	}
 | 
			
		||||
	// TODO(dmcgowan): Check array
 | 
			
		||||
 | 
			
		||||
	// TODO(dmcgowan): Check for error cases
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue