increase test coverage and fix some minor bugs

pull/674/head
Simon Aronsson 4 years ago
parent 723d2e9488
commit 2b68874087
No known key found for this signature in database
GPG Key ID: 8DA57A5FD341605B

@ -76,7 +76,11 @@ func GetChallengeRequest(url url2.URL) (*http.Request, error) {
func GetBearerToken(ctx context.Context, challenge string, img string, err error, credentials *types.RegistryCredentials) (string, error) { func GetBearerToken(ctx context.Context, challenge string, img string, err error, credentials *types.RegistryCredentials) (string, error) {
log := logger.GetLogger(ctx) log := logger.GetLogger(ctx)
client := http.Client{} client := http.Client{}
authURL := GetAuthURL(challenge, img)
authURL, err := GetAuthURL(challenge, img)
if err != nil {
return "", err
}
var r *http.Request var r *http.Request
if r, err = http.NewRequest("GET", authURL.String(), nil); err != nil { if r, err = http.NewRequest("GET", authURL.String(), nil); err != nil {
@ -107,8 +111,10 @@ func GetBearerToken(ctx context.Context, challenge string, img string, err error
} }
// GetAuthURL from the instructions in the challenge // GetAuthURL from the instructions in the challenge
func GetAuthURL(challenge string, img string) *url2.URL { func GetAuthURL(challenge string, img string) (*url2.URL, error) {
raw := strings.TrimPrefix(challenge, "bearer") loweredChallenge := strings.ToLower(challenge)
raw := strings.TrimPrefix(loweredChallenge, "bearer")
pairs := strings.Split(raw, ",") pairs := strings.Split(raw, ",")
values := make(map[string]string, 0) values := make(map[string]string, 0)
for _, pair := range pairs { for _, pair := range pairs {
@ -119,6 +125,10 @@ func GetAuthURL(challenge string, img string) *url2.URL {
values[key] = val values[key] = val
} }
if values["realm"] == "" || values["service"] == "" || values["scope"] == "" {
return nil, fmt.Errorf("challenge header did not include all values needed to construct an auth url")
}
authURL, _ := url2.Parse(fmt.Sprintf("%s", values["realm"])) authURL, _ := url2.Parse(fmt.Sprintf("%s", values["realm"]))
q := authURL.Query() q := authURL.Query()
q.Add("service", values["service"]) q.Add("service", values["service"])
@ -127,7 +137,7 @@ func GetAuthURL(challenge string, img string) *url2.URL {
q.Add("scope", scope) q.Add("scope", scope)
authURL.RawQuery = q.Encode() authURL.RawQuery = q.Encode()
return authURL return authURL, nil
} }
// GetChallengeURL creates a URL object based on the image info // GetChallengeURL creates a URL object based on the image info

@ -0,0 +1,52 @@
package auth
import (
"net/url"
"testing"
. "github.com/onsi/gomega"
. "github.com/onsi/ginkgo"
)
func TestAuth(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Registry Auth Suite")
}
var _ = Describe("the auth module", func() {
When("getting an auth url", func() {
It("should create a valid auth url object based on the challenge header supplied", func() {
input := `bearer realm="https://ghcr.io/token",service="ghcr.io",scope="repository:user/image:pull"`
expected := &url.URL{
Host: "ghcr.io",
Scheme: "https",
Path: "/token",
RawQuery: "scope=repository%3Acontainrrr%2Fwatchtower%3Apull&service=ghcr.io",
}
res, err := GetAuthURL(input, "containrrr/watchtower")
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expected))
})
It("should create a valid auth url object based on the challenge header supplied", func() {
input := `bearer realm="https://ghcr.io/token",service="ghcr.io"`
res, err := GetAuthURL(input, "containrrr/watchtower")
Expect(err).To(HaveOccurred())
Expect(res).To(BeNil())
})
})
When("getting a challenge url", func() {
It("should create a valid challenge url object based on the image ref supplied", func() {
expected := url.URL{ Host: "ghcr.io", Scheme: "https", Path: "/v2/"}
Expect(GetChallengeURL("ghcr.io/containrrr/watchtower:latest")).To(Equal(expected))
})
It("should assume dockerhub if the image ref is not fully qualified", func() {
expected := url.URL{ Host: "index.docker.io", Scheme: "https", Path: "/v2/"}
Expect(GetChallengeURL("containrrr/watchtower:latest")).To(Equal(expected))
})
It("should convert legacy dockerhub hostnames to index.docker.io", func() {
expected := url.URL{ Host: "index.docker.io", Scheme: "https", Path: "/v2/"}
Expect(GetChallengeURL("docker.io/containrrr/watchtower:latest")).To(Equal(expected))
Expect(GetChallengeURL("registry-1.docker.io/containrrr/watchtower:latest")).To(Equal(expected))
})
})
})

@ -11,12 +11,9 @@ import (
// BuildManifestURL from raw image data // BuildManifestURL from raw image data
func BuildManifestURL(image apiTypes.ImageInspect) (string, error) { func BuildManifestURL(image apiTypes.ImageInspect) (string, error) {
parts := strings.Split(image.RepoTags[0], ":") img, tag := extractImageAndTag(image)
img := parts[0]
tag := parts[1]
hostName, err := ref.ParseNormalizedNamed(img) hostName, err := ref.ParseNormalizedNamed(img)
fmt.Println(hostName)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -25,7 +22,7 @@ func BuildManifestURL(image apiTypes.ImageInspect) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
img = strings.TrimPrefix(img, host) img = strings.TrimPrefix(img, fmt.Sprintf("%s/", host))
url := url2.URL{ url := url2.URL{
Scheme: "https", Scheme: "https",
Host: host, Host: host,
@ -33,3 +30,17 @@ func BuildManifestURL(image apiTypes.ImageInspect) (string, error) {
} }
return url.String(), nil return url.String(), nil
} }
func extractImageAndTag(image apiTypes.ImageInspect) (string, string) {
var img string
var tag string
if strings.Contains(image.RepoTags[0], ":") {
parts := strings.Split(image.RepoTags[0], ":")
img = parts[0]
tag = parts[1]
} else {
img = image.RepoTags[0]
tag = "latest"
}
return img, tag
}

@ -0,0 +1,57 @@
package manifest_test
import (
"github.com/containrrr/watchtower/pkg/registry/manifest"
apiTypes "github.com/docker/docker/api/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestManifest(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Manifest Suite")
}
var _ = Describe("the manifest module", func() {
When("building a manifest url", func() {
It("should return a valid url given a fully qualified image", func() {
expected := "https://ghcr.io/v2/containrrr/watchtower/manifests/latest"
imageInfo := apiTypes.ImageInspect{
RepoTags: []string {
"ghcr.io/containrrr/watchtower:latest",
},
}
res, err := manifest.BuildManifestURL(imageInfo)
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expected))
})
It("should assume dockerhub for non-qualified images", func() {
expected := "https://index.docker.io/v2/containrrr/watchtower/manifests/latest"
imageInfo := apiTypes.ImageInspect{
RepoTags: []string {
"containrrr/watchtower:latest",
},
}
res, err := manifest.BuildManifestURL(imageInfo)
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expected))
})
It("should assume latest for images that lack an explicit tag", func() {
expected := "https://index.docker.io/v2/containrrr/watchtower/manifests/latest"
imageInfo := apiTypes.ImageInspect{
RepoTags: []string {
"containrrr/watchtower",
},
}
res, err := manifest.BuildManifestURL(imageInfo)
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(expected))
})
})
})
Loading…
Cancel
Save