containerd Documentation

See for upstream containerd

115 stars Go Go 43 files · ~52,378 tokens
RAW Doc

Technical Documentation: docker/containerd

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)


containerd is an industry-standard container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc..

containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.

State of the Project

containerd currently has two active branches.
There is a v0.2.x branch for the current release of containerd that is being consumed by Docker and others and the master branch is the development branch for the 1.0 roadmap and feature set.
Any PR or issue that is intended for the current v0.2.x release should be tagged with the same v0.2.x tag.

Communication

For async communication and long running discussions please use issues and pull requests on the github repo.
This will be the best place to discuss design and implementation.

For sync communication we have a community slack with a #containerd channel that everyone is welcome to join and chat about development.

Slack: https://dockr.ly/community

Developer Quick-Start

To build the daemon and ctr simple test client, the following build system dependencies are required:

  • Go 1.8.x or above (requires 1.8 due to use of golang plugin(s))
  • Protoc 3.x compiler and headers (download at the Google protobuf releases page)
  • Btrfs headers and libraries for your distribution. Note that building the btrfs driver can be disabled via build tag removing this dependency.

For proper results, install the protoc release into /usr/local on your build system. For example, the following commands will download and install the 3.1.0 release for a 64-bit Linux host:

text
$ wget -c https://github.com/google/protobuf/releases/download/v3.1.0/protoc-3.1.0-linux-x86_64.zip
$ sudo unzip protoc-3.1.0-linux-x86_64.zip -d /usr/local

With the required dependencies installed, the Makefile target named binaries will compile the ctr and containerd binaries and place them in the bin/ directory. Using sudo make install will place the binaries in /usr/local/bin. When making any changes to the gRPC API, make generate will use the installed protoc compiler to regenerate the API generated code packages.

Note: A build tag is currently available to disable building the btrfs snapshot driver.
Adding BUILDTAGS=no_btrfs to your environment before calling the binaries
Makefile target will disable the btrfs driver within the containerd Go build.

Vendoring of external imports uses the vndr tool which uses a simple config file, vendor.conf, to provide the URL and version or hash details for each vendored import. After modifying vendor.conf run the vndr tool to update the vendor/ directory contents. Combining the vendor.conf update with the changeset in vendor/ after running vndr should become a single commit for a PR which relies on vendored updates.

Please refer to RUNC.md for the currently supported version of runc that is used by containerd.

Features

  • OCI Image Spec support
  • OCI Runtime Spec support
  • Image push and pull support
  • Container runtime and lifecycle support
  • Management of network namespaces containers to join existing namespaces
  • Multi-tenant supported with CAS storage for global images

Scope and Principles

Having a clearly defined scope of a project is important for ensuring consistency and focus.
These following criteria will be used when reviewing pull requests, features, and changes for the project before being accepted.

Components

Components should not have tight dependencies on each other so that they are able to be used independently.
The APIs for images and containers should be designed in a way that when used together the components have a natural flow but still be useful independently.

An example for this design can be seen with the overlay filesystems and the container execution layer.
The execution layer and overlay filesystems can be used independently but if you were to use both, they share a common Mount struct that the filesystems produce and the execution layer consumes.

Primitives

containerd should expose primitives to solve problems instead of building high level abstractions in the API.
A common example of this is how build would be implemented.
Instead of having a build API in containerd we should expose the lower level primitives that allow things required in build to work.
Breaking up the filesystem APIs to allow snapshots, copy functionality, and mounts allow people implementing build at the higher levels more flexibility.

Extensibility and Defaults

For the various components in containerd there should be defined extension points where implementations can be swapped for alternatives.
The best example of this is that containerd will use runc from OCI as the default runtime in the execution layer but other runtimes conforming to the OCI Runtime specification they can be easily added to containerd.

containerd will come with a default implementation for the various components.
These defaults will be chosen by the maintainers of the project and should not change unless better tech for that component comes out.
Additional implementations will not be accepted into the core repository and should be developed in a separate repository not maintained by the containerd maintainers.

Releases

containerd will be released with a 1.0 when feature complete and this version will be supported for 1 year with security and bug fixes applied and released.

The upgrade path for containerd is that the 0.0.x patch releases are always backward compatible with its major and minor version.
Minor (0.x.0) version will always be compatible with the previous minor release. i.e. 1.2.0 is backwards compatible with 1.1.0 and 1.1.0 is compatible with 1.0.0.
There is no compatibility guarantees with upgrades from two minor releases. i.e. 1.0.0 to 1.2.0.

There are not backwards compatibility guarantees with upgrades to major versions. i.e 1.0.0 to 2.0.0.
Each major version will be supported for 1 year with bug fixes and security patches.

Scope

The following table specifies the various components of containerd and general features of container runtimes.
The table specifies whether or not the feature/component is in or out of scope.

Name Description In/Out Reason
execution Provide an extensible execution layer for executing a container in Create,start, stop pause, resume exec, signal, delete
cow filesystem Built in functionality for overlay, aufs, and other copy on write filesystems for containers in
distribution Having the ability to push and pull images as well as operations on images as a first class API object in containerd will fully support the management and retrieval of images
metrics container-level metrics, cgroup stats, and OOM events in
networking creation and management of network interfaces out Networking will be handled and provided to containerd via higher level systems.
build Building images as a first class API out Build is a higher level tooling feature and can be implemented in many different ways on top of containerd
volumes Volume management for external data out The API supports mounts, binds, etc where all volumes type systems can be built on top of containerd.
logging Persisting container logs out Logging can be build on top of containerd because the container’s STDIO will be provided to the clients and they can persist any way they see fit. There is no io copying of container STDIO in containerd.

containerd is scoped to a single host and makes assumptions based on that fact.
It can be used to build things like a node agent that launches containers but does not have any concepts of a distributed system.

containerd is designed to be embedded into a larger system, hence it only includes a barebone CLI (ctr) specifically for development and debugging purpose, with no mandate to be human-friendly, and no guarantee of interface stability over time.

Also things like service discovery are out of scope even though networking is in scope.
containerd should provide the primitives to create, add, remove, or manage network interfaces and network namespaces for a container but IP allocation, discovery, and DNS should be handled at higher layers.

How is the scope changed?

The scope of this project is a whitelist.
If it's not mentioned as being in scope, it is out of scope.
For the scope of this project to change it requires a 100% vote from all maintainers of the project.

Development reports.

Weekly summary on the progress and what is being worked on.
https://github.com/containerd/containerd/tree/master/reports

Copyright © 2016 Docker, Inc. All rights reserved, except as follows. Code
is released under the Apache 2.0 license. The README.md file, and files in the
"docs" folder are licensed under the Creative Commons Attribution 4.0
International License under the terms and conditions set forth in the file
"LICENSE.docs". You may obtain a duplicate copy of the same license, titled
CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.


Overview (`docs/README.md`)

Containerd website

The containerd website is built using Jekyll and published to Github pages.

In order to build and test locally:

text
docker run -v "$PWD":/usr/src/app -p "4000:4000" starefossen/github-pages

Then browser to localhost:4000 to see the rendered site. The site autorefreshes when you modify files locally.


Overview (`vendor/google.golang.org/grpc/README.md`)

#gRPC-Go

The Go implementation of gRPC: A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the gRPC Quick Start guide.

Installation

To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run:

text
$ go get google.golang.org/grpc

Prerequisites

This requires Go 1.5 or later.

A note on the version used: significant performance improvements in benchmarks
of grpc-go have been seen by upgrading the go version from 1.5 to the latest
1.7.1.

From https://golang.org/doc/install, one way to install the latest version of go is:

text
$ GO_VERSION=1.7.1
$ OS=linux
$ ARCH=amd64
$ curl -O https://storage.googleapis.com/golang/go${GO_VERSION}.${OS}-${ARCH}.tar.gz
$ sudo tar -C /usr/local -xzf go$GO_VERSION.$OS-$ARCH.tar.gz
$ # Put go on the PATH, keep the usual installation dir
$ sudo ln -s /usr/local/go/bin/go /usr/bin/go
$ rm go$GO_VERSION.$OS-$ARCH.tar.gz

Constraints

The grpc package should only depend on standard Go packages and a small number of exceptions. If your contribution introduces new dependencies which are NOT in the list, you need a discussion with gRPC-Go authors and consultants.

Documentation

See API documentation for package and API descriptions and find examples in the examples directory.

Status

GA

FAQ

Compiling error, undefined: grpc.SupportPackageIsVersion

Please update proto package, gRPC package and rebuild the proto files:

  • go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
  • go get -u google.golang.org/grpc
  • protoc --go_out=plugins=grpc:. *.proto

Overview (`vendor/github.com/Azure/go-ansiterm/README.md`)

go-ansiterm

This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent.

For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position.

The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go).

See parser_test.go for examples exercising the state machine and generating appropriate function calls.


This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.


Overview (`vendor/github.com/BurntSushi/toml/README.md`)

TOML parser and encoder for Go with reflection

TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
reflection interface similar to Go's standard library json and xml
packages. This package also supports the encoding.TextUnmarshaler and
encoding.TextMarshaler interfaces so that you can define custom data
representations. (There is an example of this below.)

Spec: https://github.com/mojombo/toml

Compatible with TOML version
v0.2.0

Documentation: http://godoc.org/github.com/BurntSushi/toml

Installation:

bash
go get github.com/BurntSushi/toml

Try the toml validator:

bash
go get github.com/BurntSushi/toml/cmd/tomlv
tomlv some-toml-file.toml

Testing

This package passes all tests in
toml-test for both the decoder
and the encoder.

Examples

This package works similarly to how the Go standard library handles XML
and JSON. Namely, data is loaded into Go values via reflection.

For the simplest example, consider some TOML file as just a list of keys
and values:

toml
Age = 25
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z

Which could be defined in Go as:

go
type Config struct {
  Age int
  Cats []string
  Pi float64
  Perfection []int
  DOB time.Time // requires `import time`
}

And then decoded with:

go
var conf Config
if _, err := toml.Decode(tomlData, &conf); err != nil {
  // handle error
}

You can also use struct tags if your struct field name doesn't map to a TOML
key value directly:

toml
some_key_NAME = "wat"
go
type TOML struct {
  ObscureKey string `toml:"some_key_NAME"`
}

Using the `encoding.TextUnmarshaler` interface

Here's an example that automatically parses duration strings into
time.Duration values:

toml
[[song]]
name = "Thunder Road"
duration = "4m49s"

[[song]]
name = "Stairway to Heaven"
duration = "8m03s"

Which can be decoded with:

go
type song struct {
  Name     string
  Duration duration
}
type songs struct {
  Song []song
}
var favorites songs
if _, err := toml.Decode(blob, &favorites); err != nil {
  log.Fatal(err)
}

for _, s := range favorites.Song {
  fmt.Printf("%s (%s)\n", s.Name, s.Duration)
}

And you'll also need a duration type that satisfies the
encoding.TextUnmarshaler interface:

go
type duration struct {
	time.Duration
}

func (d *duration) UnmarshalText(text []byte) error {
	var err error
	d.Duration, err = time.ParseDuration(string(text))
	return err
}

More complex usage

Here's an example of how to load the example from the official spec page:

toml
# This is a TOML document. Boom.

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

[servers]

  # You can indent as you please. Tabs or spaces. TOML don't care.
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it

# Line breaks are OK when inside arrays
hosts = [
  "alpha",
  "omega"
]

And the corresponding Go types are:

go
type tomlConfig struct {
	Title string
	Owner ownerInfo
	DB database `toml:"database"`
	Servers map[string]server
	Clients clients
}

type ownerInfo struct {
	Name string
	Org string `toml:"organization"`
	Bio string
	DOB time.Time
}

type database struct {
	Server string
	Ports []int
	ConnMax int `toml:"connection_max"`
	Enabled bool
}

type server struct {
	IP string
	DC string
}

type clients struct {
	Data [][]interface{}
	Hosts []string
}

Note that a case insensitive match will be tried if an exact match can't be
found.

A working example of the above can be found in _examples/example.{go,toml}.


Overview (`vendor/github.com/Microsoft/go-winio/README.md`)

go-winio

This repository contains utilities for efficiently performing Win32 IO operations in
Go. Currently, this is focused on accessing named pipes and other file handles, and
for using named pipes as a net transport.

This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
newer operating systems. This is similar to the implementation of network sockets in Go's net
package.

Please see the LICENSE file for licensing information.

This project has adopted the Microsoft Open Source Code of
Conduct
. For more information
see the Code of Conduct
FAQ
or contact
[email protected] with any additional
questions or comments.

Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
for another named pipe implementation.


Overview (`vendor/github.com/Microsoft/hcsshim/README.md`)

hcsshim

This package supports launching Windows Server containers from Go. It is
primarily used in the Docker Engine project,
but it can be freely used by other projects as well.

This project has adopted the Microsoft Open Source Code of
Conduct
. For more information
see the Code of Conduct
FAQ
or contact
[email protected] with any additional
questions or comments.


Overview (`vendor/github.com/Sirupsen/logrus/README.md`)

Logrus  [](https://travis-ci.org/Sirupsen/logrus) [](https://godoc.org/github.com/Sirupsen/logrus)

Logrus is a structured logger for Go (golang), completely API compatible with
the standard library logger. [Godoc][godoc]. Please note the Logrus API is not
yet stable (pre 1.0). Logrus itself is completely stable and has been used in
many large deployments. The core API is unlikely to change much but please
version control your Logrus to make sure you aren't fetching latest master on
every build.

Nicely color-coded in development (when a TTY is attached, otherwise just
plain text):

With log.SetFormatter(&log.JSONFormatter{}), for easy parsing by logstash
or Splunk:

json
{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}

{"level":"warning","msg":"The group's number increased tremendously!",
"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}

{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}

{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}

{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}

With the default log.SetFormatter(&log.TextFormatter{}) when a TTY is not
attached, the output is compatible with the
logfmt format:

text
time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true
exit status 1

Example

The simplest way to use Logrus is simply the package-level exported logger:

go
package main

import (
  log "github.com/Sirupsen/logrus"
)

func main() {
  log.WithFields(log.Fields{
    "animal": "walrus",
  }).Info("A walrus appears")
}

Note that it's completely api-compatible with the stdlib logger, so you can
replace your log imports everywhere with log "github.com/Sirupsen/logrus"
and you'll now have the flexibility of Logrus. You can customize it all you
want:

go
package main

import (
  "os"
  log "github.com/Sirupsen/logrus"
)

func init() {
  // Log as JSON instead of the default ASCII formatter.
  log.SetFormatter(&log.JSONFormatter{})

  // Output to stderr instead of stdout, could also be a file.
  log.SetOutput(os.Stderr)

  // Only log the warning severity or above.
  log.SetLevel(log.WarnLevel)
}

func main() {
  log.WithFields(log.Fields{
    "animal": "walrus",
    "size":   10,
  }).Info("A group of walrus emerges from the ocean")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 122,
  }).Warn("The group's number increased tremendously!")

  log.WithFields(log.Fields{
    "omg":    true,
    "number": 100,
  }).Fatal("The ice breaks!")

  // A common pattern is to re-use fields between logging statements by re-using
  // the logrus.Entry returned from WithFields()
  contextLogger := log.WithFields(log.Fields{
    "common": "this is a common field",
    "other": "I also should be logged always",
  })

  contextLogger.Info("I'll be logged with common and other field")
  contextLogger.Info("Me too")
}

For more advanced usage such as logging to multiple locations from the same
application, you can also create an instance of the logrus Logger:

go
package main

import (
  "github.com/Sirupsen/logrus"
)

// Create a new instance of the logger. You can have any number of instances.
var log = logrus.New()

func main() {
  // The API for setting attributes is a little different than the package level
  // exported logger. See Godoc.
  log.Out = os.Stderr

  log.WithFields(logrus.Fields{
    "animal": "walrus",
    "size":   10,
  }).Info("A group of walrus emerges from the ocean")
}

Fields

Logrus encourages careful, structured logging though logging fields instead of
long, unparseable error messages. For example, instead of: log.Fatalf("Failed to send event %s to topic %s with key %d"), you should log the much more
discoverable:

go
log.WithFields(log.Fields{
  "event": event,
  "topic": topic,
  "key": key,
}).Fatal("Failed to send event")

We've found this API forces you to think about logging in a way that produces
much more useful logging messages. We've been in countless situations where just
a single added field to a log statement that was already there would've saved us
hours. The WithFields call is optional.

In general, with Logrus using any of the printf-family functions should be
seen as a hint you should add a field, however, you can still use the
printf-family functions with Logrus.

Hooks

You can add hooks for logging levels. For example to send errors to an exception
tracking service on Error, Fatal and Panic, info to StatsD or log to
multiple places simultaneously, e.g. syslog.

Logrus comes with built-in hooks. Add those, or your custom hook, in
init:

go
import (
  log "github.com/Sirupsen/logrus"
  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
  "log/syslog"
)

