Skip to content

Commit 50f2580

Browse files
authored
Merge pull request #1056 from AkihiroSuda/fix-logging-argv1
logging: ensure that MagicArgv1 is always argv1
2 parents 23232e3 + d81dcf3 commit 50f2580

File tree

5 files changed

+74
-37
lines changed

5 files changed

+74
-37
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ Metadata flags:
474474

475475
Logging flags:
476476
- :whale: `--log-driver=(json-file)`: Logging driver for the container (default `json-file`).
477-
- :whale: `--log-driver=json-log`: The logs are formatted as JSON. The default logging driver for nerdctl.
477+
- :whale: `--log-driver=json-file`: The logs are formatted as JSON. The default logging driver for nerdctl.
478478
- The `json-file` logging driver supports the following logging options:
479479
- :whale: `--log-opt=max-size=<MAX-SIZE>`: The maximum size of the log before it is rolled. A positive integer plus a modifier representing the unit of measure (k, m, or g). Defaults to unlimited.
480480
- :whale: `--log-opt=max-file=<MAX-FILE>`: The maximum number of log files that can be present. If rolling the logs creates excess files, the oldest file is removed. Only effective when `max-size` is also set. A positive integer. Defaults to 1.

cmd/nerdctl/main.go

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,10 @@ func main() {
7171
}
7272

