New Upstream Release - golang-github-vishvananda-netns
Ready changes
Summary
Merged new upstream version: 0.0~git20230405.16c2fa0 (was: 0.0~git20221102.43aa913).
Resulting package
Built on 2023-05-22T10:26 (took 5m38s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-vishvananda-netns-dev
Lintian Result
- golang-github-vishvananda-netns-dev_0.0~git20230405.16c2fa0-1~jan+nur1_all.deb
- golang-github-vishvananda-netns_0.0~git20230405.16c2fa0-1~jan+nur1.dsc
- golang-github-vishvananda-netns_0.0~git20230405.16c2fa0-1~jan+nur1_amd64.buildinfo
- golang-github-vishvananda-netns_0.0~git20230405.16c2fa0-1~jan+nur1_amd64.changes
Diff
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..7f451b7
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "monthly"
+
+ - package-ecosystem: "gomod" # Dependencies listed in go.mod
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..7780563
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,43 @@
+name: test
+on:
+ push:
+ tags:
+ - v*
+ branches:
+ - master
+ - main
+ pull_request:
+ branches:
+ - master
+ - main
+
+jobs:
+ test:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ timeout-minutes: 10
+
+ strategy:
+ matrix:
+ # test against the "oldest" supported version and the current version
+ # of go. Go 1.17 is kept in this matrix as it is the minimum version
+ # specified in go.mod, and maintaining compatibility with go 1.17 is
+ # currently not much of a burden. Most projects using this module are
+ # using newer versions than that, so we can drop the old version if
+ # it becomes too much of a burden.
+ go-version: [1.17.x, stable]
+ os: [ubuntu-20.04, ubuntu-22.04, windows-2022]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: ${{ matrix.go-version }}
+ - name: Checkout code
+ uses: actions/checkout@v3
+ - name: go mod tidy
+ run: |
+ go mod tidy
+ git diff --exit-code
+ - name: Test
+ run: go test -exec "sudo -n" -v ./...
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
new file mode 100644
index 0000000..c8d3423
--- /dev/null
+++ b/.github/workflows/validate.yml
@@ -0,0 +1,54 @@
+name: validate
+on:
+ push:
+ tags:
+ - v*
+ branches:
+ - master
+ - main
+ pull_request:
+ branches:
+ - master
+ - main
+
+jobs:
+ linters:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
+ timeout-minutes: 10
+
+ strategy:
+ matrix:
+ # We only run on the latest version of go, as some linters may be
+ # version-dependent (for example gofmt can change between releases).
+ go-version: [stable]
+ os: [ubuntu-22.04, windows-2022]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: ${{ matrix.go-version }}
+ - name: Checkout code
+ uses: actions/checkout@v3
+ - name: YAML Lint
+ if: runner.os == 'Linux'
+ uses: ibiqlik/action-yamllint@v3
+ with:
+ format: auto
+ - name: Golangci-lint
+ uses: golangci/golangci-lint-action@v3
+ with:
+ version: latest
+ skip-cache: true
+ args: --print-resources-usage --verbose
+
+ # Optional: show only new issues if it's a pull request. The default value is `false`.
+ # only-new-issues: true
+
+ # Optional: if set to true then the action don't cache or restore ~/go/pkg.
+ # skip-pkg-cache: true
+
+ # Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
+ # skip-build-cache: true
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..2b6988f
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,26 @@
+linters:
+ enable:
+ - errcheck
+ - errorlint
+ - gocritic
+ - gosec
+ - gosimple
+ - govet
+ - gci
+ - misspell
+ - nonamedreturns
+ - staticcheck
+ - unconvert
+ - unparam
+ - unused
+ - whitespace
+
+linters-settings:
+ gci:
+ sections:
+ - standard
+ - default
+ - prefix(github.com/vishvananda)
+
+run:
+ timeout: 5m
diff --git a/.yamllint.yml b/.yamllint.yml
new file mode 100644
index 0000000..1b2830c
--- /dev/null
+++ b/.yamllint.yml
@@ -0,0 +1,9 @@
+---
+extends: default
+
+rules:
+ document-start: disable
+ line-length: disable
+ truthy:
+ ignore: |
+ .github/workflows/*.yml
diff --git a/README.md b/README.md
index 1fdb2d3..bdfedbe 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ import (
"fmt"
"net"
"runtime"
+
"github.com/vishvananda/netns"
)
@@ -48,14 +49,3 @@ func main() {
}
```
-
-## NOTE
-
-The library can be safely used only with Go >= 1.10 due to [golang/go#20676](https://github.com/golang/go/issues/20676).
-
-After locking a goroutine to its current OS thread with `runtime.LockOSThread()`
-and changing its network namespace, any new subsequent goroutine won't be
-scheduled on that thread while it's locked. Therefore, the new goroutine
-will run in a different namespace leading to unexpected results.
-
-See [here](https://www.weave.works/blog/linux-namespaces-golang-followup) for more details.
diff --git a/debian/changelog b/debian/changelog
index f6b9ea0..554c7b2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,14 @@
-golang-github-vishvananda-netns (0.0~git20211101.5004558-2) UNRELEASED; urgency=medium
+golang-github-vishvananda-netns (0.0~git20230405.16c2fa0-1) UNRELEASED; urgency=medium
+ [ Tianon Gravi ]
* Team upload.
* Remove self from Uploaders
- -- Tianon Gravi <tianon@debian.org> Wed, 23 Feb 2022 11:11:33 -0800
+ [ Debian Janitor ]
+ * New upstream snapshot.
+ * New upstream snapshot.
+
+ -- Tianon Gravi <tianon@debian.org> Mon, 22 May 2023 10:21:37 -0000
golang-github-vishvananda-netns (0.0~git20211101.5004558-1) unstable; urgency=medium
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..cd4093a
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,9 @@
+// Package netns allows ultra-simple network namespace handling. NsHandles
+// can be retrieved and set. Note that the current namespace is thread
+// local so actions that set and reset namespaces should use LockOSThread
+// to make sure the namespace doesn't change due to a goroutine switch.
+// It is best to close NsHandles when you are done with them. This can be
+// accomplished via a `defer ns.Close()` on the handle. Changing namespaces
+// requires elevated privileges, so in most cases this code needs to be run
+// as root.
+package netns
diff --git a/go.mod b/go.mod
index 9cdf577..4a240d9 100644
--- a/go.mod
+++ b/go.mod
@@ -1,5 +1,5 @@
module github.com/vishvananda/netns
-go 1.12
+go 1.17
-require golang.org/x/sys v0.0.0-20200217220822-9197077df867
+require golang.org/x/sys v0.2.0
diff --git a/go.sum b/go.sum
index 1d4adf4..beac707 100644
--- a/go.sum
+++ b/go.sum
@@ -1,2 +1,2 @@
-golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
-golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/netns_linux.go b/netns_linux.go
index 6be5c55..8c9b177 100644
--- a/netns_linux.go
+++ b/netns_linux.go
@@ -1,57 +1,55 @@
-//go:build linux && go1.10
-// +build linux,go1.10
-
package netns
import (
"fmt"
- "io/ioutil"
"os"
"path"
"path/filepath"
"strconv"
"strings"
- "syscall"
"golang.org/x/sys/unix"
)
-// Deprecated: use syscall pkg instead (go >= 1.5 needed).
+// Deprecated: use golang.org/x/sys/unix pkg instead.
const (
- CLONE_NEWUTS = 0x04000000 /* New utsname group? */
- CLONE_NEWIPC = 0x08000000 /* New ipcs */
- CLONE_NEWUSER = 0x10000000 /* New user namespace */
- CLONE_NEWPID = 0x20000000 /* New pid namespace */
- CLONE_NEWNET = 0x40000000 /* New network namespace */
- CLONE_IO = 0x80000000 /* Get io context */
- bindMountPath = "/run/netns" /* Bind mount path for named netns */
+ CLONE_NEWUTS = unix.CLONE_NEWUTS /* New utsname group? */
+ CLONE_NEWIPC = unix.CLONE_NEWIPC /* New ipcs */
+ CLONE_NEWUSER = unix.CLONE_NEWUSER /* New user namespace */
+ CLONE_NEWPID = unix.CLONE_NEWPID /* New pid namespace */
+ CLONE_NEWNET = unix.CLONE_NEWNET /* New network namespace */
+ CLONE_IO = unix.CLONE_IO /* Get io context */
)
-// Setns sets namespace using syscall. Note that this should be a method
-// in syscall but it has not been added.
-func Setns(ns NsHandle, nstype int) (err error) {
+const bindMountPath = "/run/netns" /* Bind mount path for named netns */
+
+// Setns sets namespace using golang.org/x/sys/unix.Setns.
+//
+// Deprecated: Use golang.org/x/sys/unix.Setns instead.
+func Setns(ns NsHandle, nstype int) error {
return unix.Setns(int(ns), nstype)
}
// Set sets the current network namespace to the namespace represented
// by NsHandle.
-func Set(ns NsHandle) (err error) {
- return Setns(ns, CLONE_NEWNET)
+func Set(ns NsHandle) error {
+ return unix.Setns(int(ns), unix.CLONE_NEWNET)
}
// New creates a new network namespace, sets it as current and returns
// a handle to it.
-func New() (ns NsHandle, err error) {
- if err := unix.Unshare(CLONE_NEWNET); err != nil {
+func New() (NsHandle, error) {
+ if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
return -1, err
}
return Get()
}
-// NewNamed creates a new named network namespace and returns a handle to it
+// NewNamed creates a new named network namespace, sets it as current,
+// and returns a handle to it
func NewNamed(name string) (NsHandle, error) {
if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
- err = os.MkdirAll(bindMountPath, 0755)
+ err = os.MkdirAll(bindMountPath, 0o755)
if err != nil {
return None(), err
}
@@ -64,15 +62,17 @@ func NewNamed(name string) (NsHandle, error) {
namedPath := path.Join(bindMountPath, name)
- f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
+ f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0o444)
if err != nil {
+ newNs.Close()
return None(), err
}
f.Close()
- nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())
- err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "")
+ nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
+ err = unix.Mount(nsPath, namedPath, "bind", unix.MS_BIND, "")
if err != nil {
+ newNs.Close()
return None(), err
}
@@ -83,7 +83,7 @@ func NewNamed(name string) (NsHandle, error) {
func DeleteNamed(name string) error {
namedPath := path.Join(bindMountPath, name)
- err := syscall.Unmount(namedPath, syscall.MNT_DETACH)
+ err := unix.Unmount(namedPath, unix.MNT_DETACH)
if err != nil {
return err
}
@@ -109,7 +109,7 @@ func GetFromPath(path string) (NsHandle, error) {
// GetFromName gets a handle to a named network namespace such as one
// created by `ip netns add`.
func GetFromName(name string) (NsHandle, error) {
- return GetFromPath(fmt.Sprintf("/var/run/netns/%s", name))
+ return GetFromPath(filepath.Join(bindMountPath, name))
}
// GetFromPid gets a handle to the network namespace of a given pid.
@@ -135,7 +135,7 @@ func GetFromDocker(id string) (NsHandle, error) {
// borrowed from docker/utils/utils.go
func findCgroupMountpoint(cgroupType string) (int, string, error) {
- output, err := ioutil.ReadFile("/proc/mounts")
+ output, err := os.ReadFile("/proc/mounts")
if err != nil {
return -1, "", err
}
@@ -165,7 +165,7 @@ func findCgroupMountpoint(cgroupType string) (int, string, error) {
// borrowed from docker/utils/utils.go
// modified to get the docker pid instead of using /proc/self
func getDockerCgroup(cgroupVer int, cgroupType string) (string, error) {
- dockerpid, err := ioutil.ReadFile("/var/run/docker.pid")
+ dockerpid, err := os.ReadFile("/var/run/docker.pid")
if err != nil {
return "", err
}
@@ -177,7 +177,7 @@ func getDockerCgroup(cgroupVer int, cgroupType string) (string, error) {
if err != nil {
return "", err
}
- output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
+ output, err := os.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
if err != nil {
return "", err
}
@@ -217,11 +217,12 @@ func getPidForContainer(id string) (int, error) {
id += "*"
var pidFile string
- if cgroupVer == 1 {
+ switch cgroupVer {
+ case 1:
pidFile = "tasks"
- } else if cgroupVer == 2 {
+ case 2:
pidFile = "cgroup.procs"
- } else {
+ default:
return -1, fmt.Errorf("Invalid cgroup version '%d'", cgroupVer)
}
@@ -264,7 +265,7 @@ func getPidForContainer(id string) (int, error) {
return pid, fmt.Errorf("Unable to find container: %v", id[:len(id)-1])
}
- output, err := ioutil.ReadFile(filename)
+ output, err := os.ReadFile(filename)
if err != nil {
return pid, err
}
@@ -276,7 +277,7 @@ func getPidForContainer(id string) (int, error) {
pid, err = strconv.Atoi(result[0])
if err != nil {
- return pid, fmt.Errorf("Invalid pid '%s': %s", result[0], err)
+ return pid, fmt.Errorf("Invalid pid '%s': %w", result[0], err)
}
return pid, nil
diff --git a/netns_test.go b/netns_linux_test.go
similarity index 93%
rename from netns_test.go
rename to netns_linux_test.go
index e51981c..b8d9bd9 100644
--- a/netns_test.go
+++ b/netns_linux_test.go
@@ -24,7 +24,9 @@ func TestGetNewSetDelete(t *testing.T) {
if err := Set(origns); err != nil {
t.Fatal(err)
}
- newns.Close()
+ if err := newns.Close(); err != nil {
+ t.Error("Failed to close ns", err)
+ }
if newns.IsOpen() {
t.Fatal("newns still open after close", newns)
}
diff --git a/netns_others.go b/netns_others.go
new file mode 100644
index 0000000..f444f6e
--- /dev/null
+++ b/netns_others.go
@@ -0,0 +1,56 @@
+//go:build !linux
+// +build !linux
+
+package netns
+
+import "errors"
+
+var ErrNotImplemented = errors.New("not implemented")
+
+// Setns sets namespace using golang.org/x/sys/unix.Setns on Linux. It
+// is not implemented on other platforms.
+//
+// Deprecated: Use golang.org/x/sys/unix.Setns instead.
+func Setns(ns NsHandle, nstype int) error {
+ return ErrNotImplemented
+}
+
+func Set(ns NsHandle) error {
+ return ErrNotImplemented
+}
+
+func New() (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func NewNamed(name string) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func DeleteNamed(name string) error {
+ return ErrNotImplemented
+}
+
+func Get() (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func GetFromPath(path string) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func GetFromName(name string) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func GetFromPid(pid int) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func GetFromThread(pid int, tid int) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
+
+func GetFromDocker(id string) (NsHandle, error) {
+ return -1, ErrNotImplemented
+}
diff --git a/netns_unspecified.go b/netns_unspecified.go
deleted file mode 100644
index d06af62..0000000
--- a/netns_unspecified.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// +build !linux
-
-package netns
-
-import (
- "errors"
-)
-
-var (
- ErrNotImplemented = errors.New("not implemented")
-)
-
-func Set(ns NsHandle) (err error) {
- return ErrNotImplemented
-}
-
-func New() (ns NsHandle, err error) {
- return -1, ErrNotImplemented
-}
-
-func Get() (NsHandle, error) {
- return -1, ErrNotImplemented
-}
-
-func GetFromPath(path string) (NsHandle, error) {
- return -1, ErrNotImplemented
-}
-
-func GetFromName(name string) (NsHandle, error) {
- return -1, ErrNotImplemented
-}
-
-func GetFromPid(pid int) (NsHandle, error) {
- return -1, ErrNotImplemented
-}
-
-func GetFromThread(pid, tid int) (NsHandle, error) {
- return -1, ErrNotImplemented
-}
-
-func GetFromDocker(id string) (NsHandle, error) {
- return -1, ErrNotImplemented
-}
diff --git a/netns.go b/nshandle_linux.go
similarity index 75%
rename from netns.go
rename to nshandle_linux.go
index 116befd..1baffb6 100644
--- a/netns.go
+++ b/nshandle_linux.go
@@ -1,11 +1,3 @@
-// Package netns allows ultra-simple network namespace handling. NsHandles
-// can be retrieved and set. Note that the current namespace is thread
-// local so actions that set and reset namespaces should use LockOSThread
-// to make sure the namespace doesn't change due to a goroutine switch.
-// It is best to close NsHandles when you are done with them. This can be
-// accomplished via a `defer ns.Close()` on the handle. Changing namespaces
-// requires elevated privileges, so in most cases this code needs to be run
-// as root.
package netns
import (
@@ -38,7 +30,7 @@ func (ns NsHandle) Equal(other NsHandle) bool {
// String shows the file descriptor number and its dev and inode.
func (ns NsHandle) String() string {
if ns == -1 {
- return "NS(None)"
+ return "NS(none)"
}
var s unix.Stat_t
if err := unix.Fstat(int(ns), &s); err != nil {
@@ -71,7 +63,7 @@ func (ns *NsHandle) Close() error {
if err := unix.Close(int(*ns)); err != nil {
return err
}
- (*ns) = -1
+ *ns = -1
return nil
}
diff --git a/nshandle_others.go b/nshandle_others.go
new file mode 100644
index 0000000..af727bc
--- /dev/null
+++ b/nshandle_others.go
@@ -0,0 +1,45 @@
+//go:build !linux
+// +build !linux
+
+package netns
+
+// NsHandle is a handle to a network namespace. It can only be used on Linux,
+// but provides stub methods on other platforms.
+type NsHandle int
+
+// Equal determines if two network handles refer to the same network
+// namespace. It is only implemented on Linux.
+func (ns NsHandle) Equal(_ NsHandle) bool {
+ return false
+}
+
+// String shows the file descriptor number and its dev and inode.
+// It is only implemented on Linux, and returns "NS(none)" on other
+// platforms.
+func (ns NsHandle) String() string {
+ return "NS(none)"
+}
+
+// UniqueId returns a string which uniquely identifies the namespace
+// associated with the network handle. It is only implemented on Linux,
+// and returns "NS(none)" on other platforms.
+func (ns NsHandle) UniqueId() string {
+ return "NS(none)"
+}
+
+// IsOpen returns true if Close() has not been called. It is only implemented
+// on Linux and always returns false on other platforms.
+func (ns NsHandle) IsOpen() bool {
+ return false
+}
+
+// Close closes the NsHandle and resets its file descriptor to -1.
+// It is only implemented on Linux.
+func (ns *NsHandle) Close() error {
+ return nil
+}
+
+// None gets an empty (closed) NsHandle.
+func None() NsHandle {
+ return NsHandle(-1)
+}
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/doc.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/netns_linux_test.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/netns_others.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/nshandle_linux.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/nshandle_others.go
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/netns.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/netns_test.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/vishvananda/netns/netns_unspecified.go
No differences were encountered in the control files