func init() {

  // Use the Airbrake hook to report errors that have Error severity or above to
  // an exception tracker. You can create custom hooks, see the Hooks section.
  log.AddHook(airbrake.NewHook(123, "xyz", "production"))

  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
  if err != nil {
    log.Error("Unable to connect to local syslog daemon")
  } else {
    log.AddHook(hook)
  }
}

Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the syslog hook README.

Hook Description
Airbrake Send errors to the Airbrake API V3. Uses the official gobrake behind the scenes.
Airbrake "legacy" Send errors to an exception tracking service compatible with the Airbrake API V2. Uses airbrake-go behind the scenes.
Papertrail Send errors to the Papertrail hosted logging service via UDP.
Syslog Send errors to remote syslog server. Uses standard library log/syslog behind the scenes.
Bugsnag Send errors to the Bugsnag exception tracking service.
Sentry Send errors to the Sentry error logging and aggregation service.
Hiprus Send errors to a channel in hipchat.
Logrusly Send logs to Loggly
Slackrus Hook for Slack chat.
Journalhook Hook for logging to systemd-journald
Graylog Hook for logging to Graylog
Raygun Hook for logging to Raygun.io
LFShook Hook for logging to the local filesystem
Honeybadger Hook for sending exceptions to Honeybadger
Mail Hook for sending exceptions via mail
Rollrus Hook for sending errors to rollbar
Fluentd Hook for logging to fluentd
Mongodb Hook for logging to mongodb
[Influxus] (http://github.com/vlad-doru/influxus) Hook for concurrently logging to [InfluxDB] (http://influxdata.com/)
InfluxDB Hook for logging to influxdb
Octokit Hook for logging to github via octokit
DeferPanic Hook for logging to DeferPanic
Redis-Hook Hook for logging to a ELK stack (through Redis)
Amqp-Hook Hook for logging to Amqp broker (Like RabbitMQ)
KafkaLogrus Hook for logging to kafka
Typetalk Hook for logging to Typetalk
ElasticSearch Hook for logging to ElasticSearch
Sumorus Hook for logging to SumoLogic
Scribe Hook for logging to Scribe
Logstash Hook for logging to Logstash
logz.io Hook for logging to logz.io, a Log as a Service using Logstash
Logmatic.io Hook for logging to Logmatic.io
Pushover Send error via Pushover

Level logging

Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.

go
log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
log.Error("Something failed but I'm not quitting.")
// Calls os.Exit(1) after logging
log.Fatal("Bye.")
// Calls panic() after logging
log.Panic("I'm bailing.")

You can set the logging level on a Logger, then it will only log entries with
that severity or anything above it:

go
// Will log anything that is info or above (warn, error, fatal, panic). Default.
log.SetLevel(log.InfoLevel)

It may be useful to set log.Level = logrus.DebugLevel in a debug or verbose
environment if your application has that.

Entries

Besides the fields added with WithField or WithFields some fields are
automatically added to all logging events:

  1. time. The timestamp when the entry was created.
  2. msg. The logging message passed to {Info,Warn,Error,Fatal,Panic} after
    the AddFields call. E.g. Failed to send event.
  3. level. The logging level. E.g. info.

Environments

Logrus has no notion of environment.

If you wish for hooks and formatters to only be used in specific environments,
you should handle that yourself. For example, if your application has a global
variable Environment, which is a string representation of the environment you
could do:

go
import (
  log "github.com/Sirupsen/logrus"
)

init() {
  // do something here to set environment depending on an environment variable
  // or command-line flag
  if Environment == "production" {
    log.SetFormatter(&log.JSONFormatter{})
  } else {
    // The TextFormatter is default, you don't actually have to do this.
    log.SetFormatter(&log.TextFormatter{})
  }
}

This configuration is how logrus was intended to be used, but JSON in
production is mostly only useful if you do log aggregation with tools like
Splunk or Logstash.

Formatters

The built-in logging formatters are:

  • logrus.TextFormatter. Logs the event in colors if stdout is a tty, otherwise
    without colors.
    • Note: to force colored output when there is no TTY, set the ForceColors
      field to true. To force no colored output even if there is a TTY set the
      DisableColors field to true
  • logrus.JSONFormatter. Logs fields as JSON.

Third party logging formatters:

  • logstash. Logs fields as Logstash Events.
  • prefixed. Displays log entry source along with alternative layout.
  • zalgo. Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.

You can define your formatter by implementing the Formatter interface,
requiring a Format method. Format takes an *Entry. entry.Data is a
Fields type (map[string]interface{}) with all your fields as well as the
default ones (see Entries section above):

go
type MyJSONFormatter struct {
}

log.SetFormatter(new(MyJSONFormatter))

func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) {
  // Note this doesn't include Time, Level and Message which are available on
  // the Entry. Consult `godoc` on information about those fields or read the
  // source of the official loggers.
  serialized, err := json.Marshal(entry.Data)
    if err != nil {
      return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
    }
  return append(serialized, '\n'), nil
}

Logger as an `io.Writer`

Logrus can be transformed into an io.Writer. That writer is the end of an io.Pipe and it is your responsibility to close it.

go
w := logger.Writer()
defer w.Close()

srv := http.Server{
    // create a stdlib log.Logger that writes to
    // logrus.Logger.
    ErrorLog: log.New(w, "", 0),
}

Each line written to that writer will be printed the usual way, using formatters
and hooks. The level for those entries is info.

Rotation

Log rotation is not provided with Logrus. Log rotation should be done by an
external program (like logrotate(8)) that can compress and delete old log
entries. It should not be a feature of the application-level logger.

Tools

Tool Description
Logrus Mate Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.
Logrus Viper Helper An Helper arround Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of Logrus Mate. sample

Testing

Logrus has a built in facility for asserting the presence of log messages. This is implemented through the test hook and provides:

  • decorators for existing logger (test.NewLocal and test.NewGlobal) which basically just add the test hook
  • a test logger (test.NewNullLogger) that just records log messages (and does not output any):
go
logger, hook := NewNullLogger()
logger.Error("Hello error")

assert.Equal(1, len(hook.Entries))
assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
assert.Equal("Hello error", hook.LastEntry().Message)

hook.Reset()
assert.Nil(hook.LastEntry())

Fatal handlers

Logrus can register one or more functions that will be called when any fatal
level message is logged. The registered handlers will be executed before
logrus performs a os.Exit(1). This behavior may be helpful if callers need
to gracefully shutdown. Unlike a panic("Something went wrong...") call which can be intercepted with a deferred recover a call to os.Exit(1) can not be intercepted.

text
...
handler := func() {
  // gracefully shutdown something...
}
logrus.RegisterExitHandler(handler)
...

Thread safty

By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.

Situation when locking is not needed includes:

  • You have no hooks registered, or hooks calling is already thread-safe.

  • Writing to logger.Out is already thread-safe, for example:

    1. logger.Out is protected by locks.

    2. logger.Out is a os.File handler opened with O_APPEND flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing)

      (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/)


Overview (`vendor/github.com/beorn7/perks/README.md`)

Perks for Go (golang.org)

Perks contains the Go package quantile that computes approximate quantiles over
an unbounded data stream within low memory and CPU bounds.

For more information and examples, see:
http://godoc.org/github.com/bmizerany/perks

A very special thank you and shout out to Graham Cormode (Rutgers University),
Flip Korn (AT&T Labs–Research), S. Muthukrishnan (Rutgers University), and
Divesh Srivastava (AT&T Labs–Research) for their research and publication of
Effective Computation of Biased Quantiles over Data Streams

Thank you, also:

  • Armon Dadgar (@armon)
  • Andrew Gerrand (@nf)
  • Brad Fitzpatrick (@bradfitz)
  • Keith Rarick (@kr)

FAQ:

Q: Why not move the quantile package into the project root?
A: I want to add more packages to perks later.

Copyright (C) 2013 Blake Mizerany

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Overview (`vendor/github.com/boltdb/bolt/README.md`)

Bolt [](https://coveralls.io/r/boltdb/bolt?branch=master) [](https://godoc.org/github.com/boltdb/bolt)

Bolt is a pure Go key/value store inspired by Howard Chu's
LMDB project. The goal of the project is to provide a simple,
fast, and reliable database for projects that don't require a full database
server such as Postgres or MySQL.

Since Bolt is meant to be used as such a low-level piece of functionality,
simplicity is key. The API will be small and only focus on getting values
and setting values. That's it.

Project Status

Bolt is stable, the API is fixed, and the file format is fixed. Full unit
test coverage and randomized black box testing are used to ensure database
consistency and thread safety. Bolt is currently used in high-load production
environments serving databases as large as 1TB. Many companies such as
Shopify and Heroku use Bolt-backed services every day.

Table of Contents

Getting Started

Installing

To start using Bolt, install Go and run go get:

sh
$ go get github.com/boltdb/bolt/...

This will retrieve the library and install the bolt command line utility into
your $GOBIN path.

Opening a database

The top-level object in Bolt is a DB. It is represented as a single file on
your disk and represents a consistent snapshot of your data.

To open your database, simply use the bolt.Open() function:

go
package main

import (
	"log"

	"github.com/boltdb/bolt"
)

func main() {
	// Open the my.db data file in your current directory.
	// It will be created if it doesn't exist.
	db, err := bolt.Open("my.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	...
}

Please note that Bolt obtains a file lock on the data file so multiple processes
cannot open the same database at the same time. Opening an already open Bolt
database will cause it to hang until the other process closes it. To prevent
an indefinite wait you can pass a timeout option to the Open() function:

go
db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})

Transactions

Bolt allows only one read-write transaction at a time but allows as many
read-only transactions as you want at a time. Each transaction has a consistent
view of the data as it existed when the transaction started.

Individual transactions and all objects created from them (e.g. buckets, keys)
are not thread safe. To work with data in multiple goroutines you must start
a transaction for each one or use locking to ensure only one goroutine accesses
a transaction at a time. Creating transaction from the DB is thread safe.

Read-only transactions and read-write transactions should not depend on one
another and generally shouldn't be opened simultaneously in the same goroutine.
This can cause a deadlock as the read-write transaction needs to periodically
re-map the data file but it cannot do so while a read-only transaction is open.

Read-write transactions

To start a read-write transaction, you can use the DB.Update() function:

go
err := db.Update(func(tx *bolt.Tx) error {
	...
	return nil
})

Inside the closure, you have a consistent view of the database. You commit the
transaction by returning nil at the end. You can also rollback the transaction
at any point by returning an error. All database operations are allowed inside
a read-write transaction.

Always check the return error as it will report any disk failures that can cause
your transaction to not complete. If you return an error within your closure
it will be passed through.

Read-only transactions

To start a read-only transaction, you can use the DB.View() function:

go
err := db.View(func(tx *bolt.Tx) error {
	...
	return nil
})

You also get a consistent view of the database within this closure, however,
no mutating operations are allowed within a read-only transaction. You can only
retrieve buckets, retrieve values, and copy the database within a read-only
transaction.

Batch read-write transactions

Each DB.Update() waits for disk to commit the writes. This overhead
can be minimized by combining multiple updates with the DB.Batch()
function:

go
err := db.Batch(func(tx *bolt.Tx) error {
	...
	return nil
})

Concurrent Batch calls are opportunistically combined into larger
transactions. Batch is only useful when there are multiple goroutines
calling it.

The trade-off is that Batch can call the given
function multiple times, if parts of the transaction fail. The
function must be idempotent and side effects must take effect only
after a successful return from DB.Batch().

For example: don't display messages from inside the function, instead
set variables in the enclosing scope:

go
var id uint64
err := db.Batch(func(tx *bolt.Tx) error {
	// Find last key in bucket, decode as bigendian uint64, increment
	// by one, encode back to []byte, and add new key.
	...
	id = newValue
	return nil
})
if err != nil {
	return ...
}
fmt.Println("Allocated ID %d", id)

Managing transactions manually

The DB.View() and DB.Update() functions are wrappers around the DB.Begin()
function. These helper functions will start the transaction, execute a function,
and then safely close your transaction if an error is returned. This is the
recommended way to use Bolt transactions.

However, sometimes you may want to manually start and end your transactions.
You can use the DB.Begin() function directly but please be sure to close
the transaction.

go
// Start a writable transaction.
tx, err := db.Begin(true)
if err != nil {
    return err
}
defer tx.Rollback()

// Use the transaction...
_, err := tx.CreateBucket([]byte("MyBucket"))
if err != nil {
    return err
}

// Commit the transaction and check for error.
if err := tx.Commit(); err != nil {
    return err
}

The first argument to DB.Begin() is a boolean stating if the transaction
should be writable.

Using buckets

Buckets are collections of key/value pairs within the database. All keys in a
bucket must be unique. You can create a bucket using the DB.CreateBucket()
function:

go
db.Update(func(tx *bolt.Tx) error {
	b, err := tx.CreateBucket([]byte("MyBucket"))
	if err != nil {
		return fmt.Errorf("create bucket: %s", err)
	}
	return nil
})

You can also create a bucket only if it doesn't exist by using the
Tx.CreateBucketIfNotExists() function. It's a common pattern to call this
function for all your top-level buckets after you open your database so you can
guarantee that they exist for future transactions.

To delete a bucket, simply call the Tx.DeleteBucket() function.

Using key/value pairs

To save a key/value pair to a bucket, use the Bucket.Put() function:

go
db.Update(func(tx *bolt.Tx) error {
	b := tx.Bucket([]byte("MyBucket"))
	err := b.Put([]byte("answer"), []byte("42"))
	return err
})

This will set the value of the "answer" key to "42" in the MyBucket
bucket. To retrieve this value, we can use the Bucket.Get() function:

go
db.View(func(tx *bolt.Tx) error {
	b := tx.Bucket([]byte("MyBucket"))
	v := b.Get([]byte("answer"))
	fmt.Printf("The answer is: %s\n", v)
	return nil
})

The Get() function does not return an error because its operation is
guaranteed to work (unless there is some kind of system failure). If the key
exists then it will return its byte slice value. If it doesn't exist then it
will return nil. It's important to note that you can have a zero-length value
set to a key which is different than the key not existing.

Use the Bucket.Delete() function to delete a key from the bucket.

Please note that values returned from Get() are only valid while the
transaction is open. If you need to use a value outside of the transaction
then you must use copy() to copy it to another byte slice.

Autoincrementing integer for the bucket

By using the NextSequence() function, you can let Bolt determine a sequence
which can be used as the unique identifier for your key/value pairs. See the
example below.

go
// CreateUser saves u to the store. The new user ID is set on u once the data is persisted.
func (s *Store) CreateUser(u *User) error {
    return s.db.Update(func(tx *bolt.Tx) error {
        // Retrieve the users bucket.
        // This should be created when the DB is first opened.
        b := tx.Bucket([]byte("users"))

        // Generate ID for the user.
        // This returns an error only if the Tx is closed or not writeable.
        // That can't happen in an Update() call so I ignore the error check.
        id, _ := b.NextSequence()
        u.ID = int(id)

        // Marshal user data into bytes.
        buf, err := json.Marshal(u)
        if err != nil {
            return err
        }

        // Persist bytes to users bucket.
        return b.Put(itob(u.ID), buf)
    })
}

// itob returns an 8-byte big endian representation of v.
func itob(v int) []byte {
    b := make([]byte, 8)
    binary.BigEndian.PutUint64(b, uint64(v))
    return b
}

type User struct {
    ID int
    ...
}

Iterating over keys

Bolt stores its keys in byte-sorted order within a bucket. This makes sequential
iteration over these keys extremely fast. To iterate over keys we'll use a
Cursor:

go
db.View(func(tx *bolt.Tx) error {
	// Assume bucket exists and has keys
	b := tx.Bucket([]byte("MyBucket"))

	c := b.Cursor()

	for k, v := c.First(); k != nil; k, v = c.Next() {
		fmt.Printf("key=%s, value=%s\n", k, v)
	}

	return nil
})

The cursor allows you to move to a specific point in the list of keys and move
forward or backward through the keys one at a time.

The following functions are available on the cursor:

text
First()  Move to the first key.
Last()   Move to the last key.
Seek()   Move to a specific key.
Next()   Move to the next key.
Prev()   Move to the previous key.

Each of those functions has a return signature of (key []byte, value []byte).
When you have iterated to the end of the cursor then Next() will return a
nil key. You must seek to a position using First(), Last(), or Seek()
before calling Next() or Prev(). If you do not seek to a position then
these functions will return a nil key.

During iteration, if the key is non-nil but the value is nil, that means
the key refers to a bucket rather than a value. Use Bucket.Bucket() to
access the sub-bucket.

Prefix scans

To iterate over a key prefix, you can combine Seek() and bytes.HasPrefix():

go
db.View(func(tx *bolt.Tx) error {
	// Assume bucket exists and has keys
	c := tx.Bucket([]byte("MyBucket")).Cursor()

	prefix := []byte("1234")
	for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
		fmt.Printf("key=%s, value=%s\n", k, v)
	}

	return nil
})

