Переглянути джерело

Merge pull request #44885 from thaJeztah/23.0_backport_update_containerd

[23.0 backport] vendor: github.com/containerd/containerd v1.6.16
Sebastiaan van Stijn 2 роки тому
батько
коміт
d7573ab867

+ 2 - 2
vendor.mod

@@ -19,7 +19,7 @@ require (
 	github.com/bsphere/le_go v0.0.0-20200109081728-fc06dab2caa8
 	github.com/bsphere/le_go v0.0.0-20200109081728-fc06dab2caa8
 	github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5
 	github.com/cloudflare/cfssl v0.0.0-20180323000720-5d63dbd981b5
 	github.com/containerd/cgroups v1.0.4
 	github.com/containerd/cgroups v1.0.4
-	github.com/containerd/containerd v1.6.15
+	github.com/containerd/containerd v1.6.16
 	github.com/containerd/continuity v0.3.0
 	github.com/containerd/continuity v0.3.0
 	github.com/containerd/fifo v1.0.0
 	github.com/containerd/fifo v1.0.0
 	github.com/containerd/typeurl v1.0.2
 	github.com/containerd/typeurl v1.0.2
@@ -67,7 +67,7 @@ require (
 	github.com/opencontainers/runc v1.1.3
 	github.com/opencontainers/runc v1.1.3
 	github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
 	github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
 	github.com/opencontainers/selinux v1.10.2
 	github.com/opencontainers/selinux v1.10.2
-	github.com/pelletier/go-toml v1.9.4
+	github.com/pelletier/go-toml v1.9.5
 	github.com/pkg/errors v0.9.1
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.14.0
 	github.com/prometheus/client_golang v1.14.0
 	github.com/rootless-containers/rootlesskit v1.1.0
 	github.com/rootless-containers/rootlesskit v1.1.0

+ 4 - 3
vendor.sum

@@ -261,8 +261,8 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV
 github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
 github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
 github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
-github.com/containerd/containerd v1.6.15 h1:4wWexxzLNHNE46aIETc6ge4TofO550v+BlLoANrbses=
-github.com/containerd/containerd v1.6.15/go.mod h1:U2NnBPIhzJDm59xF7xB2MMHnKtggpZ+phKg8o2TKj2c=
+github.com/containerd/containerd v1.6.16 h1:0H5xH6ABsN7XTrxIAKxFpBkFCBtrZ/OSORhCpUnHjrc=
+github.com/containerd/containerd v1.6.16/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw=
 github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -900,8 +900,9 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
 github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
+github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
+github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
 github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs=
 github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs=
 github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
 github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=

+ 11 - 9
vendor/github.com/containerd/containerd/Vagrantfile

@@ -17,7 +17,7 @@
 
 
 # Vagrantfile for Fedora and EL
 # Vagrantfile for Fedora and EL
 Vagrant.configure("2") do |config|
 Vagrant.configure("2") do |config|
-  config.vm.box = ENV["BOX"] || "fedora/36-cloud-base"
+  config.vm.box = ENV["BOX"] || "fedora/37-cloud-base"
   config.vm.box_version = ENV["BOX_VERSION"]
   config.vm.box_version = ENV["BOX_VERSION"]
   memory = 4096
   memory = 4096
   cpus = 2
   cpus = 2
@@ -30,6 +30,8 @@ Vagrant.configure("2") do |config|
     v.cpus = cpus
     v.cpus = cpus
   end
   end
 
 
+  config.vm.synced_folder ".", "/vagrant", type: "rsync"
+
   # Disabled by default. To run:
   # Disabled by default. To run:
   #   vagrant up --provision-with=upgrade-packages
   #   vagrant up --provision-with=upgrade-packages
   # To upgrade only specific packages:
   # To upgrade only specific packages:
@@ -91,7 +93,7 @@ EOF
   config.vm.provision "install-golang", type: "shell", run: "once" do |sh|
   config.vm.provision "install-golang", type: "shell", run: "once" do |sh|
     sh.upload_path = "/tmp/vagrant-install-golang"
     sh.upload_path = "/tmp/vagrant-install-golang"
     sh.env = {
     sh.env = {
-        'GO_VERSION': ENV['GO_VERSION'] || "1.18.9",
+        'GO_VERSION': ENV['GO_VERSION'] || "1.18.10",
     }
     }
     sh.inline = <<~SHELL
     sh.inline = <<~SHELL
         #!/usr/bin/env bash
         #!/usr/bin/env bash
@@ -146,7 +148,8 @@ EOF
         source /etc/environment
         source /etc/environment
         source /etc/profile.d/sh.local
         source /etc/profile.d/sh.local
         set -eux -o pipefail
         set -eux -o pipefail
-        ${GOPATH}/src/github.com/containerd/containerd/script/setup/install-cni
+        cd ${GOPATH}/src/github.com/containerd/containerd
+        script/setup/install-cni
         PATH=/opt/cni/bin:$PATH type ${CNI_BINARIES} || true
         PATH=/opt/cni/bin:$PATH type ${CNI_BINARIES} || true
     SHELL
     SHELL
   end
   end
@@ -212,8 +215,8 @@ EOF
     SHELL
     SHELL
   end
   end
 
 
-  # SELinux is permissive by default (via provisioning) in this VM. To re-run with SELinux enforcing:
-  #   vagrant up --provision-with=selinux-enforcing,test-integration
+  # SELinux is Enforcing by default (via provisioning) in this VM. To re-run with SELinux disabled:
+  #   SELINUX=Disabled vagrant up --provision-with=selinux,test-integration
   #
   #
   config.vm.provision "test-integration", type: "shell", run: "never" do |sh|
   config.vm.provision "test-integration", type: "shell", run: "never" do |sh|
     sh.upload_path = "/tmp/test-integration"
     sh.upload_path = "/tmp/test-integration"
@@ -234,8 +237,8 @@ EOF
     SHELL
     SHELL
   end
   end
 
 
-  # SELinux is permissive by default (via provisioning) in this VM. To re-run with SELinux enforcing:
-  #   vagrant up --provision-with=selinux-enforcing,test-cri
+  # SELinux is Enforcing by default (via provisioning) in this VM. To re-run with SELinux disabled:
+  #   SELINUX=Disabled vagrant up --provision-with=selinux,test-cri
   #
   #
   config.vm.provision "test-cri", type: "shell", run: "never" do |sh|
   config.vm.provision "test-cri", type: "shell", run: "never" do |sh|
     sh.upload_path = "/tmp/test-cri"
     sh.upload_path = "/tmp/test-cri"
@@ -253,6 +256,7 @@ EOF
         function cleanup()
         function cleanup()
         {
         {
             journalctl -u containerd > /tmp/containerd.log
             journalctl -u containerd > /tmp/containerd.log
+            cat /tmp/containerd.log
             systemctl stop containerd
             systemctl stop containerd
         }
         }
         selinux=$(getenforce)
         selinux=$(getenforce)
@@ -291,8 +295,6 @@ EOF
 [registries.search]
 [registries.search]
 registries = ['docker.io']
 registries = ['docker.io']
 EOF
 EOF
-        # Disable SELinux to allow overlayfs
-        setenforce 0
     SHELL
     SHELL
   end
   end
 
 

+ 22 - 18
vendor/github.com/containerd/containerd/remotes/docker/pusher.go

@@ -377,17 +377,24 @@ func (pw *pushWriter) Write(p []byte) (n int, err error) {
 
 
 			// If content has already been written, the bytes
 			// If content has already been written, the bytes
 			// cannot be written and the caller must reset
 			// cannot be written and the caller must reset
-			if status.Offset > 0 {
-				status.Offset = 0
-				status.UpdatedAt = time.Now()
-				pw.tracker.SetStatus(pw.ref, status)
-				return 0, content.ErrReset
-			}
+			status.Offset = 0
+			status.UpdatedAt = time.Now()
+			pw.tracker.SetStatus(pw.ref, status)
+			return 0, content.ErrReset
 		default:
 		default:
 		}
 		}
 	}
 	}
 
 
 	n, err = pw.pipe.Write(p)
 	n, err = pw.pipe.Write(p)
