Skip to content

Commit

Permalink
Keep host order as defined in TOML file
Browse files Browse the repository at this point in the history
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
  • Loading branch information
mxpv committed Apr 1, 2021
1 parent 6866b36 commit 5ada2f7
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
2 changes: 1 addition & 1 deletion pkg/cri/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type Runtime struct {
// This only works for runtime type "io.containerd.runtime.v1.linux".
Root string `toml:"runtime_root" json:"runtimeRoot"`
// Options are config options for the runtime. If options is loaded
// from toml config, it will be toml.Primitive.
// from toml config, it will be toml.Tree.
Options *toml.Tree `toml:"options" json:"options"`
// PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the
// runtime spec when the container is privileged. Defaults to false.
Expand Down
49 changes: 38 additions & 11 deletions remotes/docker/config/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ import (
"os"
"path"
"path/filepath"
"sort"
"strings"
"time"

"github.com/pelletier/go-toml"
"github.com/pkg/errors"

"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/remotes/docker"
"github.com/pelletier/go-toml"
"github.com/pkg/errors"
)

// UpdateClientFunc is a function that lets you to amend http Client behavior used by registry clients.
Expand Down Expand Up @@ -317,6 +317,11 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) {
HostConfigs map[string]hostFileConfig `toml:"host"`
}{}

orderedHosts, err := getSortedHosts(tree)
if err != nil {
return nil, err
}

var (
hosts []hostConfig
)
Expand All @@ -325,22 +330,24 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) {
return nil, err
}

// Parse root host config
parsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig)
if err != nil {
return nil, err
}
hosts = append(hosts, parsed)

// Parse hosts array
for host, config := range c.HostConfigs {
for _, host := range orderedHosts {
config := c.HostConfigs[host]

parsed, err := parseHostConfig(host, baseDir, config)
if err != nil {
return nil, err
}
hosts = append(hosts, parsed)
}

// Parse root host config and append it as the last element
parsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig)
if err != nil {
return nil, err
}
hosts = append(hosts, parsed)

return hosts, nil
}

Expand Down Expand Up @@ -464,6 +471,26 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
return result, nil
}

// getSortedHosts returns the list of hosts as they defined in the file.
func getSortedHosts(root *toml.Tree) ([]string, error) {
iter, ok := root.Get("host").(*toml.Tree)
if !ok {
return nil, errors.Errorf("invalid `host` tree")
}

list := append([]string{}, iter.Keys()...)

// go-toml stores TOML sections in the map object, so no order guaranteed.
// We retrieve line number for each key and sort the keys by position.
sort.Slice(list, func(i, j int) bool {
h1 := iter.GetPath([]string{list[i]}).(*toml.Tree)
h2 := iter.GetPath([]string{list[j]}).(*toml.Tree)
return h1.Position().Line < h2.Position().Line
})

return list, nil
}

// makeStringSlice is a helper func to convert from []interface{} to []string.
// Additionally an optional cb func may be passed to perform string mapping.
func makeStringSlice(slice []interface{}, cb func(string) string) ([]string, error) {
Expand Down
12 changes: 9 additions & 3 deletions remotes/docker/config/hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"

"github.com/containerd/containerd/log/logtest"
"github.com/containerd/containerd/remotes/docker"
)
Expand Down Expand Up @@ -181,7 +179,15 @@ ca = "/etc/path/default"
}
}()

assert.ElementsMatch(t, expected, hosts)
if len(hosts) != len(expected) {
t.Fatalf("Unexpected number of hosts %d, expected %d", len(hosts), len(expected))
}

for i := range hosts {
if !compareHostConfig(hosts[i], expected[i]) {
t.Fatalf("Mismatch at host %d", i)
}
}
}

func TestLoadCertFiles(t *testing.T) {
Expand Down

0 comments on commit 5ada2f7

Please sign in to comment.