Range scans

Another common use case is scanning over a range such as a time range. If you
use a sortable time encoding such as RFC3339 then you can query a specific
date range like this:

go
db.View(func(tx *bolt.Tx) error {
	// Assume our events bucket exists and has RFC3339 encoded time keys.
	c := tx.Bucket([]byte("Events")).Cursor()

	// Our time range spans the 90's decade.
	min := []byte("1990-01-01T00:00:00Z")
	max := []byte("2000-01-01T00:00:00Z")

	// Iterate over the 90's.
	for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() {
		fmt.Printf("%s: %s\n", k, v)
	}

	return nil
})

Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable.

ForEach()

You can also use the function ForEach() if you know you'll be iterating over
all the keys in a bucket:

go
db.View(func(tx *bolt.Tx) error {
	// Assume bucket exists and has keys
	b := tx.Bucket([]byte("MyBucket"))

	b.ForEach(func(k, v []byte) error {
		fmt.Printf("key=%s, value=%s\n", k, v)
		return nil
	})
	return nil
})

Please note that keys and values in ForEach() are only valid while
the transaction is open. If you need to use a key or value outside of
the transaction, you must use copy() to copy it to another byte
slice.

Nested buckets

You can also store a bucket in a key to create nested buckets. The API is the
same as the bucket management API on the DB object:

go
func (*Bucket) CreateBucket(key []byte) (*Bucket, error)
func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error)
func (*Bucket) DeleteBucket(key []byte) error

Say you had a multi-tenant application where the root level bucket was the account bucket. Inside of this bucket was a sequence of accounts which themselves are buckets. And inside the sequence bucket you could have many buckets pertaining to the Account itself (Users, Notes, etc) isolating the information into logical groupings.

go
// createUser creates a new user in the given account.
func createUser(accountID int, u *User) error {
    // Start the transaction.
    tx, err := db.Begin(true)
    if err != nil {
        return err
    }
    defer tx.Rollback()

    // Retrieve the root bucket for the account.
    // Assume this has already been created when the account was set up.
    root := tx.Bucket([]byte(strconv.FormatUint(accountID, 10)))

    // Setup the users bucket.
    bkt, err := root.CreateBucketIfNotExists([]byte("USERS"))
    if err != nil {
        return err
    }

    // Generate an ID for the new user.
    userID, err := bkt.NextSequence()
    if err != nil {
        return err
    }
    u.ID = userID

    // Marshal and save the encoded user.
    if buf, err := json.Marshal(u); err != nil {
        return err
    } else if err := bkt.Put([]byte(strconv.FormatUint(u.ID, 10)), buf); err != nil {
        return err
    }

    // Commit the transaction.
    if err := tx.Commit(); err != nil {
        return err
    }

    return nil
}

Database backups

Bolt is a single file so it's easy to backup. You can use the Tx.WriteTo()
function to write a consistent view of the database to a writer. If you call
this from a read-only transaction, it will perform a hot backup and not block
your other database reads and writes.

By default, it will use a regular file handle which will utilize the operating
system's page cache. See the Tx
documentation for information about optimizing for larger-than-RAM datasets.

One common use case is to backup over HTTP so you can use tools like cURL to
do database backups:

go
func BackupHandleFunc(w http.ResponseWriter, req *http.Request) {
	err := db.View(func(tx *bolt.Tx) error {
		w.Header().Set("Content-Type", "application/octet-stream")
		w.Header().Set("Content-Disposition", `attachment; filename="my.db"`)
		w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size())))
		_, err := tx.WriteTo(w)
		return err
	})
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

Then you can backup using this command:

sh
$ curl http://localhost/backup > my.db

Or you can open your browser to http://localhost/backup and it will download
automatically.

If you want to backup to another file you can use the Tx.CopyFile() helper
function.

Statistics

The database keeps a running count of many of the internal operations it
performs so you can better understand what's going on. By grabbing a snapshot
of these stats at two points in time we can see what operations were performed
in that time range.

For example, we could start a goroutine to log stats every 10 seconds:

go
go func() {
	// Grab the initial stats.
	prev := db.Stats()

	for {
		// Wait for 10s.
		time.Sleep(10 * time.Second)

		// Grab the current stats and diff them.
		stats := db.Stats()
		diff := stats.Sub(&prev)

		// Encode stats to JSON and print to STDERR.
		json.NewEncoder(os.Stderr).Encode(diff)

		// Save stats for the next loop.
		prev = stats
	}
}()

It's also useful to pipe these stats to a service such as statsd for monitoring
or to provide an HTTP endpoint that will perform a fixed-length sample.

Read-Only Mode

Sometimes it is useful to create a shared, read-only Bolt database. To this,
set the Options.ReadOnly flag when opening your database. Read-only mode
uses a shared lock to allow multiple processes to read from the database but
it will block any processes from opening the database in read-write mode.

go
db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true})
if err != nil {
	log.Fatal(err)
}

Mobile Use (iOS/Android)

Bolt is able to run on mobile devices by leveraging the binding feature of the
gomobile tool. Create a struct that will
contain your database logic and a reference to a *bolt.DB with a initializing
constructor that takes in a filepath where the database file will be stored.
Neither Android nor iOS require extra permissions or cleanup from using this method.

go
func NewBoltDB(filepath string) *BoltDB {
	db, err := bolt.Open(filepath+"/demo.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}

	return &BoltDB{db}
}

type BoltDB struct {
	db *bolt.DB
	...
}

func (b *BoltDB) Path() string {
	return b.db.Path()
}

func (b *BoltDB) Close() {
	b.db.Close()
}

Database logic should be defined as methods on this wrapper struct.

To initialize this struct from the native language (both platforms now sync
their local storage to the cloud. These snippets disable that functionality for the
database file):

Android

java
String path;
if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){
    path = getNoBackupFilesDir().getAbsolutePath();
} else{
    path = getFilesDir().getAbsolutePath();
}
Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path)

iOS

objc
- (void)demo {
    NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
                                                          NSUserDomainMask,
                                                          YES) objectAtIndex:0];
	GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path);
	[self addSkipBackupAttributeToItemAtPath:demo.path];
	//Some DB Logic would go here
	[demo close];
}

- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
{
    NSURL* URL= [NSURL fileURLWithPath: filePathString];
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    return success;
}

Resources

For more information on getting started with Bolt, check out the following articles:

Comparison with other databases

Postgres, MySQL, & other relational databases

Relational databases structure data into rows and are only accessible through
the use of SQL. This approach provides flexibility in how you store and query
your data but also incurs overhead in parsing and planning SQL statements. Bolt
accesses all data by a byte slice key. This makes Bolt fast to read and write
data by key but provides no built-in support for joining values together.

Most relational databases (with the exception of SQLite) are standalone servers
that run separately from your application. This gives your systems
flexibility to connect multiple application servers to a single database
server but also adds overhead in serializing and transporting data over the
network. Bolt runs as a library included in your application so all data access
has to go through your application's process. This brings data closer to your
application but limits multi-process access to the data.

LevelDB, RocksDB

LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that
they are libraries bundled into the application, however, their underlying
structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes
random writes by using a write ahead log and multi-tiered, sorted files called
SSTables. Bolt uses a B+tree internally and only a single file. Both approaches
have trade-offs.

If you require a high random write throughput (>10,000 w/sec) or you need to use
spinning disks then LevelDB could be a good choice. If your application is
read-heavy or does a lot of range scans then Bolt could be a good choice.

One other important consideration is that LevelDB does not have transactions.
It supports batch writing of key/values pairs and it supports read snapshots
but it will not give you the ability to do a compare-and-swap operation safely.
Bolt supports fully serializable ACID transactions.

LMDB

Bolt was originally a port of LMDB so it is architecturally similar. Both use
a B+tree, have ACID semantics with fully serializable transactions, and support
lock-free MVCC using a single writer and multiple readers.

The two projects have somewhat diverged. LMDB heavily focuses on raw performance
while Bolt has focused on simplicity and ease of use. For example, LMDB allows
several unsafe actions such as direct writes for the sake of performance. Bolt
opts to disallow actions which can leave the database in a corrupted state. The
only exception to this in Bolt is DB.NoSync.

There are also a few differences in API. LMDB requires a maximum mmap size when
opening an mdb_env whereas Bolt will handle incremental mmap resizing
automatically. LMDB overloads the getter and setter functions with multiple
flags whereas Bolt splits these specialized cases into their own functions.

Caveats & Limitations

It's important to pick the right tool for the job and Bolt is no exception.
Here are a few things to note when evaluating and using Bolt:

  • Bolt is good for read intensive workloads. Sequential write performance is
    also fast but random writes can be slow. You can use DB.Batch() or add a
    write-ahead log to help mitigate this issue.

  • Bolt uses a B+tree internally so there can be a lot of random page access.
    SSDs provide a significant performance boost over spinning disks.

  • Try to avoid long running read transactions. Bolt uses copy-on-write so
    old pages cannot be reclaimed while an old transaction is using them.

  • Byte slices returned from Bolt are only valid during a transaction. Once the
    transaction has been committed or rolled back then the memory they point to
    can be reused by a new page or can be unmapped from virtual memory and you'll
    see an unexpected fault address panic when accessing it.

  • Bolt uses an exclusive write lock on the database file so it cannot be
    shared by multiple processes.

  • Be careful when using Bucket.FillPercent. Setting a high fill percent for
    buckets that have random inserts will cause your database to have very poor
    page utilization.

  • Use larger buckets in general. Smaller buckets causes poor page utilization
    once they become larger than the page size (typically 4KB).

  • Bulk loading a lot of random writes into a new bucket can be slow as the
    page will not split until the transaction is committed. Randomly inserting
    more than 100,000 key/value pairs into a single new bucket in a single
    transaction is not advised.

  • Bolt uses a memory-mapped file so the underlying operating system handles the
    caching of the data. Typically, the OS will cache as much of the file as it
    can in memory and will release memory as needed to other processes. This means
    that Bolt can show very high memory usage when working with large databases.
    However, this is expected and the OS will release memory as needed. Bolt can
    handle databases much larger than the available physical RAM, provided its
    memory-map fits in the process virtual address space. It may be problematic
    on 32-bits systems.

  • The data structures in the Bolt database are memory mapped so the data file
    will be endian specific. This means that you cannot copy a Bolt file from a
    little endian machine to a big endian machine and have it work. For most
    users this is not a concern since most modern CPUs are little endian.

  • Because of the way pages are laid out on disk, Bolt cannot truncate data files
    and return free pages back to the disk. Instead, Bolt maintains a free list
    of unused pages within its data file. These free pages can be reused by later
    transactions. This works well for many use cases as databases generally tend
    to grow. However, it's important to note that deleting large chunks of data
    will not allow you to reclaim that space on disk.

    For more information on page allocation, see this comment.

Reading the Source

Bolt is a relatively small code base (<3KLOC) for an embedded, serializable,
transactional key/value database so it can be a good starting point for people
interested in how databases work.

The best places to start are the main entry points into Bolt:

  • Open() - Initializes the reference to the database. It's responsible for
    creating the database if it doesn't exist, obtaining an exclusive lock on the
    file, reading the meta pages, & memory-mapping the file.

  • DB.Begin() - Starts a read-only or read-write transaction depending on the
    value of the writable argument. This requires briefly obtaining the "meta"
    lock to keep track of open transactions. Only one read-write transaction can
    exist at a time so the "rwlock" is acquired during the life of a read-write
    transaction.

  • Bucket.Put() - Writes a key/value pair into a bucket. After validating the
    arguments, a cursor is used to traverse the B+tree to the page and position
    where they key & value will be written. Once the position is found, the bucket
    materializes the underlying page and the page's parent pages into memory as
    "nodes". These nodes are where mutations occur during read-write transactions.
    These changes get flushed to disk during commit.

  • Bucket.Get() - Retrieves a key/value pair from a bucket. This uses a cursor
    to move to the page & position of a key/value pair. During a read-only
    transaction, the key and value data is returned as a direct reference to the
    underlying mmap file so there's no allocation overhead. For read-write
    transactions, this data may reference the mmap file or one of the in-memory
    node values.

  • Cursor - This object is simply for traversing the B+tree of on-disk pages
    or in-memory nodes. It can seek to a specific key, move to the first or last
    value, or it can move forward or backward. The cursor handles the movement up
    and down the B+tree transparently to the end user.

  • Tx.Commit() - Converts the in-memory dirty nodes and the list of free pages
    into pages to be written to disk. Writing to disk then occurs in two phases.
    First, the dirty pages are written to disk and an fsync() occurs. Second, a
    new meta page with an incremented transaction ID is written and another
    fsync() occurs. This two phase write ensures that partially written data
    pages are ignored in the event of a crash since the meta page pointing to them
    is never written. Partially written meta pages are invalidated because they
    are written with a checksum.

If you have additional notes that could be helpful for others, please submit
them via pull request.

Other Projects Using Bolt

Below is a list of public, open source projects that use Bolt:

  • BoltDbWeb - A web based GUI for BoltDB files.
  • Operation Go: A Routine Mission - An online programming game for Golang using Bolt for user accounts and a leaderboard.
  • Bazil - A file system that lets your data reside where it is most convenient for it to reside.
  • DVID - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb.
  • Skybox Analytics - A standalone funnel analysis tool for web analytics.
  • Scuttlebutt - Uses Bolt to store and process all Twitter mentions of GitHub projects.
  • Wiki - A tiny wiki using Goji, BoltDB and Blackfriday.
  • ChainStore - Simple key-value interface to a variety of storage engines organized as a chain of operations.
  • MetricBase - Single-binary version of Graphite.
  • Gitchain - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin".
  • event-shuttle - A Unix system service to collect and reliably deliver messages to Kafka.
  • ipxed - Web interface and api for ipxed.
  • BoltStore - Session store using Bolt.
  • photosite/session - Sessions for a photo viewing site.
  • LedisDB - A high performance NoSQL, using Bolt as optional storage.
  • ipLocator - A fast ip-geo-location-server using bolt with bloom filters.
  • cayley - Cayley is an open-source graph database using Bolt as optional backend.
  • bleve - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend.
  • tentacool - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server.
  • Seaweed File System - Highly scalable distributed key~file system with O(1) disk read.
  • InfluxDB - Scalable datastore for metrics, events, and real-time analytics.
  • Freehold - An open, secure, and lightweight platform for your files and data.
  • Prometheus Annotation Server - Annotation server for PromDash & Prometheus service monitoring system.
  • Consul - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware.
  • Kala - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs.
  • drive - drive is an unofficial Google Drive command line client for *NIX operating systems.
  • stow - a persistence manager for objects
    backed by boltdb.
  • buckets - a bolt wrapper streamlining
    simple tx and key scans.
  • mbuckets - A Bolt wrapper that allows easy operations on multi level (nested) buckets.
  • Request Baskets - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to RequestBin service
  • Go Report Card - Go code quality report cards as a (free and open source) service.
  • Boltdb Boilerplate - Boilerplate wrapper around bolt aiming to make simple calls one-liners.
  • lru - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores.
  • Storm - Simple and powerful ORM for BoltDB.
  • GoWebApp - A basic MVC web application in Go using BoltDB.
  • SimpleBolt - A simple way to use BoltDB. Deals mainly with strings.
  • Algernon - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend.
  • MuLiFS - Music Library Filesystem creates a filesystem to organise your music files.
  • GoShort - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter.
  • torrent - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development.
  • gopherpit - A web service to manage Go remote import paths with custom domains
  • bolter - Command-line app for viewing BoltDB file in your terminal.
  • btcwallet - A bitcoin wallet.
  • dcrwallet - A wallet for the Decred cryptocurrency.
  • Ironsmith - A simple, script-driven continuous integration (build - > test -> release) tool, with no external dependencies
  • BoltHold - An embeddable NoSQL store for Go types built on BoltDB

If you are using Bolt in a project please send a pull request to add it to the list.


Overview (`vendor/github.com/containerd/btrfs/README.md`)

go-btrfs

Native Go bindings for btrfs.

Status

These are in the early stages. We will try to maintain stability, but please
vendor if you are relying on these directly.

Contribute

This package may not cover all the use cases for btrfs. If something you need
is missing, please don't hesitate to submit a PR.

Note that due to struct alignment issues, this isn't yet fully native.
Preferrably, this could be resolved, so contributions in this direction are
greatly appreciated.


Overview (`vendor/github.com/containerd/cgroups/README.md`)

cgroups

Go package for creating, managing, inspecting, and destroying cgroups.
The resources format for settings on the cgroup uses the OCI runtime-spec found
here.

Examples

Create a new cgroup

This creates a new cgroup using a static path for all subsystems under /test.

  • /sys/fs/cgroup/cpu/test
  • /sys/fs/cgroup/memory/test
  • etc....

It uses a single hierarchy and specifies cpu shares as a resource constraint and
uses the v1 implementation of cgroups.