+	if errors.Is(err, io.ErrClosedPipe) {
+		// if the pipe is closed, we might have the original error on the error
+		// channel - so we should try and get it
+		select {
+		case err2 := <-pw.errC:
+			err = err2
+		default:
+		}
+	}
 	status.Offset += int64(n)
 	status.Offset += int64(n)
 	status.UpdatedAt = time.Now()
 	status.UpdatedAt = time.Now()
 	pw.tracker.SetStatus(pw.ref, status)
 	pw.tracker.SetStatus(pw.ref, status)
@@ -428,7 +435,7 @@ func (pw *pushWriter) Digest() digest.Digest {
 
 
 func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
 func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
 	// Check whether read has already thrown an error
 	// Check whether read has already thrown an error
-	if _, err := pw.pipe.Write([]byte{}); err != nil && err != io.ErrClosedPipe {
+	if _, err := pw.pipe.Write([]byte{}); err != nil && !errors.Is(err, io.ErrClosedPipe) {
 		return fmt.Errorf("pipe error before commit: %w", err)
 		return fmt.Errorf("pipe error before commit: %w", err)
 	}
 	}
 
 
@@ -439,9 +446,7 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
 	var resp *http.Response
 	var resp *http.Response
 	select {
 	select {
 	case err := <-pw.errC:
 	case err := <-pw.errC:
-		if err != nil {
-			return err
-		}
+		return err
 	case resp = <-pw.respC:
 	case resp = <-pw.respC:
 		defer resp.Body.Close()
 		defer resp.Body.Close()
 	case p, ok := <-pw.pipeC:
 	case p, ok := <-pw.pipeC:
@@ -453,18 +458,17 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di
 		}
 		}
 		pw.pipe.CloseWithError(content.ErrReset)
 		pw.pipe.CloseWithError(content.ErrReset)
 		pw.pipe = p
 		pw.pipe = p
+
+		// If content has already been written, the bytes
+		// cannot be written again and the caller must reset
 		status, err := pw.tracker.GetStatus(pw.ref)
 		status, err := pw.tracker.GetStatus(pw.ref)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		// If content has already been written, the bytes
-		// cannot be written again and the caller must reset
-		if status.Offset > 0 {
-			status.Offset = 0
-			status.UpdatedAt = time.Now()
-			pw.tracker.SetStatus(pw.ref, status)
-			return content.ErrReset
-		}
+		status.Offset = 0
+		status.UpdatedAt = time.Now()
+		pw.tracker.SetStatus(pw.ref, status)
+		return content.ErrReset
 	}
 	}
 
 
 	// 201 is specified return status, some registries return
 	// 201 is specified return status, some registries return

