Skip to content

Commit 5ada2f7

Browse files
committed
Keep host order as defined in TOML file
Signed-off-by: Maksym Pavlenko <[email protected]>
1 parent 6866b36 commit 5ada2f7

3 files changed

Lines changed: 48 additions & 15 deletions

File tree

pkg/cri/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ type Runtime struct {
4848
// This only works for runtime type "io.containerd.runtime.v1.linux".
4949
Root string `toml:"runtime_root" json:"runtimeRoot"`
5050
// Options are config options for the runtime. If options is loaded
51-
// from toml config, it will be toml.Primitive.
51+
// from toml config, it will be toml.Tree.
5252
Options *toml.Tree `toml:"options" json:"options"`
5353
// PrivilegedWithoutHostDevices overloads the default behaviour for adding host devices to the
5454
// runtime spec when the container is privileged. Defaults to false.

remotes/docker/config/hosts.go

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ import (
2727
"os"
2828
"path"
2929
"path/filepath"
30+
"sort"
3031
"strings"
3132
"time"
3233

33-
"github.com/pelletier/go-toml"
34-
"github.com/pkg/errors"
35-
3634
"github.com/containerd/containerd/errdefs"
3735
"github.com/containerd/containerd/log"
3836
"github.com/containerd/containerd/remotes/docker"
37+
"github.com/pelletier/go-toml"
38+
"github.com/pkg/errors"
3939
)
4040

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

320+
orderedHosts, err := getSortedHosts(tree)
321+
if err != nil {
322+
return nil, err
323+
}
324+
320325
var (
321326
hosts []hostConfig
322327
)
@@ -325,22 +330,24 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) {
325330
return nil, err
326331
}
327332

328-
// Parse root host config
329-
parsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig)
330-
if err != nil {
331-
return nil, err
332-
}
333-
hosts = append(hosts, parsed)
334-
335333
// Parse hosts array
336-
for host, config := range c.HostConfigs {
334+
for _, host := range orderedHosts {
335+
config := c.HostConfigs[host]
336+
337337
parsed, err := parseHostConfig(host, baseDir, config)
338338
if err != nil {
339339
return nil, err
340340
}
341341
hosts = append(hosts, parsed)
342342
}
343343

344+
// Parse root host config and append it as the last element
345+
parsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig)
346+
if err != nil {
347+
return nil, err
348+
}
349+
hosts = append(hosts, parsed)
350+
344351
return hosts, nil
345352
}
346353

@@ -464,6 +471,26 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host
464471
return result, nil
465472
}
466473

474+
// getSortedHosts returns the list of hosts as they defined in the file.
475+
func getSortedHosts(root *toml.Tree) ([]string, error) {
476+
iter, ok := root.Get("host").(*toml.Tree)
477+
if !ok {
478+
return nil, errors.Errorf("invalid `host` tree")
479+
}
480+
481+
list := append([]string{}, iter.Keys()...)
482+
483+
// go-toml stores TOML sections in the map object, so no order guaranteed.
484+
// We retrieve line number for each key and sort the keys by position.
485+
sort.Slice(list, func(i, j int) bool {
486+
h1 := iter.GetPath([]string{list[i]}).(*toml.Tree)
487+
h2 := iter.GetPath([]string{list[j]}).(*toml.Tree)
488+
return h1.Position().Line < h2.Position().Line
489+
})
490+
491+
return list, nil
492+
}
493+
467494
// makeStringSlice is a helper func to convert from []interface{} to []string.
468495
// Additionally an optional cb func may be passed to perform string mapping.
469496
func makeStringSlice(slice []interface{}, cb func(string) string) ([]string, error) {

remotes/docker/config/hosts_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import (
2626
"path/filepath"
2727
"testing"
2828

29-
"github.com/stretchr/testify/assert"
30-
3129
"github.com/containerd/containerd/log/logtest"
3230
"github.com/containerd/containerd/remotes/docker"
3331
)
@@ -181,7 +179,15 @@ ca = "/etc/path/default"
181179
}
182180
}()
183181

184-
assert.ElementsMatch(t, expected, hosts)
182+
if len(hosts) != len(expected) {
183+
t.Fatalf("Unexpected number of hosts %d, expected %d", len(hosts), len(expected))
184+
}
185+
186+
for i := range hosts {
187+
if !compareHostConfig(hosts[i], expected[i]) {
188+
t.Fatalf("Mismatch at host %d", i)
189+
}
190+
}
185191
}
186192

187193
func TestLoadCertFiles(t *testing.T) {

0 commit comments

Comments
 (0)