go
shares := uint64(100)
control, err := cgroups.New(cgroups.V1, cgroups.StaticPath("/test"), &specs.LinuxResources{
    CPU: &specs.CPU{
        Shares: &shares,
    },
})
defer control.Delete()

Create with systemd slice support

go
control, err := cgroups.New(cgroups.Systemd, cgroups.Slice("system.slice", "runc-test"), &specs.LinuxResources{
    CPU: &specs.CPU{
        Shares: &shares,
    },
})

Load an existing cgroup

go
control, err = cgroups.Load(cgroups.V1, cgroups.StaticPath("/test"))

Add a process to the cgroup

go
if err := control.Add(cgroups.Process{Pid:1234}); err != nil {
}

Update the cgroup

To update the resources applied in the cgroup

go
shares = uint64(200)
if err := control.Update(&specs.LinuxResources{
    CPU: &specs.CPU{
        Shares: &shares,
    },
}); err != nil {
}

Freeze and Thaw the cgroup

go
if err := control.Freeze(); err != nil {
}
if err := control.Thaw(); err != nil {
}

List all processes in the cgroup or recursively

go
processes, err := control.Processes(cgroups.Devices, recursive)

Get Stats on the cgroup

go
stats, err := control.Stat()

Move process across cgroups

This allows you to take processes from one cgroup and move them to another.

go
err := control.MoveTo(destination)

Create subcgroup

go
subCgroup, err := control.New("child", resources)

LICENSE

Copyright (c) 2016-2017 Michael Crosby. [email protected]

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Overview (`vendor/github.com/containerd/console/README.md`)

console

Golang package for dealing with consoles. Light on deps and a simple API.

Modifying the current process

go
current := console.Current()
defer current.Reset()

if err := current.SetRaw(); err != nil {
}
ws, err := current.Size()
current.Resize(ws)

Overview (`vendor/github.com/containerd/continuity/README.md`)

continuity


A transport-agnostic, filesystem metadata manifest system

This project is a staging area for experiments in providing transport agnostic
metadata storage.

Please see https://github.com/opencontainers/specs/issues/11 for more details.

Building Proto Package

If you change the proto file you will need to rebuild the generated Go with go generate.

text
go generate ./proto

Overview (`vendor/github.com/containerd/fifo/readme.md`)

fifo

Go package for handling fifos in a sane way.

text
// OpenFifo opens a fifo. Returns io.ReadWriteCloser.
// Context can be used to cancel this function until open(2) has not returned.
// Accepted flags:
// - syscall.O_CREAT - create new fifo if one doesn't exist
// - syscall.O_RDONLY - open fifo only from reader side
// - syscall.O_WRONLY - open fifo only from writer side
// - syscall.O_RDWR - open fifo from both sides, never block on syscall level
// - syscall.O_NONBLOCK - return io.ReadWriteCloser even if other side of the
//     fifo isn't open. read/write will be connected after the actual fifo is
//     open or after fifo is closed.
func OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)


// Read from a fifo to a byte array.
func (f *fifo) Read(b []byte) (int, error)


// Write from byte array to a fifo.
func (f *fifo) Write(b []byte) (int, error)


// Close the fifo. Next reads/writes will error. This method can also be used
// before open(2) has returned and fifo was never opened.
func (f *fifo) Close() error

Overview (`vendor/github.com/containerd/go-runc/README.md`)

go-runc

This is a package for consuming the runc binary in your Go applications.
It tries to expose all the settings and features of the runc CLI. If there is something missing then add it, its opensource!

This needs runc @ a9610f2c0
or greater.

Docs

Docs can be found at godoc.org.


Overview (`vendor/github.com/coreos/go-systemd/README.md`)

go-systemd


Go bindings to systemd. The project has several packages:

  • activation - for writing and using socket activation from Go
  • dbus - for starting/stopping/inspecting running services and units
  • journal - for writing to systemd's logging service, journald
  • sdjournal - for reading from journald by wrapping its C API
  • machine1 - for registering machines/containers with systemd
  • unit - for (de)serialization and comparison of unit files

Socket Activation

An example HTTP server using socket activation can be quickly set up by following this README on a Linux machine running systemd:

https://github.com/coreos/go-systemd/tree/master/examples/activation/httpserver

Journal

Using the pure-Go journal package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry.
The sdjournal package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available.

D-Bus

The dbus package connects to the systemd D-Bus API and lets you start, stop and introspect systemd units. The API docs are here:

http://godoc.org/github.com/coreos/go-systemd/dbus

Debugging

Create /etc/dbus-1/system-local.conf that looks like this:

text
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
    <policy user="root">
        <allow eavesdrop="true"/>
        <allow eavesdrop="true" send_destination="*"/>
    </policy>
</busconfig>

machined

The machine1 package allows interaction with the systemd machined D-Bus API.

Units

The unit package provides various functions for working with systemd unit files.


Overview (`vendor/github.com/davecgh/go-spew/README.md`)

go-spew

