Add rewrite support to hosts.toml loader
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
parent
ba6b205d0f
commit
f660f4424f
@ -54,6 +54,7 @@ type hostConfig struct {
|
|||||||
|
|
||||||
header http.Header
|
header http.Header
|
||||||
|
|
||||||
|
rewrites map[string]string
|
||||||
// TODO: Add credential configuration (domain alias, username)
|
// TODO: Add credential configuration (domain alias, username)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,6 +264,7 @@ func ConfigureHosts(ctx context.Context, options HostOptions) docker.RegistryHos
|
|||||||
rhosts[i].Path = host.path
|
rhosts[i].Path = host.path
|
||||||
rhosts[i].Capabilities = host.capabilities
|
rhosts[i].Capabilities = host.capabilities
|
||||||
rhosts[i].Header = host.header
|
rhosts[i].Header = host.header
|
||||||
|
rhosts[i].Rewrites = host.rewrites
|
||||||
}
|
}
|
||||||
|
|
||||||
return rhosts, nil
|
return rhosts, nil
|
||||||
@ -352,6 +354,10 @@ type hostFileConfig struct {
|
|||||||
// API root endpoint.
|
// API root endpoint.
|
||||||
OverridePath bool `toml:"override_path"`
|
OverridePath bool `toml:"override_path"`
|
||||||
|
|
||||||
|
// Rewrites contains a map of regex/replacement values, used to modify
|
||||||
|
// the image name when pulling.
|
||||||
|
Rewrites map[string]string `toml:"rewrite"`
|
||||||
|
|
||||||
// TODO: Credentials: helper? name? username? alternate domain? token?
|
// TODO: Credentials: helper? name? username? alternate domain? token?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,13 +395,22 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) {
|
|||||||
hosts = append(hosts, parsed)
|
hosts = append(hosts, parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse root host config and append it as the last element
|
tree, err := getTopLevelKeyValues(b)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the server key is set at the root of the tree, or no other hosts are configured,
|
||||||
|
// parse the root host config and append it as the last element.
|
||||||
|
// This allows not using upstream by including hosts and excluding the server key as documented at
|
||||||
|
// https://github.com/containerd/containerd/blob/release/1.7/docs/hosts.md#setup-a-local-mirror-for-docker
|
||||||
|
if _, ok := tree["server"]; ok || len(hosts) == 0 {
|
||||||
parsed, err := parseHostConfig(c.Server, baseDir, c.hostFileConfig)
|
parsed, err := parseHostConfig(c.Server, baseDir, c.hostFileConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hosts = append(hosts, parsed)
|
hosts = append(hosts, parsed)
|
||||||
|
}
|
||||||
return hosts, nil
|
return hosts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,6 +442,7 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.skipVerify = config.SkipVerify
|
result.skipVerify = config.SkipVerify
|
||||||
|
result.rewrites = config.Rewrites
|
||||||
|
|
||||||
if len(config.Capabilities) > 0 {
|
if len(config.Capabilities) > 0 {
|
||||||
for _, c := range config.Capabilities {
|
for _, c := range config.Capabilities {
|
||||||
@ -515,6 +531,32 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTopLevelKeyValues(b []byte) (map[string]string, error) {
|
||||||
|
keyVals := map[string]string{}
|
||||||
|
|
||||||
|
// Use toml unstable package for directly parsing toml
|
||||||
|
// See https://github.com/pelletier/go-toml/discussions/801#discussioncomment-7083586
|
||||||
|
p := tomlu.Parser{}
|
||||||
|
p.Reset(b)
|
||||||
|
|
||||||
|
// iterate over top level expressions until we find something that's not a simple KeyValue
|
||||||
|
for p.NextExpression() {
|
||||||
|
e := p.Expression()
|
||||||
|
|
||||||
|
if e.Kind != tomlu.KeyValue {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
k := e.Key()
|
||||||
|
v := e.Value()
|
||||||
|
if keyNode := k.Node(); keyNode != nil && v != nil {
|
||||||
|
keyVals[string(keyNode.Data)] = string(v.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyVals, p.Error()
|
||||||
|
}
|
||||||
|
|
||||||
// getSortedHosts returns the list of hosts in the order are they defined in the file.
|
// getSortedHosts returns the list of hosts in the order are they defined in the file.
|
||||||
func getSortedHosts(b []byte) ([]string, error) {
|
func getSortedHosts(b []byte) ([]string, error) {
|
||||||
var hostsInOrder []string
|
var hostsInOrder []string
|
||||||
|
@ -197,7 +197,7 @@ type Mirror struct {
|
|||||||
// The scheme, host and path from the endpoint URL will be used.
|
// The scheme, host and path from the endpoint URL will be used.
|
||||||
Endpoints []string `toml:"endpoint" json:"endpoint"`
|
Endpoints []string `toml:"endpoint" json:"endpoint"`
|
||||||
|
|
||||||
// Rewrites are repository rewrite rules for a namespace. When fetching image resources
|
// Rewrites is a map of repository rewrite rules for a namespace. When fetching image resources
|
||||||
// from an endpoint and a key matches the repository via regular expression matching
|
// from an endpoint and a key matches the repository via regular expression matching
|
||||||
// it will be replaced with the corresponding value from the map in the resource request.
|
// it will be replaced with the corresponding value from the map in the resource request.
|
||||||
//
|
//
|
||||||
|
@ -437,14 +437,14 @@ func (c *CRIImageService) registryHosts(ctx context.Context, credentials func(ho
|
|||||||
return func(host string) ([]docker.RegistryHost, error) {
|
return func(host string) ([]docker.RegistryHost, error) {
|
||||||
var registries []docker.RegistryHost
|
var registries []docker.RegistryHost
|
||||||
|
|
||||||
endpoints, err := c.registryEndpoints(host)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("get registry endpoints: %w", err)
|
|
||||||
}
|
|
||||||
rewrites, err := c.registryRewrites(host)
|
rewrites, err := c.registryRewrites(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get registry rewrites: %w", err)
|
return nil, fmt.Errorf("get registry rewrites: %w", err)
|
||||||
}
|
}
|
||||||
|
endpoints, err := c.registryEndpoints(host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get registry endpoints: %w", err)
|
||||||
|
}
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
u, err := url.Parse(e)
|
u, err := url.Parse(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -570,17 +570,13 @@ func (c *CRIImageService) registryEndpoints(host string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CRIImageService) registryRewrites(host string) (map[string]string, error) {
|
func (c *CRIImageService) registryRewrites(host string) (map[string]string, error) {
|
||||||
var rewrites map[string]string
|
hosts := []string{host, "*"}
|
||||||
_, ok := c.config.Registry.Mirrors[host]
|
for _, host := range hosts {
|
||||||
if ok {
|
if host, ok := c.config.Registry.Mirrors[host]; ok {
|
||||||
rewrites = c.config.Registry.Mirrors[host].Rewrites
|
return host.Rewrites, nil
|
||||||
} else {
|
|
||||||
rewrites = c.config.Registry.Mirrors["*"].Rewrites
|
|
||||||
}
|
}
|
||||||
if rewrites == nil {
|
|
||||||
rewrites = map[string]string{}
|
|
||||||
}
|
}
|
||||||
return rewrites, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTransport returns a new HTTP transport used to pull image.
|
// newTransport returns a new HTTP transport used to pull image.
|
||||||
|
Loading…
Reference in New Issue
Block a user