Add support for registry host path override

Adds support for mirrors which are non-compliant with the
OCI distribution specification but have previously mirrored
content with a namespace prefix after the API root `/v2`.

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2021-07-01 17:49:32 -07:00
parent 95c708572f
commit a7ad6b3be5
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
3 changed files with 42 additions and 7 deletions

View File

@ -274,6 +274,17 @@ or
x-custom-1-2 = "another custom header" x-custom-1-2 = "another custom header"
``` ```
## override_path field
`override_path` is used to indicate the host's API root endpoint is defined
in the URL path rather than by the API specification. This may be used with
non-compliant OCI registries which are missing the `/v2` prefix.
(Defaults to `false`)
```
override_path = true
```
## host field(s) (in the toml table format) ## host field(s) (in the toml table format)
`[host]."https://namespace"` and `[host].http://namespace` entries in the `[host]."https://namespace"` and `[host].http://namespace` entries in the
@ -310,6 +321,10 @@ for this registry host namespace:
[host."https://test-3.registry"] [host."https://test-3.registry"]
client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"] client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"]
[host."https://non-compliant-mirror.registry/v2/upstream"]
capabilities = ["pull"]
override_path = true
``` ```
**Note**: Recursion is not supported in the specification of host mirror **Note**: Recursion is not supported in the specification of host mirror

View File

@ -291,7 +291,7 @@ type hostFileConfig struct {
// Accepted types // Accepted types
// - string - Single file with public and private keys // - string - Single file with public and private keys
// - []string - Multiple files with public and private keys // - []string - Multiple files with public and private keys
// - [][2]string - Muliple keypairs with public and private keys in separate files // - [][2]string - Multiple keypairs with public and private keys in separate files
Client interface{} `toml:"client"` Client interface{} `toml:"client"`
// SkipVerify skips verification of the server's certificate chain // SkipVerify skips verification of the server's certificate chain
@ -302,6 +302,12 @@ type hostFileConfig struct {
// Header are additional header files to send to the server // Header are additional header files to send to the server
Header map[string]interface{} `toml:"header"` Header map[string]interface{} `toml:"header"`
// OverridePath indicates the API root endpoint is defined in the URL
// path rather than by the API specification.
// This may be used with non-compliant OCI registries to override the
// API root endpoint.
OverridePath bool `toml:"override_path"`
// TODO: Credentials: helper? name? username? alternate domain? token? // TODO: Credentials: helper? name? username? alternate domain? token?
} }
@ -374,16 +380,12 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
} }
result.scheme = u.Scheme result.scheme = u.Scheme
result.host = u.Host result.host = u.Host
// TODO: Handle path based on registry protocol
// Define a registry protocol type
// OCI v1 - Always use given path as is
// Docker v2 - Always ensure ends with /v2/
if len(u.Path) > 0 { if len(u.Path) > 0 {
u.Path = path.Clean(u.Path) u.Path = path.Clean(u.Path)
if !strings.HasSuffix(u.Path, "/v2") { if !strings.HasSuffix(u.Path, "/v2") && !config.OverridePath {
u.Path = u.Path + "/v2" u.Path = u.Path + "/v2"
} }
} else { } else if !config.OverridePath {
u.Path = "/v2" u.Path = "/v2"
} }
result.path = u.Path result.path = u.Path

View File

@ -104,6 +104,13 @@ ca = "/etc/path/default"
[host."https://test-3.registry"] [host."https://test-3.registry"]
client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"] client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"]
[host."https://noncompliantmirror.registry/v2/namespaceprefix"]
capabilities = ["pull"]
override_path = true
[host."https://noprefixnoncompliant.registry"]
override_path = true
` `
var tb, fb = true, false var tb, fb = true, false
expected := []hostConfig{ expected := []hostConfig{
@ -159,6 +166,17 @@ ca = "/etc/path/default"
{filepath.FromSlash("/etc/certs/client-2.pem")}, {filepath.FromSlash("/etc/certs/client-2.pem")},
}, },
}, },
{
scheme: "https",
host: "noncompliantmirror.registry",
path: "/v2/namespaceprefix",
capabilities: docker.HostCapabilityPull,
},
{
scheme: "https",
host: "noprefixnoncompliant.registry",
capabilities: allCaps,
},
{ {
scheme: "https", scheme: "https",
host: "test-default.registry", host: "test-default.registry",