diff --git a/cmd/nerdctl/run.go b/cmd/nerdctl/run.go index 7d55a30f9dd..06412130eb8 100644 --- a/cmd/nerdctl/run.go +++ b/cmd/nerdctl/run.go @@ -32,7 +32,6 @@ import ( "github.com/containerd/console" "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands/tasks" "github.com/containerd/containerd/containers" @@ -769,17 +768,25 @@ func generateLogURI(dataStore, logDriver string, logOptMap map[string]string) (* } else { return nil, fmt.Errorf("%s is not yet supported", logDriver) } - args := map[string]string{ - logging.MagicArgv1: dataStore, - } - for k, v := range logOptMap { - args[k] = v + filePath := filepath.Clean(selfExe) + if !strings.HasPrefix(filePath, "/") { + return nil, errors.New("absolute filePath needed") } if runtime.GOOS == "windows" { return nil, nil } + uri := &url.URL{ + Scheme: "binary", + Path: filePath, + } + query := strutil.NewOrderedQuery() + query.Set(logging.MagicArgv1, dataStore) - return cio.LogURIGenerator("binary", selfExe, args) + for k, v := range logOptMap { + query.Set(k, v) + } + uri.RawQuery = query.Encode() + return uri, nil } func withNerdctlOCIHook(cmd *cobra.Command, id, stateDir string) (oci.SpecOpts, error) { diff --git a/pkg/strutil/strutil.go b/pkg/strutil/strutil.go index 4d1eab00b7e..9120be1f353 100644 --- a/pkg/strutil/strutil.go +++ b/pkg/strutil/strutil.go @@ -32,6 +32,7 @@ package strutil import ( "encoding/csv" "fmt" + "net/url" "reflect" "strconv" "strings" @@ -130,3 +131,58 @@ func ParseBoolOrAuto(s string) (*bool, error) { b, err := strconv.ParseBool(s) return &b, err } + +type OrderedQuery struct { + index []string + data map[string][]string +} + +func NewOrderedQuery() *OrderedQuery { + return &OrderedQuery{[]string{}, map[string][]string{}} +} + +func (orderedQuery *OrderedQuery) Get(key string) string { + if orderedQuery == nil { + return "" + } + vs := orderedQuery.data[key] + if len(vs) == 0 { + return "" + } + return vs[0] +} + +// Set sets the key to value. It replaces any existing +// values. +func (orderedQuery *OrderedQuery) Set(key, value string) { + orderedQuery.data[key] = []string{value} + orderedQuery.index = append(orderedQuery.index, key) +} + +// Add adds the value to key. It appends to any existing +// values associated with key. +func (orderedQuery *OrderedQuery) Add(key, value string) { + orderedQuery.data[key] = append(orderedQuery.data[key], value) +} + +// Encode encodes the values into ``URL encoded'' form +// ("bar=baz&foo=quux") sorted by key. +func (orderedQuery *OrderedQuery) Encode() string { + if orderedQuery == nil { + return "" + } + var buf strings.Builder + for _, k := range orderedQuery.index { + vs := orderedQuery.data[k] + keyEscaped := url.QueryEscape(k) + for _, v := range vs { + if buf.Len() > 0 { + buf.WriteByte('&') + } + buf.WriteString(keyEscaped) + buf.WriteByte('=') + buf.WriteString(url.QueryEscape(v)) + } + } + return buf.String() +} diff --git a/pkg/strutil/strutil_test.go b/pkg/strutil/strutil_test.go index a25bb5dd2e6..e0320910c72 100644 --- a/pkg/strutil/strutil_test.go +++ b/pkg/strutil/strutil_test.go @@ -281,3 +281,11 @@ func TestParseCSVMap(t *testing.T) { }) } } + +func TestOrderedQuery(t *testing.T) { + query := NewOrderedQuery() + query.Set("abc", "1") + query.Set("aa", "2") + result := query.Encode() + assert.Equal(t, result, "abc=1&aa=2", "") +}