fix highwayhash

This commit is contained in:
Tejal Desai
2019-12-21 12:18:09 -08:00
committed by Cole Wippern
parent 5a2cfeabba
commit 6b020a1f97
806 changed files with 188665 additions and 226974 deletions
+38
View File
@@ -0,0 +1,38 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
# never checkin from the bin file (for now)
bin/*
# Test key files
*.pem
# Cover profiles
*.out
# Editor/IDE specific files.
*.sublime-project
*.sublime-workspace
.idea/*
+18
View File
@@ -0,0 +1,18 @@
Stephen J Day <stephen.day@docker.com> Stephen Day <stevvooe@users.noreply.github.com>
Stephen J Day <stephen.day@docker.com> Stephen Day <stevvooe@gmail.com>
Olivier Gambier <olivier@docker.com> Olivier Gambier <dmp42@users.noreply.github.com>
Brian Bland <brian.bland@docker.com> Brian Bland <r4nd0m1n4t0r@gmail.com>
Brian Bland <brian.bland@docker.com> Brian Bland <brian.t.bland@gmail.com>
Josh Hawn <josh.hawn@docker.com> Josh Hawn <jlhawn@berkeley.edu>
Richard Scothern <richard.scothern@docker.com> Richard <richard.scothern@gmail.com>
Richard Scothern <richard.scothern@docker.com> Richard Scothern <richard.scothern@gmail.com>
Andrew Meredith <andymeredith@gmail.com> Andrew Meredith <kendru@users.noreply.github.com>
harche <p.harshal@gmail.com> harche <harche@users.noreply.github.com>
Jessie Frazelle <jessie@docker.com> <jfrazelle@users.noreply.github.com>
Sharif Nassar <sharif@mrwacky.com> Sharif Nassar <mrwacky42@users.noreply.github.com>
Sven Dowideit <SvenDowideit@home.org.au> Sven Dowideit <SvenDowideit@users.noreply.github.com>
Vincent Giersch <vincent.giersch@ovh.net> Vincent Giersch <vincent@giersch.fr>
davidli <wenquan.li@hp.com> davidli <wenquan.li@hpe.com>
Omer Cohen <git@omer.io> Omer Cohen <git@omerc.net>
Eric Yang <windfarer@gmail.com> Eric Yang <Windfarer@users.noreply.github.com>
Nikita Tarasov <nikita@mygento.ru> Nikita <luckyraul@users.noreply.github.com>
+117
View File
@@ -0,0 +1,117 @@
# Building the registry source
## Use-case
This is useful if you intend to actively work on the registry.
### Alternatives
Most people should use the [official Registry docker image](https://hub.docker.com/r/library/registry/).
People looking for advanced operational use cases might consider rolling their own image with a custom Dockerfile inheriting `FROM registry:2`.
OS X users who want to run natively can do so following [the instructions here](https://github.com/docker/docker.github.io/blob/master/registry/recipes/osx-setup-guide.md).
### Gotchas
You are expected to know your way around with go & git.
If you are a casual user with no development experience, and no preliminary knowledge of go, building from source is probably not a good solution for you.
## Build the development environment
The first prerequisite of properly building distribution targets is to have a Go
development environment setup. Please follow [How to Write Go Code](https://golang.org/doc/code.html)
for proper setup. If done correctly, you should have a GOROOT and GOPATH set in the
environment.
If a Go development environment is setup, one can use `go get` to install the
`registry` command from the current latest:
go get github.com/docker/distribution/cmd/registry
The above will install the source repository into the `GOPATH`.
Now create the directory for the registry data (this might require you to set permissions properly)
mkdir -p /var/lib/registry
... or alternatively `export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/somewhere` if you want to store data into another location.
The `registry`
binary can then be run with the following:
$ $GOPATH/bin/registry --version
$GOPATH/bin/registry github.com/docker/distribution v2.0.0-alpha.1+unknown
> __NOTE:__ While you do not need to use `go get` to checkout the distribution
> project, for these build instructions to work, the project must be checked
> out in the correct location in the `GOPATH`. This should almost always be
> `$GOPATH/src/github.com/docker/distribution`.
The registry can be run with the default config using the following
incantation:
$ $GOPATH/bin/registry serve $GOPATH/src/github.com/docker/distribution/cmd/registry/config-example.yml
INFO[0000] endpoint local-5003 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
INFO[0000] endpoint local-8083 disabled, skipping app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
INFO[0000] listening on :5000 app.id=34bbec38-a91a-494a-9a3f-b72f9010081f version=v2.0.0-alpha.1+unknown
INFO[0000] debug server listening localhost:5001
If it is working, one should see the above log messages.
### Repeatable Builds
For the full development experience, one should `cd` into
`$GOPATH/src/github.com/docker/distribution`. From there, the regular `go`
commands, such as `go test`, should work per package (please see
[Developing](#developing) if they don't work).
A `Makefile` has been provided as a convenience to support repeatable builds.
Please install the following into `GOPATH` for it to work:
go get github.com/golang/lint/golint
Once these commands are available in the `GOPATH`, run `make` to get a full
build:
$ make
+ clean
+ fmt
+ vet
+ lint
+ build
github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar
github.com/sirupsen/logrus
github.com/docker/libtrust
...
github.com/yvasiyarov/gorelic
github.com/docker/distribution/registry/handlers
github.com/docker/distribution/cmd/registry
+ test
...
ok github.com/docker/distribution/digest 7.875s
ok github.com/docker/distribution/manifest 0.028s
ok github.com/docker/distribution/notifications 17.322s
? github.com/docker/distribution/registry [no test files]
ok github.com/docker/distribution/registry/api/v2 0.101s
? github.com/docker/distribution/registry/auth [no test files]
ok github.com/docker/distribution/registry/auth/silly 0.011s
...
+ /Users/sday/go/src/github.com/docker/distribution/bin/registry
+ /Users/sday/go/src/github.com/docker/distribution/bin/registry-api-descriptor-template
+ binaries
The above provides a repeatable build using the contents of the vendor
directory. This includes formatting, vetting, linting, building,
testing and generating tagged binaries. We can verify this worked by running
the registry binary generated in the "./bin" directory:
$ ./bin/registry --version
./bin/registry github.com/docker/distribution v2.0.0-alpha.2-80-g16d8b2c.m
### Optional build tags
Optional [build tags](http://golang.org/pkg/go/build/) can be provided using
the environment variable `DOCKER_BUILDTAGS`.
+108
View File
@@ -0,0 +1,108 @@
# Changelog
## 2.6.0 (2017-01-18)
#### Storage
- S3: fixed bug in delete due to read-after-write inconsistency
- S3: allow EC2 IAM roles to be used when authorizing region endpoints
- S3: add Object ACL Support
- S3: fix delete method's notion of subpaths
- S3: use multipart upload API in `Move` method for performance
- S3: add v2 signature signing for legacy S3 clones
- Swift: add simple heuristic to detect incomplete DLOs during read ops
- Swift: support different user and tenant domains
- Swift: bulk deletes in chunks
- Aliyun OSS: fix delete method's notion of subpaths
- Aliyun OSS: optimize data copy after upload finishes
- Azure: close leaking response body
- Fix storage drivers dropping non-EOF errors when listing repositories
- Compare path properly when listing repositories in catalog
- Add a foreign layer URL host whitelist
- Improve catalog enumerate runtime
#### Registry
- Export `storage.CreateOptions` in top-level package
- Enable notifications to endpoints that use self-signed certificates
- Properly validate multi-URL foreign layers
- Add control over validation of URLs in pushed manifests
- Proxy mode: fix socket leak when pull is cancelled
- Tag service: properly handle error responses on HEAD request
- Support for custom authentication URL in proxying registry
- Add configuration option to disable access logging
- Add notification filtering by target media type
- Manifest: `References()` returns all children
- Honor `X-Forwarded-Port` and Forwarded headers
- Reference: Preserve tag and digest in With* functions
- Add policy configuration for enforcing repository classes
#### Client
- Changes the client Tags `All()` method to follow links
- Allow registry clients to connect via HTTP2
- Better handling of OAuth errors in client
#### Spec
- Manifest: clarify relationship between urls and foreign layers
- Authorization: add support for repository classes
#### Manifest
- Override media type returned from `Stat()` for existing manifests
- Add plugin mediatype to distribution manifest
#### Docs
- Document `TOOMANYREQUESTS` error code
- Document required Let's Encrypt port
- Improve documentation around implementation of OAuth2
- Improve documentation for configuration
#### Auth
- Add support for registry type in scope
- Add support for using v2 ping challenges for v1
- Add leeway to JWT `nbf` and `exp` checking
- htpasswd: dynamically parse htpasswd file
- Fix missing auth headers with PATCH HTTP request when pushing to default port
#### Dockerfile
- Update to go1.7
- Reorder Dockerfile steps for better layer caching
#### Notes
Documentation has moved to the documentation repository at
`github.com/docker/docker.github.io/tree/master/registry`
The registry is go 1.7 compliant, and passes newer, more restrictive `lint` and `vet` ing.
## 2.5.0 (2016-06-14)
#### Storage
- Ensure uploads directory is cleaned after upload is committed
- Add ability to cap concurrent operations in filesystem driver
- S3: Add 'us-gov-west-1' to the valid region list
- Swift: Handle ceph not returning Last-Modified header for HEAD requests
- Add redirect middleware
#### Registry
- Add support for blobAccessController middleware
- Add support for layers from foreign sources
- Remove signature store
- Add support for Let's Encrypt
- Correct yaml key names in configuration
#### Client
- Add option to get content digest from manifest get
#### Spec
- Update the auth spec scope grammar to reflect the fact that hostnames are optionally supported
- Clarify API documentation around catalog fetch behavior
#### API
- Support returning HTTP 429 (Too Many Requests)
#### Documentation
- Update auth documentation examples to show "expires in" as int
#### Docker Image
- Use Alpine Linux as base image
+148
View File
@@ -0,0 +1,148 @@
# Contributing to the registry
## Before reporting an issue...
### If your problem is with...
- automated builds
- your account on the [Docker Hub](https://hub.docker.com/)
- any other [Docker Hub](https://hub.docker.com/) issue
Then please do not report your issue here - you should instead report it to [https://support.docker.com](https://support.docker.com)
### If you...
- need help setting up your registry
- can't figure out something
- are not sure what's going on or what your problem is
Then please do not open an issue here yet - you should first try one of the following support forums:
- irc: #docker-distribution on freenode
- mailing-list: <distribution@dockerproject.org> or https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
### Reporting security issues
The Docker 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
[security@docker.com](mailto:security@docker.com).
## Reporting an issue properly
By following these simple rules you will get better and faster feedback on your issue.
- search the bugtracker for an already reported issue
### If you found an issue that describes your problem:
- please read other user comments first, and confirm this is the same issue: a given error condition might be indicative of different problems - you may also find a workaround in the comments
- please refrain from adding "same thing here" or "+1" comments
- you don't need to comment on an issue to get notified of updates: just hit the "subscribe" button
- comment if you have some new, technical and relevant information to add to the case
- __DO NOT__ comment on closed issues or merged PRs. If you think you have a related problem, open up a new issue and reference the PR or issue.
### If you have not found an existing issue that describes your problem:
1. create a new issue, with a succinct title that describes your issue:
- bad title: "It doesn't work with my docker"
- good title: "Private registry push fail: 400 error with E_INVALID_DIGEST"
2. copy the output of:
- `docker version`
- `docker info`
- `docker exec <registry-container> registry --version`
3. copy the command line you used to launch your Registry
4. restart your docker daemon in debug mode (add `-D` to the daemon launch arguments)
5. reproduce your problem and get your docker daemon logs showing the error
6. if relevant, copy your registry logs that show the error
7. provide any relevant detail about your specific Registry configuration (e.g., storage backend used)
8. indicate if you are using an enterprise proxy, Nginx, or anything else between you and your Registry
## Contributing a patch for a known bug, or a small correction
You should follow the basic GitHub workflow:
1. fork
2. commit a change
3. make sure the tests pass
4. PR
Additionally, you must [sign your commits](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work). It's very simple:
- configure your name with git: `git config user.name "Real Name" && git config user.email mail@example.com`
- sign your commits using `-s`: `git commit -s -m "My commit"`
Some simple rules to ensure quick merge:
- clearly point to the issue(s) you want to fix in your PR comment (e.g., `closes #12345`)
- prefer multiple (smaller) PRs addressing individual issues over a big one trying to address multiple issues at once
- if you need to amend your PR following comments, please squash instead of adding more commits
## Contributing new features
You are heavily encouraged to first discuss what you want to do. You can do so on the irc channel, or by opening an issue that clearly describes the use case you want to fulfill, or the problem you are trying to solve.
If this is a major new feature, you should then submit a proposal that describes your technical solution and reasoning.
If you did discuss it first, this will likely be greenlighted very fast. It's advisable to address all feedback on this proposal before starting actual work.
Then you should submit your implementation, clearly linking to the issue (and possible proposal).
Your PR will be reviewed by the community, then ultimately by the project maintainers, before being merged.
It's mandatory to:
- interact respectfully with other community members and maintainers - more generally, you are expected to abide by the [Docker community rules](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#docker-community-guidelines)
- address maintainers' comments and modify your submission accordingly
- write tests for any new code
Complying to these simple rules will greatly accelerate the review process, and will ensure you have a pleasant experience in contributing code to the Registry.
Have a look at a great, successful contribution: the [Swift driver PR](https://github.com/docker/distribution/pull/493)
## Coding Style
Unless explicitly stated, we follow all coding guidelines from the Go
community. While some of these standards may seem arbitrary, they somehow seem
to result in a solid, consistent codebase.
It is possible that the code base does not currently comply with these
guidelines. We are not looking for a massive PR that fixes this, since that
goes against the spirit of the guidelines. All new contributions should make a
best effort to clean up and make the code base better than they left it.
Obviously, apply your best judgement. Remember, the goal here is to make the
code base easier for humans to navigate and understand. Always keep that in
mind when nudging others to comply.
The rules:
1. All code should be formatted with `gofmt -s`.
2. All code should pass the default levels of
[`golint`](https://github.com/golang/lint).
3. All code should follow the guidelines covered in [Effective
Go](http://golang.org/doc/effective_go.html) and [Go Code Review
Comments](https://github.com/golang/go/wiki/CodeReviewComments).
4. Comment the code. Tell us the why, the history and the context.
5. Document _all_ declarations and methods, even private ones. Declare
expectations, caveats and anything else that may be important. If a type
gets exported, having the comments already there will ensure it's ready.
6. Variable name length should be proportional to its context and no longer.
`noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`.
In practice, short methods will have short variable names and globals will
have longer names.
7. No underscores in package names. If you need a compound name, step back,
and re-examine why you need a compound name. If you still think you need a
compound name, lose the underscore.
8. No utils or helpers packages. If a function is not general enough to
warrant its own package, it has not been written generally enough to be a
part of a util package. Just leave it unexported and well-documented.
9. All tests should run with `go test` and outside tooling should not be
required. No, we don't need another unit testing framework. Assertion
packages are acceptable if they provide _real_ incremental value.
10. Even though we call these "rules" above, they are actually just
guidelines. Since you've read all the rules, you now know that.
If you are having trouble getting into the mood of idiomatic Go, we recommend
reading through [Effective Go](http://golang.org/doc/effective_go.html). The
[Go Blog](http://blog.golang.org/) is also a great resource. Drinking the
kool-aid is a lot easier than going thirsty.
+21
View File
@@ -0,0 +1,21 @@
FROM golang:1.10-alpine
ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution
ENV DOCKER_BUILDTAGS include_oss include_gcs
ARG GOOS=linux
ARG GOARCH=amd64
RUN set -ex \
&& apk add --no-cache make git
WORKDIR $DISTRIBUTION_DIR
COPY . $DISTRIBUTION_DIR
COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml
RUN make PREFIX=/go clean binaries
VOLUME ["/var/lib/registry"]
EXPOSE 5000
ENTRYPOINT ["registry"]
CMD ["serve", "/etc/docker/registry/config.yml"]
+58
View File
@@ -0,0 +1,58 @@
# Distribution maintainers file
#
# This file describes who runs the docker/distribution project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"aaronlehmann",
"dmcgowan",
"dmp42",
"richardscothern",
"shykes",
"stevvooe",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.dmcgowan]
Name = "Derek McGowan"
Email = "derek@mcgstyle.net"
GitHub = "dmcgowan"
[people.dmp42]
Name = "Olivier Gambier"
Email = "olivier@docker.com"
GitHub = "dmp42"
[people.richardscothern]
Name = "Richard Scothern"
Email = "richard.scothern@gmail.com"
GitHub = "richardscothern"
[people.shykes]
Name = "Solomon Hykes"
Email = "solomon@docker.com"
GitHub = "shykes"
[people.stevvooe]
Name = "Stephen Day"
Email = "stephen.day@docker.com"
GitHub = "stevvooe"
+99
View File
@@ -0,0 +1,99 @@
# Set an output prefix, which is the local directory if not specified
PREFIX?=$(shell pwd)
# Used to populate version variable in main package.
VERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always)
# Allow turning off function inlining and variable registerization
ifeq (${DISABLE_OPTIMIZATION},true)
GO_GCFLAGS=-gcflags "-N -l"
VERSION:="$(VERSION)-noopt"
endif
GO_LDFLAGS=-ldflags "-X `go list ./version`.Version=$(VERSION)"
.PHONY: all build binaries clean dep-restore dep-save dep-validate fmt lint test test-full vet
.DEFAULT: all
all: fmt vet lint build test binaries
AUTHORS: .mailmap .git/HEAD
git log --format='%aN <%aE>' | sort -fu > $@
# This only needs to be generated by hand when cutting full releases.
version/version.go:
./version/version.sh > $@
# Required for go 1.5 to build
GO15VENDOREXPERIMENT := 1
# Go files
GOFILES=$(shell find . -type f -name '*.go')
# Package list
PKGS=$(shell go list -tags "${DOCKER_BUILDTAGS}" ./... | grep -v ^github.com/docker/distribution/vendor/)
# Resolving binary dependencies for specific targets
GOLINT=$(shell which golint || echo '')
VNDR=$(shell which vndr || echo '')
${PREFIX}/bin/registry: $(GOFILES)
@echo "+ $@"
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry
${PREFIX}/bin/digest: $(GOFILES)
@echo "+ $@"
@go build -tags "${DOCKER_BUILDTAGS}" -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/digest
${PREFIX}/bin/registry-api-descriptor-template: $(GOFILES)
@echo "+ $@"
@go build -o $@ ${GO_LDFLAGS} ${GO_GCFLAGS} ./cmd/registry-api-descriptor-template
docs/spec/api.md: docs/spec/api.md.tmpl ${PREFIX}/bin/registry-api-descriptor-template
./bin/registry-api-descriptor-template $< > $@
vet:
@echo "+ $@"
@go vet -tags "${DOCKER_BUILDTAGS}" $(PKGS)
fmt:
@echo "+ $@"
@test -z "$$(gofmt -s -l . 2>&1 | grep -v ^vendor/ | tee /dev/stderr)" || \
(echo >&2 "+ please format Go code with 'gofmt -s'" && false)
lint:
@echo "+ $@"
$(if $(GOLINT), , \
$(error Please install golint: `go get -u github.com/golang/lint/golint`))
@test -z "$$($(GOLINT) ./... 2>&1 | grep -v ^vendor/ | tee /dev/stderr)"
build:
@echo "+ $@"
@go build -tags "${DOCKER_BUILDTAGS}" -v ${GO_LDFLAGS} $(PKGS)
test:
@echo "+ $@"
@go test -test.short -tags "${DOCKER_BUILDTAGS}" $(PKGS)
test-full:
@echo "+ $@"
@go test -tags "${DOCKER_BUILDTAGS}" $(PKGS)
binaries: ${PREFIX}/bin/registry ${PREFIX}/bin/digest ${PREFIX}/bin/registry-api-descriptor-template
@echo "+ $@"
clean:
@echo "+ $@"
@rm -rf "${PREFIX}/bin/registry" "${PREFIX}/bin/digest" "${PREFIX}/bin/registry-api-descriptor-template"
dep-validate:
@echo "+ $@"
$(if $(VNDR), , \
$(error Please install vndr: go get github.com/lk4d4/vndr))
@rm -Rf .vendor.bak
@mv vendor .vendor.bak
@$(VNDR)
@test -z "$$(diff -r vendor .vendor.bak 2>&1 | tee /dev/stderr)" || \
(echo >&2 "+ inconsistent dependencies! what you have in vendor.conf does not match with what you have in vendor" && false)
@rm -Rf vendor
@mv .vendor.bak vendor
+130
View File
@@ -0,0 +1,130 @@
# Distribution
The Docker toolset to pack, ship, store, and deliver content.
This repository's main product is the Docker Registry 2.0 implementation
for storing and distributing Docker images. It supersedes the
[docker/docker-registry](https://github.com/docker/docker-registry)
project with a new API design, focused around security and performance.
<img src="https://www.docker.com/sites/default/files/oyster-registry-3.png" width=200px/>
[![Circle CI](https://circleci.com/gh/docker/distribution/tree/master.svg?style=svg)](https://circleci.com/gh/docker/distribution/tree/master)
[![GoDoc](https://godoc.org/github.com/docker/distribution?status.svg)](https://godoc.org/github.com/docker/distribution)
This repository contains the following components:
|**Component** |Description |
|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **registry** | An implementation of the [Docker Registry HTTP API V2](docs/spec/api.md) for use with docker 1.6+. |
| **libraries** | A rich set of libraries for interacting with distribution components. Please see [godoc](https://godoc.org/github.com/docker/distribution) for details. **Note**: These libraries are **unstable**. |
| **specifications** | _Distribution_ related specifications are available in [docs/spec](docs/spec) |
| **documentation** | Docker's full documentation set is available at [docs.docker.com](https://docs.docker.com). This repository [contains the subset](docs/) related just to the registry. |
### How does this integrate with Docker engine?
This project should provide an implementation to a V2 API for use in the [Docker
core project](https://github.com/docker/docker). The API should be embeddable
and simplify the process of securely pulling and pushing content from `docker`
daemons.
### What are the long term goals of the Distribution project?
The _Distribution_ project has the further long term goal of providing a
secure tool chain for distributing content. The specifications, APIs and tools
should be as useful with Docker as they are without.
Our goal is to design a professional grade and extensible content distribution
system that allow users to:
* Enjoy an efficient, secured and reliable way to store, manage, package and
exchange content
* Hack/roll their own on top of healthy open-source components
* Implement their own home made solution through good specs, and solid
extensions mechanism.
## More about Registry 2.0
The new registry implementation provides the following benefits:
- faster push and pull
- new, more efficient implementation
- simplified deployment
- pluggable storage backend
- webhook notifications
For information on upcoming functionality, please see [ROADMAP.md](ROADMAP.md).
### Who needs to deploy a registry?
By default, Docker users pull images from Docker's public registry instance.
[Installing Docker](https://docs.docker.com/engine/installation/) gives users this
ability. Users can also push images to a repository on Docker's public registry,
if they have a [Docker Hub](https://hub.docker.com/) account.
For some users and even companies, this default behavior is sufficient. For
others, it is not.
For example, users with their own software products may want to maintain a
registry for private, company images. Also, you may wish to deploy your own
image repository for images used to test or in continuous integration. For these
use cases and others, [deploying your own registry instance](https://github.com/docker/docker.github.io/blob/master/registry/deploying.md)
may be the better choice.
### Migration to Registry 2.0
For those who have previously deployed their own registry based on the Registry
1.0 implementation and wish to deploy a Registry 2.0 while retaining images,
data migration is required. A tool to assist with migration efforts has been
created. For more information see [docker/migrator](https://github.com/docker/migrator).
## Contribute
Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute
issues, fixes, and patches to this project. If you are contributing code, see
the instructions for [building a development environment](BUILDING.md).
## Support
If any issues are encountered while using the _Distribution_ project, several
avenues are available for support:
<table>
<tr>
<th align="left">
IRC
</th>
<td>
#docker-distribution on FreeNode
</td>
</tr>
<tr>
<th align="left">
Issue Tracker
</th>
<td>
github.com/docker/distribution/issues
</td>
</tr>
<tr>
<th align="left">
Google Groups
</th>
<td>
https://groups.google.com/a/dockerproject.org/forum/#!forum/distribution
</td>
</tr>
<tr>
<th align="left">
Mailing List
</th>
<td>
docker@dockerproject.org
</td>
</tr>
</table>
## License
This project is distributed under [Apache License, Version 2.0](LICENSE).
+44
View File
@@ -0,0 +1,44 @@
## Registry Release Checklist
10. Compile release notes detailing features and since the last release.
Update the `CHANGELOG.md` file and create a PR to master with the updates.
Once that PR has been approved by maintainers the change may be cherry-picked
to the release branch (new release branches may be forked from this commit).
20. Update the version file: `https://github.com/docker/distribution/blob/master/version/version.go`
30. Update the `MAINTAINERS` (if necessary), `AUTHORS` and `.mailmap` files.
```
make AUTHORS
```
40. Create a signed tag.
Distribution uses semantic versioning. Tags are of the format
`vx.y.z[-rcn]`. You will need PGP installed and a PGP key which has been added
to your Github account. The comment for the tag should include the release
notes, use previous tags as a guide for formatting consistently. Run
`git tag -s vx.y.z[-rcn]` to create tag and `git -v vx.y.z[-rcn]` to verify tag,
check comment and correct commit hash.
50. Push the signed tag
60. Create a new [release](https://github.com/docker/distribution/releases). In the case of a release candidate, tick the `pre-release` checkbox.
70. Update the registry binary in [distribution library image repo](https://github.com/docker/distribution-library-image) by running the update script and opening a pull request.
80. Update the official image. Add the new version in the [official images repo](https://github.com/docker-library/official-images) by appending a new version to the `registry/registry` file with the git hash pointed to by the signed tag. Update the major version to point to the latest version and the minor version to point to new patch release if necessary.
e.g. to release `2.3.1`
`2.3.1 (new)`
`2.3.0 -> 2.3.0` can be removed
`2 -> 2.3.1`
`2.3 -> 2.3.1`
90. Build a new distribution/registry image on [Docker hub](https://hub.docker.com/u/distribution/dashboard) by adding a new automated build with the new tag and re-building the images.
+267
View File
@@ -0,0 +1,267 @@
# Roadmap
The Distribution Project consists of several components, some of which are
still being defined. This document defines the high-level goals of the
project, identifies the current components, and defines the release-
relationship to the Docker Platform.
* [Distribution Goals](#distribution-goals)
* [Distribution Components](#distribution-components)
* [Project Planning](#project-planning): release-relationship to the Docker Platform.
This road map is a living document, providing an overview of the goals and
considerations made in respect of the future of the project.
## Distribution Goals
- Replace the existing [docker registry](github.com/docker/docker-registry)
implementation as the primary implementation.
- Replace the existing push and pull code in the docker engine with the
distribution package.
- Define a strong data model for distributing docker images
- Provide a flexible distribution tool kit for use in the docker platform
- Unlock new distribution models
## Distribution Components
Components of the Distribution Project are managed via github [milestones](https://github.com/docker/distribution/milestones). Upcoming
features and bugfixes for a component will be added to the relevant milestone. If a feature or
bugfix is not part of a milestone, it is currently unscheduled for
implementation.
* [Registry](#registry)
* [Distribution Package](#distribution-package)
***
### Registry
The new Docker registry is the main portion of the distribution repository.
Registry 2.0 is the first release of the next-generation registry. This was
primarily focused on implementing the [new registry
API](https://github.com/docker/distribution/blob/master/docs/spec/api.md),
with a focus on security and performance.
Following from the Distribution project goals above, we have a set of goals
for registry v2 that we would like to follow in the design. New features
should be compared against these goals.
#### Data Storage and Distribution First
The registry's first goal is to provide a reliable, consistent storage
location for Docker images. The registry should only provide the minimal
amount of indexing required to fetch image data and no more.
This means we should be selective in new features and API additions, including
those that may require expensive, ever growing indexes. Requests should be
servable in "constant time".
#### Content Addressability
All data objects used in the registry API should be content addressable.
Content identifiers should be secure and verifiable. This provides a secure,
reliable base from which to build more advanced content distribution systems.
#### Content Agnostic
In the past, changes to the image format would require large changes in Docker
and the Registry. By decoupling the distribution and image format, we can
allow the formats to progress without having to coordinate between the two.
This means that we should be focused on decoupling Docker from the registry
just as much as decoupling the registry from Docker. Such an approach will
allow us to unlock new distribution models that haven't been possible before.
We can take this further by saying that the new registry should be content
agnostic. The registry provides a model of names, tags, manifests and content
addresses and that model can be used to work with content.
#### Simplicity
The new registry should be closer to a microservice component than its
predecessor. This means it should have a narrower API and a low number of
service dependencies. It should be easy to deploy.
This means that other solutions should be explored before changing the API or
adding extra dependencies. If functionality is required, can it be added as an
extension or companion service.
#### Extensibility
The registry should provide extension points to add functionality. By keeping
the scope narrow, but providing the ability to add functionality.
Features like search, indexing, synchronization and registry explorers fall
into this category. No such feature should be added unless we've found it
impossible to do through an extension.
#### Active Feature Discussions
The following are feature discussions that are currently active.
If you don't see your favorite, unimplemented feature, feel free to contact us
via IRC or the mailing list and we can talk about adding it. The goal here is
to make sure that new features go through a rigid design process before
landing in the registry.
##### Proxying to other Registries
A _pull-through caching_ mode exists for the registry, but is restricted from
within the docker client to only mirror the official Docker Hub. This functionality
can be expanded when image provenance has been specified and implemented in the
distribution project.
##### Metadata storage
Metadata for the registry is currently stored with the manifest and layer data on
the storage backend. While this is a big win for simplicity and reliably maintaining
state, it comes with the cost of consistency and high latency. The mutable registry
metadata operations should be abstracted behind an API which will allow ACID compliant
storage systems to handle metadata.
##### Peer to Peer transfer
Discussion has started here: https://docs.google.com/document/d/1rYDpSpJiQWmCQy8Cuiaa3NH-Co33oK_SC9HeXYo87QA/edit
##### Indexing, Search and Discovery
The original registry provided some implementation of search for use with
private registries. Support has been elided from V2 since we'd like to both
decouple search functionality from the registry. The makes the registry
simpler to deploy, especially in use cases where search is not needed, and
let's us decouple the image format from the registry.
There are explorations into using the catalog API and notification system to
build external indexes. The current line of thought is that we will define a
common search API to index and query docker images. Such a system could be run
as a companion to a registry or set of registries to power discovery.
The main issue with search and discovery is that there are so many ways to
accomplish it. There are two aspects to this project. The first is deciding on
how it will be done, including an API definition that can work with changing
data formats. The second is the process of integrating with `docker search`.
We expect that someone attempts to address the problem with the existing tools
and propose it as a standard search API or uses it to inform a standardization
process. Once this has been explored, we integrate with the docker client.
Please see the following for more detail:
- https://github.com/docker/distribution/issues/206
##### Deletes
> __NOTE:__ Deletes are a much asked for feature. Before requesting this
feature or participating in discussion, we ask that you read this section in
full and understand the problems behind deletes.
While, at first glance, implementing deleting seems simple, there are a number
mitigating factors that make many solutions not ideal or even pathological in
the context of a registry. The following paragraph discuss the background and
approaches that could be applied to arrive at a solution.
The goal of deletes in any system is to remove unused or unneeded data. Only
data requested for deletion should be removed and no other data. Removing
unintended data is worse than _not_ removing data that was requested for
removal but ideally, both are supported. Generally, according to this rule, we
err on holding data longer than needed, ensuring that it is only removed when
we can be certain that it can be removed. With the current behavior, we opt to
hold onto the data forever, ensuring that data cannot be incorrectly removed.
To understand the problems with implementing deletes, one must understand the
data model. All registry data is stored in a filesystem layout, implemented on
a "storage driver", effectively a _virtual file system_ (VFS). The storage
system must assume that this VFS layer will be eventually consistent and has
poor read- after-write consistency, since this is the lower common denominator
among the storage drivers. This is mitigated by writing values in reverse-
dependent order, but makes wider transactional operations unsafe.
Layered on the VFS model is a content-addressable _directed, acyclic graph_
(DAG) made up of blobs. Manifests reference layers. Tags reference manifests.
Since the same data can be referenced by multiple manifests, we only store
data once, even if it is in different repositories. Thus, we have a set of
blobs, referenced by tags and manifests. If we want to delete a blob we need
to be certain that it is no longer referenced by another manifest or tag. When
we delete a manifest, we also can try to delete the referenced blobs. Deciding
whether or not a blob has an active reference is the crux of the problem.
Conceptually, deleting a manifest and its resources is quite simple. Just find
all the manifests, enumerate the referenced blobs and delete the blobs not in
that set. An astute observer will recognize this as a garbage collection
problem. As with garbage collection in programming languages, this is very
simple when one always has a consistent view. When one adds parallelism and an
inconsistent view of data, it becomes very challenging.
A simple example can demonstrate this. Let's say we are deleting a manifest
_A_ in one process. We scan the manifest and decide that all the blobs are
ready for deletion. Concurrently, we have another process accepting a new
manifest _B_ referencing one or more blobs from the manifest _A_. Manifest _B_
is accepted and all the blobs are considered present, so the operation
proceeds. The original process then deletes the referenced blobs, assuming
they were unreferenced. The manifest _B_, which we thought had all of its data
present, can no longer be served by the registry, since the dependent data has
been deleted.
Deleting data from the registry safely requires some way to coordinate this
operation. The following approaches are being considered:
- _Reference Counting_ - Maintain a count of references to each blob. This is
challenging for a number of reasons: 1. maintaining a consistent consensus
of reference counts across a set of Registries and 2. Building the initial
list of reference counts for an existing registry. These challenges can be
met with a consensus protocol like Paxos or Raft in the first case and a
necessary but simple scan in the second..
- _Lock the World GC_ - Halt all writes to the data store. Walk the data store
and find all blob references. Delete all unreferenced blobs. This approach
is very simple but requires disabling writes for a period of time while the
service reads all data. This is slow and expensive but very accurate and
effective.
- _Generational GC_ - Do something similar to above but instead of blocking
writes, writes are sent to another storage backend while reads are broadcast
to the new and old backends. GC is then performed on the read-only portion.
Because writes land in the new backend, the data in the read-only section
can be safely deleted. The main drawbacks of this approach are complexity
and coordination.
- _Centralized Oracle_ - Using a centralized, transactional database, we can
know exactly which data is referenced at any given time. This avoids
coordination problem by managing this data in a single location. We trade
off metadata scalability for simplicity and performance. This is a very good
option for most registry deployments. This would create a bottleneck for
registry metadata. However, metadata is generally not the main bottleneck
when serving images.
Please let us know if other solutions exist that we have yet to enumerate.
Note that for any approach, implementation is a massive consideration. For
example, a mark-sweep based solution may seem simple but the amount of work in
coordination offset the extra work it might take to build a _Centralized
Oracle_. We'll accept proposals for any solution but please coordinate with us
before dropping code.
At this time, we have traded off simplicity and ease of deployment for disk
space. Simplicity and ease of deployment tend to reduce developer involvement,
which is currently the most expensive resource in software engineering. Taking
on any solution for deletes will greatly effect these factors, trading off
very cheap disk space for a complex deployment and operational story.
Please see the following issues for more detail:
- https://github.com/docker/distribution/issues/422
- https://github.com/docker/distribution/issues/461
- https://github.com/docker/distribution/issues/462
### Distribution Package
At its core, the Distribution Project is a set of Go packages that make up
Distribution Components. At this time, most of these packages make up the
Registry implementation.
The package itself is considered unstable. If you're using it, please take care to vendor the dependent version.
For feature additions, please see the Registry section. In the future, we may break out a
separate Roadmap for distribution-specific features that apply to more than
just the registry.
***
### Project Planning
An [Open-Source Planning Process](https://github.com/docker/distribution/wiki/Open-Source-Planning-Process) is used to define the Roadmap. [Project Pages](https://github.com/docker/distribution/wiki) define the goals for each Milestone and identify current progress.
+94
View File
@@ -0,0 +1,94 @@
# Pony-up!
machine:
pre:
# Install gvm
- bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/1.0.22/binscripts/gvm-installer)
# Install codecov for coverage
- pip install --user codecov
post:
# go
- gvm install go1.10 --prefer-binary --name=stable
environment:
# Convenient shortcuts to "common" locations
CHECKOUT: /home/ubuntu/$CIRCLE_PROJECT_REPONAME
BASE_DIR: src/github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
# Trick circle brainflat "no absolute path" behavior
BASE_STABLE: ../../../$HOME/.gvm/pkgsets/stable/global/$BASE_DIR
DOCKER_BUILDTAGS: "include_oss include_gcs"
# Workaround Circle parsing dumb bugs and/or YAML wonkyness
CIRCLE_PAIN: "mode: set"
hosts:
# Not used yet
fancy: 127.0.0.1
dependencies:
pre:
# Copy the code to the gopath of all go versions
- >
gvm use stable &&
mkdir -p "$(dirname $BASE_STABLE)" &&
cp -R "$CHECKOUT" "$BASE_STABLE"
override:
# Install dependencies for every copied clone/go version
- gvm use stable && go get github.com/lk4d4/vndr:
pwd: $BASE_STABLE
post:
# For the stable go version, additionally install linting tools
- >
gvm use stable &&
go get github.com/axw/gocov/gocov github.com/golang/lint/golint
test:
pre:
# Output the go versions we are going to test
# - gvm use old && go version
- gvm use stable && go version
# Ensure validation of dependencies
- git fetch origin:
pwd: $BASE_STABLE
- gvm use stable && if test -n "`git diff --stat=1000 origin/master | grep -E \"^[[:space:]]*vendor\"`"; then make dep-validate; fi:
pwd: $BASE_STABLE
# First thing: build everything. This will catch compile errors, and it's
# also necessary for go vet to work properly (see #807).
- gvm use stable && go install $(go list ./... | grep -v "/vendor/"):
pwd: $BASE_STABLE
# FMT
- gvm use stable && make fmt:
pwd: $BASE_STABLE
# VET
- gvm use stable && make vet:
pwd: $BASE_STABLE
# LINT
- gvm use stable && make lint:
pwd: $BASE_STABLE
override:
# Test stable, and report
- gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; go test -tags "$DOCKER_BUILDTAGS" -test.short -coverprofile=$GOPATH/src/$PACKAGE/coverage.out -coverpkg=$(./coverpkg.sh $PACKAGE $ROOT_PACKAGE) $PACKAGE':
timeout: 1000
pwd: $BASE_STABLE
# Test stable with race
- gvm use stable; export ROOT_PACKAGE=$(go list .); go list -tags "$DOCKER_BUILDTAGS" ./... | grep -v "/vendor/" | grep -v "registry/handlers" | grep -v "registry/storage/driver" | xargs -L 1 -I{} bash -c 'export PACKAGE={}; go test -race -tags "$DOCKER_BUILDTAGS" -test.short $PACKAGE':
timeout: 1000
pwd: $BASE_STABLE
post:
# Report to codecov
- bash <(curl -s https://codecov.io/bash):
pwd: $BASE_STABLE
## Notes
# Do we want these as well?
# - go get code.google.com/p/go.tools/cmd/goimports
# - test -z "$(goimports -l -w ./... | tee /dev/stderr)"
# http://labix.org/gocheck
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Given a subpackage and the containing package, figures out which packages
# need to be passed to `go test -coverpkg`: this includes all of the
# subpackage's dependencies within the containing package, as well as the
# subpackage itself.
DEPENDENCIES="$(go list -f $'{{range $f := .Deps}}{{$f}}\n{{end}}' ${1} | grep ${2} | grep -v github.com/docker/distribution/vendor)"
echo "${1} ${DEPENDENCIES}" | xargs echo -n | tr ' ' ','
+52
View File
@@ -0,0 +1,52 @@
github.com/Azure/azure-sdk-for-go 4650843026a7fdec254a8d9cf893693a254edd0b
github.com/Azure/go-autorest eaa7994b2278094c904d31993d26f56324db3052
github.com/sirupsen/logrus 3d4380f53a34dcdc95f0c1db702615992b38d9a4
github.com/aws/aws-sdk-go 5bcc0a238d880469f949fc7cd24e35f32ab80cbd
github.com/bshuster-repo/logrus-logstash-hook d2c0ecc1836d91814e15e23bb5dc309c3ef51f4a
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/bugsnag/bugsnag-go b1d153021fcd90ca3f080db36bec96dc690fb274
github.com/bugsnag/osext 0dd3f918b21bec95ace9dc86c7e70266cfc5c702
github.com/bugsnag/panicwrap e2c28503fcd0675329da73bf48b33404db873782
github.com/denverdino/aliyungo afedced274aa9a7fcdd47ac97018f0f8db4e5de2
github.com/dgrijalva/jwt-go a601269ab70c205d26370c16f7c81e9017c14e04
github.com/docker/go-metrics 399ea8c73916000c64c2c76e8da00ca82f8387ab
github.com/docker/goamz f0a21f5b2e12f83a505ecf79b633bb2035cf6f85
github.com/docker/libtrust fa567046d9b14f6aa788882a950d69651d230b21
github.com/garyburd/redigo 535138d7bcd717d6531c701ef5933d98b1866257
github.com/go-ini/ini 2ba15ac2dc9cdf88c110ec2dc0ced7fa45f5678c
github.com/golang/protobuf 8d92cf5fc15a4382f8964b08e1f42a75c0591aa3
github.com/gorilla/handlers 60c7bfde3e33c201519a200a4507a158cc03a17b
github.com/gorilla/mux 599cba5e7b6137d46ddf58fb1765f5d928e69604
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d
github.com/marstr/guid 8bd9a64bf37eb297b492a4101fb28e80ac0b290f
github.com/satori/go.uuid f58768cc1a7a7e77a3bd49e98cdd21419399b6a3
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
github.com/miekg/dns 271c58e0c14f552178ea321a545ff9af38930f39
github.com/mitchellh/mapstructure 482a9fd5fa83e8c4e7817413b80f3eb8feec03ef
github.com/ncw/swift b964f2ca856aac39885e258ad25aec08d5f64ee6
github.com/prometheus/client_golang c332b6f63c0658a65eca15c0e5247ded801cf564
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
github.com/spf13/cobra 312092086bed4968099259622145a0c9ae280064
github.com/spf13/pflag 5644820622454e71517561946e3d94b9f9db6842
github.com/stevvooe/resumable 2aaf90b2ceea5072cb503ef2a620b08ff3119870
github.com/xenolf/lego a9d8cec0e6563575e5868a005359ac97911b5985
github.com/yvasiyarov/go-metrics 57bccd1ccd43f94bb17fdd8bf3007059b802f85e
github.com/yvasiyarov/gorelic a9bba5b9ab508a086f9a12b8c51fab68478e2128
github.com/yvasiyarov/newrelic_platform_go b21fdbd4370f3717f3bbd2bf41c223bc273068e6
golang.org/x/crypto c10c31b5e94b6f7a0283272dc2bb27163dcea24b
golang.org/x/net 4876518f9e71663000c348837735820161a42df7
golang.org/x/oauth2 045497edb6234273d67dbc25da3f2ddbc4c4cacf
golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb
google.golang.org/api 9bf6e6e569ff057f75d9604a46c52928f17d2b54
google.golang.org/appengine 12d5545dc1cfa6047a286d5e853841b6471f4c19
google.golang.org/cloud 975617b05ea8a58727e6c1a06b6161ff4185a9f2
google.golang.org/grpc d3ddb4469d5a1b949fc7a7da7c1d6a0d1b6de994
gopkg.in/check.v1 64131543e7896d5bcc6bd5a76287eb75ea96c673
gopkg.in/square/go-jose.v1 40d457b439244b546f023d056628e5184136899b
gopkg.in/yaml.v2 bef53efd0c76e49e6de55ead051f886bea7e9420
rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git
github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb
github.com/opencontainers/image-spec ab7389ef9f50030c9b245bc16b981c7ddf192882
+42
View File
@@ -0,0 +1,42 @@
# Working on the Engine API
The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon.
It consists of various components in this repository:
- `api/swagger.yaml` A Swagger definition of the API.
- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this.
- `cli/` The command-line client.
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
- `daemon/` The daemon, which serves the API.
## Swagger definition
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
1. Automatically generate documentation.
2. Automatically generate the Go server and client. (A work-in-progress.)
3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc.
## Updating the API documentation
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation.
The file is split into two main sections:
- `definitions`, which defines re-usable objects used in requests and responses
- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable)
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919).
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing.
## Viewing the API documentation
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
+12
View File
@@ -0,0 +1,12 @@
layout:
models:
- name: definition
source: asset:model
target: "{{ joinFilePath .Target .ModelPackage }}"
file_name: "{{ (snakize (pascalize .Name)) }}.go"
operations:
- name: handler
source: asset:serverOperation
target: "{{ joinFilePath .Target .APIPackage .Package }}"
file_name: "{{ (snakize (pascalize .Name)) }}.go"
+10122
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
syntax = "proto3";
message LogEntry {
string source = 1;
int64 time_nano = 2;
bytes line = 3;
bool partial = 4;
}
+20
View File
@@ -0,0 +1,20 @@
syntax = "proto3";
option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime";
// PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime.
message PluginSpec {
string name = 1;
string remote = 2;
repeated PluginPrivilege privileges = 3;
bool disabled = 4;
}
// PluginPrivilege describes a permission the user has to accept
// upon installing a plugin.
message PluginPrivilege {
string name = 1;
string description = 2;
repeated string value = 3;
}
+14
View File
@@ -0,0 +1,14 @@
# Legacy API type versions
This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
## Package name conventions
The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.
+232
View File
@@ -0,0 +1,232 @@
A|hello | hello
A|he'll'o | hello
A|he'llo | error
A|he\'llo | he'llo
A|he\\'llo | error
A|abc\tdef | abctdef
A|"abc\tdef" | abc\tdef
A|"abc\\tdef" | abc\tdef
A|'abc\tdef' | abc\tdef
A|hello\ | hello
A|hello\\ | hello\
A|"hello | error
A|"hello\" | error
A|"hel'lo" | hel'lo
A|'hello | error
A|'hello\' | hello\
A|'hello\there' | hello\there
A|'hello\\there' | hello\\there
A|"''" | ''
A|$. | $.
A|he$1x | hex
A|he$.x | he$.x
# Next one is different on Windows as $pwd==$PWD
U|he$pwd. | he.
W|he$pwd. | he/home.
A|he$PWD | he/home
A|he\$PWD | he$PWD
A|he\\$PWD | he\/home
A|"he\$PWD" | he$PWD
A|"he\\$PWD" | he\/home
A|\${} | ${}
A|\${}aaa | ${}aaa
A|he\${} | he${}
A|he\${}xx | he${}xx
A|${} | error
A|${}aaa | error
A|he${} | error
A|he${}xx | error
A|he${hi} | he
A|he${hi}xx | hexx
A|he${PWD} | he/home
A|he${.} | error
A|he${XXX:-000}xx | he000xx
A|he${PWD:-000}xx | he/homexx
A|he${XXX:-$PWD}xx | he/homexx
A|he${XXX:-${PWD:-yyy}}xx | he/homexx
A|he${XXX:-${YYY:-yyy}}xx | heyyyxx
A|he${XXX:YYY} | error
A|he${XXX:+${PWD}}xx | hexx
A|he${PWD:+${XXX}}xx | hexx
A|he${PWD:+${SHELL}}xx | hebashxx
A|he${XXX:+000}xx | hexx
A|he${PWD:+000}xx | he000xx
A|'he${XX}' | he${XX}
A|"he${PWD}" | he/home
A|"he'$PWD'" | he'/home'
A|"$PWD" | /home
A|'$PWD' | $PWD
A|'\$PWD' | \$PWD
A|'"hello"' | "hello"
A|he\$PWD | he$PWD
A|"he\$PWD" | he$PWD
A|'he\$PWD' | he\$PWD
A|he${PWD | error
A|he${PWD:=000}xx | error
A|he${PWD:+${PWD}:}xx | he/home:xx
A|he${XXX:-\$PWD:}xx | he$PWD:xx
A|he${XXX:-\${PWD}z}xx | he${PWDz}xx
A|안녕하세요 | 안녕하세요
A|안'녕'하세요 | 안녕하세요
A|안'녕하세요 | error
A|안녕\'하세요 | 안녕'하세요
A|안\\'녕하세요 | error
A|안녕\t하세요 | 안녕t하세요
A|"안녕\t하세요" | 안녕\t하세요
A|'안녕\t하세요 | error
A|안녕하세요\ | 안녕하세요
A|안녕하세요\\ | 안녕하세요\
A|"안녕하세요 | error
A|"안녕하세요\" | error
A|"안녕'하세요" | 안녕'하세요
A|'안녕하세요 | error
A|'안녕하세요\' | 안녕하세요\
A|안녕$1x | 안녕x
A|안녕$.x | 안녕$.x
# Next one is different on Windows as $pwd==$PWD
U|안녕$pwd. | 안녕.
W|안녕$pwd. | 안녕/home.
A|안녕$PWD | 안녕/home
A|안녕\$PWD | 안녕$PWD
A|안녕\\$PWD | 안녕\/home
A|안녕\${} | 안녕${}
A|안녕\${}xx | 안녕${}xx
A|안녕${} | error
A|안녕${}xx | error
A|안녕${hi} | 안녕
A|안녕${hi}xx | 안녕xx
A|안녕${PWD} | 안녕/home
A|안녕${.} | error
A|안녕${XXX:-000}xx | 안녕000xx
A|안녕${PWD:-000}xx | 안녕/homexx
A|안녕${XXX:-$PWD}xx | 안녕/homexx
A|안녕${XXX:-${PWD:-yyy}}xx | 안녕/homexx
A|안녕${XXX:-${YYY:-yyy}}xx | 안녕yyyxx
A|안녕${XXX:YYY} | error
A|안녕${XXX:+${PWD}}xx | 안녕xx
A|안녕${PWD:+${XXX}}xx | 안녕xx
A|안녕${PWD:+${SHELL}}xx | 안녕bashxx
A|안녕${XXX:+000}xx | 안녕xx
A|안녕${PWD:+000}xx | 안녕000xx
A|'안녕${XX}' | 안녕${XX}
A|"안녕${PWD}" | 안녕/home
A|"안녕'$PWD'" | 안녕'/home'
A|'"안녕"' | "안녕"
A|안녕\$PWD | 안녕$PWD
A|"안녕\$PWD" | 안녕$PWD
A|'안녕\$PWD' | 안녕\$PWD
A|안녕${PWD | error
A|안녕${PWD:=000}xx | error
A|안녕${PWD:+${PWD}:}xx | 안녕/home:xx
A|안녕${XXX:-\$PWD:}xx | 안녕$PWD:xx
A|안녕${XXX:-\${PWD}z}xx | 안녕${PWDz}xx
A|$KOREAN | 한국어
A|안녕$KOREAN | 안녕한국어
A|${{aaa} | error
A|${aaa}} | }
A|${aaa | error
A|${{aaa:-bbb} | error
A|${aaa:-bbb}} | bbb}
A|${aaa:-bbb | error
A|${aaa:-bbb} | bbb
A|${aaa:-${bbb:-ccc}} | ccc
A|${aaa:-bbb ${foo} | error
A|${aaa:-bbb {foo} | bbb {foo
A|${:} | error
A|${:-bbb} | error
A|${:+bbb} | error
# Positional parameters won't be set:
# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_05_01
A|$1 |
A|${1} |
A|${1:+bbb} |
A|${1:-bbb} | bbb
A|$2 |
A|${2} |
A|${2:+bbb} |
A|${2:-bbb} | bbb
A|$3 |
A|${3} |
A|${3:+bbb} |
A|${3:-bbb} | bbb
A|$4 |
A|${4} |
A|${4:+bbb} |
A|${4:-bbb} | bbb
A|$5 |
A|${5} |
A|${5:+bbb} |
A|${5:-bbb} | bbb
A|$6 |
A|${6} |
A|${6:+bbb} |
A|${6:-bbb} | bbb
A|$7 |
A|${7} |
A|${7:+bbb} |
A|${7:-bbb} | bbb
A|$8 |
A|${8} |
A|${8:+bbb} |
A|${8:-bbb} | bbb
A|$9 |
A|${9} |
A|${9:+bbb} |
A|${9:-bbb} | bbb
A|$999 |
A|${999} |
A|${999:+bbb} |
A|${999:-bbb} | bbb
A|$999aaa | aaa
A|${999}aaa | aaa
A|${999:+bbb}aaa | aaa
A|${999:-bbb}aaa | bbbaaa
A|$001 |
A|${001} |
A|${001:+bbb} |
A|${001:-bbb} | bbb
A|$001aaa | aaa
A|${001}aaa | aaa
A|${001:+bbb}aaa | aaa
A|${001:-bbb}aaa | bbbaaa
# Special parameters won't be set in the Dockerfile:
# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_05_02
A|$@ |
A|${@} |
A|${@:+bbb} |
A|${@:-bbb} | bbb
A|$@@@ | @@
A|$@aaa | aaa
A|${@}aaa | aaa
A|${@:+bbb}aaa | aaa
A|${@:-bbb}aaa | bbbaaa
A|$* |
A|${*} |
A|${*:+bbb} |
A|${*:-bbb} | bbb
A|$# |
A|${#} |
A|${#:+bbb} |
A|${#:-bbb} | bbb
A|$? |
A|${?} |
A|${?:+bbb} |
A|${?:-bbb} | bbb
A|$- |
A|${-} |
A|${-:+bbb} |
A|${-:-bbb} | bbb
A|$$ |
A|${$} |
A|${$:+bbb} |
A|${$:-bbb} | bbb
A|$! |
A|${!} |
A|${!:+bbb} |
A|${!:-bbb} | bbb
A|$0 |
A|${0} |
A|${0:+bbb} |
A|${0:-bbb} | bbb
+30
View File
@@ -0,0 +1,30 @@
hello | hello
hello${hi}bye | hellobye
ENV hi=hi
hello${hi}bye | hellohibye
ENV space=abc def
hello${space}bye | helloabc,defbye
hello"${space}"bye | helloabc defbye
hello "${space}"bye | hello,abc defbye
ENV leading= ab c
hello${leading}def | hello,ab,cdef
hello"${leading}" def | hello ab c,def
hello"${leading}" | hello ab c
hello${leading} | hello,ab,c
# next line MUST have 3 trailing spaces, don't erase them!
ENV trailing=ab c
hello${trailing} | helloab,c
hello${trailing}d | helloab,c,d
hello"${trailing}"d | helloab c d
# next line MUST have 3 trailing spaces, don't erase them!
hel"lo${trailing}" | helloab c
hello" there " | hello there
hello there | hello,there
hello\ there | hello there
hello" there | error
hello\" there | hello",there
hello"\\there" | hello\there
hello"\there" | hello\there
hello'\\there' | hello\\there
hello'\there' | hello\there
hello'$there' | hello$there
+7
View File
@@ -0,0 +1,7 @@
syntax = "proto3";
package remotecontext; // no namespace because only used internally
message TarsumBackup {
map<string, string> Hashes = 1;
}
+35
View File
@@ -0,0 +1,35 @@
# Go client for the Docker Engine API
The `docker` command uses this package to communicate with the daemon. It can also be used by your own Go applications to do anything the command-line interface does – running containers, pulling images, managing swarms, etc.
For example, to list running containers (the equivalent of `docker ps`):
```go
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func main() {
cli, err := client.NewEnvClient()
if err != nil {
panic(err)
}
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
}
}
```
[Full documentation is available on GoDoc.](https://godoc.org/github.com/docker/docker/client)
-22
View File
@@ -1,22 +0,0 @@
Copyright (c) 2013 Honza Pokorny
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$(readlink -f "$BASH_SOURCE")")/.."
# see also ".mailmap" for how email addresses and names are deduplicated
{
cat <<-'EOH'
# This file lists all individuals having contributed content to the repository.
# For how it is generated, see `hack/generate-authors.sh`.
EOH
echo
git log --format='%aN <%aE>' | LC_ALL=C.UTF-8 sort -uf
} > AUTHORS
@@ -1 +0,0 @@
../../../integration/testdata/https/ca.pem
@@ -1 +0,0 @@
../../../integration/testdata/https/client-cert.pem
@@ -1 +0,0 @@
../../../integration/testdata/https/client-key.pem
@@ -1 +0,0 @@
../../../integration/testdata/https/server-cert.pem
@@ -1 +0,0 @@
../../../integration/testdata/https/server-key.pem
+1
View File
@@ -0,0 +1 @@
This code provides helper functions for dealing with archive files.
-97
View File
@@ -1,97 +0,0 @@
// +build ignore
// Simple tool to create an archive stream from an old and new directory
//
// By default it will stream the comparison of two temporary directories with junk files
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path"
"github.com/docker/docker/pkg/archive"
"github.com/sirupsen/logrus"
)
var (
flDebug = flag.Bool("D", false, "debugging output")
flNewDir = flag.String("newdir", "", "")
flOldDir = flag.String("olddir", "", "")
log = logrus.New()
)
func main() {
flag.Usage = func() {
fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
fmt.Printf("%s [OPTIONS]\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
log.Out = os.Stderr
if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
logrus.SetLevel(logrus.DebugLevel)
}
var newDir, oldDir string
if len(*flNewDir) == 0 {
var err error
newDir, err = ioutil.TempDir("", "docker-test-newDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(newDir)
if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
log.Fatal(err)
}
} else {
newDir = *flNewDir
}
if len(*flOldDir) == 0 {
oldDir, err := ioutil.TempDir("", "docker-test-oldDir")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(oldDir)
} else {
oldDir = *flOldDir
}
changes, err := archive.ChangesDirs(newDir, oldDir)
if err != nil {
log.Fatal(err)
}
a, err := archive.ExportChanges(newDir, changes)
if err != nil {
log.Fatal(err)
}
defer a.Close()
i, err := io.Copy(os.Stdout, a)
if err != nil && err != io.EOF {
log.Fatal(err)
}
fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
}
func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
fileData := []byte("fooo")
for n := 0; n < numberOfFiles; n++ {
fileName := fmt.Sprintf("file-%d", n)
if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
return 0, err
}
if makeLinks {
if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
return 0, err
}
}
}
totalSize := numberOfFiles * len(fileData)
return totalSize, nil
}
+5
View File
@@ -0,0 +1,5 @@
# reexec
The `reexec` package facilitates the busybox style reexec of the docker binary that we require because
of the forking limitations of using Go. Handlers can be registered with a name and the argv 0 of
the exec of the binary will be used to find and execute custom init paths.
+1
View File
@@ -0,0 +1 @@
This package provides helper functions for dealing with signals across various operating systems
+1
View File
@@ -0,0 +1 @@
This package provides helper functions for dealing with string identifiers
+6
View File
@@ -0,0 +1,6 @@
Package symlink implements EvalSymlinksInScope which is an extension of filepath.EvalSymlinks,
as well as a Windows long-path aware version of filepath.EvalSymlinks
from the [Go standard library](https://golang.org/pkg/path/filepath).
The code from filepath.EvalSymlinks has been adapted in fs.go.
Please read the LICENSE.BSD file that governs fs.go and LICENSE.APACHE for fs_test.go.
+230
View File
@@ -0,0 +1,230 @@
page_title: TarSum checksum specification
page_description: Documentation for algorithms used in the TarSum checksum calculation
page_keywords: docker, checksum, validation, tarsum
# TarSum Checksum Specification
## Abstract
This document describes the algorithms used in performing the TarSum checksum
calculation on filesystem layers, the need for this method over existing
methods, and the versioning of this calculation.
## Warning
This checksum algorithm is for best-effort comparison of file trees with fuzzy logic.
This is _not_ a cryptographic attestation, and should not be considered secure.
## Introduction
The transportation of filesystems, regarding Docker, is done with tar(1)
archives. There are a variety of tar serialization formats [2], and a key
concern here is ensuring a repeatable checksum given a set of inputs from a
generic tar archive. Types of transportation include distribution to and from a
registry endpoint, saving and loading through commands or Docker daemon APIs,
transferring the build context from client to Docker daemon, and committing the
filesystem of a container to become an image.
As tar archives are used for transit, but not preserved in many situations, the
focus of the algorithm is to ensure the integrity of the preserved filesystem,
while maintaining a deterministic accountability. This includes neither
constraining the ordering or manipulation of the files during the creation or
unpacking of the archive, nor include additional metadata state about the file
system attributes.
## Intended Audience
This document is outlining the methods used for consistent checksum calculation
for filesystems transported via tar archives.
Auditing these methodologies is an open and iterative process. This document
should accommodate the review of source code. Ultimately, this document should
be the starting point of further refinements to the algorithm and its future
versions.
## Concept
The checksum mechanism must ensure the integrity and assurance of the
filesystem payload.
## Checksum Algorithm Profile
A checksum mechanism must define the following operations and attributes:
* Associated hashing cipher - used to checksum each file payload and attribute
information.
* Checksum list - each file of the filesystem archive has its checksum
calculated from the payload and attributes of the file. The final checksum is
calculated from this list, with specific ordering.
* Version - as the algorithm adapts to requirements, there are behaviors of the
algorithm to manage by versioning.
* Archive being calculated - the tar archive having its checksum calculated
## Elements of TarSum checksum
The calculated sum output is a text string. The elements included in the output
of the calculated sum comprise the information needed for validation of the sum
(TarSum version and hashing cipher used) and the expected checksum in hexadecimal
form.
There are two delimiters used:
* '+' separates TarSum version from hashing cipher
* ':' separates calculation mechanics from expected hash
Example:
```
"tarsum.v1+sha256:220a60ecd4a3c32c282622a625a54db9ba0ff55b5ba9c29c7064a2bc358b6a3e"
| | \ |
| | \ |
|_version_|_cipher__|__ |
| \ |
|_calculation_mechanics_|______________________expected_sum_______________________|
```
## Versioning
Versioning was introduced [0] to accommodate differences in calculation needed,
and ability to maintain reverse compatibility.
The general algorithm will be describe further in the 'Calculation'.
### Version0
This is the initial version of TarSum.
Its element in the TarSum checksum string is `tarsum`.
### Version1
Its element in the TarSum checksum is `tarsum.v1`.
The notable changes in this version:
* Exclusion of file `mtime` from the file information headers, in each file
checksum calculation
* Inclusion of extended attributes (`xattrs`. Also seen as `SCHILY.xattr.` prefixed Pax
tar file info headers) keys and values in each file checksum calculation
### VersionDev
*Do not use unless validating refinements to the checksum algorithm*
Its element in the TarSum checksum is `tarsum.dev`.
This is a floating place holder for a next version and grounds for testing
changes. The methods used for calculation are subject to change without notice,
and this version is for testing and not for production use.
## Ciphers
The official default and standard hashing cipher used in the calculation mechanic
is `sha256`. This refers to SHA256 hash algorithm as defined in FIPS 180-4.
Though the TarSum algorithm itself is not exclusively bound to the single
hashing cipher `sha256`, support for alternate hashing ciphers was later added
[1]. Use cases for alternate cipher could include future-proofing TarSum
checksum format and using faster cipher hashes for tar filesystem checksums.
## Calculation
### Requirement
As mentioned earlier, the calculation is such that it takes into consideration
the lifecycle of the tar archive. In that the tar archive is not an immutable,
permanent artifact. Otherwise options like relying on a known hashing cipher
checksum of the archive itself would be reliable enough. The tar archive of the
filesystem is used as a transportation medium for Docker images, and the
archive is discarded once its contents are extracted. Therefore, for consistent
validation items such as order of files in the tar archive and time stamps are
subject to change once an image is received.
### Process
The method is typically iterative due to reading tar info headers from the
archive stream, though this is not a strict requirement.
#### Files
Each file in the tar archive have their contents (headers and body) checksummed
individually using the designated associated hashing cipher. The ordered
headers of the file are written to the checksum calculation first, and then the
payload of the file body.
The resulting checksum of the file is appended to the list of file sums. The
sum is encoded as a string of the hexadecimal digest. Additionally, the file
name and position in the archive is kept as reference for special ordering.
#### Headers
The following headers are read, in this
order ( and the corresponding representation of its value):
* 'name' - string
* 'mode' - string of the base10 integer
* 'uid' - string of the integer
* 'gid' - string of the integer
* 'size' - string of the integer
* 'mtime' (_Version0 only_) - string of integer of the seconds since 1970-01-01 00:00:00 UTC
* 'typeflag' - string of the char
* 'linkname' - string
* 'uname' - string
* 'gname' - string
* 'devmajor' - string of the integer
* 'devminor' - string of the integer
For >= Version1, the extended attribute headers ("SCHILY.xattr." prefixed pax
headers) included after the above list. These xattrs key/values are first
sorted by the keys.
#### Header Format
The ordered headers are written to the hash in the format of
"{.key}{.value}"
with no newline.
#### Body
After the order headers of the file have been added to the checksum for the
file, the body of the file is written to the hash.
#### List of file sums
The list of file sums is sorted by the string of the hexadecimal digest.
If there are two files in the tar with matching paths, the order of occurrence
for that path is reflected for the sums of the corresponding file header and
body.
#### Final Checksum
Begin with a fresh or initial state of the associated hash cipher. If there is
additional payload to include in the TarSum calculation for the archive, it is
written first. Then each checksum from the ordered list of file sums is written
to the hash.
The resulting digest is formatted per the Elements of TarSum checksum,
including the TarSum version, the associated hash cipher and the hexadecimal
encoded checksum digest.
## Security Considerations
The initial version of TarSum has undergone one update that could invalidate
handcrafted tar archives. The tar archive format supports appending of files
with same names as prior files in the archive. The latter file will clobber the
prior file of the same path. Due to this the algorithm now accounts for files
with matching paths, and orders the list of file sums accordingly [3].
## Footnotes
* [0] Versioning https://github.com/docker/docker/commit/747f89cd327db9d50251b17797c4d825162226d0
* [1] Alternate ciphers https://github.com/docker/docker/commit/4e9925d780665149b8bc940d5ba242ada1973c4e
* [2] Tar http://en.wikipedia.org/wiki/Tar_%28computing%29
* [3] Name collision https://github.com/docker/docker/commit/c5e6362c53cbbc09ddbabd5a7323e04438b57d31
## Acknowledgments
Joffrey F (shin-) and Guillaume J. Charmes (creack) on the initial work of the
TarSum calculation.
+1
View File
@@ -0,0 +1 @@
This package provides helper functions to pack version information into a single User-Agent header.
-1
View File
@@ -1 +0,0 @@
../CONTRIBUTING.md
View File
+24
View File
@@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
+70
View File
@@ -0,0 +1,70 @@
# Contributing to Docker open source projects
Want to hack on go-events? Awesome! Here are instructions to get you started.
go-events is part of the [Docker](https://www.docker.com) project, and
follows the same rules and principles. If you're already familiar with the way
Docker does things, you'll feel right at home.
Otherwise, go read Docker's
[contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md),
[issue triaging](https://github.com/docker/docker/blob/master/project/ISSUE-TRIAGE.md),
[review process](https://github.com/docker/docker/blob/master/project/REVIEWING.md) and
[branches and tags](https://github.com/docker/docker/blob/master/project/BRANCHES-AND-TAGS.md).
For an in-depth description of our contribution process, visit the
contributors guide: [Understand how to contribute](https://docs.docker.com/opensource/workflow/make-a-contribution/)
### Sign your work
The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch 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](http://developercertificate.org/)):
```
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:
Signed-off-by: Joe Smith <joe.smith@email.com>
Use your real name (sorry, no pseudonyms or anonymous contributions.)
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.
+46
View File
@@ -0,0 +1,46 @@
# go-events maintainers file
#
# This file describes who runs the docker/go-events project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"aaronlehmann",
"aluzzardi",
"lk4d4",
"stevvooe",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.aluzzardi]
Name = "Andrea Luzzardi"
Email = "al@docker.com"
GitHub = "aluzzardi"
[people.lk4d4]
Name = "Alexander Morozov"
Email = "lk4d4@docker.com"
GitHub = "lk4d4"
[people.stevvooe]
Name = "Stephen Day"
Email = "stephen.day@docker.com"
GitHub = "stevvooe"
+117
View File
@@ -0,0 +1,117 @@
# Docker Events Package
[![GoDoc](https://godoc.org/github.com/docker/go-events?status.svg)](https://godoc.org/github.com/docker/go-events)
[![Circle CI](https://circleci.com/gh/docker/go-events.svg?style=shield)](https://circleci.com/gh/docker/go-events)
The Docker `events` package implements a composable event distribution package
for Go.
Originally created to implement the [notifications in Docker Registry
2](https://github.com/docker/distribution/blob/master/docs/notifications.md),
we've found the pattern to be useful in other applications. This package is
most of the same code with slightly updated interfaces. Much of the internals
have been made available.
## Usage
The `events` package centers around a `Sink` type. Events are written with
calls to `Sink.Write(event Event)`. Sinks can be wired up in various
configurations to achieve interesting behavior.
The canonical example is that employed by the
[docker/distribution/notifications](https://godoc.org/github.com/docker/distribution/notifications)
package. Let's say we have a type `httpSink` where we'd like to queue
notifications. As a rule, it should send a single http request and return an
error if it fails:
```go
func (h *httpSink) Write(event Event) error {
p, err := json.Marshal(event)
if err != nil {
return err
}
body := bytes.NewReader(p)
resp, err := h.client.Post(h.url, "application/json", body)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.Status != 200 {
return errors.New("unexpected status")
}
return nil
}
// implement (*httpSink).Close()
```
With just that, we can start using components from this package. One can call
`(*httpSink).Write` to send events as the body of a post request to a
configured URL.
### Retries
HTTP can be unreliable. The first feature we'd like is to have some retry:
```go
hs := newHTTPSink(/*...*/)
retry := NewRetryingSink(hs, NewBreaker(5, time.Second))
```
We now have a sink that will retry events against the `httpSink` until they
succeed. The retry will backoff for one second after 5 consecutive failures
using the breaker strategy.
### Queues
This isn't quite enough. We we want a sink that doesn't block while we are
waiting for events to be sent. Let's add a `Queue`:
```go
queue := NewQueue(retry)
```
Now, we have an unbounded queue that will work through all events sent with
`(*Queue).Write`. Events can be added asynchronously to the queue without
blocking the current execution path. This is ideal for use in an http request.
### Broadcast
It usually turns out that you want to send to more than one listener. We can
use `Broadcaster` to support this:
```go
var broadcast = NewBroadcaster() // make it available somewhere in your application.
broadcast.Add(queue) // add your queue!
broadcast.Add(queue2) // and another!
```
With the above, we can now call `broadcast.Write` in our http handlers and have
all the events distributed to each queue. Because the events are queued, not
listener blocks another.
### Extending
For the most part, the above is sufficient for a lot of applications. However,
extending the above functionality can be done implementing your own `Sink`. The
behavior and semantics of the sink can be completely dependent on the
application requirements. The interface is provided below for reference:
```go
type Sink {
Write(Event) error
Close() error
}
```
Application behavior can be controlled by how `Write` behaves. The examples
above are designed to queue the message and return as quickly as possible.
Other implementations may block until the event is committed to durable
storage.
## Copyright and license
Copyright © 2016 Docker, Inc. go-events is licensed under the Apache License,
Version 2.0. See [LICENSE](LICENSE) for the full license text.
+55
View File
@@ -0,0 +1,55 @@
# Contributing
## Sign your work
The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch 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](http://developercertificate.org/)):
```
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:
Signed-off-by: Joe Smith <joe.smith@email.com>
Use your real name (sorry, no pseudonyms or anonymous contributions.)
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.
+91
View File
@@ -0,0 +1,91 @@
# go-metrics [![GoDoc](https://godoc.org/github.com/docker/go-metrics?status.svg)](https://godoc.org/github.com/docker/go-metrics) ![Badge Badge](http://doyouevenbadge.com/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](https://prometheus.io/docs/practices/naming/).
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.
2. 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.
3. 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)
```
4. 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](https://godoc.org/github.com/docker/go-metrics).
## HTTP Metrics
To instrument a http handler, you can wrap the code like this:
```go
namespace := metrics.NewNamespace("docker_distribution", "http", metrics.Labels{"handler": "your_http_handler_name"})
httpMetrics := namespace.NewDefaultHttpMetrics()
metrics.Register(namespace)
instrumentedHandler = metrics.InstrumentHandler(httpMetrics, unInstrumentedHandler)
```
Note: The `handler` label must be provided when a new namespace is created.
## Additional Metrics
Additional metrics are also defined here that are not available 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 and license
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/.
+67
View File
@@ -0,0 +1,67 @@
# Contributing to go-units
Want to hack on go-units? Awesome! Here are instructions to get you started.
go-units is a part of the [Docker](https://www.docker.com) project, and follows
the same rules and principles. If you're already familiar with the way
Docker does things, you'll feel right at home.
Otherwise, go read Docker's
[contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md),
[issue triaging](https://github.com/docker/docker/blob/master/project/ISSUE-TRIAGE.md),
[review process](https://github.com/docker/docker/blob/master/project/REVIEWING.md) and
[branches and tags](https://github.com/docker/docker/blob/master/project/BRANCHES-AND-TAGS.md).
### Sign your work
The sign-off is a simple line at the end of the explanation for the patch. Your
signature certifies that you wrote the patch 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](http://developercertificate.org/)):
```
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:
Signed-off-by: Joe Smith <joe.smith@email.com>
Use your real name (sorry, no pseudonyms or anonymous contributions.)
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.
+46
View File
@@ -0,0 +1,46 @@
# go-units maintainers file
#
# This file describes who runs the docker/go-units project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"akihirosuda",
"dnephin",
"thajeztah",
"vdemeester",
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.akihirosuda]
Name = "Akihiro Suda"
Email = "suda.akihiro@lab.ntt.co.jp"
GitHub = "AkihiroSuda"
[people.dnephin]
Name = "Daniel Nephin"
Email = "dnephin@gmail.com"
GitHub = "dnephin"
[people.thajeztah]
Name = "Sebastiaan van Stijn"
Email = "github@gone.nl"
GitHub = "thaJeztah"
[people.vdemeester]
Name = "Vincent Demeester"
Email = "vincent@sbr.pm"
GitHub = "vdemeester"
+16
View File
@@ -0,0 +1,16 @@
[![GoDoc](https://godoc.org/github.com/docker/go-units?status.svg)](https://godoc.org/github.com/docker/go-units)
# Introduction
go-units is a library to transform human friendly measurements into machine friendly values.
## Usage
See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation.
## Copyright and license
Copyright © 2015 Docker, Inc.
go-units is licensed under the Apache License, Version 2.0.
See [LICENSE](LICENSE) for the full text of the license.
+11
View File
@@ -0,0 +1,11 @@
dependencies:
post:
# install golint
- go get github.com/golang/lint/golint
test:
pre:
# run analysis before tests
- go vet ./...
- test -z "$(golint ./... | tee /dev/stderr)"
- test -z "$(gofmt -s -l . | tee /dev/stderr)"
+24
View File
@@ -0,0 +1,24 @@
### Notice
Do not change .pb.go files directly. You need to change the corresponding .proto files and run the following command to regenerate the .pb.go files.
```
$ make generate
```
Click [here](https://github.com/google/protobuf) for more information about protobuf.
The `api.pb.txt` file contains merged descriptors of all defined services and messages.
Definitions present here are considered frozen after the release.
At release time, the current `api.pb.txt` file will be moved into place to
freeze the API changes for the minor version. For example, when 1.0.0 is
released, `api.pb.txt` should be moved to `1.0.txt`. Notice that we leave off
the patch number, since the API will be completely locked down for a given
patch series.
We may find that by default, protobuf descriptors are too noisy to lock down
API changes. In that case, we may filter out certain fields in the descriptors,
possibly regenerating for old versions.
This process is similar to the [process used to ensure backwards compatibility
in Go](https://github.com/golang/go/tree/master/api).
+10067
View File
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/types.proto";
import "github.com/docker/swarmkit/api/specs.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// CA defines the RPC methods for requesting certificates from a CA.
service CA {
rpc GetRootCACertificate(GetRootCACertificateRequest) returns (GetRootCACertificateResponse) {
option (docker.protobuf.plugin.tls_authorization) = { insecure: true };
};
// GetUnlockKey returns the current unlock key for the cluster for the role of the client
// asking.
rpc GetUnlockKey(GetUnlockKeyRequest) returns (GetUnlockKeyResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: ["swarm-manager"] };
};
}
service NodeCA {
rpc IssueNodeCertificate(IssueNodeCertificateRequest) returns (IssueNodeCertificateResponse) {
option (docker.protobuf.plugin.tls_authorization) = { insecure: true };
};
rpc NodeCertificateStatus(NodeCertificateStatusRequest) returns (NodeCertificateStatusResponse) {
option (docker.protobuf.plugin.tls_authorization) = { insecure: true };
};
}
message NodeCertificateStatusRequest {
string node_id = 1;
}
message NodeCertificateStatusResponse {
IssuanceStatus status = 1;
Certificate certificate = 2;
}
message IssueNodeCertificateRequest {
// DEPRECATED: Role is now selected based on which secret is matched.
NodeRole role = 1 [deprecated=true];
// CSR is the certificate signing request.
bytes csr = 2 [(gogoproto.customname) = "CSR"];
// Token represents a user-provided string that is necessary for new
// nodes to join the cluster
string token = 3;
// Availability allows a user to control the current scheduling status of a node
NodeSpec.Availability availability = 4;
}
message IssueNodeCertificateResponse {
string node_id = 1;
NodeSpec.Membership node_membership = 2;
}
message GetRootCACertificateRequest {}
message GetRootCACertificateResponse {
bytes certificate = 1;
}
message GetUnlockKeyRequest {}
message GetUnlockKeyResponse {
bytes unlock_key = 1;
Version version = 2 [(gogoproto.nullable) = false];
}
+554
View File
@@ -0,0 +1,554 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/specs.proto";
import "github.com/docker/swarmkit/api/objects.proto";
import "github.com/docker/swarmkit/api/types.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// Control defines the RPC methods for controlling a cluster.
service Control {
rpc GetNode(GetNodeRequest) returns (GetNodeResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc ListNodes(ListNodesRequest) returns (ListNodesResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc UpdateNode(UpdateNodeRequest) returns (UpdateNodeResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc RemoveNode(RemoveNodeRequest) returns (RemoveNodeResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc GetTask(GetTaskRequest) returns (GetTaskResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc ListTasks(ListTasksRequest) returns (ListTasksResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc RemoveTask(RemoveTaskRequest) returns (RemoveTaskResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc GetService(GetServiceRequest) returns (GetServiceResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc ListServices(ListServicesRequest) returns (ListServicesResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc CreateService(CreateServiceRequest) returns (CreateServiceResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc UpdateService(UpdateServiceRequest) returns (UpdateServiceResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc RemoveService(RemoveServiceRequest) returns (RemoveServiceResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc GetNetwork(GetNetworkRequest) returns (GetNetworkResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc ListNetworks(ListNetworksRequest) returns (ListNetworksResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc CreateNetwork(CreateNetworkRequest) returns (CreateNetworkResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc RemoveNetwork(RemoveNetworkRequest) returns (RemoveNetworkResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc GetCluster(GetClusterRequest) returns (GetClusterResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc ListClusters(ListClustersRequest) returns (ListClustersResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
rpc UpdateCluster(UpdateClusterRequest) returns (UpdateClusterResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// --- secret APIs ---
// GetSecret returns a `GetSecretResponse` with a `Secret` with the same
// id as `GetSecretRequest.SecretID`
// - Returns `NotFound` if the Secret with the given id is not found.
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if getting fails.
rpc GetSecret(GetSecretRequest) returns (GetSecretResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// UpdateSecret returns a `UpdateSecretResponse` with a `Secret` with the same
// id as `GetSecretRequest.SecretID`
// - Returns `NotFound` if the Secret with the given id is not found.
// - Returns `InvalidArgument` if the `GetSecretRequest.SecretID` is empty.
// - Returns an error if updating fails.
rpc UpdateSecret(UpdateSecretRequest) returns (UpdateSecretResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// ListSecrets returns a `ListSecretResponse` with a list of all non-internal `Secret`s being
// managed, or all secrets matching any name in `ListSecretsRequest.Names`, any
// name prefix in `ListSecretsRequest.NamePrefixes`, any id in
// `ListSecretsRequest.SecretIDs`, or any id prefix in `ListSecretsRequest.IDPrefixes`.
// - Returns an error if listing fails.
rpc ListSecrets(ListSecretsRequest) returns (ListSecretsResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// CreateSecret creates and return a `CreateSecretResponse` with a `Secret` based
// on the provided `CreateSecretRequest.SecretSpec`.
// - Returns `InvalidArgument` if the `CreateSecretRequest.SecretSpec` is malformed,
// or if the secret data is too long or contains invalid characters.
// - Returns an error if the creation fails.
rpc CreateSecret(CreateSecretRequest) returns (CreateSecretResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// RemoveSecret removes the secret referenced by `RemoveSecretRequest.ID`.
// - Returns `InvalidArgument` if `RemoveSecretRequest.ID` is empty.
// - Returns `NotFound` if the a secret named `RemoveSecretRequest.ID` is not found.
// - Returns an error if the deletion fails.
rpc RemoveSecret(RemoveSecretRequest) returns (RemoveSecretResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// --- config APIs ---
// GetConfig returns a `GetConfigResponse` with a `Config` with the same
// id as `GetConfigRequest.ConfigID`
// - Returns `NotFound` if the Config with the given id is not found.
// - Returns `InvalidArgument` if the `GetConfigRequest.ConfigID` is empty.
// - Returns an error if getting fails.
rpc GetConfig(GetConfigRequest) returns (GetConfigResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// UpdateConfig returns a `UpdateConfigResponse` with a `Config` with the same
// id as `GetConfigRequest.ConfigID`
// - Returns `NotFound` if the Config with the given id is not found.
// - Returns `InvalidArgument` if the `GetConfigRequest.ConfigID` is empty.
// - Returns an error if updating fails.
rpc UpdateConfig(UpdateConfigRequest) returns (UpdateConfigResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// ListConfigs returns a `ListConfigResponse` with a list of `Config`s being
// managed, or all configs matching any name in `ListConfigsRequest.Names`, any
// name prefix in `ListConfigsRequest.NamePrefixes`, any id in
// `ListConfigsRequest.ConfigIDs`, or any id prefix in `ListConfigsRequest.IDPrefixes`.
// - Returns an error if listing fails.
rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// CreateConfig creates and return a `CreateConfigResponse` with a `Config` based
// on the provided `CreateConfigRequest.ConfigSpec`.
// - Returns `InvalidArgument` if the `CreateConfigRequest.ConfigSpec` is malformed,
// or if the config data is too long or contains invalid characters.
// - Returns an error if the creation fails.
rpc CreateConfig(CreateConfigRequest) returns (CreateConfigResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
// RemoveConfig removes the config referenced by `RemoveConfigRequest.ID`.
// - Returns `InvalidArgument` if `RemoveConfigRequest.ID` is empty.
// - Returns `NotFound` if the a config named `RemoveConfigRequest.ID` is not found.
// - Returns an error if the deletion fails.
rpc RemoveConfig(RemoveConfigRequest) returns (RemoveConfigResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
}
message GetNodeRequest {
string node_id = 1;
}
message GetNodeResponse {
Node node = 1;
}
message ListNodesRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
repeated NodeSpec.Membership memberships = 4 [packed=false];
repeated NodeRole roles = 5 [packed=false];
// NamePrefixes matches all objects with the given prefixes
repeated string name_prefixes = 6;
}
Filters filters = 1;
}
message ListNodesResponse {
repeated Node nodes = 1;
}
// UpdateNodeRequest requests an update to the specified node. This may be used
// to request a new availability for a node, such as PAUSE. Invalid updates
// will be denied and cause an error.
message UpdateNodeRequest {
string node_id = 1;
Version node_version = 2;
NodeSpec spec = 3;
}
message UpdateNodeResponse {
Node node = 1;
}
// RemoveNodeRequest requests to delete the specified node from store.
message RemoveNodeRequest {
string node_id = 1;
bool force = 2;
}
message RemoveNodeResponse {
}
message GetTaskRequest {
string task_id = 1;
}
message GetTaskResponse {
Task task = 1;
}
message RemoveTaskRequest {
string task_id = 1;
}
message RemoveTaskResponse {
}
message ListTasksRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
repeated string service_ids = 4;
repeated string node_ids = 5;
repeated docker.swarmkit.v1.TaskState desired_states = 6 [packed=false];
// NamePrefixes matches all objects with the given prefixes
repeated string name_prefixes = 7;
repeated string runtimes = 9;
// UpToDate matches tasks that are consistent with the current
// service definition.
// Note: this is intended for internal status reporting rather
// than being exposed to users. It may be removed in the future.
bool up_to_date = 8;
}
Filters filters = 1;
}
message ListTasksResponse {
repeated Task tasks = 1;
}
message CreateServiceRequest {
ServiceSpec spec = 1;
}
message CreateServiceResponse {
Service service = 1;
}
message GetServiceRequest {
string service_id = 1;
bool insert_defaults = 2;
}
message GetServiceResponse {
Service service = 1;
}
message UpdateServiceRequest {
string service_id = 1;
Version service_version = 2;
ServiceSpec spec = 3;
enum Rollback {
// This is not a rollback. The spec field of the request will
// be honored.
NONE = 0;
// Roll back the service - get spec from the service's
// previous_spec.
PREVIOUS = 1;
}
// Rollback may be set to PREVIOUS to request a rollback (the service's
// spec will be set to the value of its previous_spec field). In this
// case, the spec field of this request is ignored.
Rollback rollback = 4;
}
message UpdateServiceResponse {
Service service = 1;
}
message RemoveServiceRequest {
string service_id = 1;
}
message RemoveServiceResponse {
}
message ListServicesRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
// NamePrefixes matches all objects with the given prefixes
repeated string name_prefixes = 4;
repeated string runtimes = 5;
}
Filters filters = 1;
}
message ListServicesResponse {
repeated Service services = 1;
}
message CreateNetworkRequest {
NetworkSpec spec = 1;
}
message CreateNetworkResponse {
Network network = 1;
}
message GetNetworkRequest {
string name = 1;
string network_id = 2;
}
message GetNetworkResponse {
Network network = 1;
}
message RemoveNetworkRequest {
string name = 1;
string network_id = 2;
}
message RemoveNetworkResponse {}
message ListNetworksRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
// NamePrefixes matches all objects with the given prefixes
repeated string name_prefixes = 4;
}
Filters filters = 1;
}
message ListNetworksResponse {
repeated Network networks = 1;
}
message GetClusterRequest {
string cluster_id = 1;
}
message GetClusterResponse {
Cluster cluster = 1;
}
message ListClustersRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
// NamePrefixes matches all objects with the given prefixes
repeated string name_prefixes = 4;
}
Filters filters = 1;
}
message ListClustersResponse {
repeated Cluster clusters = 1;
}
// KeyRotation tells UpdateCluster what items to rotate
message KeyRotation {
// WorkerJoinToken tells UpdateCluster to rotate the worker secret token.
bool worker_join_token = 1;
// ManagerJoinToken tells UpdateCluster to rotate the manager secret token.
bool manager_join_token = 2;
// ManagerUnlockKey tells UpdateCluster to rotate the manager unlock key
bool manager_unlock_key = 3;
}
message UpdateClusterRequest {
// ClusterID is the cluster ID to update.
string cluster_id = 1;
// ClusterVersion is the version of the cluster being updated.
Version cluster_version = 2;
// Spec is the new spec to apply to the cluster.
ClusterSpec spec = 3;
// Rotation contains flags for join token and unlock key rotation
KeyRotation rotation = 4 [(gogoproto.nullable) = false];
}
message UpdateClusterResponse {
Cluster cluster = 1;
}
// GetSecretRequest is the request to get a `Secret` object given a secret id.
message GetSecretRequest {
string secret_id = 1;
}
// GetSecretResponse contains the Secret corresponding to the id in
// `GetSecretRequest`, but the `Secret.Spec.Data` field in each `Secret`
// object should be nil instead of actually containing the secret bytes.
message GetSecretResponse {
Secret secret = 1;
}
message UpdateSecretRequest {
// SecretID is the secret ID to update.
string secret_id = 1;
// SecretVersion is the version of the secret being updated.
Version secret_version = 2;
// Spec is the new spec to apply to the Secret
// Only some fields are allowed to be updated.
SecretSpec spec = 3;
}
message UpdateSecretResponse {
Secret secret = 1;
}
// ListSecretRequest is the request to list all non-internal secrets in the secret store,
// or all secrets filtered by (name or name prefix or id prefix) and labels.
message ListSecretsRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
repeated string name_prefixes = 4;
}
Filters filters = 1;
}
// ListSecretResponse contains a list of all the secrets that match the name or
// name prefix filters provided in `ListSecretRequest`. The `Secret.Spec.Data`
// field in each `Secret` object should be nil instead of actually containing
// the secret bytes.
message ListSecretsResponse {
repeated Secret secrets = 1;
}
// CreateSecretRequest specifies a new secret (it will not update an existing
// secret) to create.
message CreateSecretRequest {
SecretSpec spec = 1;
}
// CreateSecretResponse contains the newly created `Secret` corresponding to the
// name in `CreateSecretRequest`. The `Secret.Spec.Data` field should be nil instead
// of actually containing the secret bytes.
message CreateSecretResponse {
Secret secret = 1;
}
// RemoveSecretRequest contains the ID of the secret that should be removed. This
// removes all versions of the secret.
message RemoveSecretRequest {
string secret_id = 1;
}
// RemoveSecretResponse is an empty object indicating the successful removal of
// a secret.
message RemoveSecretResponse {}
// GetConfigRequest is the request to get a `Config` object given a config id.
message GetConfigRequest {
string config_id = 1;
}
// GetConfigResponse contains the Config corresponding to the id in
// `GetConfigRequest`.
message GetConfigResponse {
Config config = 1;
}
message UpdateConfigRequest {
// ConfigID is the config ID to update.
string config_id = 1;
// ConfigVersion is the version of the config being updated.
Version config_version = 2;
// Spec is the new spec to apply to the Config
// Only some fields are allowed to be updated.
ConfigSpec spec = 3;
}
message UpdateConfigResponse {
Config config = 1;
}
// ListConfigRequest is the request to list all configs in the config store,
// or all configs filtered by (name or name prefix or id prefix) and labels.
message ListConfigsRequest {
message Filters {
repeated string names = 1;
repeated string id_prefixes = 2;
map<string, string> labels = 3;
repeated string name_prefixes = 4;
}
Filters filters = 1;
}
// ListConfigResponse contains a list of all the configs that match the name or
// name prefix filters provided in `ListConfigRequest`.
message ListConfigsResponse {
repeated Config configs = 1;
}
// CreateConfigRequest specifies a new config (it will not update an existing
// config) to create.
message CreateConfigRequest {
ConfigSpec spec = 1;
}
// CreateConfigResponse contains the newly created `Config` corresponding to the
// name in `CreateConfigRequest`.
message CreateConfigResponse {
Config config = 1;
}
// RemoveConfigRequest contains the ID of the config that should be removed. This
// removes all versions of the config.
message RemoveConfigRequest {
string config_id = 1;
}
// RemoveConfigResponse is an empty object indicating the successful removal of
// a config.
message RemoveConfigResponse {}
+218
View File
@@ -0,0 +1,218 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/types.proto";
import "github.com/docker/swarmkit/api/objects.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
import "google/protobuf/duration.proto";
// Dispatcher is the API provided by a manager group for agents to connect to. Agents
// connect to this service to receive task assignments and report status.
//
// API methods on this service are used only by agent nodes.
service Dispatcher { // maybe dispatch, al likes this
// Session starts an agent session with the dispatcher. The session is
// started after the first SessionMessage is received.
//
// Once started, the agent is controlled with a stream of SessionMessage.
// Agents should list on the stream at all times for instructions.
rpc Session(SessionRequest) returns (stream SessionMessage) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
// Heartbeat is heartbeat method for nodes. It returns new TTL in response.
// Node should send new heartbeat earlier than now + TTL, otherwise it will
// be deregistered from dispatcher and its status will be updated to NodeStatus_DOWN
rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
// UpdateTaskStatus updates status of task. Node should send such updates
// on every status change of its tasks.
//
// Whether receiving batch updates or single status updates, this method
// should be accepting. Errors should only be returned if the entire update
// should be retried, due to data loss or other problems.
//
// If a task is unknown the dispatcher, the status update should be
// accepted regardless.
rpc UpdateTaskStatus(UpdateTaskStatusRequest) returns (UpdateTaskStatusResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
// Tasks is a stream of tasks state for node. Each message contains full list
// of tasks which should be run on node, if task is not present in that list,
// it should be terminated.
rpc Tasks(TasksRequest) returns (stream TasksMessage) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
option deprecated = true;
};
// Assignments is a stream of assignments such as tasks and secrets for node.
// The first message in the stream contains all of the tasks and secrets
// that are relevant to the node. Future messages in the stream are updates to
// the set of assignments.
rpc Assignments(AssignmentsRequest) returns (stream AssignmentsMessage) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
}
// SessionRequest starts a session.
message SessionRequest {
NodeDescription description = 1;
// SessionID can be provided to attempt resuming an existing session. If the
// SessionID is empty or invalid, a new SessionID will be assigned.
//
// See SessionMessage.SessionID for details.
string session_id = 2;
}
// SessionMessage instructs an agent on various actions as part of the current
// session. An agent should act immediately on the contents.
message SessionMessage {
// SessionID is allocated after a successful registration. It should be
// used on all RPC calls after registration. A dispatcher may choose to
// change the SessionID, at which time an agent must re-register and obtain
// a new one.
//
// All Dispatcher calls after register should include the SessionID. If the
// Dispatcher so chooses, it may reject the call with an InvalidArgument
// error code, at which time the agent should call Register to start a new
// session.
//
// As a rule, once an agent has a SessionID, it should never save it to
// disk or try to otherwise reuse. If the agent loses its SessionID, it
// must start a new session through a call to Register. A Dispatcher may
// choose to reuse the SessionID, if it sees fit, but it is not advised.
//
// The actual implementation of the SessionID is Dispatcher specific and
// should be treated as opaque by agents.
//
// From a Dispatcher perspective, there are many ways to use the SessionID
// to ensure uniqueness of a set of client RPC calls. One method is to keep
// the SessionID unique to every call to Register in a single Dispatcher
// instance. This ensures that the SessionID represents the unique
// session from a single Agent to Manager. If the Agent restarts, we
// allocate a new session, since the restarted Agent is not aware of the
// new SessionID.
//
// The most compelling use case is to support duplicate node detection. If
// one clones a virtual machine, including certificate material, two nodes
// may end up with the same identity. This can also happen if two identical
// agent processes are coming from the same node. If the SessionID is
// replicated through the cluster, we can immediately detect the condition
// and address it.
//
// Extending from the case above, we can actually detect a compromised
// identity. Coupled with provisions to rebuild node identity, we can ban
// the compromised node identity and have the nodes re-authenticate and
// build a new identity. At this time, an administrator can then
// re-authorize the compromised nodes, if it was a mistake or ensure that a
// misbehaved node can no longer connect to the cluster.
//
// We considered placing this field in a GRPC header. Because this is a
// critical feature of the protocol, we thought it should be represented
// directly in the RPC message set.
string session_id = 1;
// Node identifies the registering node.
Node node = 2;
// Managers provides a weight list of alternative dispatchers
repeated WeightedPeer managers = 3;
// Symmetric encryption key distributed by the lead manager. Used by agents
// for securing network bootstrapping and communication.
repeated EncryptionKey network_bootstrap_keys = 4;
// Which root certificates to trust
bytes RootCA = 5;
}
// HeartbeatRequest provides identifying properties for a single heartbeat.
message HeartbeatRequest {
string session_id = 1;
}
message HeartbeatResponse {
// Period is the duration to wait before sending the next heartbeat.
// Well-behaved agents should update this on every heartbeat round trip.
google.protobuf.Duration period = 1 [(gogoproto.stdduration) = true, (gogoproto.nullable) = false];
}
message UpdateTaskStatusRequest {
// Tasks should contain all statuses for running tasks. Only the status
// field must be set. The spec is not required.
string session_id = 1;
message TaskStatusUpdate {
string task_id = 1;
TaskStatus status = 2;
}
repeated TaskStatusUpdate updates = 3;
}
message UpdateTaskStatusResponse{
// void
}
message TasksRequest {
string session_id = 1;
}
message TasksMessage {
// Tasks is the set of tasks that should be running on the node.
// Tasks outside of this set running on the node should be terminated.
repeated Task tasks = 1;
}
message AssignmentsRequest {
string session_id = 1;
}
message Assignment {
oneof item {
Task task = 1;
Secret secret = 2;
Config config = 3;
}
}
message AssignmentChange {
enum AssignmentAction {
UPDATE = 0 [(gogoproto.enumvalue_customname) = "AssignmentActionUpdate"];
REMOVE = 1 [(gogoproto.enumvalue_customname) = "AssignmentActionRemove"];
}
Assignment assignment = 1;
AssignmentAction action = 2;
}
message AssignmentsMessage {
// AssignmentType specifies whether this assignment message carries
// the full state, or is an update to an existing state.
enum Type {
COMPLETE = 0;
INCREMENTAL = 1;
}
Type type = 1;
// AppliesTo references the previous ResultsIn value, to chain
// incremental updates together. For the first update in a stream,
// AppliesTo is empty. If AppliesTo does not match the previously
// received ResultsIn, the consumer of the stream should start a new
// Assignments stream to re-sync.
string applies_to = 2;
// ResultsIn identifies the result of this assignments message, to
// match against the next message's AppliesTo value and protect
// against missed messages.
string results_in = 3;
// AssignmentChange is a set of changes to apply on this node.
repeated AssignmentChange changes = 4;
}
+34
View File
@@ -0,0 +1,34 @@
syntax = "proto3";
// See: https://github.com/grpc/grpc-go/blob/master/health/grpc_health_v1/health.proto
//
// We use the same health check service proto description defined in the gRPC documentation,
// including the authorization check. This requires our own implementation of the health
// package located in `manager/health`.
//
// For more infos, refer to:
// https://github.com/grpc/grpc/blob/master/doc/health-checking.md
package docker.swarmkit.v1;
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
service Health {
rpc Check(HealthCheckRequest) returns (HealthCheckResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
}
message HealthCheckRequest {
string service = 1;
}
message HealthCheckResponse {
enum ServingStatus {
UNKNOWN = 0;
SERVING = 1;
NOT_SERVING = 2;
}
ServingStatus status = 1;
}
+188
View File
@@ -0,0 +1,188 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// LogStream defines the stream from which the log message came.
enum LogStream {
option (gogoproto.goproto_enum_prefix) = false;
option (gogoproto.enum_customname) = "LogStream";
LOG_STREAM_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "LogStreamUnknown"];
LOG_STREAM_STDOUT = 1 [(gogoproto.enumvalue_customname) = "LogStreamStdout"];
LOG_STREAM_STDERR = 2 [(gogoproto.enumvalue_customname) = "LogStreamStderr"];
}
message LogSubscriptionOptions {
// Streams defines which log streams should be sent from the task source.
// Empty means send all the messages.
repeated LogStream streams = 1 [packed=false];
// Follow instructs the publisher to continue sending log messages as they
// are produced, after satisfying the initial query.
bool follow = 2;
// Tail defines how many messages relative to the log stream to send when
// starting the stream.
//
// Positive values will skip that number of messages from the start of the
// stream before publishing.
//
// Negative values will specify messages relative to the end of the stream,
// offset by one. We can say that the last (-n-1) lines are returned when n
// < 0. As reference, -1 would mean send no log lines (typically used with
// follow), -2 would return the last log line, -11 would return the last 10
// and so on.
//
// The default value of zero will return all logs.
//
// Note that this is very different from the Docker API.
int64 tail = 3;
// Since indicates that only log messages produced after this timestamp
// should be sent.
// Note: can't use stdtime because this field is nullable.
google.protobuf.Timestamp since = 4;
}
// LogSelector will match logs from ANY of the defined parameters.
//
// For the best effect, the client should use the least specific parameter
// possible. For example, if they want to listen to all the tasks of a service,
// they should use the service id, rather than specifying the individual tasks.
message LogSelector {
repeated string service_ids = 1;
repeated string node_ids = 2;
repeated string task_ids = 3;
}
// LogContext marks the context from which a log message was generated.
message LogContext {
string service_id = 1;
string node_id = 2;
string task_id = 3;
}
// LogAttr is an extra key/value pair that may be have been set by users
message LogAttr {
string key = 1;
string value = 2;
}
// LogMessage
message LogMessage {
// Context identifies the source of the log message.
LogContext context = 1 [(gogoproto.nullable) = false];
// Timestamp is the time at which the message was generated.
// Note: can't use stdtime because this field is nullable.
google.protobuf.Timestamp timestamp = 2;
// Stream identifies the stream of the log message, stdout or stderr.
LogStream stream = 3;
// Data is the raw log message, as generated by the application.
bytes data = 4;
// Attrs is a list of key value pairs representing additional log details
// that may have been returned from the logger
repeated LogAttr attrs = 5 [(gogoproto.nullable) = false];
}
// Logs defines the methods for retrieving task logs messages from a cluster.
service Logs {
// SubscribeLogs starts a subscription with the specified selector and options.
//
// The subscription will be distributed to relevant nodes and messages will
// be collected and sent via the returned stream.
//
// The subscription will end with an EOF.
rpc SubscribeLogs(SubscribeLogsRequest) returns (stream SubscribeLogsMessage) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
}
}
message SubscribeLogsRequest {
// LogSelector describes the logs to which the subscriber is
LogSelector selector = 1;
LogSubscriptionOptions options = 2;
}
message SubscribeLogsMessage {
repeated LogMessage messages = 1 [(gogoproto.nullable) = false];
}
// LogBroker defines the API used by the worker to send task logs back to a
// manager. A client listens for subscriptions then optimistically retrieves
// logs satisfying said subscriptions, calling PublishLogs for results that are
// relevant.
//
// The structure of ListenSubscriptions is similar to the Dispatcher API but
// decoupled to allow log distribution to work outside of the regular task
// flow.
service LogBroker {
// ListenSubscriptions starts a subscription stream for the node. For each
// message received, the node should attempt to satisfy the subscription.
//
// Log messages that match the provided subscription should be sent via
// PublishLogs.
rpc ListenSubscriptions(ListenSubscriptionsRequest) returns (stream SubscriptionMessage) {
option (docker.protobuf.plugin.tls_authorization) = {
roles: "swarm-worker"
roles: "swarm-manager"
};
}
// PublishLogs receives sets of log messages destined for a single
// subscription identifier.
rpc PublishLogs(stream PublishLogsMessage) returns (PublishLogsResponse) {
option (docker.protobuf.plugin.tls_authorization) = {
roles: "swarm-worker"
roles: "swarm-manager"
};
}
}
// ListenSubscriptionsRequest is a placeholder to begin listening for
// subscriptions.
message ListenSubscriptionsRequest { }
// SubscriptionMessage instructs the listener to start publishing messages for
// the stream or end a subscription.
//
// If Options.Follow == false, the worker should end the subscription on its own.
message SubscriptionMessage {
// ID identifies the subscription.
string id = 1;
// Selector defines which sources should be sent for the subscription.
LogSelector selector = 2;
// Options specify how the subscription should be satisfied.
LogSubscriptionOptions options = 3;
// Close will be true if the node should shutdown the subscription with the
// provided identifier.
bool close = 4;
}
message PublishLogsMessage {
// SubscriptionID identifies which subscription the set of messages should
// be sent to. We can think of this as a "mail box" for the subscription.
string subscription_id = 1;
// Messages is the log message for publishing.
repeated LogMessage messages = 2 [(gogoproto.nullable) = false];
// Close is a boolean for whether or not the client has completed its log
// stream. When close is called, the manager can hang up the subscription.
// Any further logs from this subscription are an error condition. Any
// messages included when close is set can be discarded
bool close = 3;
}
message PublishLogsResponse { }
+464
View File
@@ -0,0 +1,464 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/types.proto";
import "github.com/docker/swarmkit/api/specs.proto";
import "google/protobuf/timestamp.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// This file contains definitions for all first-class objects in the cluster
// API. Such types typically have a corresponding specification, with the
// naming XXXSpec, but not all.
// Meta contains metadata about objects. Every object contains a meta field.
message Meta {
// Version tracks the current version of the object.
Version version = 1 [(gogoproto.nullable) = false];
// Object timestamps.
// Note: can't use stdtime because these fields are nullable.
google.protobuf.Timestamp created_at = 2;
google.protobuf.Timestamp updated_at = 3;
}
// Node provides the internal node state as seen by the cluster.
message Node {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
role: true
membership: true
}
};
// ID specifies the identity of the node.
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
// Spec defines the desired state of the node as specified by the user.
// The system will honor this and will *never* modify it.
NodeSpec spec = 3 [(gogoproto.nullable) = false];
// Description encapsulated the properties of the Node as reported by the
// agent.
NodeDescription description = 4;
// Status provides the current status of the node, as seen by the manager.
NodeStatus status = 5 [(gogoproto.nullable) = false];
// ManagerStatus provides the current status of the node's manager
// component, if the node is a manager.
ManagerStatus manager_status = 6;
// DEPRECATED: Use Attachments to find the ingress network
// The node attachment to the ingress network.
NetworkAttachment attachment = 7 [deprecated=true];
// Certificate is the TLS certificate issued for the node, if any.
Certificate certificate = 8 [(gogoproto.nullable) = false];
// Role is the *observed* role for this node. It differs from the
// desired role set in Node.Spec.Role because the role here is only
// updated after the Raft member list has been reconciled with the
// desired role from the spec.
//
// This field represents the current reconciled state. If an action is
// to be performed, first verify the role in the cert. This field only
// shows the privilege level that the CA would currently grant when
// issuing or renewing the node's certificate.
NodeRole role = 9;
// Attachments enumerates the network attachments for the node to set up an
// endpoint on the node to be used for load balancing. Each overlay
// network, including ingress network, will have an NetworkAttachment.
repeated NetworkAttachment attachments = 10;
}
message Service {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
ServiceSpec spec = 3 [(gogoproto.nullable) = false];
// SpecVersion versions Spec, to identify changes in the spec. Note that
// this is not directly comparable to the service's Version.
Version spec_version = 10;
// PreviousSpec is the previous service spec that was in place before
// "Spec".
ServiceSpec previous_spec = 6;
// PreviousSpecVersion versions PreviousSpec. Note that this is not
// directly comparable to the service's Version.
Version previous_spec_version = 11;
// Runtime state of service endpoint. This may be different
// from the spec version because the user may not have entered
// the optional fields like node_port or virtual_ip and it
// could be auto allocated by the system.
Endpoint endpoint = 4;
// UpdateStatus contains the status of an update, if one is in
// progress.
UpdateStatus update_status = 5;
}
// Endpoint specified all the network parameters required to
// correctly discover and load balance a service
message Endpoint {
EndpointSpec spec = 1;
// Runtime state of the exposed ports which may carry
// auto-allocated swarm ports in addition to the user
// configured information.
repeated PortConfig ports = 2;
// An endpoint attachment specifies the data that the process
// of attaching an endpoint to a network creates.
// VirtualIP specifies a set of networks this endpoint will be attached to
// and the IP addresses the target service will be made available under.
message VirtualIP {
// NetworkID for which this endpoint attachment was created.
string network_id = 1;
// A virtual IP is used to address this service in IP
// layer that the client can use to send requests to
// this service. A DNS A/AAAA query on the service
// name might return this IP to the client. This is
// strictly a logical IP and there may not be any
// interfaces assigned this IP address or any route
// created for this address. More than one to
// accommodate for both IPv4 and IPv6
string addr = 2;
}
// VirtualIPs specifies the IP addresses under which this endpoint will be
// made available.
repeated VirtualIP virtual_ips = 3 [(gogoproto.customname) = "VirtualIPs"];
}
// Task specifies the parameters for implementing a Spec. A task is effectively
// immutable and idempotent. Once it is dispatched to a node, it will not be
// dispatched to another node.
message Task {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
service_id: true
node_id: true
slot: true
desired_state: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
// Spec defines the desired state of the task as specified by the user.
// The system will honor this and will *never* modify it.
TaskSpec spec = 3 [(gogoproto.nullable) = false];
// SpecVersion is copied from Service, to identify which version of the
// spec this task has. Note that this is not directly comparable to the
// service's Version.
Version spec_version = 14;
// ServiceID indicates the service under which this task is orchestrated. This
// should almost always be set.
string service_id = 4;
// Slot is the service slot number for a task.
// For example, if a replicated service has replicas = 2, there will be a
// task with slot = 1, and another with slot = 2.
uint64 slot = 5;
// NodeID indicates the node to which the task is assigned. If this field
// is empty or not set, the task is unassigned.
string node_id = 6;
// Annotations defines the names and labels for the runtime, as set by
// the cluster manager.
//
// As backup, if this field has an empty name, the runtime will
// allocate a unique name for the actual container.
//
// NOTE(stevvooe): The preserves the ability for us to making naming
// decisions for tasks in orchestrator, albeit, this is left empty for now.
Annotations annotations = 7 [(gogoproto.nullable) = false];
// ServiceAnnotations is a direct copy of the service name and labels when
// this task is created.
//
// Labels set here will *not* be propagated to the runtime target, such as a
// container. Use labels on the runtime target for that purpose.
Annotations service_annotations = 8 [(gogoproto.nullable) = false];
TaskStatus status = 9 [(gogoproto.nullable) = false];
// DesiredState is the target state for the task. It is set to
// TaskStateRunning when a task is first created, and changed to
// TaskStateShutdown if the manager wants to terminate the task. This field
// is only written by the manager.
TaskState desired_state = 10;
// List of network attachments by the task.
repeated NetworkAttachment networks = 11;
// A copy of runtime state of service endpoint from Service
// object to be distributed to agents as part of the task.
Endpoint endpoint = 12;
// LogDriver specifies the selected log driver to use for the task. Agent
// processes should always favor the value in this field.
//
// If present in the TaskSpec, this will be a copy of that value. The
// orchestrator may choose to insert a value here, which should be honored,
// such a cluster default or policy-based value.
//
// If not present, the daemon's default will be used.
Driver log_driver = 13;
repeated GenericResource assigned_generic_resources = 15;
}
// NetworkAttachment specifies the network parameters of attachment to
// a single network by an object such as task or node.
message NetworkAttachment {
// Network state as a whole becomes part of the object so that
// it always is available for use in agents so that agents
// don't have any other dependency during execution.
Network network = 1;
// List of IPv4/IPv6 addresses that are assigned to the object
// as part of getting attached to this network.
repeated string addresses = 2;
// List of aliases by which a task is resolved in a network
repeated string aliases = 3;
// Map of all the driver attachment options for this network
map<string,string> driver_attachment_opts = 4;
}
message Network {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
NetworkSpec spec = 3 [(gogoproto.nullable) = false];
// Driver specific operational state provided by the network driver.
Driver driver_state = 4;
// Runtime state of IPAM options. This may not reflect the
// ipam options from NetworkSpec.
IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
}
// Cluster provides global cluster settings.
message Cluster {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
ClusterSpec spec = 3 [(gogoproto.nullable) = false];
// RootCA contains key material for the root CA.
RootCA root_ca = 4 [(gogoproto.nullable)=false, (gogoproto.customname) = "RootCA"];
// Symmetric encryption key distributed by the lead manager. Used by agents
// for securing network bootstrapping and communication.
repeated EncryptionKey network_bootstrap_keys = 5;
// Logical clock used to timestamp every key. It allows other managers
// and agents to unambiguously identify the older key to be deleted when
// a new key is allocated on key rotation.
uint64 encryption_key_lamport_clock = 6;
// BlacklistedCertificates tracks certificates that should no longer
// be honored. It's a mapping from CN -> BlacklistedCertificate.
// swarm. Their certificates should effectively be blacklisted.
map<string, BlacklistedCertificate> blacklisted_certificates = 8;
// UnlockKeys defines the keys that lock node data at rest. For example,
// this would contain the key encrypting key (KEK) that will encrypt the
// manager TLS keys at rest and the raft encryption keys at rest.
// If the key is empty, the node will be unlocked (will not require a key
// to start up from a shut down state).
repeated EncryptionKey unlock_keys = 9;
// FIPS specifies whether this cluster should be in FIPS mode. This changes
// the format of the join tokens, and nodes that are not FIPS-enabled should
// reject joining the cluster. Nodes that report themselves to be non-FIPS
// should be rejected from the cluster.
bool fips = 10 [(gogoproto.customname) = "FIPS"];
}
// Secret represents a secret that should be passed to a container or a node,
// and is immutable.
message Secret {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
// Spec contains the actual secret data, as well as any context around the
// secret data that the user provides.
SecretSpec spec = 3 [(gogoproto.nullable) = false];
// Whether the secret is an internal secret (not set by a user) or not.
bool internal = 4;
}
// Config represents a set of configuration files that should be passed to a
// container.
message Config {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1;
Meta meta = 2 [(gogoproto.nullable) = false];
// Spec contains the actual config data, as well as any context around the
// config data that the user provides.
ConfigSpec spec = 3 [(gogoproto.nullable) = false];
}
// Resource is a top-level object with externally defined content and indexing.
// SwarmKit can serve as a store for these objects without understanding their
// meanings.
message Resource {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
kind: true
}
};
string id = 1 [(gogoproto.customname) = "ID"];
Meta meta = 2 [(gogoproto.nullable) = false];
Annotations annotations = 3 [(gogoproto.nullable) = false];
// Kind identifies this class of object. It is essentially a namespace
// to keep IDs or indices from colliding between unrelated Resource
// objects. This must correspond to the name of an Extension.
string kind = 4;
// Payload bytes. This data is not interpreted in any way by SwarmKit.
// By convention, it should be a marshalled protocol buffers message.
google.protobuf.Any payload = 5;
}
// Extension declares a type of "resource" object. This message provides some
// metadata about the objects.
message Extension {
option (docker.protobuf.plugin.store_object) = {
watch_selectors: {
id: true
id_prefix: true
name: true
name_prefix: true
custom: true
custom_prefix: true
}
};
string id = 1 [(gogoproto.customname) = "ID"];
Meta meta = 2 [(gogoproto.nullable) = false];
Annotations annotations = 3 [(gogoproto.nullable) = false];
string description = 4;
// TODO(aaronl): Add optional indexing capabilities. It would be
// extremely useful be able to automatically introspect protobuf, json,
// etc. objects and automatically index them based on a schema and field
// paths defined here.
//
//oneof Schema {
// google.protobuf.Descriptor protobuf = 1;
// bytes json = 2;
//}
//
//Schema schema = 5;
//
// // Indices, with values expressed as Go templates.
//repeated IndexEntry index_templates = 6;
}
+150
View File
@@ -0,0 +1,150 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/objects.proto";
import "github.com/docker/swarmkit/api/types.proto";
import "github.com/coreos/etcd/raft/raftpb/raft.proto";
import weak "gogoproto/gogo.proto";
import weak "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// Raft defines the RPC communication between raft nodes.
service Raft {
// ProcessRaftMessage sends a raft message to be processed on a raft member, it is
// called from the RaftMember willing to send a message to its destination ('To' field)
rpc ProcessRaftMessage(ProcessRaftMessageRequest) returns (ProcessRaftMessageResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// StreamRaftMessage accepts a stream of raft messages of type StreamRaftMessageRequest
// to be processed on a raft member, returning a StreamRaftMessageResponse
// when processing of the streamed messages is complete. A single stream corresponds
// to a single raft message, which may be disassembled and streamed as individual messages.
// It is called from the Raft leader, which uses it to stream messages to a raft member.
rpc StreamRaftMessage(stream StreamRaftMessageRequest) returns (StreamRaftMessageResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// ResolveAddress returns the address where the node with the given ID can be reached.
rpc ResolveAddress(ResolveAddressRequest) returns (ResolveAddressResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
}
// RaftMembership defines RPCs for adding and removing members from the
// cluster. These RPCs must always run on the leader, so they are in a separate
// service to support the raft proxy.
service RaftMembership {
// Join adds a RaftMember to the raft cluster.
rpc Join(JoinRequest) returns (JoinResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
// Leave removes a RaftMember from the raft cluster.
rpc Leave(LeaveRequest) returns (LeaveResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
}
message RaftMember {
// RaftID specifies the internal ID used by the manager in a raft context, it can never be modified
// and is used only for information purposes
uint64 raft_id = 1;
// NodeID is the node's ID.
string node_id = 2;
// Addr specifies the address of the member
string addr = 3;
// Status provides the current status of the manager from the perspective of another manager.
RaftMemberStatus status = 4 [(gogoproto.nullable) = false];
}
message JoinRequest {
// Addr specifies the address of the member
string addr = 1;
}
message JoinResponse {
// RaftID is the ID assigned to the new member.
uint64 raft_id = 1;
// Members is the membership set of the cluster.
repeated RaftMember members = 2;
// RemovedMembers is a list of members that have been removed from
// the cluster, so the new node can avoid communicating with them.
repeated uint64 removed_members = 3 [packed=false];
}
message LeaveRequest {
RaftMember node = 1;
}
message LeaveResponse {}
message ProcessRaftMessageRequest {
option (docker.protobuf.plugin.deepcopy) = false;
raftpb.Message message = 1;
}
message ProcessRaftMessageResponse {}
// Raft message streaming request.
message StreamRaftMessageRequest {
option (docker.protobuf.plugin.deepcopy) = false;
raftpb.Message message = 1;
}
// Raft message streaming response.
message StreamRaftMessageResponse {}
message ResolveAddressRequest {
// raft_id is the ID to resolve to an address.
uint64 raft_id = 1;
}
message ResolveAddressResponse {
// Addr specifies the address of the member
string addr = 1;
}
// Contains one of many protobuf encoded objects to replicate
// over the raft backend with a request ID to track when the
// action is effectively applied
message InternalRaftRequest {
uint64 id = 1;
repeated StoreAction action = 2 [(gogoproto.nullable) = false];
}
// TODO(stevvooe): Storage actions may belong in another protobuf file. They
// aren't necessarily first-class "types" in the cluster schema.
// StoreActionKind defines the operation to take on the store for the target of
// a storage action.
enum StoreActionKind {
option (gogoproto.goproto_enum_prefix) = false;
option (gogoproto.enum_customname) = "StoreActionKind";
UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "StoreActionKindUnknown"]; // default value, invalid
STORE_ACTION_CREATE = 1 [(gogoproto.enumvalue_customname) = "StoreActionKindCreate"];
STORE_ACTION_UPDATE = 2 [(gogoproto.enumvalue_customname) = "StoreActionKindUpdate"];
STORE_ACTION_REMOVE = 3 [(gogoproto.enumvalue_customname) = "StoreActionKindRemove"];
}
// StoreAction defines a target and operation to apply on the storage system.
message StoreAction {
StoreActionKind action = 1;
oneof target {
Node node = 2;
Service service = 3;
Task task = 4;
Network network = 5;
Cluster cluster = 6;
Secret secret = 7;
Resource resource = 8;
Extension extension = 9;
Config config = 10;
}
}
+34
View File
@@ -0,0 +1,34 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/types.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
// Allocator is the API provided by a manager group for agents to control the allocation of certain entities.
//
// API methods on this service are used only by agent nodes.
service ResourceAllocator {
rpc AttachNetwork(AttachNetworkRequest) returns (AttachNetworkResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
rpc DetachNetwork(DetachNetworkRequest) returns (DetachNetworkResponse) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-worker" roles: "swarm-manager" };
};
}
message AttachNetworkRequest {
NetworkAttachmentConfig config = 1;
string container_id = 2;
}
message AttachNetworkResponse {
string attachment_id = 1;
}
message DetachNetworkRequest {
string attachment_id = 1;
}
message DetachNetworkResponse {}
+44
View File
@@ -0,0 +1,44 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/objects.proto";
import "github.com/docker/swarmkit/api/raft.proto";
import weak "gogoproto/gogo.proto";
// StoreSnapshot is used to store snapshots of the store.
message StoreSnapshot {
// TODO(aaronl): The current method of assembling a StoreSnapshot
// structure and marshalling it is not optimal. It may be better to
// write out nodes, networks, tasks, etc. one at a time to an io.Writer
// using gogo-protobuf's io.DelimitedWriter. A new value of the version
// field could support this approach.
repeated Node nodes = 1;
repeated Service services = 2;
repeated Network networks = 3;
repeated Task tasks = 4;
repeated Cluster clusters = 5;
repeated Secret secrets = 6;
repeated Resource resources = 7;
repeated Extension extensions = 8;
repeated Config configs = 9;
}
// ClusterSnapshot stores cluster membership information in snapshots.
message ClusterSnapshot {
repeated RaftMember members = 1;
repeated uint64 removed = 2 [packed=false];
}
message Snapshot {
enum Version {
// V0 is the initial version of the StoreSnapshot message.
V0 = 0;
}
Version version = 1;
ClusterSnapshot membership = 2 [(gogoproto.nullable) = false];
StoreSnapshot store = 3 [(gogoproto.nullable) = false];
}
+456
View File
@@ -0,0 +1,456 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/types.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/any.proto";
import "google/protobuf/wrappers.proto";
// Specs are container objects for user provided input. All creations and
// updates are done through spec types. As a convention, user input from a spec
// is never touched in created objects. This allows one to verify that the
// users intent has not been modified.
//
// Put differently, spec types can be said to represent the desired state of
// the system. In situations where modifications need to be made to a
// particular component, API objects will either contain a copy of the spec
// component or a different representation to reflect allocation or resolution.
message NodeSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
enum Membership {
option (gogoproto.goproto_enum_prefix) = false;
PENDING = 0 [(gogoproto.enumvalue_customname) = "NodeMembershipPending"];
ACCEPTED = 1 [(gogoproto.enumvalue_customname) = "NodeMembershipAccepted"];
}
enum Availability {
option (gogoproto.goproto_enum_prefix) = false;
// Active nodes.
ACTIVE = 0 [(gogoproto.enumvalue_customname) = "NodeAvailabilityActive"];
// Paused nodes won't be considered by the scheduler, preventing any
// further task to run on them.
PAUSE = 1 [(gogoproto.enumvalue_customname) = "NodeAvailabilityPause"];
// Drained nodes are paused and any task already running on them will
// be evicted.
DRAIN = 2 [(gogoproto.enumvalue_customname) = "NodeAvailabilityDrain"];
}
// DesiredRole defines the role the node should have.
NodeRole desired_role = 2;
// Membership controls the admission of the node into the cluster.
Membership membership = 3;
// Availability allows a user to control the current scheduling status of a
// node.
Availability availability = 4;
}
// ServiceSpec defines the properties of a service.
//
// A service instructs the cluster in orchestrating repeated instances of a
// template, implemented as tasks. Based on the number of instances, scheduling
// strategy and restart policy, a number of application-level behaviors can be
// defined.
message ServiceSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
// Task defines the task template this service will spawn.
TaskSpec task = 2 [(gogoproto.nullable) = false];
oneof mode {
ReplicatedService replicated = 3;
GlobalService global = 4;
}
// Update contains settings which affect updates.
UpdateConfig update = 6;
// Rollback contains settings which affect rollbacks of updates.
UpdateConfig rollback = 9;
// ServiceSpec.Networks has been deprecated and is replaced by
// Networks field in Task (TaskSpec.Networks).
// This field (ServiceSpec.Networks) is kept for compatibility.
// In case TaskSpec.Networks does not exist, ServiceSpec.Networks
// is still honored if it exists.
repeated NetworkAttachmentConfig networks = 7 [deprecated=true];
// Service endpoint specifies the user provided configuration
// to properly discover and load balance a service.
EndpointSpec endpoint = 8;
}
// ReplicatedService sets the reconciliation target to certain number of replicas.
message ReplicatedService {
uint64 replicas = 1;
}
// GlobalService represents global service.
message GlobalService {
// Empty message for now.
}
message TaskSpec {
oneof runtime {
NetworkAttachmentSpec attachment = 8;
ContainerSpec container = 1;
GenericRuntimeSpec generic = 10;
}
// Resource requirements for the container.
ResourceRequirements resources = 2;
// RestartPolicy specifies what to do when a task fails or finishes.
RestartPolicy restart = 4;
// Placement specifies node selection constraints
Placement placement = 5;
// LogDriver specifies the log driver to use for the task. Any runtime will
// direct logs into the specified driver for the duration of the task.
Driver log_driver = 6;
// Networks specifies the list of network attachment
// configurations (which specify the network and per-network
// aliases) that this task spec is bound to.
repeated NetworkAttachmentConfig networks = 7;
// ForceUpdate is a counter that triggers an update even if no relevant
// parameters have been changed. We do this to allow forced restarts
// using the same reconciliation-based mechanism that performs rolling
// updates.
uint64 force_update = 9;
// ResourceReferences provides a generic way to specify resources that
// are used by this task, and should be sent down to agents along with
// the task. Inside the runtime field there may be more specific
// information about how to use the resource, but ResourceReferences
// establishes the relationship at the store level, and instructs the
// dispatcher to send the related objects.
//
// ResourceReferences is a list of ResourceReferences used by the task.
repeated ResourceReference resource_references = 11 [(gogoproto.nullable) = false];
}
message ResourceReference {
string resource_id = 1;
ResourceType resource_type = 2;
}
message GenericRuntimeSpec {
string kind = 1;
google.protobuf.Any payload = 2;
}
// NetworkAttachmentSpec specifies runtime parameters required to attach
// a container to a network.
message NetworkAttachmentSpec {
// ContainerID specifies a unique ID of the container for which
// this attachment is for.
string container_id = 1;
}
// Container specifies runtime parameters for a container.
message ContainerSpec {
// image defines the image reference, as specified in the
// distribution/reference package. This may include a registry host, name,
// tag or digest.
//
// The field will be directly passed to the engine pulling. Well-behaved
// service definitions will used immutable references, either through tags
// that don't change or verifiable digests.
string image = 1;
// Labels defines labels to be added to the container at creation time. If
// collisions with system labels occur, these labels will be overridden.
//
// This field *must* remain compatible with the Labels field of
// Annotations.
map<string, string> labels = 2;
// Command to run the the container. The first element is a path to the
// executable and the following elements are treated as arguments.
//
// If command is empty, execution will fall back to the image's entrypoint.
//
// Command should only be used when overriding entrypoint.
repeated string command = 3;
// Args specifies arguments provided to the image's entrypoint.
//
// If Command and Args are provided, Args will be appended to Command.
repeated string args = 4;
// Hostname specifies the hostname that will be set on containers created by docker swarm.
// All containers for a given service will have the same hostname
string hostname = 14;
// Env specifies the environment variables for the container in NAME=VALUE
// format. These must be compliant with [IEEE Std
// 1003.1-2001](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html).
repeated string env = 5;
// Dir defines the working directory to set for the container process.
string dir = 6;
// User specifies the user that should be employed to run the container.
//
// Note that the primary group may be specified by appending the group name
// or id to the user name, separated by a `:`. This syntax is
// `<user>:<group>`.
string user = 7;
// Groups specifies supplementary groups available to the user.
repeated string groups = 11;
// Privileges specifies security configuration/permissions.
Privileges privileges = 22;
// Init declares that a custom init will be running inside the container, if null, use the daemon's configured settings
google.protobuf.BoolValue init = 23;
// TTY declares that a TTY should be attached to the standard streams,
// including stdin if it is still open.
bool tty = 13 [(gogoproto.customname) = "TTY"];
// OpenStdin declares that the standard input (stdin) should be open.
bool open_stdin = 18;
// ReadOnly declares that the container root filesystem is read-only.
// This only impacts the root filesystem, not additional mounts (including
// tmpfs). For additional mounts that are not part of the initial rootfs,
// they will be decided by the modes passed in the mount definition.
bool read_only = 19;
// StopSignal defines the signal to stop the container.
string stop_signal = 20;
repeated Mount mounts = 8 [(gogoproto.nullable) = false];
// StopGracePeriod the grace period for stopping the container before
// forcefully killing the container.
// Note: Can't use stdduration here because this needs to be nullable.
google.protobuf.Duration stop_grace_period = 9;
// PullOptions allows one to parameterize an image pull.
message PullOptions {
// RegistryAuth is the registry auth token obtained from the client, required
// to pull private images. This is the unmodified JSON used as part of
// the `X-Registry-Auth` header.
// TODO(nishanttotla): This field will later be deprecated
string registry_auth = 64;
}
// PullOptions parameterize the behavior of image pulls.
PullOptions pull_options = 10;
// SecretReference contains references to zero or more secrets that
// will be exposed to the container.
repeated SecretReference secrets = 12;
// ConfigReference contains references to zero or more configs that
// will be exposed to the container.
repeated ConfigReference configs = 21;
// Hosts allow additional entries to be specified in /etc/hosts
// that associates IP addresses with hostnames.
// Detailed documentation is available in:
// http://man7.org/linux/man-pages/man5/hosts.5.html
// IP_address canonical_hostname [aliases...]
//
// The format of the Hosts in swarmkit follows the same as
// above.
// This is different from `docker run --add-host <hostname>:<ip>`
// where format is `<hostname>:<ip>`
repeated string hosts = 17;
// DNSConfig specifies DNS related configurations in resolver configuration file (resolv.conf)
// Detailed documentation is available in:
// http://man7.org/linux/man-pages/man5/resolv.conf.5.html
// TODO: domain is not supported yet
message DNSConfig {
// Nameservers specifies the IP addresses of the name servers
repeated string nameservers = 1;
// Search specifies the search list for host-name lookup
repeated string search = 2;
// Options allows certain internal resolver variables to be modified
repeated string options = 3;
}
// DNSConfig allows one to specify DNS related configuration in resolv.conf
DNSConfig dns_config = 15 [(gogoproto.customname) = "DNSConfig"];
// Healthcheck describes how to check the container is healthy. If the
// container is considered unhealthy, it will be destroyed, its creating
// task will exit and a new task will be rescheduled elsewhere. A container
// is considered unhealthy after `Retries` number of consecutive failures.
HealthConfig healthcheck = 16;
enum Isolation {
option (gogoproto.goproto_enum_prefix) = false;
// ISOLATION_DEFAULT uses whatever default value from the container runtime
ISOLATION_DEFAULT = 0 [(gogoproto.enumvalue_customname) = "ContainerIsolationDefault"];
// ISOLATION_PROCESS forces windows container isolation
ISOLATION_PROCESS = 1 [(gogoproto.enumvalue_customname) = "ContainerIsolationProcess"];
// ISOLATION_HYPERV forces Hyper-V isolation
ISOLATION_HYPERV = 2 [(gogoproto.enumvalue_customname) = "ContainerIsolationHyperV"];
}
// Isolation defines the isolation level for windows containers (default, process, hyperv).
// Runtimes that don't support it ignore that field
Isolation isolation = 24;
// PidsLimit prevents from OS resource damage by applications inside the container
// using fork bomb attack.
int64 pidsLimit = 25;
}
// EndpointSpec defines the properties that can be configured to
// access and loadbalance the service.
message EndpointSpec {
// ResolutionMode specifies the mode of resolution to use for
// internal loadbalancing between tasks which are all within
// the cluster. This is sometimes calls east-west data path.
enum ResolutionMode {
option (gogoproto.goproto_enum_prefix) = false;
// VIP resolution mode specifies that the
// service resolves to a logical IP and the requests
// are sent to that logical IP. Packets hitting that
// logical IP are load balanced to a chosen backend.
VIP = 0 [(gogoproto.enumvalue_customname) = "ResolutionModeVirtualIP"];
// DNSRR resolution mode specifies that the
// service directly gets resolved to one of the
// backend IP and the client directly initiates a
// request towards the actual backend. This requires
// that the client does not cache the DNS responses
// when the DNS response TTL is 0.
DNSRR = 1 [(gogoproto.enumvalue_customname) = "ResolutionModeDNSRoundRobin"];
}
ResolutionMode mode = 1;
// List of exposed ports that this service is accessible from
// external to the cluster.
repeated PortConfig ports = 2;
}
// NetworkSpec specifies user defined network parameters.
message NetworkSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
// DriverConfig specific configuration consumed by the network driver.
Driver driver_config = 2;
// IPv6Enabled enables support for IPv6 on the network.
bool ipv6_enabled = 3;
// internal restricts external access to the network. This may be
// accomplished by disabling the default gateway or through other means.
bool internal = 4;
IPAMOptions ipam = 5 [(gogoproto.customname) = "IPAM"];
// Attachable allows external(to swarm) entities to manually
// attach to this network. With this flag enabled, external
// entities such as containers running in an worker node in
// the cluster can manually attach to this network and access
// the services attached to this network. If this flag is not
// enabled(default case) no manual attachment to this network
// can happen.
bool attachable = 6;
// Ingress indicates this network will provide the routing-mesh.
// In older versions, the network providing the routing mesh was
// swarm internally created only and it was identified by the name
// "ingress" and the label "com.docker.swarm.internal": "true".
bool ingress = 7;
// ConfigFrom is the source of the configuration for this network.
oneof config_from {
// Network is the name of a network that provides the network
// specific configuration for this network, locally on the node
// where this network is being plumbed.
string network = 8;
}
}
// ClusterSpec specifies global cluster settings.
message ClusterSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
// DEPRECATED: AcceptancePolicy defines the certificate issuance policy.
// Acceptance policy is no longer customizable, and secrets have been
// replaced with join tokens.
AcceptancePolicy acceptance_policy = 2 [deprecated=true, (gogoproto.nullable) = false];
// Orchestration defines cluster-level orchestration settings.
OrchestrationConfig orchestration = 3 [(gogoproto.nullable) = false];
// Raft defines the cluster's raft settings.
RaftConfig raft = 4 [(gogoproto.nullable) = false];
// Dispatcher defines cluster-level dispatcher settings.
DispatcherConfig dispatcher = 5 [(gogoproto.nullable) = false];
// CAConfig defines cluster-level certificate authority settings.
CAConfig ca_config = 6 [(gogoproto.nullable) = false, (gogoproto.customname) = "CAConfig"];
// TaskDefaults specifies the default values to use for task creation.
TaskDefaults task_defaults = 7 [(gogoproto.nullable) = false];
// EncryptionConfig defines the cluster's encryption settings.
EncryptionConfig encryption_config = 8 [(gogoproto.nullable) = false];
}
// SecretSpec specifies a user-provided secret.
message SecretSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
// Data is the secret payload - the maximum size is 500KB (that is, 500*1024 bytes)
bytes data = 2;
// Templating controls whether and how to evaluate the secret payload as
// a template. If it is not set, no templating is used.
//
// The currently recognized values are:
// - golang: Go templating
Driver templating = 3;
// Driver is the the secret driver that is used to store the specified secret
Driver driver = 4;
}
// ConfigSpec specifies user-provided configuration files.
message ConfigSpec {
Annotations annotations = 1 [(gogoproto.nullable) = false];
// Data is the config payload - the maximum size is 500KB (that is, 500*1024 bytes)
// TODO(aaronl): Do we want to revise this to include multiple payloads in a single
// ConfigSpec? Define this to be a tar? etc...
bytes data = 2;
// Templating controls whether and how to evaluate the secret payload as
// a template. If it is not set, no templating is used.
//
// The currently recognized values are:
// - golang: Go templating
Driver templating = 3;
}
+1086
View File
File diff suppressed because it is too large Load Diff
+154
View File
@@ -0,0 +1,154 @@
syntax = "proto3";
package docker.swarmkit.v1;
import "github.com/docker/swarmkit/api/specs.proto";
import "github.com/docker/swarmkit/api/objects.proto";
import "github.com/docker/swarmkit/api/types.proto";
import "gogoproto/gogo.proto";
import "github.com/docker/swarmkit/protobuf/plugin/plugin.proto";
message Object {
oneof Object {
Node node = 1;
Service service = 2;
Network network = 3;
Task task = 4;
Cluster cluster = 5;
Secret secret = 6;
Resource resource = 7;
Extension extension = 8;
Config config = 9;
}
}
// FIXME(aaronl): These messages should ideally be embedded in SelectBy, but
// protoc generates bad code for that.
message SelectBySlot {
string service_id = 1 [(gogoproto.customname) = "ServiceID"];
uint64 slot = 2;
}
message SelectByCustom {
string kind = 1;
string index = 2;
string value = 3;
}
message SelectBy {
// TODO(aaronl): Are all of these things we want to expose in
// the API? Exposing them may commit us to maintaining those
// internal indices going forward.
oneof By {
// supported by all object types
string id = 1 [(gogoproto.customname) = "ID"]; // not applicable for FindObjects - use GetObject instead
string id_prefix = 2 [(gogoproto.customname) = "IDPrefix"];
string name = 3;
string name_prefix = 4;
SelectByCustom custom = 5;
SelectByCustom custom_prefix = 6;
// supported by tasks only
string service_id = 7 [(gogoproto.customname) = "ServiceID"];
string node_id = 8 [(gogoproto.customname) = "NodeID"];
SelectBySlot slot = 9;
TaskState desired_state = 10;
// supported by nodes only
NodeRole role = 11;
NodeSpec.Membership membership = 12;
// supported by: service, task
string referenced_network_id = 13 [(gogoproto.customname) = "ReferencedNetworkID"];
string referenced_secret_id = 14 [(gogoproto.customname) = "ReferencedSecretID"];
string referenced_config_id = 16 [(gogoproto.customname) = "ReferencedConfigID"];
// supported by: resource
string kind = 15;
}
}
// Watch defines the RPC methods for monitoring data store change.
service Watch {
// Watch starts a stream that returns any changes to objects that match
// the specified selectors. When the stream begins, it immediately sends
// an empty message back to the client. It is important to wait for
// this message before taking any actions that depend on an established
// stream of changes for consistency.
rpc Watch(WatchRequest) returns (stream WatchMessage) {
option (docker.protobuf.plugin.tls_authorization) = { roles: "swarm-manager" };
};
}
message WatchRequest {
message WatchEntry {
// Kind can contain a builtin type such as "node", "secret", etc. or
// the kind specified by a custom-defined object.
string kind = 1;
// Action (create/update/delete)
// This is a bitmask, so multiple actions may be OR'd together
WatchActionKind action = 2;
// Filters are combined using AND logic - an event must match
// all of them to pass the filter.
repeated SelectBy filters = 3;
}
// Multiple entries are combined using OR logic - i.e. if an event
// matches all of the selectors specified in any single watch entry,
// the event will be sent to the client.
repeated WatchEntry entries = 1;
// ResumeFrom provides an version to resume the watch from, if non-nil.
// The watch will return changes since this version, and continue to
// return new changes afterwards. Watch will return an error if the
// server has compacted its log and no longer has complete history to
// this point.
Version resume_from = 2;
// IncludeOldObject causes WatchMessages to include a copy of the
// previous version of the object on updates. Note that only live
// changes will include the old object (not historical changes
// retrieved using ResumeFrom).
bool include_old_object = 3;
}
// WatchMessage is the type of the stream that's returned to the client by
// Watch. Note that the first item of this stream will always be a WatchMessage
// with a nil Object, to signal that the stream has started.
message WatchMessage {
message Event {
// Action (create/update/delete)
// Note that WatchMessage does not expose "commit" events that
// mark transaction boundaries.
WatchActionKind action = 1;
// Matched object
Object object = 2;
// For updates, OldObject will optionally be included in the
// watch message, containing the previous version of the
// object, if IncludeOldObject was set in WatchRequest.
Object old_object = 3;
}
repeated Event events = 1;
// Index versions this change to the data store. It can be used to
// resume the watch from this point.
Version version = 2;
}
// WatchActionKind distinguishes between creations, updates, and removals. It
// is structured as a bitmap so multiple kinds of events can be requested with
// a mask.
enum WatchActionKind {
option (gogoproto.goproto_enum_prefix) = false;
option (gogoproto.enum_customname) = "WatchActionKind";
WATCH_ACTION_UNKNOWN = 0 [(gogoproto.enumvalue_customname) = "WatchActionKindUnknown"]; // default value, invalid
WATCH_ACTION_CREATE = 1 [(gogoproto.enumvalue_customname) = "WatchActionKindCreate"];
WATCH_ACTION_UPDATE = 2 [(gogoproto.enumvalue_customname) = "WatchActionKindUpdate"];
WATCH_ACTION_REMOVE = 4 [(gogoproto.enumvalue_customname) = "WatchActionKindRemove"];
}
+53
View File
@@ -0,0 +1,53 @@
syntax = "proto2";
package docker.protobuf.plugin;
import "google/protobuf/descriptor.proto";
message WatchSelectors {
// supported by all object types
optional bool id = 1;
optional bool id_prefix = 2;
optional bool name = 3;
optional bool name_prefix = 4;
optional bool custom = 5;
optional bool custom_prefix = 6;
// supported by tasks only
optional bool service_id = 7;
optional bool node_id = 8;
optional bool slot = 9;
optional bool desired_state = 10;
// supported by nodes only
optional bool role = 11;
optional bool membership = 12;
// supported by: resource
optional bool kind = 13;
}
message StoreObject {
required WatchSelectors watch_selectors = 1;
}
extend google.protobuf.MessageOptions {
optional bool deepcopy = 70000 [default=true];
optional StoreObject store_object = 70001;
}
message TLSAuthorization {
// Roles contains the acceptable TLS OU roles for the handler.
repeated string roles = 1;
// Insecure is set to true if this method does not require
// authorization. NOTE: Specifying both "insecure" and a nonempty
// list of roles is invalid. This would fail at codegen time.
optional bool insecure = 2;
}
extend google.protobuf.MethodOptions {
// TLSAuthorization contains the authorization parameters for this
// method.
optional TLSAuthorization tls_authorization = 73626345;
}