[]
(https://travis-ci.org/davecgh/go-spew) ![ISC License]
(http://img.shields.io/badge/license-ISC-blue.svg)
[![Coverage Status]
(https://img.shields.io/coveralls/davecgh/go-spew.svg)]
(https://coveralls.io/r/davecgh/go-spew?branch=master)

Go-spew implements a deep pretty printer for Go data structures to aid in
debugging. A comprehensive suite of tests with 100% test coverage is provided
to ensure proper functionality. See test_coverage.txt for the gocov coverage
report. Go-spew is licensed under the liberal ISC license, so it may be used in
open source or commercial projects.

If you're interested in reading about how this package came to life and some
of the challenges involved in providing a deep pretty printer, there is a blog
post about it
here.

Documentation

[]
(http://godoc.org/github.com/davecgh/go-spew/spew)

Full go doc style documentation for the project can be viewed online without
installing this package by using the excellent GoDoc site here:
http://godoc.org/github.com/davecgh/go-spew/spew

You can also view the documentation locally once the package is installed with
the godoc tool by running godoc -http=":6060" and pointing your browser to
http://localhost:6060/pkg/github.com/davecgh/go-spew/spew

Installation

bash
$ go get -u github.com/davecgh/go-spew/spew

Quick Start

Add this import line to the file you're working in:

go
import "github.com/davecgh/go-spew/spew"

To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:

go
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)

Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most
compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types
and pointer addresses):

go
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)

Debugging a Web Application Example

Here is an example of how you can use spew.Sdump() to help debug a web application. Please be sure to wrap your output using the html.EscapeString() function for safety reasons. You should also only use this debugging technique in a development environment, never in production.

go
package main

import (
    "fmt"
    "html"
    "net/http"

    "github.com/davecgh/go-spew/spew"
)

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html")
    fmt.Fprintf(w, "Hi there, %s!", r.URL.Path[1:])
    fmt.Fprintf(w, "")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Sample Dump Output

text
(main.Foo) {
 unexportedField: (*main.Bar)(0xf84002e210)({
  flag: (main.Flag) flagTwo,
  data: (uintptr) <nil>
 }),
 ExportedField: (map[interface {}]interface {}) {
  (string) "one": (bool) true
 }
}
([]uint8) {
 00000000  11 12 13 14 15 16 17 18  19 1a 1b 1c 1d 1e 1f 20  |............... |
 00000010  21 22 23 24 25 26 27 28  29 2a 2b 2c 2d 2e 2f 30  |!"#$%&'()*+,-./0|
 00000020  31 32                                             |12|
}

Sample Formatter Output

Double pointer to a uint8:

text
%v: <**>5
	 %+v: <**>(0xf8400420d0->0xf8400420c8)5
	 %#v: (**uint8)5
	%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5

Pointer to circular struct with a uint8 field and a pointer to itself:

text
%v: <*>{1 <*><shown>}
	 %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
	 %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
	%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}

Configuration Options

Configuration of spew is handled by fields in the ConfigState type. For
convenience, all of the top-level functions use a global state available via the
spew.Config global.

It is also possible to create a ConfigState instance that provides methods
equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.

text
/* Detailed source-code truncated for AI context efficiency. */

Unsafe Package Dependency

This package relies on the unsafe package to perform some of the more advanced
features, however it also supports a "limited" mode which allows it to work in
environments where the unsafe package is not available. By default, it will
operate in this mode on Google App Engine and when compiled with GopherJS. The
"safe" build tag may also be specified to force the package to build without
using the unsafe package.

License

Go-spew is licensed under the copyfree ISC License.


Overview (`vendor/github.com/docker/go-metrics/README.md`)

go-metrics [](https://godoc.org/github.com/docker/go-metrics)

This package is small wrapper around the prometheus go client to help enforce convention and best practices for metrics collection in Docker projects.

Best Practices

This packages is meant to be used for collecting metrics in Docker projects.
It is not meant to be used as a replacement for the prometheus client but to help enforce consistent naming across metrics collected.
If you have not already read the prometheus best practices around naming and labels you can read the page here.

The following are a few Docker specific rules that will help you name and work with metrics in your project.

  1. Namespace and Subsystem

This package provides you with a namespace type that allows you to specify the same namespace and subsystem for your metrics.

go
ns := metrics.NewNamespace("engine", "daemon", metrics.Labels{
        "version": dockerversion.Version,
        "commit":  dockerversion.GitCommit,
})

In the example above we are creating metrics for the Docker engine's daemon package.
engine would be the namespace in this example where daemon is the subsystem or package where we are collecting the metrics.

A namespace also allows you to attach constant labels to the metrics such as the git commit and version that it is collecting.

  1. Declaring your Metrics

Try to keep all your metric declarations in one file.
This makes it easy for others to see what constant labels are defined on the namespace and what labels are defined on the metrics when they are created.

  1. Use labels instead of multiple metrics

Labels allow you to define one metric such as the time it takes to perform a certain action on an object.
If we wanted to collect timings on various container actions such as create, start, and delete then we can define one metric called container_actions and use labels to specify the type of action.

go
containerActions = ns.NewLabeledTimer("container_actions", "The number of milliseconds it takes to process each container action", "action")

The last parameter is the label name or key.
When adding a data point to the metric you will use the WithValues function to specify the action that you are collecting for.

go
containerActions.WithValues("create").UpdateSince(start)
  1. Always use a unit

The metric name should describe what you are measuring but you also need to provide the unit that it is being measured with.
For a timer, the standard unit is seconds and a counter's standard unit is a total.
For gauges you must provide the unit.
This package provides a standard set of units for use within the Docker projects.

go
Nanoseconds Unit = "nanoseconds"
Seconds     Unit = "seconds"
Bytes       Unit = "bytes"
Total       Unit = "total"

If you need to use a unit but it is not defined in the package please open a PR to add it but first try to see if one of the already created units will work for your metric, i.e. seconds or nanoseconds vs adding milliseconds.

Docs

Package documentation can be found here.

Additional Metrics

Additional metrics are also defined here that are not avaliable in the prometheus client.
If you need a custom metrics and it is generic enough to be used by multiple projects, define it here.

Copyright © 2016 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. The README.md file, and files in the "docs" folder are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file "LICENSE.docs". You may obtain a duplicate copy of the same license, titled CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.


Overview (`vendor/github.com/docker/go-units/README.md`)

Introduction

go-units is a library to transform human friendly measurements into machine friendly values.

Usage

See the docs in godoc for examples and documentation.

Copyright © 2015 Docker, Inc.

go-units is licensed under the Apache License, Version 2.0.
See LICENSE for the full text of the license.


Overview (`vendor/github.com/gogo/protobuf/Readme.md`)

Protocol Buffers for Go with Gadgets

gogoprotobuf is a fork of golang/protobuf with extra code generation features.

This code generation is used to achieve:

  • fast marshalling and unmarshalling
  • more canonical Go structures
  • goprotobuf compatibility
  • less typing by optionally generating extra helper code
  • peace of mind by optionally generating test and benchmark code
  • other serialization formats

Keeping track of how up to date gogoprotobuf is relative to golang/protobuf is done in this
issue

Users

These projects use gogoprotobuf:

Please lets us know if you are using gogoprotobuf by posting on our GoogleGroup.

Mentioned

Getting Started

There are several ways to use gogoprotobuf, but for all you need to install go and protoc.
After that you can choose:

  • Speed
  • More Speed and more generated code
  • Most Speed and most customization

Installation

To install it, you must first have Go (at least version 1.3.3) installed (see http://golang.org/doc/install). Go 1.7.1 is continuously tested.

Next, install the standard protocol buffer implementation from https://github.com/google/protobuf.
Most versions from 2.3.1 should not give any problems, but 2.6.1, 3.0.2 and 3.1.0 are continuously tested.

Speed

Install the protoc-gen-gofast binary

text
go get github.com/gogo/protobuf/protoc-gen-gofast

Use it to generate faster marshaling and unmarshaling go code for your protocol buffers.

text
protoc --gofast_out=. myproto.proto

This does not allow you to use any of the other gogoprotobuf extensions.

More Speed and more generated code

Fields without pointers cause less time in the garbage collector.
More code generation results in more convenient methods.

Other binaries are also included:

text
protoc-gen-gogofast (same as gofast, but imports gogoprotobuf)
protoc-gen-gogofaster (same as gogofast, without XXX_unrecognized, less pointer fields)
protoc-gen-gogoslick (same as gogofaster, but with generated string, gostring and equal methods)

Installing any of these binaries is easy. Simply run:

text
go get github.com/gogo/protobuf/proto
go get github.com/gogo/protobuf/{binary}
go get github.com/gogo/protobuf/gogoproto

These binaries allow you to using gogoprotobuf extensions.

Most Speed and most customization

Customizing the fields of the messages to be the fields that you actually want to use removes the need to copy between the structs you use and structs you use to serialize.
gogoprotobuf also offers more serialization formats and generation of tests and even more methods.

Please visit the extensions page for more documentation.

Install protoc-gen-gogo:

text
go get github.com/gogo/protobuf/proto
go get github.com/gogo/protobuf/jsonpb
go get github.com/gogo/protobuf/protoc-gen-gogo
go get github.com/gogo/protobuf/gogoproto

GRPC

It works the same as golang/protobuf, simply specify the plugin.
Here is an example using gofast:

text
protoc --gofast_out=plugins=grpc:. my.proto

Overview (`vendor/github.com/golang/protobuf/README.md`)

Go support for Protocol Buffers

Google's data interchange format.
Copyright 2010 The Go Authors.
https://github.com/golang/protobuf

This package and the code it generates requires at least Go 1.4.

This software implements Go bindings for protocol buffers. For
information about protocol buffers themselves, see
https://developers.google.com/protocol-buffers/

Installation

To use this software, you must:

This software has two parts: a 'protocol compiler plugin' that
generates Go source files that, once compiled, can access and manage
protocol buffers; and a library that implements run-time support for
encoding (marshaling), decoding (unmarshaling), and accessing protocol
buffers.

There is support for gRPC in Go using protocol buffers.
See the note at the bottom of this file for details.

There are no insertion points in the plugin.

Using protocol buffers with Go

Once the software is installed, there are two steps to using it.
First you must compile the protocol buffer definitions and then import
them, with the support library, into your program.

To compile the protocol buffer definition, run protoc with the --go_out
parameter set to the directory you want to output the Go code to.

text
protoc --go_out=. *.proto

The generated files will be suffixed .pb.go. See the Test code below
for an example using such a file.

The package comment for the proto library contains text describing
the interface provided in Go for protocol buffers. Here is an edited
version.

==========

The proto package converts data structures to and from the
wire format of protocol buffers. It works in concert with the
Go source code generated for .proto files by the protocol compiler.

A summary of the properties of the protocol buffer interface
for a protocol buffer variable v:

  • Names are turned from camel_case to CamelCase for export.
  • There are no methods on v to set fields; just treat
    them as structure fields.
  • There are getters that return a field's value if set,
    and return the field's default value if unset.
    The getters work even if the receiver is a nil message.
  • The zero value for a struct is its correct initialization state.
    All desired fields must be set before marshaling.
  • A Reset() method will restore a protobuf struct to its zero state.
  • Non-repeated fields are pointers to the values; nil means unset.
    That is, optional or required field int32 f becomes F *int32.
  • Repeated fields are slices.
  • Helper functions are available to aid the setting of fields.
    Helpers for getting values are superseded by the
    GetFoo methods and their use is deprecated.
    msg.Foo = proto.String("hello") // set field
  • Constants are defined to hold the default values of all fields that
    have them. They have the form Default_StructName_FieldName.
    Because the getter methods handle defaulted values,
    direct use of these constants should be rare.
  • Enums are given type names and maps from names to values.
    Enum values are prefixed with the enum's type name. Enum types have
    a String method, and a Enum method to assist in message construction.
  • Nested groups and enums have type names prefixed with the name of
    the surrounding message type.
  • Extensions are given descriptor names that start with E_,
    followed by an underscore-delimited list of the nested messages
    that contain it (if any) followed by the CamelCased name of the
    extension field itself. HasExtension, ClearExtension, GetExtension
    and SetExtension are functions for manipulating extensions.
  • Oneof field sets are given a single field in their message,
    with distinguished wrapper types for each possible field value.
  • Marshal and Unmarshal are functions to encode and decode the wire format.

When the .proto file specifies syntax="proto3", there are some differences:

  • Non-repeated fields of non-message type are values instead of pointers.
  • Getters are only generated for message and oneof fields.
  • Enum types do not get an Enum method.

Consider file test.proto, containing

proto
package example;
	
	enum FOO { X = 17; };
	
	message Test {
	  required string label = 1;
	  optional int32 type = 2 [default=77];
	  repeated int64 reps = 3;
	  optional group OptionalGroup = 4 {
	    required string RequiredField = 5;
	  }
	}

To create and play with a Test object from the example package,

go
package main

	import (
		"log"

		"github.com/golang/protobuf/proto"
		"path/to/example"
	)

	func main() {
		test := &example.Test {
			Label: proto.String("hello"),
			Type:  proto.Int32(17),
			Reps:  []int64{1, 2, 3},
			Optionalgroup: &example.Test_OptionalGroup {
				RequiredField: proto.String("good bye"),
			},
		}
		data, err := proto.Marshal(test)
		if err != nil {
			log.Fatal("marshaling error: ", err)
		}
		newTest := &example.Test{}
		err = proto.Unmarshal(data, newTest)
		if err != nil {
			log.Fatal("unmarshaling error: ", err)
		}
		// Now test and newTest contain the same data.
		if test.GetLabel() != newTest.GetLabel() {
			log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
		}
		// etc.
	}

Parameters

To pass extra parameters to the plugin, use a comma-separated
parameter list separated from the output directory by a colon:

text
protoc --go_out=plugins=grpc,import_path=mypackage:. *.proto
  • import_prefix=xxx - a prefix that is added onto the beginning of
    all imports. Useful for things like generating protos in a
    subdirectory, or regenerating vendored protobufs in-place.
  • import_path=foo/bar - used as the package if no input files
    declare go_package. If it contains slashes, everything up to the
    rightmost slash is ignored.
  • plugins=plugin1+plugin2 - specifies the list of sub-plugins to
    load. The only plugin in this repo is grpc.
  • Mfoo/bar.proto=quux/shme - declares that foo/bar.proto is
    associated with Go package quux/shme. This is subject to the
    import_prefix parameter.

gRPC Support

If a proto file specifies RPC services, protoc-gen-go can be instructed to
generate code compatible with gRPC (http://www.grpc.io/). To do this, pass
the plugins parameter to protoc-gen-go; the usual way is to insert it into
the --go_out argument to protoc:

text
protoc --go_out=plugins=grpc:. *.proto

Compatibility

The library and the generated code are expected to be stable over time.
However, we reserve the right to make breaking changes without notice for the
following reasons:

  • Security. A security issue in the specification or implementation may come to
    light whose resolution requires breaking compatibility. We reserve the right
    to address such security issues.
  • Unspecified behavior. There are some aspects of the Protocol Buffers
    specification that are undefined. Programs that depend on such unspecified
    behavior may break in future releases.
  • Specification errors or changes. If it becomes necessary to address an
    inconsistency, incompleteness, or change in the Protocol Buffers
    specification, resolving the issue could affect the meaning or legality of
    existing programs. We reserve the right to address such issues, including
    updating the implementations.
  • Bugs. If the library has a bug that violates the specification, a program
    that depends on the buggy behavior may break if the bug is fixed. We reserve
    the right to fix such bugs.
  • Adding methods or fields to generated structs. These may conflict with field
    names that already exist in a schema, causing applications to break. When the
    code generator encounters a field in the schema that would collide with a
    generated field or method name, the code generator will append an underscore
    to the generated field or method name.
  • Adding, removing, or changing methods or fields in generated structs that
    start with XXX. These parts of the generated code are exported out of
    necessity, but should not be considered part of the public API.
  • Adding, removing, or changing unexported symbols in generated code.

Any breaking changes outside of these will be announced 6 months in advance to
[email protected].

You should, whenever possible, use generated code created by the protoc-gen-go
tool built at the same commit as the proto package. The proto package
declares package-level constants in the form ProtoPackageIsVersionX.
Application code and generated code may depend on one of these constants to
ensure that compilation will fail if the available version of the proto library
is too old. Whenever we make a change to the generated code that requires newer
library support, in the same commit we will increment the version number of the
generated code and declare a new package-level constant whose name incorporates
the latest version number. Removing a compatibility constant is considered a
breaking change and would be subject to the announcement policy stated above.

The protoc-gen-go/generator package exposes a plugin interface,
which is used by the gRPC code generation. This interface is not
supported and is subject to incompatible changes without notice.


Overview (`vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md`)

Go gRPC Interceptors for Prometheus monitoring




Prometheus monitoring for your gRPC Go servers and clients.

A sister implementation for gRPC Java (same metrics, same semantics) is in grpc-ecosystem/java-grpc-prometheus.

Interceptors

gRPC Go recently acquired support for Interceptors, i.e. middleware that is executed
by a gRPC Server before the request is passed onto the user's application logic. It is a perfect way to implement
common patterns: auth, logging and... monitoring.

To use Interceptors in chains, please see go-grpc-middleware.

Usage

There are two types of interceptors: client-side and server-side. This package provides monitoring Interceptors for both.

Server-side

go
import "github.com/grpc-ecosystem/go-grpc-prometheus"
...
    // Initialize your gRPC server's interceptor.
    myServer := grpc.NewServer(
        grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
        grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
    )
    // Register your gRPC service implementations.
    myservice.RegisterMyServiceServer(s.server, &myServiceImpl{})
    // After all your registrations, make sure all of the Prometheus metrics are initialized.
    grpc_prometheus.Register(myServer)
    // Register Prometheus metrics handler.    
    http.Handle("/metrics", prometheus.Handler())
...

Client-side

go
import "github.com/grpc-ecosystem/go-grpc-prometheus"
...
   clientConn, err = grpc.Dial(
       address,
		   grpc.WithUnaryInterceptor(UnaryClientInterceptor),
		   grpc.WithStreamInterceptor(StreamClientInterceptor)
   )
   client = pb_testproto.NewTestServiceClient(clientConn)
   resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
...

Metrics

Labels

All server-side metrics start with grpc_server as Prometheus subsystem name. All client-side metrics start with grpc_client. Both of them have mirror-concepts. Similarly all methods
contain the same rich labels:

  • grpc_service - the gRPC service name, which is the combination of protobuf package and
    the grpc_service section name. E.g. for package = mwitkow.testproto and
    service TestService the label will be grpc_service="mwitkow.testproto.TestService"

  • grpc_method - the name of the method called on the gRPC service. E.g.
    grpc_method="Ping"

  • grpc_type - the gRPC type of request.
    Differentiating between the two is important especially for latency measurements.

    • unary is single request, single response RPC
    • client_stream is a multi-request, single response RPC
    • server_stream is a single request, multi-response RPC
    • bidi_stream is a multi-request, multi-response RPC

Additionally for completed RPCs, the following labels are used:

  • grpc_code - the human-readable gRPC status code.
    The list of all statuses is to long, but here are some common ones:

    • OK - means the RPC was successful
    • IllegalArgument - RPC contained bad values
    • Internal - server-side error not disclosed to the clients

Counters

The counters and their up to date documentation is in server_reporter.go and client_reporter.go
the respective Prometheus handler (usually /metrics).

For the purpose of this documentation we will only discuss grpc_server metrics. The grpc_client ones contain mirror concepts.

For simplicity, let's assume we're tracking a single server-side RPC call of mwitkow.testproto.TestService,
calling the method PingList. The call succeeds and returns 20 messages in the stream.

First, immediately after the server receives the call it will increment the
grpc_server_started_total and start the handling time clock (if histograms are enabled).

jsoniq
grpc_server_started_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1

Then the user logic gets invoked. It receives one message from the client containing the request
(it's a server_stream):

jsoniq
grpc_server_msg_received_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1

The user logic may return an error, or send multiple messages back to the client. In this case, on
each of the 20 messages sent back, a counter will be incremented:

jsoniq
grpc_server_msg_sent_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 20

After the call completes, it's status (OK or other gRPC status code)
and the relevant call labels increment the grpc_server_handled_total counter.

jsoniq
grpc_server_handled_total{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1

Histograms

Prometheus histograms are a great way
to measure latency distributions of your RPCs. However since it is bad practice to have metrics
of high cardinality)
the latency monitoring metrics are disabled by default. To enable them please call the following
in your server initialization code:

jsoniq
grpc_prometheus.EnableHandlingTimeHistogram()

After the call completes, it's handling time will be recorded in a Prometheus histogram
variable grpc_server_handling_seconds. It contains three sub-metrics:

  • grpc_server_handling_seconds_count - the count of all completed RPCs by status and method
  • grpc_server_handling_seconds_sum - cumulative time of RPCs by status and method, useful for
    calculating average handling times
  • grpc_server_handling_seconds_bucket - contains the counts of RPCs by status and method in respective
    handling-time buckets. These buckets can be used by Prometheus to estimate SLAs (see here)

The counter values will look as follows:

text
/* Detailed source-code truncated for AI context efficiency. */

Useful query examples

Prometheus philosophy is to provide the most detailed metrics possible to the monitoring system, and
let the aggregations be handled there. The verbosity of above metrics make it possible to have that
flexibility. Here's a couple of useful monitoring queries:

request inbound rate

jsoniq
sum(rate(grpc_server_started_total{job="foo"}[1m])) by (grpc_service)

For job="foo" (common label to differentiate between Prometheus monitoring targets), calculate the
rate of requests per second (1 minute window) for each gRPC grpc_service that the job has. Please note
how the grpc_method is being omitted here: all methods of a given gRPC service will be summed together.

unary request error rate

jsoniq
sum(rate(grpc_server_handled_total{job="foo",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service)

For job="foo", calculate the per-grpc_service rate of unary (1:1) RPCs that failed, i.e. the
ones that didn't finish with OK code.

unary request error percentage

jsoniq
sum(rate(grpc_server_handled_total{job="foo",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service)
 / 
sum(rate(grpc_server_started_total{job="foo",grpc_type="unary"}[1m])) by (grpc_service)
 * 100.0

For job="foo", calculate the percentage of failed requests by service. It's easy to notice that
this is a combination of the two above examples. This is an example of a query you would like to
alert on in your system for SLA violations, e.g.
"no more than 1% requests should fail".

average response stream size

jsoniq
sum(rate(grpc_server_msg_sent_total{job="foo",grpc_type="server_stream"}[10m])) by (grpc_service)
 /
sum(rate(grpc_server_started_total{job="foo",grpc_type="server_stream"}[10m])) by (grpc_service)

For job="foo" what is the grpc_service-wide 10m average of messages returned for all server_stream RPCs. This allows you to track the stream sizes returned by your system, e.g. allows
you to track when clients started to send "wide" queries that ret
Note the divisor is the number of started RPCs, in order to account for in-flight requests.

99%-tile latency of unary requests

jsoniq
histogram_quantile(0.99, 
  sum(rate(grpc_server_handling_seconds_bucket{job="foo",grpc_type="unary"}[5m])) by (grpc_service,le)
)

For job="foo", returns an 99%-tile quantile estimation
of the handling time of RPCs per service. Please note the 5m rate, this means that the quantile
estimation will take samples in a rolling 5m window. When combined with other quantiles
(e.g. 50%, 90%), this query gives you tremendous insight into the responsiveness of your system
(e.g. impact of caching).

percentage of slow unary queries (>250ms)

jsoniq
100.0 - (
sum(rate(grpc_server_handling_seconds_bucket{job="foo",grpc_type="unary",le="0.25"}[5m])) by (grpc_service)
 / 
sum(rate(grpc_server_handling_seconds_count{job="foo",grpc_type="unary"}[5m])) by (grpc_service)
) * 100.0

For job="foo" calculate the by-grpc_service fraction of slow requests that took longer than 0.25
seconds. This query is relatively complex, since the Prometheus aggregations use le (less or equal)
buckets, meaning that counting "fast" requests fractions is easier. However, simple maths helps.
This is an example of a query you would like to alert on in your system for SLA violations,
e.g. "less than 1% of requests are slower than 250ms".

Status

This code has been used since August 2015 as the basis for monitoring of production gRPC micro services at Improbable.

License

go-grpc-prometheus is released under the Apache 2.0 license. See the LICENSE file for details.


Overview (`vendor/github.com/matttproud/golang_protobuf_extensions/README.md`)

Overview

This repository provides various Protocol Buffer extensions for the Go
language (golang), namely support for record length-delimited message
streaming.

Java Go
MessageLite#parseDelimitedFrom pbutil.ReadDelimited
MessageLite#writeDelimitedTo pbutil.WriteDelimited

Because Code Review 9102043 is
destined to never be merged into mainline (i.e., never be promoted to formal
goprotobuf features), this repository
will live here in the wild.

Documentation

We have generated Go Doc documentation here.

Testing


Overview (`vendor/github.com/nightlyone/lockfile/README.md`)

lockfile

Handle locking via pid files.

Build Status Unix
Build status Windows

install

Install Go 1, either from source or with a prepackaged binary.
For Windows suport, Go 1.4 or newer is required.

Then run

text
go get github.com/nightlyone/lockfile

LICENSE

BSD

documentation

package documentation at godoc.org

install

text
go get github.com/nightlyone/lockfile

contributing

Contributions are welcome. Please open an issue or send me a pull request for a dedicated branch.
Make sure the git commit hooks show it works.

git commit hooks

enable commit hooks via

text
cd .git ; rm -rf hooks; ln -s ../git-hooks hooks ; cd ..

Overview (`vendor/github.com/opencontainers/go-digest/README.md`)

go-digest

Common digest package used across the container ecosystem.

Please see the godoc for more information.

What is a digest?

A digest is just a hash.

The most common use case for a digest is to create a content
identifier for use in Content Addressable Storage
systems:

go
id := digest.FromBytes([]byte("my content"))

In the example above, the id can be used to uniquely identify
the byte slice "my content". This allows two disparate applications
to agree on a verifiable identifier without having to trust one
another.

An identifying digest can be verified, as follows:

go
if id != digest.FromBytes([]byte("my content")) {
  return errors.New("the content has changed!")
}

A Verifier type can be used to handle cases where an io.Reader
makes more sense:

go
rd := getContent()
verifier := id.Verifier()
io.Copy(verifier, rd)

if !verifier.Verified() {
  return errors.New("the content has changed!")
}

Using Merkle DAGs, this
can power a rich, safe, content distribution system.

Usage

While the godoc is
considered the best resource, a few important items need to be called
out when using this package.

  1. Make sure to import the hash implementations into your application
    or the package will panic. You should have something like the
    following in the main (or other entrypoint) of your application:

    go
    import (
        _ "crypto/sha256"
           _ "crypto/sha512"
    )

    This may seem inconvenient but it allows you replace the hash
    implementations with others, such as https://github.com/stevvooe/resumable.

  2. Even though digest.Digest may be assemable as a string, always
    verify your input with digest.Parse or use Digest.Validate
    when accepting untrusted input. While there are measures to
    avoid common problems, this will ensure you have valid digests
    in the rest of your application.

Stability

The Go API, at this stage, is considered stable, unless otherwise noted.

As always, before using a package export, read the godoc.

Contributing

This package is considered fairly complete. It has been in production
in thousands (millions?) of deployments and is fairly battle-hardened.
New additions will be met with skepticism. If you think there is a
missing feature, please file a bug clearly describing the problem and
the alternatives you tried before submitting a PR.

Reporting security issues

The maintainers take security seriously. If you discover a security
issue, please bring it to their attention right away!

Please DO NOT file a public issue, instead send your report privately
to [email protected].

Security reports are greatly appreciated and we will publicly thank you
for it. We also like to send gifts—if you're into Docker schwag, make
sure to let us know. We currently do not offer a paid security bounty
program, but are not ruling it out in the future.

Copyright © 2016 Docker, Inc. All rights reserved, except as follows. Code is released under the Apache 2.0 license. This README.md file and the CONTRIBUTING.md file are licensed under the Creative Commons Attribution 4.0 International License under the terms and conditions set forth in the file LICENSE.docs. You may obtain a duplicate copy of the same license, titled CC BY-SA 4.0, at http://creativecommons.org/licenses/by-sa/4.0/.


Overview (`vendor/github.com/opencontainers/image-spec/README.md`)

OCI Image Format Specification

The OCI Image Format project creates and maintains the software shipping container image format spec (OCI Image Format).

The specification can be found here.

This repository also provides Go types, intra-blob validation tooling, and JSON Schema.
The Go types and validation should be compatible with the current Go release; earlier Go releases are not supported.

Additional documentation about how this group operates:

The optional and base layers of all OCI projects are tracked in the OCI Scope Table.

Running an OCI Image

The OCI Image Format partner project is the OCI Runtime Spec project.
The Runtime Specification outlines how to run a "filesystem bundle" that is unpacked on disk.
At a high-level an OCI implementation would download an OCI Image then unpack that image into an OCI Runtime filesystem bundle.
At this point the OCI Runtime Bundle would be run by an OCI Runtime.

This entire workflow supports the UX that users have come to expect from container engines like Docker and rkt: primarily, the ability to run an image with no additional arguments:

  • docker run example.com/org/app:v1.0.0
  • rkt run example.com/org/app,version=v1.0.0

To support this UX the OCI Image Format contains sufficient information to launch the application on the target platform (e.g. command, arguments, environment variables, etc).

FAQ

Q: Why doesn't this project mention distribution?

A: Distribution, for example using HTTP as both Docker v2.2 and AppC do today, is currently out of scope on the OCI Scope Table.
There has been some discussion on the TOB mailing list to make distribution an optional layer, but this topic is a work in progress.

Q: Why a new project?

A: The first OCI spec centered around defining the run side of a container.
This is generally seen to be an orthogonal concern to the shipping container component.
As practical examples of this separation you see many organizations separating these concerns into different teams and organizations: the Docker Distribution project and the Docker containerd project; Amazon ECS and Amazon EC2 Container Registry, etc.

Q: Why work on this?

A: We are seeing many independent implementations of container image handling including build systems, registries, and image analysis tools.
As an organization we would like to encourage this growth and bring people together to ensure a technically correct and open specification continues to evolve reflecting the OCI values.

Q: What happens to AppC or Docker Image Formats?

A: Existing formats can continue to be a proving ground for technologies, as needed.
The OCI Image Format project strives to provide a dependable open specification that can be shared between different tools and be evolved for years or decades of compatibility; as the deb and rpm format have.

Roadmap

The GitHub milestones lay out the path to the OCI v1.0.0 release in late 2016.

Contributing

Development happens on GitHub for the spec.
Issues are used for bugs and actionable items and longer discussions can happen on the mailing list.

The specification and code is licensed under the Apache 2.0 license found in the LICENSE file of this repository.

Discuss your design

The project welcomes submissions, but please let everyone know what you are working on.

Before undertaking a nontrivial change to this specification, send mail to the mailing list to discuss what you plan to do.
This gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits.
It also guarantees that the design is sound before code is written; a GitHub pull-request is not the place for high-level discussions.

Typos and grammatical errors can go straight to a pull-request.
When in doubt, start on the mailing-list.

Weekly Call

The contributors and maintainers of all OCI projects have a weekly meeting Wednesdays at 2:00 PM (USA Pacific).
Everyone is welcome to participate via UberConference web or audio-only: +1-415-968-0849 (no PIN needed).
An initial agenda will be posted to the mailing list earlier in the week, and everyone is welcome to propose additional topics or suggest other agenda alterations there.
Minutes are posted to the mailing list and minutes from past calls are archived to the wiki for those who are unable to join the call.

Mailing List

You can subscribe and join the mailing list on Google Groups.

IRC

OCI discussion happens on #opencontainers on Freenode (logs).

Markdown style

To keep consistency throughout the Markdown files in the Open Container spec all files should be formatted one sentence per line.
This fixes two things: it makes diffing easier with git and it resolves fights about line wrapping length.
For example, this paragraph will span three lines in the Markdown source.

Git commit

Sign your work

The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch.
The rules are pretty simple: if you can certify the below (from developercertificate.org):

text
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

then you just add a line to every git commit message:

text
Signed-off-by: Joe Smith <[email protected]>

using your real name (sorry, no pseudonyms or anonymous contributions.)

You can add the sign off when creating the git commit via git commit -s.

Commit Style

Simple house-keeping for clean git history.
Read more on How to Write a Git Commit Message or the Discussion section of git-commit(1).

  1. Separate the subject from body with a blank line
  2. Limit the subject line to 50 characters
  3. Capitalize the subject line
  4. Do not end the subject line with a period
  5. Use the imperative mood in the subject line
  6. Wrap the body at 72 characters
  7. Use the body to explain what and why vs. how
  • If there was important/useful/essential conversation or information, copy or include a reference
  1. When possible, one keyword to scope the change in the subject (i.e. "README: ...", "runtime: ...")

Overview (`vendor/github.com/opencontainers/runc/README.md`)

runc



Introduction

runc is a CLI tool for spawning and running containers according to the OCI specification.

Releases

runc depends on and tracks the runtime-spec repository.
We will try to make sure that runc and the OCI specification major versions stay in lockstep.
This means that runc 1.0.0 should implement the 1.0 version of the specification.

You can find official releases of runc on the release page.

Security

If you wish to report a security issue, please disclose the issue responsibly
to [email protected].

Building

runc currently supports the Linux platform with various architecture support.
It must be built with Go version 1.6 or higher in order for some features to function properly.

In order to enable seccomp support you will need to install libseccomp on your platform.

e.g. libseccomp-devel for CentOS, or libseccomp-dev for Ubuntu

Otherwise, if you do not want to build runc with seccomp support you can add BUILDTAGS="" when running make.

bash
# create a 'github.com/opencontainers' in your GOPATH/src
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc

make
sudo make install

runc will be installed to /usr/local/sbin/runc on your system.

Build Tags

runc supports optional build tags for compiling support of various features.
To add build tags to the make option the BUILDTAGS variable must be set.

bash
make BUILDTAGS='seccomp apparmor'
Build Tag Feature Dependency
seccomp Syscall filtering libseccomp
selinux selinux process and mount labeling
apparmor apparmor profile support libapparmor
ambient ambient capability support kernel 4.3

Running the test suite

runc currently supports running its test suite via Docker.
To run the suite just type make test.

bash
make test

There are additional make targets for running the tests outside of a container but this is not recommended as the tests are written with the expectation that they can write and remove anywhere.

You can run a specific test case by setting the TESTFLAGS variable.

bash
# make test TESTFLAGS="-run=SomeTestFunction"

Dependencies Management

runc uses vndr for dependencies management.
Please refer to vndr for how to add or update
new dependencies.

Using runc

Creating an OCI Bundle

In order to use runc you must have your container in the format of an OCI bundle.
If you have Docker installed you can use its export method to acquire a root filesystem from an existing Docker container.

bash
# create the top most bundle directory
mkdir /mycontainer
cd /mycontainer

# create the rootfs directory
mkdir rootfs

# export busybox via Docker into the rootfs directory
docker export $(docker create busybox) | tar -C rootfs -xvf -

After a root filesystem is populated you just generate a spec in the format of a config.json file inside your bundle.
runc provides a spec command to generate a base template spec that you are then able to edit.
To find features and documentation for fields in the spec please refer to the specs repository.

bash
runc spec

Running Containers

Assuming you have an OCI bundle from the previous step you can execute the container in two different ways.

The first way is to use the convenience command run that will handle creating, starting, and deleting the container after it exits.

bash
# run as root
cd /mycontainer
runc run mycontainerid

If you used the unmodified runc spec template this should give you a sh session inside the container.

The second way to start a container is using the specs lifecycle operations.
This gives you more power over how the container is created and managed while it is running.
This will also launch the container in the background so you will have to edit the config.json to remove the terminal setting for the simple examples here.
Your process field in the config.json should look like this below with "terminal": false and "args": ["sleep", "5"].

json
"process": {
                "terminal": false,
                "user": {
                        "uid": 0,
                        "gid": 0
                },
                "args": [
                        "sleep", "5"
                ],
                "env": [
                        "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                        "TERM=xterm"
                ],
                "cwd": "/",
                "capabilities": [
                        "CAP_AUDIT_WRITE",
                        "CAP_KILL",
                        "CAP_NET_BIND_SERVICE"
                ],
                "rlimits": [
                        {
                                "type": "RLIMIT_NOFILE",
                                "hard": 1024,
                                "soft": 1024
                        }
                ],
                "noNewPrivileges": true
        },

Now we can go though the lifecycle operations in your shell.

bash
# run as root
cd /mycontainer
runc create mycontainerid

# view the container is created and in the "created" state
runc list

# start the process inside the container
runc start mycontainerid

# after 5 seconds view that the container has exited and is now in the stopped state
runc list

# now delete the container
runc delete mycontainerid

This adds more complexity but allows higher level systems to manage runc and provides points in the containers creation to setup various settings after the container has created and/or before it is deleted.
This is commonly used to setup the container's network stack after create but before start where the user's defined process will be running.

Rootless containers

runc has the ability to run containers without root privileges. This is called rootless. You need to pass some parameters to runc in order to run rootless containers. See below and compare with the previous version. Run the following commands as an ordinary user:

bash
# Same as the first example
mkdir ~/mycontainer
cd ~/mycontainer
mkdir rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -

# The --rootless parameter instructs runc spec to generate a configuration for a rootless container, which will allow you to run the container as a non-root user.
runc spec --rootless

# The --root parameter tells runc where to store the container state. It must be writable by the user.
runc --root /tmp/runc run mycontainerid

Supervisors

runc can be used with process supervisors and init systems to ensure that containers are restarted when they exit.
An example systemd unit file looks something like this.

systemd
[Unit]
Description=Start My Container

[Service]
Type=forking
ExecStart=/usr/local/sbin/runc run -d --pid-file /run/mycontainerid.pid mycontainerid
ExecStopPost=/usr/local/sbin/runc delete mycontainerid
WorkingDirectory=/mycontainer
PIDFile=/run/mycontainerid.pid

[Install]
WantedBy=multi-user.target

Overview (`vendor/github.com/opencontainers/runtime-spec/README.md`)

Open Container Initiative Runtime Specification

The Open Container Initiative develops specifications for standards on Operating System process and application containers.

The specification can be found here.

Table of Contents

Additional documentation about how this group operates:

Use Cases

To provide context for users the following section gives example use cases for each part of the spec.

Application Bundle Builders

Application bundle builders can create a bundle directory that includes all of the files required for launching an application as a container.
The bundle contains an OCI configuration file where the builder can specify host-independent details such as which executable to launch and host-specific settings such as mount locations, hook paths, Linux namespaces and cgroups.
Because the configuration includes host-specific settings, application bundle directories copied between two hosts may require configuration adjustments.

Hook Developers

Hook developers can extend the functionality of an OCI-compliant runtime by hooking into a container's lifecycle with an external application.
Example use cases include sophisticated network configuration, volume garbage collection, etc.

Runtime Developers

Runtime developers can build runtime implementations that run OCI-compliant bundles and container configuration, containing low-level OS and host specific details, on a particular platform.

Releases

There is a loose Road Map.
During the 0.x series of OCI releases we make no backwards compatibility guarantees and intend to break the schema during this series.

Contributing

Development happens on GitHub for the spec.
Issues are used for bugs and actionable items and longer discussions can happen on the mailing list.

The specification and code is licensed under the Apache 2.0 license found in the LICENSE file.

Discuss your design

The project welcomes submissions, but please let everyone know what you are working on.

Before undertaking a nontrivial change to this specification, send mail to the mailing list to discuss what you plan to do.
This gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits.
It also guarantees that the design is sound before code is written; a GitHub pull-request is not the place for high-level discussions.

Typos and grammatical errors can go straight to a pull-request.
When in doubt, start on the mailing-list.

Weekly Call

The contributors and maintainers of all OCI projects have a weekly meeting Wednesdays at 2:00 PM (USA Pacific).
Everyone is welcome to participate via UberConference web or audio-only: 415-968-0849 (no PIN needed.)
An initial agenda will be posted to the mailing list earlier in the week, and everyone is welcome to propose additional topics or suggest other agenda alterations there.
Minutes are posted to the mailing list and minutes from past calls are archived to the wiki.

Mailing List

You can subscribe and join the mailing list on Google Groups.

IRC

OCI discussion happens on #opencontainers on Freenode (logs).

Git commit

Sign your work

The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch.
The rules are pretty simple: if you can certify the below (from http://developercertificate.org):

text
Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

then you just add a line to every git commit message:

text
Signed-off-by: Joe Smith <[email protected]>

using your real name (sorry, no pseudonyms or anonymous contributions.)

You can add the sign off when creating the git commit via git commit -s.

Commit Style

Simple house-keeping for clean git history.
Read more on How to Write a Git Commit Message or the Discussion section of git-commit(1).

  1. Separate the subject from body with a blank line
  2. Limit the subject line to 50 characters
  3. Capitalize the subject line
  4. Do not end the subject line with a period
  5. Use the imperative mood in the subject line
  6. Wrap the body at 72 characters
  7. Use the body to explain what and why vs. how
  • If there was important/useful/essential conversation or information, copy or include a reference
  1. When possible, one keyword to scope the change in the subject (i.e. "README: ...", "runtime: ...")

Overview (`vendor/github.com/pkg/errors/README.md`)

errors [](https://travis-ci.org/pkg/errors) [](https://ci.appveyor.com/project/davecheney/errors/branch/master) [](http://godoc.org/github.com/pkg/errors) [](https://goreportcard.com/report/github.com/pkg/errors)

Package errors provides simple error handling primitives.

go get github.com/pkg/errors

The traditional error handling idiom in Go is roughly akin to

go
if err != nil {
        return err
}

which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.

Adding context to an error

The errors.Wrap function returns a new error that adds context to the original error. For example

go
_, err := ioutil.ReadAll(r)
if err != nil {
        return errors.Wrap(err, "read failed")
}

Retrieving the cause of an error

Using errors.Wrap constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by errors.Cause.

go
type causer interface {
        Cause() error
}

errors.Cause will recursively retrieve the topmost error which does not implement causer, which is assumed to be the original cause. For example:

go
switch err := errors.Cause(err).(type) {
case *MyError:
        // handle specifically
default:
        // unknown error
}

Read the package documentation for more information.

Contributing

We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.

Before proposing a change, please discuss your change by raising an issue.

Licence

BSD-2-Clause


Overview (`vendor/github.com/pmezard/go-difflib/README.md`)

go-difflib


Go-difflib is a partial port of python 3 difflib package. Its main goal
was to make unified and context diff available in pure Go, mostly for
testing purposes.

The following class and functions (and related tests) have be ported:

  • SequenceMatcher
  • unified_diff()
  • context_diff()

Installation

bash
$ go get github.com/pmezard/go-difflib/difflib

Quick Start

Diffs are configured with Unified (or ContextDiff) structures, and can
be output to an io.Writer or returned as a string.

go
diff := UnifiedDiff{
    A:        difflib.SplitLines("foo\nbar\n"),
    B:        difflib.SplitLines("foo\nbaz\n"),
    FromFile: "Original",
    ToFile:   "Current",
    Context:  3,
}
text, _ := GetUnifiedDiffString(diff)
fmt.Printf(text)

would output:

text
--- Original
+++ Current
@@ -1,3 +1,3 @@
 foo
-bar
+baz

Overview (`vendor/github.com/prometheus/client_golang/README.md`)

Prometheus Go client library

This is the Go client library for
Prometheus. It has two separate parts, one for
instrumenting application code, and one for creating clients that talk to the
Prometheus HTTP API.

Instrumenting applications

The
prometheus directory
contains the instrumentation library. See the
best practices section of the
Prometheus documentation to learn more about instrumenting applications.

The
examples directory
contains simple examples of instrumented code.

Client for the Prometheus HTTP API

The
api/prometheus directory
contains the client for the
Prometheus HTTP API. It allows you
to write Go applications that query time series data from a Prometheus server.

Where is `model`, `extraction`, and `text`?

The model packages has been moved to
prometheus/common/model.

The extraction and text packages are now contained in
prometheus/common/expfmt.

Contributing and community

See the contributing guidelines and the
Community section of the homepage.


Overview (`vendor/github.com/prometheus/client_model/README.md`)

Background

Under most circumstances, manually downloading this repository should never
be required.

Prerequisites

Base

Java

Go

Ruby

Building

text
$ make

Getting Started


Overview (`vendor/github.com/prometheus/common/README.md`)

Common

This repository contains Go libraries that are shared across Prometheus
components and libraries.

  • config: Common configuration structures
  • expfmt: Decoding and encoding for the exposition format
  • log: A logging wrapper around logrus
  • model: Shared data structures
  • route: A routing wrapper around httprouter using context.Context
  • version: Version informations and metric

Overview (`vendor/github.com/prometheus/procfs/README.md`)

procfs

This procfs package provides functions to retrieve system, kernel and process
metrics from the pseudo-filesystem proc.

WARNING: This package is a work in progress. Its API may still break in
backwards-incompatible ways without warnings. Use it at your own risk.



Overview (`vendor/github.com/stretchr/testify/README.md`)

Testify - Thou Shalt Write Tests

Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend.

Features include:

Get started:

[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package

The assert package provides some helpful methods that allow you to write better test code in Go.

  • Prints friendly, easy to read failure descriptions
  • Allows for very readable code
  • Optionally annotate each assertion with a message

See it in action:

go
package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {

  // assert equality
  assert.Equal(t, 123, 123, "they should be equal")

  // assert inequality
  assert.NotEqual(t, 123, 456, "they should not be equal")

  // assert for nil (good for errors)
  assert.Nil(t, object)

  // assert for not nil (good when you expect something)
  if assert.NotNil(t, object) {

    // now we know that object isn't nil, we are safe to make
    // further assertions without causing any errors
    assert.Equal(t, "Something", object.Value)

  }

}
  • Every assert func takes the testing.T object as the first argument. This is how it writes the errors out through the normal go test capabilities.
  • Every assert func returns a bool indicating whether the assertion was successful or not, this is useful for if you want to go on making further assertions under certain conditions.

if you assert many times, use the below:

go
package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {
  assert := assert.New(t)

  // assert equality
  assert.Equal(123, 123, "they should be equal")

  // assert inequality
  assert.NotEqual(123, 456, "they should not be equal")

  // assert for nil (good for errors)
  assert.Nil(object)

  // assert for not nil (good when you expect something)
  if assert.NotNil(object) {

    // now we know that object isn't nil, we are safe to make
    // further assertions without causing any errors
    assert.Equal("Something", object.Value)
  }
}

[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package

The require package provides same global functions as the assert package, but instead of returning a boolean result they terminate current test.

See t.FailNow for details.

[`http`](http://godoc.org/github.com/stretchr/testify/http "API documentation") package

The http package contains test objects useful for testing code that relies on the net/http package. Check out the (deprecated) API documentation for the http package.

We recommend you use httptest instead.

[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package

The mock package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code.

An example test function that tests a piece of code that relies on an external object testObj, can setup expectations (testify) and assert that they indeed happened:

go
package yours

import (
  "testing"
  "github.com/stretchr/testify/mock"
)

/*
  Test objects
*/

// MyMockedObject is a mocked object that implements an interface
// that describes an object that the code I am testing relies on.
type MyMockedObject struct{
  mock.Mock
}

// DoSomething is a method on MyMockedObject that implements some interface
// and just records the activity, and returns what the Mock object tells it to.
//
// In the real object, this method would do something useful, but since this
// is a mocked object - we're just going to stub it out.
//
// NOTE: This method is not being tested here, code that uses this object is.
func (m *MyMockedObject) DoSomething(number int) (bool, error) {

  args := m.Called(number)
  return args.Bool(0), args.Error(1)

}

/*
  Actual test functions
*/

// TestSomething is an example of how to use our test object to
// make assertions about some target code we are testing.
func TestSomething(t *testing.T) {

  // create an instance of our test object
  testObj := new(MyMockedObject)

  // setup expectations
  testObj.On("DoSomething", 123).Return(true, nil)

  // call the code we are testing
  targetFuncThatDoesSomethingWithObj(testObj)

  // assert that the expectations were met
  testObj.AssertExpectations(t)

}

For more information on how to write mock code, check out the API documentation for the mock package.

You can use the mockery tool to autogenerate the mock code against an interface as well, making using mocks much quicker.

[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package

The suite package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal.

An example suite is shown below:

go
// Basic imports
import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/suite"
)

// Define the suite, and absorb the built-in basic suite
// functionality from testify - including a T() method which
// returns the current testing context
type ExampleTestSuite struct {
    suite.Suite
    VariableThatShouldStartAtFive int
}

// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
    suite.VariableThatShouldStartAtFive = 5
}

// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
    assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}

// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
    suite.Run(t, new(ExampleTestSuite))
}

For a more complete example, using all of the functionality provided by the suite package, look at our example testing suite

For more information on writing suites, check out the API documentation for the suite package.

Suite object has assertion methods:

go
// Basic imports
import (
    "testing"
    "github.com/stretchr/testify/suite"
)

// Define the suite, and absorb the built-in basic suite
// functionality from testify - including assertion methods.
type ExampleTestSuite struct {
    suite.Suite
    VariableThatShouldStartAtFive int
}

// Make sure that VariableThatShouldStartAtFive is set to five
// before each test
func (suite *ExampleTestSuite) SetupTest() {
    suite.VariableThatShouldStartAtFive = 5
}

// All methods that begin with "Test" are run as tests within a
// suite.
func (suite *ExampleTestSuite) TestExample() {
    suite.Equal(suite.VariableThatShouldStartAtFive, 5)
}

// In order for 'go test' to run this suite, we need to create
// a normal test function and pass our suite to suite.Run
func TestExampleTestSuite(t *testing.T) {
    suite.Run(t, new(ExampleTestSuite))
}

Installation

To install Testify, use go get:

text
* Latest version: go get github.com/stretchr/testify
* Specific version: go get gopkg.in/stretchr/testify.v1

This will then make the following packages available to you:

text
github.com/stretchr/testify/assert
github.com/stretchr/testify/mock
github.com/stretchr/testify/http

Import the testify/assert package into your code using this template:

go
package yours

import (
  "testing"
  "github.com/stretchr/testify/assert"
)

func TestSomething(t *testing.T) {

  assert.True(t, true, "True is true!")

}

Staying up to date

To update Testify to the latest version, use go get -u github.com/stretchr/testify.


Version History

  • 1.0 - New package versioning strategy adopted.

Contributing

Please feel free to submit issues, fork the repository and send pull requests!

When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it.


Licence

Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell

Please consider promoting this project if you find it useful.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Overview (`vendor/github.com/urfave/cli/README.md`)

cli






/

Notice: This is the library formerly known as
github.com/codegangsta/cli -- Github will automatically redirect requests
to this repository, but we recommend updating your references for clarity.

cli is a simple, fast, and fun package for building command line apps in Go. The
goal is to enable developers to write fast and distributable command line
applications in an expressive way.

Overview

Command line apps are usually so tiny that there is absolutely no reason why
your code should not be self-documenting. Things like generating help text and
parsing command flags/options should not hinder productivity when writing a
command line app.

This is where cli comes into play. cli makes command line programming fun,
organized, and expressive!

Installation

Make sure you have a working Go environment. Go version 1.2+ is supported. See
the install instructions for Go
.

To install cli, simply run:

text
$ go get github.com/urfave/cli

Make sure your PATH includes the $GOPATH/bin directory so your commands can
be easily used:

text
export PATH=$PATH:$GOPATH/bin

Supported platforms

cli is tested against multiple versions of Go on Linux, and against the latest
released version of Go on OS X and Windows. For full details, see
./.travis.yml and ./appveyor.yml.

Using the `v2` branch

Warning: The v2 branch is currently unreleased and considered unstable.

There is currently a long-lived branch named v2 that is intended to land as
the new master branch once development there has settled down. The current
master branch (mirrored as v1) is being manually merged into v2 on
an irregular human-based schedule, but generally if one wants to "upgrade" to
v2 now and accept the volatility (read: "awesomeness") that comes along with
that, please use whatever version pinning of your preference, such as via
gopkg.in:

text
$ go get gopkg.in/urfave/cli.v2
go
...
import (
  "gopkg.in/urfave/cli.v2" // imports as package "cli"
)
...

Pinning to the `v1` releases

Similarly to the section above describing use of the v2 branch, if one wants
to avoid any unexpected compatibility pains once v2 becomes master, then
pinning to v1 is an acceptable option, e.g.:

text
$ go get gopkg.in/urfave/cli.v1
go
...
import (
  "gopkg.in/urfave/cli.v1" // imports as package "cli"
)
...

This will pull the latest tagged v1 release (e.g. v1.18.1 at the time of writing).

Getting Started

One of the philosophies behind cli is that an API should be playful and full of
discovery. So a cli app can be as little as one line of code in main().

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.NewApp().Run(os.Args)
}

This app will run and show help text, but is not very useful. Let's give an
action to execute and some help documentation:

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "boom"
  app.Usage = "make an explosive entrance"
  app.Action = func(c *cli.Context) error {
    fmt.Println("boom! I say!")
    return nil
  }

  app.Run(os.Args)
}

Running this already gives you a ton of functionality, plus support for things
like subcommands and flags, which are covered below.

Examples

Being a programmer can be a lonely job. Thankfully by the power of automation
that is not the case! Let's create a greeter app to fend off our demons of
loneliness!

Start by creating a directory named greet, and within it, add a file,
greet.go with the following code in it:

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Name = "greet"
  app.Usage = "fight the loneliness!"
  app.Action = func(c *cli.Context) error {
    fmt.Println("Hello friend!")
    return nil
  }

  app.Run(os.Args)
}

Install our command to the $GOPATH/bin directory:

text
$ go install

Finally run our new command:

text
$ greet
Hello friend!

cli also generates neat help text:

text
$ greet help
NAME:
    greet - fight the loneliness!

USAGE:
    greet [global options] command [command options] [arguments...]

VERSION:
    0.0.0

COMMANDS:
    help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS
    --version Shows version information

Arguments

You can lookup arguments by calling the Args function on cli.Context, e.g.:

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Action = func(c *cli.Context) error {
    fmt.Printf("Hello %q", c.Args().Get(0))
    return nil
  }

  app.Run(os.Args)
}

Flags

Setting and querying flags is simple.

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang",
      Value: "english",
      Usage: "language for the greeting",
    },
  }

  app.Action = func(c *cli.Context) error {
    name := "Nefertiti"
    if c.NArg() > 0 {
      name = c.Args().Get(0)
    }
    if c.String("lang") == "spanish" {
      fmt.Println("Hola", name)
    } else {
      fmt.Println("Hello", name)
    }
    return nil
  }

  app.Run(os.Args)
}

You can also set a destination variable for a flag, to which the content will be
scanned.

go
package main

import (
  "os"
  "fmt"

  "github.com/urfave/cli"
)

func main() {
  var language string

  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name:        "lang",
      Value:       "english",
      Usage:       "language for the greeting",
      Destination: &language,
    },
  }

  app.Action = func(c *cli.Context) error {
    name := "someone"
    if c.NArg() > 0 {
      name = c.Args()[0]
    }
    if language == "spanish" {
      fmt.Println("Hola", name)
    } else {
      fmt.Println("Hello", name)
    }
    return nil
  }

  app.Run(os.Args)
}

See full list of flags at http://godoc.org/github.com/urfave/cli

Placeholder Values

Sometimes it's useful to specify a flag's value within the usage string itself.
Such placeholders are indicated with back quotes.

For example this:

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag{
    cli.StringFlag{
      Name:  "config, c",
      Usage: "Load configuration from `FILE`",
    },
  }

  app.Run(os.Args)
}

Will result in help output like:

text
--config FILE, -c FILE   Load configuration from FILE

Note that only the first placeholder is used. Subsequent back-quoted words will
be left as-is.

Alternate Names

You can set alternate (or short) names for flags by providing a comma-delimited
list for the Name. e.g.

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
    },
  }

  app.Run(os.Args)
}