+ 1 - 1
vendor/github.com/containerd/containerd/version/version.go

@@ -23,7 +23,7 @@ var (
 	Package = "github.com/containerd/containerd"
 	Package = "github.com/containerd/containerd"
 
 
 	// Version holds the complete version number. Filled in at linking time.
 	// Version holds the complete version number. Filled in at linking time.
-	Version = "1.6.15+unknown"
+	Version = "1.6.16+unknown"
 
 
 	// Revision is filled with the VCS (e.g. git) revision being used to build
 	// Revision is filled with the VCS (e.g. git) revision being used to build
 	// the program at linking time.
 	// the program at linking time.

+ 3 - 3
vendor/github.com/pelletier/go-toml/README.md

@@ -25,9 +25,9 @@ and [much faster][v2-bench]. If you only need reading and writing TOML documents
 (majority of cases), those features are implemented and the API unlikely to
 (majority of cases), those features are implemented and the API unlikely to
 change.
 change.
 
 
-The remaining features (Document structure editing and tooling) will be added
-shortly. While pull-requests are welcome on v1, no active development is
-expected on it. When v2.0.0 is released, v1 will be deprecated.
+The remaining features will be added shortly. While pull-requests are welcome on
+v1, no active development is expected on it. When v2.0.0 is released, v1 will be
+deprecated.
 
 
 👉 [go-toml v2][v2]
 👉 [go-toml v2][v2]
 
 

+ 19 - 0
vendor/github.com/pelletier/go-toml/SECURITY.md

@@ -0,0 +1,19 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version    | Supported          |
+| ---------- | ------------------ |
+| Latest 2.x | :white_check_mark: |
+| All 1.x    | :x:                |
+| All 0.x    | :x:                |
+
+## Reporting a Vulnerability
+
+Email a vulnerability report to `security@pelletier.codes`. Make sure to include
+as many details as possible to reproduce the vulnerability. This is a
+side-project: I will try to get back to you as quickly as possible, time
+permitting in my personal life. Providing a working patch helps very much!

+ 1 - 1
vendor/github.com/pelletier/go-toml/marshal.go

@@ -1113,7 +1113,7 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref
 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String())
 			}
 			}
 
 
