Documentation
¶
Overview ¶
Package spacetest supports tests working with Linux kernel namespaces.
This package leverages the Ginkgo testing framework with Gomega matchers.
The top-level “spacetest” package is mostly agnostic to the particular type of namespace handled, but different test helper functions come with different restrictions due to restrictions imposed by the Linux kernel. Please carefully check the documentation for the individual helper functions.
Network Namespaces ¶
The spacetest/netns package is basically just a convenience wrapper around the generic test helper functions from the base spacetest package. Yet, this package helps DRY, especially avoiding litanies of unix.CLONE_NEWNET.
Mount Namespaces ¶
In some situations, mount namespaces need special treatment which the dedicated spacetest/mntns package takes care of: in particular, the test helper functions in this package ensure to remount the “/” in the new mount namespace with private mount point propagation to avoid mishaps (trust us, we /know/).
Other than that, this package helps again with DRY, such as unix.CLONE_NEWNS litanies.
PID and User Namespaces ¶
Please note that user and PID namespaces are notoriously difficult to work with, especially in multi-threaded Go tests. Thus, the spacetest package has somewhat limited support for dealing with user namespaces. Please refer to the github.com/thediveo/spacetest/spacer package for details.
Background ¶
The origins of this module lie in thediveo/notwork: in order to reuse the namespace-specific elements without the need to pull in dependencies related solely to “notwork” testing, “spacetest” was born. And in the tradition of short and preably misleading idiomatic Go package names, the name “spacetest” was chosen. Because “namespacetest” would have been much too precise. We promise that our module won't explode in your face.
Index ¶
- Variables
- func Call[R any](fn func() R, nsfd int, nsfds ...int) R
- func Current(typ int) int
- func CurrentIno(typ int) uint64
- func EnterTransient(typ int) func()
- func Execute(fn func(), nsfd int, nsfds ...int)
- func Ino[R Reference](ref R, typ int) uint64
- func Name(typ int) string
- func NewTransient(typ int) int
- func Type[R Reference](ref R) int
- type Reference
Constants ¶
This section is empty.
Variables ¶
var NS_GET_NSTYPE = ioctl.IO(_NSIO, 0x3) //nolint:godoclint // out of touch
NS_GET_NSTYPE defines the unix.IoctlRetInt request code that returns the type of namespace CLONE_NEW* value referred to by a file descriptor.
Functions ¶
func Call ¶ added in v0.10.0
Call the passed fn synchronously, returning fn's single result value, while attached to the specified namespace(s) and otherwise defaulting to the caller's currently attached namespaces. See Execute for details and semantics about the other parameters as well as the behaviour especially regarding mount namespaces.
func Current ¶
Current returns a file descriptor referencing the calling OS-level thread's current namespace of type “typ”. Please note that the caller's go routine should be thread-locked. “typ” should be any of unix.CLONE_NEWNS (for mount namespaces), unix.CLONE_NETNS (network), et cetera.
Additionally, Current schedules a DeferCleanup of the returned file descriptor to be closed at the end of the current test in order to avoid leaking it.
If the specified typ of namespace is unknown, Current fails the current test.
func CurrentIno ¶
CurrentIno returns the identification (inode number) for the namespace (of the specified type) the OS-level thread is currently attached to.
func EnterTransient ¶
func EnterTransient(typ int) func()
EnterTransient creates and enters a new (and isolated) Linux kernel namespace of the specified type, returning a function that needs to be defer'ed in order to correctly switch the calling go routine and its locked OS-level thread back when the caller itself wants to leave (returns). For instance:
defer spacetest.EnterTransient(unix.CLONE_NEWNET)()
EnterTransient locks the caller's go routine to its OS-level thread and unlocks it when the deferred clean up function finally gets called.
In case the caller cannot be switched back correctly, the defer'ed cleanup function will panic with an error description detailing the reason.
EnterTransient can be used for the following types of namespaces:
- unix.CLONE_NEWCGROUP,
- unix.CLONE_NEWIPC,
- unix.CLONE_NEWNET,
- unix.CLONE_NEWUTS.
For mount namespaces (unix.CLONE_NEWNS) you will need to use the mount namespace-specific github.com/thediveo/spacetest/mntns.EnterTransient instead.
In order to work with transient PID (unix.CLONE_NEWPID) namespaces use NewTransient and then Execute, as it is not possible to re-associate the current OS-level thread with the original (parent) PID namespace after creating and switching into a new child PID namespace; the returned cleanup function would fail and purposely trigger a panic.
Also, user namespaces cannot be entered with EnterTransient as the Linux kernel does not allow a thread to re-enter one of the original (that is, parent) user namespace(s). Use Execute instead to call a specific function synchronously from a transient go routine with its own transient OS-level thread.
To work with transient time (unix.CLONE_NEWTIME) namespaces use NewTransient and then Execute, as it is not possible to re-associate the current OS-level thread with the original (parent) PID or time namespace after creating and switching into a new child PID or time namespace; the returned cleanup function would fail and purposely trigger a panic.
func Execute ¶
Execute the passed fn synchronously while attached to the specified namespace(s) and otherwise defaulting to the caller's currently attached namespaces.
Execute will fail the current test when trying to switch to a different user namespace: switching the user namespace is not possible for multi-threaded processes, this is a design decision of the Linux kernel user namespace developers.
When a mount namespace is passed in, then fn will be executed on a separate throw-away go routine (and locked to a throw-away OS-level thread). Where the caller does not specify different namespace(s) the underlying thread will be attached to the caller's namespaces. This ensures the expected behavior when using Execute after especially EnterTransient.
When the list of namespaces to switch to does not contain a mount namespace then the passed fn will be called synchronously on the caller's go routine, while locked to the underlying OS-level thread.
func Ino ¶
Ino returns the identification (inode number) of the passed Linux kernel namespace that is either referenced by a file descriptor or a VFS path name.
If the specified reference is invalid or doesn't match the passed type of namespace, Ino fails the current test.
func Name ¶
Name returns the name for the type of Linux kernel namespace specified, or "???" if not known.
func NewTransient ¶
NewTransient creates a new Linux kernel namespace of the specified type, but doesn't enter it. Instead, it returns a file descriptor referencing the newly created namespace. NewTransient can be used for the following types of namespaces:
- unix.CLONE_NEWCGROUP,
- unix.CLONE_NEWIPC,
- unix.CLONE_NEWNET,
- unix.CLONE_NEWUTS.
For mount namespaces (unix.CLONE_NEWNS) you will need to use the mount namespace-specific github.com/thediveo/spacetest/mntns.NewTransient instead.
Additionally to creating a new namespace, NewTransient also schedules a Ginkgo deferred cleanup in order to close the fd referencing this new namespace. The caller thus must not close the file descriptor returned.
When NewTransient returns, the caller's Go routine is in the same OS-level thread lock/unlock state as before the call.
Types ¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package mntns supports running unit tests in separated transient mount namespaces.
|
Package mntns supports running unit tests in separated transient mount namespaces. |
|
Package netns supports running unit tests in separated transient network namespaces, handling cleanup and error checking automatically.
|
Package netns supports running unit tests in separated transient network namespaces, handling cleanup and error checking automatically. |
|
Package spacer provides a client to create and communicate with so-called “spacer services” that on demand create new Linux kernel namespaces, especially sub user and PID namespaces.
|
Package spacer provides a client to create and communicate with so-called “spacer services” that on demand create new Linux kernel namespaces, especially sub user and PID namespaces. |
|
api
Package api defines the specific protocol requests and responses used between clients and servers of the “spacer” namespace creation service.
|
Package api defines the specific protocol requests and responses used between clients and servers of the “spacer” namespace creation service. |
|
gobmsg
Package gobmsg supports working with gob-encoded discrete messages (as opposed to streams).
|
Package gobmsg supports working with gob-encoded discrete messages (as opposed to streams). |
|
service
Package service serves the spacer API.
|
Package service serves the spacer API. |
|
service/cmd/spacer-service
command
Package main provides the command for running a spacer service as a separate process.
|
Package main provides the command for running a spacer service as a separate process. |
|
Package uds supports transferring open file descriptors across process boundaries using peer-to-peer pairs of (stream) unix domain sockets.
|
Package uds supports transferring open file descriptors across process boundaries using peer-to-peer pairs of (stream) unix domain sockets. |