7373
func xmain() error {
74-
loggingMode := false
75-
for _, arg := range os.Args {
76-
if arg == logging.MagicArgv1 {
77-
loggingMode = true
78-
break
79-
}
80-
}
81-
if len(os.Args) >= 3 && loggingMode {
74+
if len(os.Args) == 3 && os.Args[1] == logging.MagicArgv1 {
8275
// containerd runtime v2 logging plugin mode.
83-
// "binary://BIN?KEY1=VALUE1&KEY2=VALUE2" URI is parsed into Args {BIN, KEY1, VALUE1, KEY2, VALUE2}.
84-
argsMap := make(map[string]string)
85-
args := os.Args[1:]
86-
for i := 0; i < len(args); i += 2 {
87-
argsMap[args[i]] = args[i+1]
88-
}
89-
return logging.Main(argsMap)
76+
// "binary://BIN?KEY=VALUE" URI is parsed into Args {BIN, KEY, VALUE}.
77+
return logging.Main(os.Args[2])
9078
}
9179
// nerdctl CLI mode
9280
app, err := newApp()

cmd/nerdctl/run.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,23 @@ func createContainer(cmd *cobra.Command, ctx context.Context, client *containerd
478478
if err != nil {
479479
return nil, "", nil, err
480480
}
481-
if lu, err := generateLogURI(dataStore, logDriver, logOptMap); err != nil {
481+
logConfig := &logging.LogConfig{
482+
Drivers: []logging.LogDriverConfig{
483+
{
484+
Driver: logDriver,
485+
Opts: logOptMap,
486+
},
487+
},
488+
}
489+
logConfigB, err := json.Marshal(logConfig)
490+
if err != nil {
491+
return nil, "", nil, err
492+
}
493+
logConfigFilePath := logging.LogConfigFilePath(dataStore, ns, id)
494+
if err = os.WriteFile(logConfigFilePath, logConfigB, 0600); err != nil {
495+
return nil, "", nil, err
496+
}
497+
if lu, err := generateLogURI(dataStore); err != nil {
482498
return nil, "", nil, err
483499
} else if lu != nil {
484500
logURI = lu.String()
@@ -758,23 +774,14 @@ func withBindMountHostProcfs(_ context.Context, _ oci.Client, _ *containers.Cont
758774
return nil
759775
}
760776

761-
func generateLogURI(dataStore, logDriver string, logOptMap map[string]string) (*url.URL, error) {
762-
var selfExe string
763-
if logDriver == "json-file" {
764-
var err error
765-
selfExe, err = os.Executable()
766-
if err != nil {
767-
return nil, err
768-
}
769-
} else {
770-
return nil, fmt.Errorf("%s is not yet supported", logDriver)
777+
func generateLogURI(dataStore string) (*url.URL, error) {
778+
selfExe, err := os.Executable()
779+
if err != nil {
780+
return nil, err
771781
}
772782
args := map[string]string{
773783
logging.MagicArgv1: dataStore,
774784
}
775-
for k, v := range logOptMap {
776-
args[k] = v
777-
}
778785
if runtime.GOOS == "windows" {
779786
return nil, nil
780787
}

docs/dir.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ e.g. `/var/lib/nerdctl/1935db59/containers/default/c4ed811cc361d26faffdee8d696dd
3131
Files:
3232
- `resolv.conf`: mounted to the container as `/etc/resolv.conf`
3333
- `hostname`: mounted to the container as `/etc/hostname`
34+
- `log-config.json`: used for storing the `--log-opts` map of `nerdctl run`
3435
- `<CID>-json.log`: used by `nerdctl logs`
3536
- `oci-hook.*.log`: logs of the OCI hook
3637

pkg/logging/logging.go

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package logging
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"errors"
2223
"fmt"
2324
"os"
@@ -40,24 +41,64 @@ const (
4041
// Main is the entrypoint for the containerd runtime v2 logging plugin mode.
4142
//
4243
// Should be called only if argv1 == MagicArgv1.
43-
func Main(argsMap map[string]string) error {
44-
fn, err := getLoggerFunc(argsMap)
44+
func Main(argv2 string) error {
45+
fn, err := getLoggerFunc(argv2)
4546
if err != nil {
4647
return err
4748
}
4849
logging.Run(fn)
4950
return nil
5051
}
5152

52-
func getLoggerFunc(argsMap map[string]string) (logging.LoggerFunc, error) {
53-
if argsMap[MagicArgv1] == "" {
53+
// LogConfig is marshalled as "log-config.json"
54+
type LogConfig struct {
55+
Drivers []LogDriverConfig `json:"drivers,omitempty"`
56+
}
57+
58+
// LogDriverConfig is defined per a driver
59+
type LogDriverConfig struct {
60+
Driver string `json:"driver"`
61+
Opts map[string]string `json:"opts,omitempty"`
62+
}
63+
64+
// LogConfigFilePath returns the path of log-config.json
65+
func LogConfigFilePath(dataStore, ns, id string) string {
66+
return filepath.Join(dataStore, "containers", ns, id, "log-config.json")
67+
}
68+
69+
func getLoggerFunc(dataStore string) (logging.LoggerFunc, error) {
70+
if dataStore == "" {
5471
return nil, errors.New("got empty data store")
5572
}
5673
return func(_ context.Context, config *logging.Config, ready func() error) error {
5774
if config.Namespace == "" || config.ID == "" {
5875
return errors.New("got invalid config")
5976
}
60-
logJSONFilePath := jsonfile.Path(argsMap[MagicArgv1], config.Namespace, config.ID)
77+
jsonFileDriverOpts := make(map[string]string)
78+
logConfigFilePath := LogConfigFilePath(dataStore, config.Namespace, config.ID)
79+
if _, err := os.Stat(logConfigFilePath); err == nil {
80+
var logConfig LogConfig
81+
logConfigFileB, err := os.ReadFile(logConfigFilePath)
82+
if err != nil {
83+
return err
84+
}
85+
if err = json.Unmarshal(logConfigFileB, &logConfig); err != nil {
86+
return err
87+
}
88+
for _, f := range logConfig.Drivers {
89+
switch f.Driver {
90+
case "json-file":
91+
jsonFileDriverOpts = f.Opts
92+
default:
93+
return fmt.Errorf("unknown driver %q", f.Driver)
94+
}
95+
}
96+
} else if !errors.Is(err, os.ErrNotExist) {
97+
// the file does not exist if the container was created with nerdctl < 0.20
98+
return err
99+
}
100+
101+
logJSONFilePath := jsonfile.Path(dataStore, config.Namespace, config.ID)
61102
if err := os.MkdirAll(filepath.Dir(logJSONFilePath), 0700); err != nil {
62103
return err
63104
}
@@ -70,7 +111,7 @@ func getLoggerFunc(argsMap map[string]string) (logging.LoggerFunc, error) {
70111
//maxSize Defaults to unlimited.
71112
var capVal int64
72113
capVal = -1
73-
if capacity, ok := argsMap[MaxSize]; ok {
114+
if capacity, ok := jsonFileDriverOpts[MaxSize]; ok {
74115
var err error
75116
capVal, err = units.FromHumanSize(capacity)
76117
if err != nil {
@@ -82,7 +123,7 @@ func getLoggerFunc(argsMap map[string]string) (logging.LoggerFunc, error) {
82123
}
83124
l.MaxBytes = capVal
84125
maxFile := 1
85-
if maxFileString, ok := argsMap[MaxFile]; ok {
126+
if maxFileString, ok := jsonFileDriverOpts[MaxFile]; ok {
86127
var err error
87128
maxFile, err = strconv.Atoi(maxFileString)
88129
if err != nil {

0 commit comments

Comments
 (0)