github.com/thediveo/gons@v0.9.9/README.md (about)

     1  # gons
     2  
     3  [![Go Reference](https://pkg.go.dev/badge/godoc.org/github.com/TheDiveO/gons.svg)](https://pkg.go.dev/github.com/TheDiveO/gons)
     4  [![GitHub](https://img.shields.io/github/license/thediveo/gons)](https://img.shields.io/github/license/thediveo/gons)
     5  ![build and test](https://github.com/TheDiveO/gons/workflows/build%20and%20test/badge.svg?branch=master)
     6  [![Go Report Card](https://goreportcard.com/badge/github.com/thediveo/gons)](https://goreportcard.com/report/github.com/thediveo/gons)
     7  ![Coverage](https://img.shields.io/badge/Coverage-82.9%25-brightgreen)
     8  
     9  ## gons
    10  
    11  `gons` ("go [*into*] namespaces") is a small Go package that selectively
    12  switches your Go application into other already existing Linux namespaces.
    13  This must happen before the Go runtime spins up, blocking certain namespace
    14  changes, such as changing into a different mount namespace.
    15  
    16  - `gons` switches the Go application *itself* it is linked to into a set of
    17    already existing namespaces, and only so at *startup*.
    18  - `gons` does *neither fork nor re-execute* in order to switch namespaces.
    19  - `gons` *does not* create new namespaces.
    20  
    21  In consequence, `gons` is a package tackling a different usecase than
    22  `runc/libcontainer`'s famous
    23  [*nsenter*](https://github.com/opencontainers/runc/tree/master/libcontainer/nsenter)
    24  package.
    25  
    26  The existing namespaces to join/switch into are referenced by their paths in
    27  the filesystem (such as `/proc/123456/ns/mnt`), and are specified using
    28  environment variables. Set only the environment variables for those namespaces
    29  that should be switched at startup. These variables need to be set before your
    30  application is started. The names of the environment variables are as follows
    31  and must be all lowercase:
    32  
    33  - `gons_cgroup=...`
    34  - `gons_ipc=...`
    35  - `gons_mnt=...`
    36  - `gons_net=...`
    37  - `gons_pid=...` (*please note that this does not switch your application's
    38    own PID namespace, but rather controls the PID namespace any child processes
    39    of your application will be put into.*)
    40  - `gons_user=...`
    41  - `gons_uts=...`
    42  
    43  Additionally, you can specify the order in which the namespaces should be
    44  switched, as well as when the namespace paths are to be opened:
    45  
    46  - if not overridden by the optional environment variable `gons_order=...`,
    47    then the default order is `!user,!mnt,!cgroup,!ipc,!net,!pid,!uts` (see
    48    below for the meaning of "`!`"). It's not necessary to specify all 7
    49    namespace types when you don't intend to switch them all. For instance, if
    50    you just switch the net and IPC namespaces, then `gons_order=net,ipc` is
    51    sufficient.
    52  - when a namespace type name is preceded by a bang "`!`", such as `!user`,
    53    then the its path will be opened before the first namespace switch takes
    54    place. Without a bang, the namespace path is opened just right before
    55    switching into this namespace. This is mostly of importance when switching
    56    the mount namespace, as this can also change the filesystem and thus how the
    57    namespace paths are resolved.
    58  
    59  > **Note:** if a given namespace path is invalid, or if there are insufficient
    60  > rights to access the path or switch to the specified namespace, then an
    61  > error message is stored which you need to pick up later in your application
    62  > using `gons.Status()`. Please see the package documentation for details.
    63  
    64  The `gons` package requires [cgo](https://golang.org/cmd/cgo/): the required
    65  namespace switches can only safely be done while your application is still
    66  single-threaded and that's only the case before the Go runtime is spinning up.
    67  
    68  ## gons/reexec
    69  
    70  `gons/reexec` helps with forking and re-executing an application in order to
    71  switch namespaces, run some action, sending back intelligence to the parent
    72  application process, and then terminating the re-executed child. The parent
    73  process (or rather: go routine) then continues, working on the intelligence
    74  gathered.
    75  
    76  A very simplistic example:
    77  
    78  ```go
    79  package main
    80  
    81  import (
    82    "fmt"
    83    "github.com/thediveo/gons/reexec"
    84  )
    85  
    86  func init() {
    87    reexec.Register("answertoeverything", func() {
    88      fmt.Fprintln(os.Stdout, `42`)
    89    })
    90  }
    91  
    92  func main() {
    93    var answer int
    94    reexec.RunReexecAction("answertoeverything", reexec.Result(&s))
    95    fmt.Printf("answer: %d\n", answer)
    96  }
    97  ```
    98  
    99  - `reexec.Register` registers an action with its name and the code to execute.
   100  - `reexec.RunReexecAction` forks and re-executes itself as a child process,
   101    triggering the named action. It then picks up the result, which the action
   102    has to print to `os.Stdout` in JSON format, and prints the result.
   103  
   104  ## gons/reexec/testing
   105  
   106  So you want to get code coverage data even across one or several
   107  re-executions? Then you'll need to add a `TestMain` as follows:
   108  
   109  ```go
   110  package foobar
   111  
   112  import (
   113      "testing"
   114  
   115      rxtst "github.com/thediveo/gons/reexec/testing"
   116  )
   117  
   118  func TestMain(m *testing.M) {
   119      mm := &rxtst.M{M: m}
   120      os.Exit(mm.Run())
   121  }
   122  ```
   123  
   124  As you can see from this code above, `TestMain` takes the usual `m *testing.M`
   125  parameter. But instead of directly calling `m.Run()` we have to wrap it into a
   126  `txtst.M` instead, and call `Run()` only on the wrapper. This wrapper contains
   127  the magic to cause re-executed actions to write coverage profile data and to
   128  merge it with the main process' coverage profile data.
   129  
   130  ## Copyright and License
   131  
   132  `gons` is Copyright 2019-23 Harald Albrecht, and licensed under the Apache
   133  License, Version 2.0.