-			if val.Convert(reflect.TypeOf(int(1))).Int() < 0 {
+			if val.Type().Kind() != reflect.Uint64 && val.Convert(reflect.TypeOf(int(1))).Int() < 0 {
 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String())
 			}
 			}
 			if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) {
 			if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) {

+ 23 - 24
vendor/github.com/pelletier/go-toml/parser.go

@@ -293,42 +293,41 @@ func (p *tomlParser) parseRvalue() interface{} {
 		return math.NaN()
 		return math.NaN()
 	case tokenInteger:
 	case tokenInteger:
 		cleanedVal := cleanupNumberToken(tok.val)
 		cleanedVal := cleanupNumberToken(tok.val)
-		var err error
-		var val int64
+		base := 10
+		s := cleanedVal
+		checkInvalidUnderscore := numberContainsInvalidUnderscore
 		if len(cleanedVal) >= 3 && cleanedVal[0] == '0' {
 		if len(cleanedVal) >= 3 && cleanedVal[0] == '0' {
 			switch cleanedVal[1] {
 			switch cleanedVal[1] {
 			case 'x':
 			case 'x':
-				err = hexNumberContainsInvalidUnderscore(tok.val)
-				if err != nil {
-					p.raiseError(tok, "%s", err)
-				}
-				val, err = strconv.ParseInt(cleanedVal[2:], 16, 64)
+				checkInvalidUnderscore = hexNumberContainsInvalidUnderscore
+				base = 16
 			case 'o':
 			case 'o':
-				err = numberContainsInvalidUnderscore(tok.val)
-				if err != nil {
-					p.raiseError(tok, "%s", err)
-				}
-				val, err = strconv.ParseInt(cleanedVal[2:], 8, 64)
+				base = 8
 			case 'b':
 			case 'b':
-				err = numberContainsInvalidUnderscore(tok.val)
-				if err != nil {
-					p.raiseError(tok, "%s", err)
-				}
-				val, err = strconv.ParseInt(cleanedVal[2:], 2, 64)
+				base = 2
 			default:
 			default:
 				panic("invalid base") // the lexer should catch this first
 				panic("invalid base") // the lexer should catch this first
 			}
 			}
-		} else {
-			err = numberContainsInvalidUnderscore(tok.val)
-			if err != nil {
-				p.raiseError(tok, "%s", err)
-			}
-			val, err = strconv.ParseInt(cleanedVal, 10, 64)
+			s = cleanedVal[2:]
 		}
 		}
+
+		err := checkInvalidUnderscore(tok.val)
 		if err != nil {
 		if err != nil {
 			p.raiseError(tok, "%s", err)
 			p.raiseError(tok, "%s", err)
 		}
 		}
-		return val
+
+		var val interface{}
+		val, err = strconv.ParseInt(s, base, 64)
+		if err == nil {
+			return val
+		}
+
+		if s[0] != '-' {
+			if val, err = strconv.ParseUint(s, base, 64); err == nil {
+				return val
+			}
+		}
+		p.raiseError(tok, "%s", err)
 	case tokenFloat:
 	case tokenFloat:
 		err := numberContainsInvalidUnderscore(tok.val)
 		err := numberContainsInvalidUnderscore(tok.val)
 		if err != nil {
 		if err != nil {

+ 1 - 1
vendor/github.com/pelletier/go-toml/toml.go

@@ -471,7 +471,7 @@ func LoadBytes(b []byte) (tree *Tree, err error) {
 			if _, ok := r.(runtime.Error); ok {
 			if _, ok := r.(runtime.Error); ok {
 				panic(r)
 				panic(r)
 			}
 			}
-			err = errors.New(r.(string))
+			err = fmt.Errorf("%s", r)
 		}
 		}
 	}()
 	}()
 
 

+ 2 - 2
vendor/modules.txt

@@ -160,7 +160,7 @@ github.com/containerd/cgroups/v2/stats
 # github.com/containerd/console v1.0.3
 # github.com/containerd/console v1.0.3
 ## explicit; go 1.13
 ## explicit; go 1.13
 github.com/containerd/console
 github.com/containerd/console
-# github.com/containerd/containerd v1.6.15
+# github.com/containerd/containerd v1.6.16
 ## explicit; go 1.17
 ## explicit; go 1.17
 github.com/containerd/containerd
 github.com/containerd/containerd
 github.com/containerd/containerd/api/events
 github.com/containerd/containerd/api/events
@@ -727,7 +727,7 @@ github.com/opencontainers/selinux/go-selinux
 github.com/opencontainers/selinux/go-selinux/label
 github.com/opencontainers/selinux/go-selinux/label
 github.com/opencontainers/selinux/pkg/pwalk
 github.com/opencontainers/selinux/pkg/pwalk
 github.com/opencontainers/selinux/pkg/pwalkdir
 github.com/opencontainers/selinux/pkg/pwalkdir
-# github.com/pelletier/go-toml v1.9.4
+# github.com/pelletier/go-toml v1.9.5
 ## explicit; go 1.12
 ## explicit; go 1.12
 github.com/pelletier/go-toml
 github.com/pelletier/go-toml
 # github.com/philhofer/fwd v1.1.2
 # github.com/philhofer/fwd v1.1.2