That flag can then be set with --lang spanish or -l spanish. Note that
giving two different forms of the same flag in the same command invocation is an
error.

Ordering

Flags for the application and commands are shown in the order they are defined.
However, it's possible to sort them from outside this library by using FlagsByName
or CommandsByName with sort.

For example this:

go
package main

import (
  "os"
  "sort"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "Language for the greeting",
    },
    cli.StringFlag{
      Name: "config, c",
      Usage: "Load configuration from `FILE`",
    },
  }

  app.Commands = []cli.Command{
    {
      Name:    "complete",
      Aliases: []string{"c"},
      Usage:   "complete a task on the list",
      Action:  func(c *cli.Context) error {
        return nil
      },
    },
    {
      Name:    "add",
      Aliases: []string{"a"},
      Usage:   "add a task to the list",
      Action:  func(c *cli.Context) error {
        return nil
      },
    },
  }

  sort.Sort(cli.FlagsByName(app.Flags))
  sort.Sort(cli.CommandsByName(app.Commands))

  app.Run(os.Args)
}

Will result in help output like:

text
--config FILE, -c FILE  Load configuration from FILE
--lang value, -l value  Language for the greeting (default: "english")

Values from the Environment

You can also have the default value set from the environment via EnvVar. e.g.

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
      EnvVar: "APP_LANG",
    },
  }

  app.Run(os.Args)
}

