unite trust.ParseServerAddress & helpers.NormalizeRegistry

This commit is contained in:
Reinier van der Leer 2023-01-22 16:56:44 +01:00
parent f0e075c390
commit 85f5c1fdb1
No known key found for this signature in database
GPG key ID: DBC4942A5C29D7FA
8 changed files with 46 additions and 95 deletions

View file

@ -177,9 +177,7 @@ func GetScopeFromImageName(img, svc string) string {
// GetChallengeURL creates a URL object based on the image info
func GetChallengeURL(img string) (url.URL, error) {
normalizedNamed, _ := reference.ParseNormalizedNamed(img)
host, err := helpers.NormalizeRegistry(normalizedNamed.String())
host, err := helpers.GetRegistryAddress(img)
if err != nil {
return url.URL{}, err
}

View file

@ -1,36 +1,27 @@
package helpers
import (
"fmt"
url2 "net/url"
"github.com/docker/distribution/reference"
)
// ConvertToHostname strips a url from everything but the hostname part
func ConvertToHostname(url string) (string, string, error) {
urlWithSchema := fmt.Sprintf("x://%s", url)
u, err := url2.Parse(urlWithSchema)
if err != nil {
return "", "", err
}
hostName := u.Hostname()
port := u.Port()
const (
DefaultRegistryDomain = "docker.io"
DefaultRegistryHost = "index.docker.io"
LegacyDefaultRegistryDomain = "index.docker.io"
)
return hostName, port, err
}
// NormalizeRegistry makes sure variations of DockerHubs registry
func NormalizeRegistry(registry string) (string, error) {
hostName, port, err := ConvertToHostname(registry)
// GetRegistryAddress parses an image name
// and returns the address of the specified registry
func GetRegistryAddress(imageRef string) (string, error) {
normalizedRef, err := reference.ParseNormalizedNamed(imageRef)
if err != nil {
return "", err
}
if hostName == "registry-1.docker.io" || hostName == "docker.io" {
hostName = "index.docker.io"
}
address := reference.Domain(normalizedRef)
if port != "" {
return fmt.Sprintf("%s:%s", hostName, port), nil
if address == DefaultRegistryDomain {
address = DefaultRegistryHost
}
return hostName, nil
return address, nil
}

View file

@ -1,9 +1,10 @@
package helpers
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestHelpers(t *testing.T) {
@ -12,20 +13,21 @@ func TestHelpers(t *testing.T) {
}
var _ = Describe("the helpers", func() {
When("converting an url to a hostname", func() {
It("should return docker.io given docker.io/containrrr/watchtower:latest", func() {
host, port, err := ConvertToHostname("docker.io/containrrr/watchtower:latest")
Expect(err).NotTo(HaveOccurred())
Expect(host).To(Equal("docker.io"))
Expect(port).To(BeEmpty())
Describe("GetRegistryAddress", func() {
It("should return error if passed empty string", func() {
_, err := GetRegistryAddress("")
Expect(err).To(HaveOccurred())
})
})
When("normalizing the registry information", func() {
It("should return index.docker.io given docker.io", func() {
out, err := NormalizeRegistry("docker.io/containrrr/watchtower:latest")
Expect(err).NotTo(HaveOccurred())
Expect(out).To(Equal("index.docker.io"))
It("should return index.docker.io if passed an image name with no explicit domain", func() {
Expect(GetRegistryAddress("watchtower")).To(Equal("index.docker.io"))
Expect(GetRegistryAddress("containrrr/watchtower")).To(Equal("index.docker.io"))
})
It("should return the host if passed an image name containing a local host", func() {
Expect(GetRegistryAddress("henk:80/watchtower")).To(Equal("henk:80"))
Expect(GetRegistryAddress("localhost/watchtower")).To(Equal("localhost"))
})
It("should return the server name if passed a fully qualified image name", func() {
Expect(GetRegistryAddress("github.com/containrrr/config")).To(Equal("github.com"))
})
})
})

View file

@ -13,18 +13,16 @@ import (
// BuildManifestURL from raw image data
func BuildManifestURL(container types.Container) (string, error) {
var normalizedTaggedRef ref.NamedTagged
if normalizedRef, err := ref.ParseDockerRef(container.ImageName()); err == nil {
var isTagged bool
normalizedTaggedRef, isTagged = normalizedRef.(ref.NamedTagged)
normalizedRef, err := ref.ParseDockerRef(container.ImageName())
if err != nil {
return "", err
}
normalizedTaggedRef, isTagged := normalizedRef.(ref.NamedTagged)
if !isTagged {
return "", errors.New("Parsed container image ref has no tag: " + normalizedRef.String())
}
} else {
return "", err
}
host, err := helpers.NormalizeRegistry(normalizedTaggedRef.Name())
host, _ := helpers.GetRegistryAddress(normalizedTaggedRef.Name())
img, tag := ExtractImageAndTag(normalizedTaggedRef)
logrus.WithFields(logrus.Fields{

View file

@ -41,17 +41,17 @@ func DefaultAuthHandler() (string, error) {
// Will return false if behavior for container is unknown.
func WarnOnAPIConsumption(container watchtowerTypes.Container) bool {
normalizedName, err := ref.ParseNormalizedNamed(container.ImageName())
normalizedRef, err := ref.ParseNormalizedNamed(container.ImageName())
if err != nil {
return true
}
containerHost, err := helpers.NormalizeRegistry(normalizedName.String())
containerHost, err := helpers.GetRegistryAddress(normalizedRef.Name())
if err != nil {
return true
}
if containerHost == "index.docker.io" || containerHost == "ghcr.io" {
if containerHost == helpers.DefaultRegistryHost || containerHost == "ghcr.io" {
return true
}

View file

@ -23,11 +23,9 @@ var _ = Describe("Registry", func() {
})
When("Given a container with an image explicitly from dockerhub", func() {
It("should want to warn", func() {
Expect(testContainerWithImage("registry-1.docker.io/docker:latest")).To(BeTrue())
Expect(testContainerWithImage("index.docker.io/docker:latest")).To(BeTrue())
Expect(testContainerWithImage("docker.io/docker:latest")).To(BeTrue())
})
})
When("Given a container with an image from some other registry", func() {
It("should not want to warn", func() {

View file

@ -5,13 +5,12 @@ import (
"encoding/json"
"errors"
"os"
"strings"
"github.com/containrrr/watchtower/pkg/registry/helpers"
cliconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/cli/cli/config/types"
"github.com/docker/distribution/reference"
log "github.com/sirupsen/logrus"
)
@ -48,12 +47,13 @@ func EncodedEnvAuth(ref string) (string, error) {
// loaded from the docker config
// Returns an empty string if credentials cannot be found for the referenced server
// The docker config must be mounted on the container
func EncodedConfigAuth(ref string) (string, error) {
server, err := ParseServerAddress(ref)
func EncodedConfigAuth(imageRef string) (string, error) {
server, err := helpers.GetRegistryAddress(imageRef)
if err != nil {
log.Errorf("Unable to parse the image ref %s", err)
log.Errorf("Could not get registry from image ref %s", imageRef)
return "", err
}
configDir := os.Getenv("DOCKER_CONFIG")
if configDir == "" {
configDir = "/"
@ -70,23 +70,11 @@ func EncodedConfigAuth(ref string) (string, error) {
log.WithField("config_file", configFile.Filename).Debugf("No credentials for %s found", server)
return "", nil
}
log.Debugf("Loaded auth credentials for user %s, on registry %s, from file %s", auth.Username, ref, configFile.Filename)
log.Debugf("Loaded auth credentials for user %s, on registry %s, from file %s", auth.Username, server, configFile.Filename)
log.Tracef("Using auth password %s", auth.Password)
return EncodeAuth(auth)
}
// ParseServerAddress extracts the server part from a container image ref
func ParseServerAddress(ref string) (string, error) {
parsedRef, err := reference.Parse(ref)
if err != nil {
return ref, err
}
parts := strings.Split(parsedRef.String(), "/")
return parts[0], nil
}
// CredentialsStore returns a new credentials store based
// on the settings provided in the configuration file.
func CredentialsStore(configFile configfile.ConfigFile) credentials.Store {

View file

@ -36,30 +36,6 @@ var _ = Describe("Testing with Ginkgo", func() {
_, err = EncodedConfigAuth("")
Expect(err).To(HaveOccurred())
})
/*
* TODO:
* This part only confirms that it still works in the same way as it did
* with the old version of the docker api client sdk. I'd say that
* ParseServerAddress likely needs to be elaborated a bit to default to
* dockerhub in case no server address was provided.
*
* ++ @simskij, 2019-04-04
*/
It("parse server address_ should return error if passed empty string", func() {
_, err := ParseServerAddress("")
Expect(err).To(HaveOccurred())
})
It("parse server address_ should return the organization part if passed an image name missing server name", func() {
val, _ := ParseServerAddress("containrrr/config")
Expect(val).To(Equal("containrrr"))
})
It("parse server address_ should return the server name if passed a fully qualified image name", func() {
val, _ := ParseServerAddress("github.com/containrrrr/config")
Expect(val).To(Equal("github.com"))
})
})