The EnvVar may also be given as a comma-delimited "cascade", where the first
environment variable that resolves is used as the default.

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Flags = []cli.Flag {
    cli.StringFlag{
      Name: "lang, l",
      Value: "english",
      Usage: "language for the greeting",
      EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
    },
  }

  app.Run(os.Args)
}

Values from alternate input sources (YAML, TOML, and others)

There is a separate package altsrc that adds support for getting flag values
from other file input sources.

Currently supported input source formats:

  • YAML
  • TOML

In order to get values for a flag from an alternate input source the following
code would be added to wrap an existing cli.Flag like below:

go
altsrc.NewIntFlag(cli.IntFlag{Name: "test"})

Initialization must also occur for these flags. Below is an example initializing
getting data from a yaml file below.

go
command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))

The code above will use the "load" string as a flag name to get the file name of
a yaml file from the cli.Context. It will then use that file name to initialize
the yaml input source for any flags that are defined on that command. As a note
the "load" flag used would also have to be defined on the command flags in order
for this code snipped to work.

Currently only the aboved specified formats are supported but developers can
add support for other input sources by implementing the
altsrc.InputSourceContext for their given sources.

Here is a more complete sample of a command using YAML support:

go
package notmain

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
  "github.com/urfave/cli/altsrc"
)

func main() {
  app := cli.NewApp()

  flags := []cli.Flag{
    altsrc.NewIntFlag(cli.IntFlag{Name: "test"}),
    cli.StringFlag{Name: "load"},
  }

  app.Action = func(c *cli.Context) error {
    fmt.Println("yaml ist rad")
    return nil
  }

  app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
  app.Flags = flags

  app.Run(os.Args)
}

Subcommands

Subcommands can be defined for a more git-like command line app.

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Commands = []cli.Command{
    {
      Name:    "add",
      Aliases: []string{"a"},
      Usage:   "add a task to the list",
      Action:  func(c *cli.Context) error {
        fmt.Println("added task: ", c.Args().First())
        return nil
      },
    },
    {
      Name:    "complete",
      Aliases: []string{"c"},
      Usage:   "complete a task on the list",
      Action:  func(c *cli.Context) error {
        fmt.Println("completed task: ", c.Args().First())
        return nil
      },
    },
    {
      Name:        "template",
      Aliases:     []string{"t"},
      Usage:       "options for task templates",
      Subcommands: []cli.Command{
        {
          Name:  "add",
          Usage: "add a new template",
          Action: func(c *cli.Context) error {
            fmt.Println("new task template: ", c.Args().First())
            return nil
          },
        },
        {
          Name:  "remove",
          Usage: "remove an existing template",
          Action: func(c *cli.Context) error {
            fmt.Println("removed task template: ", c.Args().First())
            return nil
          },
        },
      },
    },
  }

  app.Run(os.Args)
}

Subcommands categories

For additional organization in apps that have many subcommands, you can
associate a category for each command to group them together in the help
output.

E.g.

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()

  app.Commands = []cli.Command{
    {
      Name: "noop",
    },
    {
      Name:     "add",
      Category: "template",
    },
    {
      Name:     "remove",
      Category: "template",
    },
  }

  app.Run(os.Args)
}

Will include:

text
COMMANDS:
    noop

  Template actions:
    add
    remove

Exit code

Calling App.Run will not automatically call os.Exit, which means that by
default the exit code will "fall through" to being 0. An explicit exit code
may be set by returning a non-nil error that fulfills cli.ExitCoder, or a
cli.MultiError that includes an error that fulfills cli.ExitCoder, e.g.:

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  app := cli.NewApp()
  app.Flags = []cli.Flag{
    cli.BoolTFlag{
      Name:  "ginger-crouton",
      Usage: "is it in the soup?",
    },
  }
  app.Action = func(ctx *cli.Context) error {
    if !ctx.Bool("ginger-crouton") {
      return cli.NewExitError("it is not in the soup", 86)
    }
    return nil
  }

  app.Run(os.Args)
}

Bash Completion

You can enable completion commands by setting the EnableBashCompletion
flag on the App object. By default, this setting will only auto-complete to
show an app's subcommands, but you can write your own completion methods for
the App or its subcommands.

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

func main() {
  tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}

  app := cli.NewApp()
  app.EnableBashCompletion = true
  app.Commands = []cli.Command{
    {
      Name:  "complete",
      Aliases: []string{"c"},
      Usage: "complete a task on the list",
      Action: func(c *cli.Context) error {
         fmt.Println("completed task: ", c.Args().First())
         return nil
      },
      BashComplete: func(c *cli.Context) {
        // This will complete if no args are passed
        if c.NArg() > 0 {
          return
        }
        for _, t := range tasks {
          fmt.Println(t)
        }
      },
    },
  }

  app.Run(os.Args)
}

Enabling

Source the autocomplete/bash_autocomplete file in your .bashrc file while
setting the PROG variable to the name of your program:

PROG=myprogram source /.../cli/autocomplete/bash_autocomplete

Distribution

Copy autocomplete/bash_autocomplete into /etc/bash_completion.d/ and rename
it to the name of the program you wish to add autocomplete support for (or
automatically install it there if you are distributing a package). Don't forget
to source the file to make it active in the current shell.

text
sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
source /etc/bash_completion.d/<myprogram>

Alternatively, you can just document that users should source the generic
autocomplete/bash_autocomplete in their bash configuration with $PROG set
to the name of their program (as above).

Customization

The default bash completion flag (--generate-bash-completion) is defined as
cli.BashCompletionFlag, and may be redefined if desired, e.g.:

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.BashCompletionFlag = cli.BoolFlag{
    Name:   "compgen",
    Hidden: true,
  }

  app := cli.NewApp()
  app.EnableBashCompletion = true
  app.Commands = []cli.Command{
    {
      Name: "wat",
    },
  }
  app.Run(os.Args)
}

Generated Help Text

The default help flag (-h/--help) is defined as cli.HelpFlag and is checked
by the cli internals in order to print generated help text for the app, command,
or subcommand, and break execution.

Customization

All of the help text generation may be customized, and at multiple levels. The
templates are exposed as variables AppHelpTemplate, CommandHelpTemplate, and
SubcommandHelpTemplate which may be reassigned or augmented, and full override
is possible by assigning a compatible func to the cli.HelpPrinter variable,
e.g.:

go
package main

import (
  "fmt"
  "io"
  "os"

  "github.com/urfave/cli"
)

func main() {
  // EXAMPLE: Append to an existing template
  cli.AppHelpTemplate = fmt.Sprintf(`%s

WEBSITE: http://awesometown.example.com

SUPPORT: [email protected]

`, cli.AppHelpTemplate)

  // EXAMPLE: Override a template
  cli.AppHelpTemplate = `NAME:
   {{.Name}} - {{.Usage}}
USAGE:
   {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
   {{if len .Authors}}
AUTHOR:
   {{range .Authors}}{{ . }}{{end}}
   {{end}}{{if .Commands}}
COMMANDS:
{{range .Commands}}{{if not .HideHelp}}   {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
   {{range .VisibleFlags}}{{.}}
   {{end}}{{end}}{{if .Copyright }}
COPYRIGHT:
   {{.Copyright}}
   {{end}}{{if .Version}}
VERSION:
   {{.Version}}
   {{end}}
`

  // EXAMPLE: Replace the `HelpPrinter` func
  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
    fmt.Println("Ha HA.  I pwnd the help!!1")
  }

  cli.NewApp().Run(os.Args)
}

The default flag may be customized to something other than -h/--help by
setting cli.HelpFlag, e.g.:

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.HelpFlag = cli.BoolFlag{
    Name: "halp, haaaaalp",
    Usage: "HALP",
    EnvVar: "SHOW_HALP,HALPPLZ",
  }

  cli.NewApp().Run(os.Args)
}

Version Flag

The default version flag (-v/--version) is defined as cli.VersionFlag, which
is checked by the cli internals in order to print the App.Version via
cli.VersionPrinter and break execution.

Customization

The default flag may be customized to something other than -v/--version by
setting cli.VersionFlag, e.g.:

go
package main

import (
  "os"

  "github.com/urfave/cli"
)

func main() {
  cli.VersionFlag = cli.BoolFlag{
    Name: "print-version, V",
    Usage: "print only the version",
  }

  app := cli.NewApp()
  app.Name = "partay"
  app.Version = "19.99.0"
  app.Run(os.Args)
}

Alternatively, the version printer at cli.VersionPrinter may be overridden, e.g.:

go
package main

import (
  "fmt"
  "os"

  "github.com/urfave/cli"
)

var (
  Revision = "fafafaf"
)

func main() {
  cli.VersionPrinter = func(c *cli.Context) {
    fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
  }

  app := cli.NewApp()
  app.Name = "partay"
  app.Version = "19.99.0"
  app.Run(os.Args)
}

Full API Example

Notice: This is a contrived (functioning) example meant strictly for API
demonstration purposes. Use of one's imagination is encouraged.

text
/* Detailed source-code truncated for AI context efficiency. */

Contribution Guidelines

Feel free to put up a pull request to fix a bug or maybe add a feature. I will
give it a code review and make sure that it does not break backwards
compatibility. If I or any other collaborators agree that it is in line with
the vision of the project, we will work with you to get the code into
a mergeable state and merge it into the master branch.

If you have contributed something significant to the project, we will most
likely add you as a collaborator. As a collaborator you are given the ability
to merge others pull requests. It is very important that new code does not
break existing code, so be careful about what code you do choose to merge.

If you feel like you have contributed to the project but have not yet been
added as a collaborator, we probably forgot to add you, please open an issue.


Overview (`vendor/github.com/opencontainers/runc/libcontainer/README.md`)

libcontainer

Libcontainer provides a native Go implementation for creating containers
with namespaces, cgroups, capabilities, and filesystem access controls.
It allows you to manage the lifecycle of the container performing additional operations
after the container is created.

Container

A container is a self contained execution environment that shares the kernel of the
host system and which is (optionally) isolated from other containers in the system.

Using libcontainer

Because containers are spawned in a two step process you will need a binary that
will be executed as the init process for the container. In libcontainer, we use
the current binary (/proc/self/exe) to be executed as the init process, and use
arg "init", we call the first step process "bootstrap", so you always need a "init"
function as the entry of "bootstrap".

In addition to the go init function the early stage bootstrap is handled by importing
nsenter.

go
import (
	_ "github.com/opencontainers/runc/libcontainer/nsenter"
)

func init() {
	if len(os.Args) > 1 && os.Args[1] == "init" {
		runtime.GOMAXPROCS(1)
		runtime.LockOSThread()
		factory, _ := libcontainer.New("")
		if err := factory.StartInitialization(); err != nil {
			logrus.Fatal(err)
		}
		panic("--this line should have never been executed, congratulations--")
	}
}

Then to create a container you first have to initialize an instance of a factory
that will handle the creation and initialization for a container.

go
factory, err := libcontainer.New("/var/lib/container", libcontainer.Cgroupfs, libcontainer.InitArgs(os.Args[0], "init"))
if err != nil {
	logrus.Fatal(err)
	return
}

Once you have an instance of the factory created we can create a configuration
struct describing how the container is to be created. A sample would look similar to this:

text
/* Detailed source-code truncated for AI context efficiency. */

Once you have the configuration populated you can create a container:

go
container, err := factory.Create("container-id", config)
if err != nil {
	logrus.Fatal(err)
	return
}

To spawn bash as the initial process inside the container and have the
processes pid returned in order to wait, signal, or kill the process:

go
process := &libcontainer.Process{
	Args:   []string{"/bin/bash"},
	Env:    []string{"PATH=/bin"},
	User:   "daemon",
	Stdin:  os.Stdin,
	Stdout: os.Stdout,
	Stderr: os.Stderr,
}

err := container.Run(process)
if err != nil {
	container.Destroy()
	logrus.Fatal(err)
	return
}

// wait for the process to finish.
_, err := process.Wait()
if err != nil {
	logrus.Fatal(err)
}

// destroy the container.
container.Destroy()

Additional ways to interact with a running container are:

go
// return all the pids for all processes running inside the container.
processes, err := container.Processes()

// get detailed cpu, memory, io, and network statistics for the container and
// it's processes.
stats, err := container.Stats()

// pause all processes inside the container.
container.Pause()

// resume all paused processes.
container.Resume()

// send signal to container's init process.
container.Signal(signal)

// update container resource constraints.
container.Set(config)

// get current status of the container.
status, err := container.Status()

// get current container's state information.
state, err := container.State()

Checkpoint & Restore

libcontainer now integrates CRIU for checkpointing and restoring containers.
This let's you save the state of a process running inside a container to disk, and then restore
that state into a new process, on the same machine or on another machine.

criu version 1.5.2 or higher is required to use checkpoint and restore.
If you don't already have criu installed, you can build it from source, following the
online instructions. criu is also installed in the docker image
generated when building libcontainer with docker.

Code and documentation copyright 2014 Docker, inc. Code released under the Apache 2.0 license.
Docs released under Creative commons.


Overview (`vendor/github.com/prometheus/client_golang/prometheus/README.md`)

See .


Overview (`vendor/github.com/opencontainers/runc/libcontainer/nsenter/README.md`)

nsenter

The nsenter package registers a special init constructor that is called before
the Go runtime has a chance to boot. This provides us the ability to setns on
existing namespaces and avoid the issues that the Go runtime has with multiple
threads. This constructor will be called if this package is registered,
imported, in your go application.

The nsenter package will import "C" and it uses cgo
package. In cgo, if the import of "C" is immediately preceded by a comment, that comment,
called the preamble, is used as a header when compiling the C parts of the package.
So every time we import package nsenter, the C code function nsexec() would be
called. And package nsenter is now only imported in main_unix.go, so every time
before we call cmd.Start on linux, that C code would run.

Because nsexec() must be run before the Go runtime in order to use the
Linux kernel namespace, you must import this library into a package if
you plan to use libcontainer directly. Otherwise Go will not execute
the nsexec() constructor, which means that the re-exec will not cause
the namespaces to be joined. You can import it like this:

go
import _ "github.com/opencontainers/runc/libcontainer/nsenter"

nsexec() will first get the file descriptor number for the init pipe
from the environment variable _LIBCONTAINER_INITPIPE (which was opened
by the parent and kept open across the fork-exec of the nsexec() init
process). The init pipe is used to read bootstrap data (namespace paths,
clone flags, uid and gid mappings, and the console path) from the parent
process. nsexec() will then call setns(2) to join the namespaces
provided in the bootstrap data (if available), clone(2) a child process
with the provided clone flags, update the user and group ID mappings, do
some further miscellaneous setup steps, and then send the PID of the
child process to the parent of the nsexec() "caller". Finally,
the parent nsexec() will exit and the child nsexec() process will
return to allow the Go runtime take over.

NOTE: We do both setns(2) and clone(2) even if we don't have any
CLONE_NEW* clone flags because we must fork a new process in order to
enter the PID namespace.


Index (`docs/index.md`)


title: containerd layout: home

News

About containerd

containerd is an industry-standard core container runtime with an emphasis on simplicity, robustness and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc..

containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users.

containerd includes a daemon exposing gRPC API over a local UNIX socket. The API is a low-level one designed for higher layers to wrap and extend. It also includes a barebone CLI (ctr) designed specifically for development and debugging purpose. It uses runC to run containers according to the OCI specification. The code can be found on GitHub, and here are the contribution guidelines.

containerd is based on the Docker Engine’s core container runtime to benefit from its maturity and existing contributors.

Features and roadmap

  • OCI Image Spec support
  • OCI Runtime Spec support (aka runC)
  • Image push and pull support
  • Container runtime and lifecycle support
  • Network primitives for creation, modification, and deletion of interfaces
  • Management of network namespaces containers to join existing namespaces
  • Multi-tenant supported with CAS storage for global images

containerd, currently in version 0.2.4, is a daemon born from extracting the container execution subset of the Docker Engine, and is used internally by Docker since the 1.11 release. containerd will graduate to version 1.0 once its feature scope matches the requirements above, from which it will commit to API stability as well as committing to a 1-year LTS release. Docker Engine commits to upgrading to containerd 1.0 as part of its regular release cycle.

containerd roadmap to implement these features is described in the containerd Github repository.

Architecture

Containerd architecture and API are described in the Github repository.

Principles and Releases

Having a clearly defined scope of a project is important for ensuring consistency and focus.
These following criteria will be used when reviewing pull requests, features, and changes for the project before being accepted.

Components

Components should not have tight dependencies on each other so that they are unable to be used independently.
The APIs for images and containers should be designed in a way that when used together the components have a natural flow but still be useful independently.

An example for this design can be seen with the overlay filesystems and the container execution layer.
The execution layer and overlay filesystems can be used independently but if you were to use both, they share a common Mount struct that the filesystems produce and the execution layer consumes.

Primitives

containerd should expose primitives to solve problems instead of building high level abstractions in the API.
A common example of this is how build would be implemented.
Instead of having a build API in containerd we should expose the lower level primitives that allow things required in build to work.
Breaking up the filesystem APIs to allow snapshots, copy functionality, and mounts allow people implementing build at the higher levels more flexibility.

Extensibility and Defaults

For the various components in containerd there should be defined extension points where implementations can be swapped for alternatives.
The best example of this is that containerd will use runc from OCI as the default runtime in the execution layer but other runtimes conforming to the OCI Runtime specification they can be easily added to containerd.

containerd will come with a default implementation for the various components.
These defaults will be chosen by the maintainers of the project and should not change unless better tech for that component comes out.
Additional implementations will not be accepted into the core repository and should be developed in a separate repository not maintained by the containerd maintainers.

Releases

containerd will be released with a 1.0 when feature complete with Linux and Windows parity and this version will be supported for 1 year with security and bug fixes applied and released.

The upgrade path for containerd is that the 0.0.x patch releases are always backward compatible with its major and minor version.
Minor (0.x.0) version will always be compatible with the previous minor release. i.e. 1.2.0 is backwards compatible with 1.1.0 and 1.1.0 is compatible with 1.0.0.
There is no compatibility guarantees with upgrades from two minor relases. i.e. 1.0.0 to 1.2.0.

There are no backwards compatibility guarantees with upgrades to major versions. i.e 1.0.0 to 2.0.0.
Each major version will be supported for 1 year with bug fixes and security patches.

FAQ

  1. What is the relationship between containerd and Docker?

Docker is a complete platform and programming environment for containerized applications. containerd is one of dozens of specialized components integrated into Docker. Developers and IT professionals looking to build, ship and run containerized applications should continue to use Docker. Operators and integrators looking for specialized components to swap into their platform should consider containerd.

containerd 0.2.4 used in Docker 1.12 covers only container execution and process management.

containerd's roadmap is to refactor the Docker Engine codebase to extract more of its logic for distribution, networking and storage on a single host into a reusable component that Docker will use, and that can be used by other container orchestration projects or hosted container services.

  1. What is the relationship between containerd, OCI and runc?

Docker donated the OCI specification to the Linux Foundation in 2015, along with a reference implementation called runc. containerd integrates OCI/runc into a feature-complete, production-ready core container runtime. runc is a component of containerd, the executor for containers. containerd has a wider scope than just executing containers: downloading container images, managing storage and network interfaces, calling runc with the right parameters to run containers. containerd fully leverages the Open Container Initiative’s (OCI) runtime, image format specifications and OCI reference implementation (runc) and will pursue OCI certification when it is available. Because of its massive adoption, containerd is the industry standard for implementing OCI.

  1. What is the relationship between containerd and container orchestration systems like Kubernetes and Mesos?

Kubernetes today uses Docker directly. In a future version Kubernetes can implement container support in the Kubelet by implementing it's Container Runtime Interface using containerd. Mesos and other orchestration engines can leverage containerd for core container runtime functionality as well.

  1. What is the relationship between containerd and cloud managed container services?

See answer above: cloud managed container services can leverage containerd instead of Docker in order to provide container functionalities to their users.


Config.Yml (`docs/_config.yml`)

markdown: kramdown
kramdown:
input: GFM
html_to_native: true
hard_wrap: false
syntax_highlighter: rouge
incremental: true
permalink: pretty
safe: false
lsi: false
exclude: [README.md]

gems:

  • jekyll-redirect-from
  • jekyll-seo-tag

defaults:

text
scope:
  path: ""
  type: "pages"
values:
  layout: default

Dockercon Summit (`docs/dockercon-summit.md`)


title: Dockercon 2017 Summit layout: home

Dockercon 2017 Summit

This year at Dockercon US 2017 we will be having a containerd Summit on Thursday morning the week of the conference.

We are going to change the format slightly compared to the previous summit that was held in February. We will be allocating more time to the breakout sessions and less time to static talks. However, the group will be much larger than the previous summit so this document serves as a way to add discussion points for the breakout sessions.

If you would like to add a discussion point to the agenda, submit a PR adding it to the list below. A simple one line sentence is enough or expand if needed.

If you have not signed up to attend the summit you can do so in this form.

Discussion Points

The following are proposed discussion points for the containerd summit at Dockercon US 2017:

  • Since containerd is one of the bottom bricks in the stack, how can we setup automated integration tests for consumers of containerd?
  • We'd like to propose an Authorization plugin to containerd that would allow an external component to police events like container start & stop (and have a discussion about the best way to go about it)
  • Should containerd provide image filesystem metrics? If yes, what metrics should be included? How to implement that?
  • Support for disk quotas: How? What is the role of containerd? How is it going to be integrated with volume managers that want to be in the same quota group?
  • Checkpoint/Restore: how can we support more use cases? One of the big issues here is the large number of options that can be passed to CRIU.
  • How to support multi-OS docker images, for example, Linux Vs Windows using one graph driver plugin properly?

--- METRICS ---