mirror of
https://github.com/rancher/os.git
synced 2025-06-20 20:21:54 +00:00
Merge pull request #2330 from niusmallnan/master
Config docker-sys bridge via system-docker args
This commit is contained in:
commit
738847dcf9
@ -82,7 +82,7 @@ ARG DFS_IMAGE=${OS_REPO}/docker:v${DOCKER_VERSION}-2
|
||||
ARG OS_BASE_URL_amd64=https://github.com/rancher/os-base/releases/download/v2018.02-3/os-base_amd64.tar.xz
|
||||
ARG OS_BASE_URL_arm64=https://github.com/rancher/os-base/releases/download/v2018.02-3/os-base_arm64.tar.xz
|
||||
|
||||
ARG SYSTEM_DOCKER_VERSION=17.06-ros3
|
||||
ARG SYSTEM_DOCKER_VERSION=17.06-ros4
|
||||
ARG SYSTEM_DOCKER_URL_amd64=https://github.com/niusmallnan/os-system-docker/releases/download/${SYSTEM_DOCKER_VERSION}/docker-amd64-${SYSTEM_DOCKER_VERSION}.tgz
|
||||
ARG SYSTEM_DOCKER_URL_arm64=https://github.com/niusmallnan/os-system-docker/releases/download/${SYSTEM_DOCKER_VERSION}/docker-arm64-${SYSTEM_DOCKER_VERSION}.tgz
|
||||
######################################################
|
||||
|
@ -1,12 +0,0 @@
|
||||
{
|
||||
"name": "bridge",
|
||||
"type": "bridge",
|
||||
"bridge": "docker-sys",
|
||||
"isDefaultGateway": true,
|
||||
"ipMasq": true,
|
||||
"hairpinMode": true,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "172.18.42.1/16"
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
bridge.d/
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"path": "/usr/bin/ros",
|
||||
"args": [
|
||||
"cni-glue",
|
||||
"poststop"
|
||||
]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"path": "/usr/bin/ros",
|
||||
"args": [
|
||||
"cni-glue"
|
||||
]
|
||||
}
|
@ -25,7 +25,6 @@ import (
|
||||
"github.com/rancher/os/config/cloudinit/datasource/metadata"
|
||||
"github.com/rancher/os/config/cloudinit/pkg"
|
||||
"github.com/rancher/os/log"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -44,14 +43,10 @@ func NewDatasource(root string) []*MetadataService {
|
||||
roots := make([]string, 0, 5)
|
||||
|
||||
if root == "" {
|
||||
if links, err := netlink.LinkList(); err == nil {
|
||||
if links, err := netconf.GetValidLinkList(); err == nil {
|
||||
log.Infof("Checking to see if a cloudstack server-identifier is available")
|
||||
for _, link := range links {
|
||||
linkName := link.Attrs().Name
|
||||
if linkName == "lo" {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Infof("searching for cloudstack server %s on %s", serverIdentifier, linkName)
|
||||
lease := netconf.GetDhcpLease(linkName)
|
||||
if server, ok := lease[serverIdentifier]; ok {
|
||||
|
@ -122,6 +122,7 @@ var schema = `{
|
||||
"storage_context": {"type": "string"},
|
||||
"exec": {"type": ["boolean", "null"]},
|
||||
"bridge": {"type": "string"},
|
||||
"bip": {"type": "string"},
|
||||
"config_file": {"type": "string"},
|
||||
"containerd": {"type": "string"},
|
||||
"debug": {"type": ["boolean", "null"]},
|
||||
|
@ -148,6 +148,7 @@ type UpgradeConfig struct {
|
||||
|
||||
type EngineOpts struct {
|
||||
Bridge string `yaml:"bridge,omitempty" opt:"bridge"`
|
||||
BIP string `yaml:"bip,omitempty" opt:"bip"`
|
||||
ConfigFile string `yaml:"config_file,omitempty" opt:"config-file"`
|
||||
Containerd string `yaml:"containerd,omitempty" opt:"containerd"`
|
||||
Debug *bool `yaml:"debug,omitempty" opt:"debug"`
|
||||
|
6
main.go
6
main.go
@ -4,11 +4,8 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/plugins/ipam/host-local"
|
||||
"github.com/containernetworking/cni/plugins/main/bridge"
|
||||
"github.com/docker/docker/docker"
|
||||
"github.com/docker/docker/pkg/reexec"
|
||||
"github.com/rancher/cniglue"
|
||||
"github.com/rancher/os/cmd/cloudinitexecute"
|
||||
"github.com/rancher/os/cmd/cloudinitsave"
|
||||
"github.com/rancher/os/cmd/control"
|
||||
@ -35,9 +32,6 @@ var entrypoints = map[string]func(){
|
||||
"ros-bootstrap": control.BootstrapMain,
|
||||
"ros-sysinit": sysinit.Main,
|
||||
"wait-for-docker": wait.Main,
|
||||
"cni-glue": glue.Main,
|
||||
"bridge": bridge.Main,
|
||||
"host-local": hostlocal.Main,
|
||||
"respawn": respawn.Main,
|
||||
|
||||
// Power commands
|
||||
|
@ -66,7 +66,7 @@ func createInterfaces(netCfg *NetworkConfig) {
|
||||
}
|
||||
|
||||
func createSlaveInterfaces(netCfg *NetworkConfig) {
|
||||
links, err := netlink.LinkList()
|
||||
links, err := GetValidLinkList()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to list links: %v", err)
|
||||
return
|
||||
@ -167,7 +167,7 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig, userSetHostname, userSetDNS bool
|
||||
createInterfaces(netCfg)
|
||||
createSlaveInterfaces(netCfg)
|
||||
|
||||
links, err := netlink.LinkList()
|
||||
links, err := GetValidLinkList()
|
||||
if err != nil {
|
||||
log.Errorf("error getting LinkList: %s", err)
|
||||
return false, err
|
||||
@ -177,10 +177,7 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig, userSetHostname, userSetDNS bool
|
||||
|
||||
//apply network config
|
||||
for _, link := range links {
|
||||
linkName := link.Attrs().Name
|
||||
if linkName != "lo" {
|
||||
applyOuter(link, netCfg, &wg, userSetHostname, userSetDNS)
|
||||
}
|
||||
applyOuter(link, netCfg, &wg, userSetHostname, userSetDNS)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@ -189,13 +186,11 @@ func ApplyNetworkConfigs(netCfg *NetworkConfig, userSetHostname, userSetDNS bool
|
||||
dnsSet := false
|
||||
for _, link := range links {
|
||||
linkName := link.Attrs().Name
|
||||
if linkName != "lo" {
|
||||
log.Infof("dns testing %s", linkName)
|
||||
lease := GetDhcpLease(linkName)
|
||||
if _, ok := lease["domain_name_servers"]; ok {
|
||||
log.Infof("dns was dhcp set for %s", linkName)
|
||||
dnsSet = true
|
||||
}
|
||||
log.Infof("dns testing %s", linkName)
|
||||
lease := GetDhcpLease(linkName)
|
||||
if _, ok := lease["domain_name_servers"]; ok {
|
||||
log.Infof("dns was dhcp set for %s", linkName)
|
||||
dnsSet = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,3 +505,22 @@ func runCmds(cmds []string, iface string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetValidLinkList() ([]netlink.Link, error) {
|
||||
var validLinkList []netlink.Link
|
||||
links, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
return validLinkList, err
|
||||
}
|
||||
|
||||
for _, l := range links {
|
||||
linkName := l.Attrs().Name
|
||||
if linkName == "lo" || linkName == "docker-sys" {
|
||||
continue
|
||||
}
|
||||
validLinkList = append(validLinkList, l)
|
||||
}
|
||||
|
||||
return validLinkList, nil
|
||||
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ rancher:
|
||||
system_docker:
|
||||
exec: true
|
||||
storage_driver: overlay2
|
||||
bridge: none
|
||||
bip: 172.18.42.1/16
|
||||
restart: false
|
||||
graph: /var/lib/system-docker
|
||||
group: root
|
||||
|
@ -5,8 +5,6 @@ github.com/boltdb/bolt v1.2.0
|
||||
github.com/cloudfoundry-incubator/candiedyaml 01cbc92901719f599b11f3a7e3b1768d7002b0bb https://github.com/rancher/candiedyaml
|
||||
github.com/cloudfoundry/gosigar 3ed7c74352dae6dc00bdc8c74045375352e3ec05
|
||||
github.com/codegangsta/cli d2b9ba9c38eb353ba3c6df3f57072348e19cc5c7 https://github.com/rancher/cli-1
|
||||
github.com/containernetworking/cni a8e4fa0dffdac6a236f85be91502603ec06957f9 https://github.com/rancher/cni.git
|
||||
github.com/coreos/go-iptables fbb73372b87f6e89951c2b6b31470c2c9d5cfae3
|
||||
github.com/coreos/go-systemd v4
|
||||
github.com/coreos/yaml 6b16a5714269b2f70720a45406b1babd947a17ef
|
||||
github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||
@ -35,7 +33,6 @@ github.com/opencontainers/specs f955d90e70a98ddfb886bd930ffd076da9b67998
|
||||
github.com/packethost/packngo v0.1.0
|
||||
github.com/pkg/errors d62207b3dc916c342cd6a7180fa861d898cf42ee
|
||||
github.com/pmezard/go-difflib d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||
github.com/rancher/cniglue b56bd68e5df113ad3fcc59c58034c22afaede877
|
||||
github.com/rancher/catalog-service/utils/version 81799167a6ed8666fb1640b3aae12bc407050c4f
|
||||
github.com/rcrowley/go-metrics eeba7bd0dd01ace6e690fa833b3f22aaec29af43
|
||||
github.com/ryanuber/go-glob 0067a9abd927e50aed5190662702f81231413ae0
|
||||
|
3
vendor/github.com/containernetworking/cni/.gitignore
generated
vendored
3
vendor/github.com/containernetworking/cni/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
||||
bin/
|
||||
gopath/
|
||||
*.sw[ponm]
|
29
vendor/github.com/containernetworking/cni/.travis.yml
generated
vendored
29
vendor/github.com/containernetworking/cni/.travis.yml
generated
vendored
@ -1,29 +0,0 @@
|
||||
language: go
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- go: 1.5.4
|
||||
env: GO15VENDOREXPERIMENT=1
|
||||
- go: 1.6.2
|
||||
- go: tip
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
env:
|
||||
global:
|
||||
- TOOLS_CMD=golang.org/x/tools/cmd
|
||||
- PATH=$GOROOT/bin:$PATH
|
||||
|
||||
install:
|
||||
- go get ${TOOLS_CMD}/cover
|
||||
- go get github.com/modocache/gover
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- ./test
|
||||
|
||||
notifications:
|
||||
email: false
|
86
vendor/github.com/containernetworking/cni/CONTRIBUTING.md
generated
vendored
86
vendor/github.com/containernetworking/cni/CONTRIBUTING.md
generated
vendored
@ -1,86 +0,0 @@
|
||||
# How to Contribute
|
||||
|
||||
CNI is [Apache 2.0 licensed](LICENSE) and accepts contributions via GitHub
|
||||
pull requests. This document outlines some of the conventions on development
|
||||
workflow, commit message formatting, contact points and other resources to make
|
||||
it easier to get your contribution accepted.
|
||||
|
||||
We gratefully welcome improvements to documentation as well as to code.
|
||||
|
||||
# Certificate of Origin
|
||||
|
||||
By contributing to this project you agree to the Developer Certificate of
|
||||
Origin (DCO). This document was created by the Linux Kernel community and is a
|
||||
simple statement that you, as a contributor, have the legal right to make the
|
||||
contribution. See the [DCO](DCO) file for details.
|
||||
|
||||
# Email and Chat
|
||||
|
||||
The project uses the the cni-dev email list and IRC chat:
|
||||
- Email: [cni-dev](https://groups.google.com/forum/#!forum/cni-dev)
|
||||
- IRC: #[containernetworking](irc://irc.freenode.org:6667/#containernetworking) channel on freenode.org
|
||||
|
||||
Please avoid emailing maintainers found in the MAINTAINERS file directly. They
|
||||
are very busy and read the mailing lists.
|
||||
|
||||
## Getting Started
|
||||
|
||||
- Fork the repository on GitHub
|
||||
- Read the [README](README.md) for build and test instructions
|
||||
- Play with the project, submit bugs, submit pull requests!
|
||||
|
||||
## Contribution workflow
|
||||
|
||||
This is a rough outline of how to prepare a contribution:
|
||||
|
||||
- Create a topic branch from where you want to base your work (usually branched from master).
|
||||
- Make commits of logical units.
|
||||
- Make sure your commit messages are in the proper format (see below).
|
||||
- Push your changes to a topic branch in your fork of the repository.
|
||||
- If you changed code, make sure the tests pass, and add any new tests as appropriate.
|
||||
- Make sure any new code files have a license header.
|
||||
- Submit a pull request to the original repository.
|
||||
|
||||
# Acceptance policy
|
||||
|
||||
These things will make a PR more likely to be accepted:
|
||||
|
||||
* a well-described requirement
|
||||
* tests for new code
|
||||
* tests for old code!
|
||||
* new code follows the conventions in old code
|
||||
* a good commit message (see below)
|
||||
|
||||
In general, we will merge a PR once two maintainers have endorsed it.
|
||||
Trivial changes (e.g., corrections to spelling) may get waved through.
|
||||
For substantial changes, more people may become involved, and you might get asked to resubmit the PR or divide the changes into more than one PR.
|
||||
|
||||
### Format of the Commit Message
|
||||
|
||||
We follow a rough convention for commit messages that is designed to answer two
|
||||
questions: what changed and why. The subject line should feature the what and
|
||||
the body of the commit should describe the why.
|
||||
|
||||
```
|
||||
scripts: add the test-cluster command
|
||||
|
||||
this uses tmux to setup a test cluster that you can easily kill and
|
||||
start for debugging.
|
||||
|
||||
Fixes #38
|
||||
```
|
||||
|
||||
The format can be described more formally as follows:
|
||||
|
||||
```
|
||||
<subsystem>: <what changed>
|
||||
<BLANK LINE>
|
||||
<why this change was made>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The first line is the subject and should be no longer than 70 characters, the
|
||||
second line is always blank, and other lines should be wrapped at 80 characters.
|
||||
This allows the message to be easier to read on GitHub as well as in various
|
||||
git tools.
|
36
vendor/github.com/containernetworking/cni/DCO
generated
vendored
36
vendor/github.com/containernetworking/cni/DCO
generated
vendored
@ -1,36 +0,0 @@
|
||||
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.
|
202
vendor/github.com/containernetworking/cni/LICENSE
generated
vendored
202
vendor/github.com/containernetworking/cni/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
5
vendor/github.com/containernetworking/cni/MAINTAINERS
generated
vendored
5
vendor/github.com/containernetworking/cni/MAINTAINERS
generated
vendored
@ -1,5 +0,0 @@
|
||||
Dan Williams <dcbw@redhat.com> (@dcbw)
|
||||
Gabe Rosenhouse <grosenhouse@pivotal.io> (@rosenhouse)
|
||||
Michael Bridgen <michael@weave.works> (@squaremo)
|
||||
Stefan Junker <stefan.junker@coreos.com> (@steveeJ)
|
||||
Tom Denham <tom@tigera.io> (@tomdee)
|
164
vendor/github.com/containernetworking/cni/README.md
generated
vendored
164
vendor/github.com/containernetworking/cni/README.md
generated
vendored
@ -1,164 +0,0 @@
|
||||
[](https://travis-ci.org/containernetworking/cni)
|
||||
[](https://coveralls.io/github/containernetworking/cni?branch=master)
|
||||
|
||||
# CNI - the Container Network Interface
|
||||
|
||||
## What is CNI?
|
||||
|
||||
The CNI (_Container Network Interface_) project consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins.
|
||||
CNI concerns itself only with network connectivity of containers and removing allocated resources when the container is deleted.
|
||||
Because of this focus, CNI has a wide range of support and the specification is simple to implement.
|
||||
|
||||
As well as the [specification](SPEC.md), this repository contains the Go source code of a library for integrating CNI into applications, an example command-line tool, a template for making new plugins, and the supported plugins.
|
||||
|
||||
The template code makes it straight-forward to create a CNI plugin for an existing container networking project.
|
||||
CNI also makes a good framework for creating a new container networking project from scratch.
|
||||
|
||||
## Why develop CNI?
|
||||
|
||||
Application containers on Linux are a rapidly evolving area, and within this area networking is not well addressed as it is highly environment-specific.
|
||||
We believe that many container runtimes and orchestrators will seek to solve the same problem of making the network layer pluggable.
|
||||
|
||||
To avoid duplication, we think it is prudent to define a common interface between the network plugins and container execution: hence we put forward this specification, along with libraries for Go and a set of plugins.
|
||||
|
||||
## Who is using CNI?
|
||||
|
||||
- [rkt - container engine](https://coreos.com/blog/rkt-cni-networking.html)
|
||||
- [Kurma - container runtime](http://kurma.io/)
|
||||
- [Kubernetes - a system to simplify container operations](http://kubernetes.io/docs/admin/network-plugins/)
|
||||
- [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/guardian-cni-adapter)
|
||||
- [Weave - a multi-host Docker network](https://github.com/weaveworks/weave)
|
||||
- [Project Calico - a layer 3 virtual network](https://github.com/projectcalico/calico-cni)
|
||||
- [Contiv Networking - policy networking for various use cases](https://github.com/contiv/netplugin)
|
||||
- [Mesos - a distributed systems kernel](https://github.com/apache/mesos/blob/master/docs/cni.md)
|
||||
|
||||
## Contributing to CNI
|
||||
|
||||
We welcome contributions, including [bug reports](https://github.com/containernetworking/cni/issues), and code and documentation improvements.
|
||||
If you intend to contribute to code or documentation, please read [CONTRIBUTING.md](CONTRIBUTING.md). Also see the [contact section](#contact) in this README.
|
||||
|
||||
## How do I use CNI?
|
||||
|
||||
### Requirements
|
||||
|
||||
CNI requires Go 1.5+ to build.
|
||||
|
||||
Go 1.5 users will need to set GO15VENDOREXPERIMENT=1 to get vendored
|
||||
dependencies. This flag is set by default in 1.6.
|
||||
|
||||
### Included Plugins
|
||||
|
||||
This repository includes a number of common plugins in the `plugins/` directory.
|
||||
Please see the [Documentation/](Documentation/) directory for documentation about particular plugins.
|
||||
|
||||
### Running the plugins
|
||||
|
||||
The scripts/ directory contains two scripts, `priv-net-run.sh` and `docker-run.sh`, that can be used to exercise the plugins.
|
||||
|
||||
**note - priv-net-run.sh depends on `jq`**
|
||||
|
||||
Start out by creating a netconf file to describe a network:
|
||||
|
||||
```bash
|
||||
$ mkdir -p /etc/cni/net.d
|
||||
$ cat >/etc/cni/net.d/10-mynet.conf <<EOF
|
||||
{
|
||||
"name": "mynet",
|
||||
"type": "bridge",
|
||||
"bridge": "cni0",
|
||||
"isGateway": true,
|
||||
"ipMasq": true,
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "10.22.0.0/16",
|
||||
"routes": [
|
||||
{ "dst": "0.0.0.0/0" }
|
||||
]
|
||||
}
|
||||
}
|
||||
EOF
|
||||
$ cat >/etc/cni/net.d/99-loopback.conf <<EOF
|
||||
{
|
||||
"type": "loopback"
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
The directory `/etc/cni/net.d` is the default location in which the scripts will look for net configurations.
|
||||
|
||||
Next, build the plugins:
|
||||
|
||||
```bash
|
||||
$ ./build
|
||||
```
|
||||
|
||||
Finally, execute a command (`ifconfig` in this example) in a private network namespace that has joined the `mynet` network:
|
||||
|
||||
```bash
|
||||
$ CNI_PATH=`pwd`/bin
|
||||
$ cd scripts
|
||||
$ sudo CNI_PATH=$CNI_PATH ./priv-net-run.sh ifconfig
|
||||
eth0 Link encap:Ethernet HWaddr f2:c2:6f:54:b8:2b
|
||||
inet addr:10.22.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
|
||||
inet6 addr: fe80::f0c2:6fff:fe54:b82b/64 Scope:Link
|
||||
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
||||
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:1 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:90 (90.0 B) TX bytes:0 (0.0 B)
|
||||
|
||||
lo Link encap:Local Loopback
|
||||
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||
inet6 addr: ::1/128 Scope:Host
|
||||
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||
```
|
||||
|
||||
The environment variable `CNI_PATH` tells the scripts and library where to look for plugin executables.
|
||||
|
||||
## Running a Docker container with network namespace set up by CNI plugins
|
||||
|
||||
Use the instructions in the previous section to define a netconf and build the plugins.
|
||||
Next, docker-run.sh script wraps `docker run`, to execute the plugins prior to entering the container:
|
||||
|
||||
```bash
|
||||
$ CNI_PATH=`pwd`/bin
|
||||
$ cd scripts
|
||||
$ sudo CNI_PATH=$CNI_PATH ./docker-run.sh --rm busybox:latest ifconfig
|
||||
eth0 Link encap:Ethernet HWaddr fa:60:70:aa:07:d1
|
||||
inet addr:10.22.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
|
||||
inet6 addr: fe80::f860:70ff:feaa:7d1/64 Scope:Link
|
||||
UP BROADCAST MULTICAST MTU:1500 Metric:1
|
||||
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:1 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:90 (90.0 B) TX bytes:0 (0.0 B)
|
||||
|
||||
lo Link encap:Local Loopback
|
||||
inet addr:127.0.0.1 Mask:255.0.0.0
|
||||
inet6 addr: ::1/128 Scope:Host
|
||||
UP LOOPBACK RUNNING MTU:65536 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:0
|
||||
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
|
||||
```
|
||||
|
||||
## What might CNI do in the future?
|
||||
|
||||
CNI currently covers a wide range of needs for network configuration due to it simple model and API.
|
||||
However, in the future CNI might want to branch out into other directions:
|
||||
|
||||
- Dynamic updates to existing network configuration
|
||||
- Dynamic policies for network bandwidth and firewall rules
|
||||
|
||||
If these topics of are interest, please contact the team via the mailing list or IRC and find some like-minded people in the community to put a proposal together.
|
||||
|
||||
## Contact
|
||||
|
||||
For any questions about CNI, please reach out on the mailing list:
|
||||
- Email: [cni-dev](https://groups.google.com/forum/#!forum/cni-dev)
|
||||
- IRC: #[containernetworking](irc://irc.freenode.org:6667/#containernetworking) channel on freenode.org
|
33
vendor/github.com/containernetworking/cni/ROADMAP.md
generated
vendored
33
vendor/github.com/containernetworking/cni/ROADMAP.md
generated
vendored
@ -1,33 +0,0 @@
|
||||
# CNI Roadmap
|
||||
|
||||
This document defines a high level roadmap for CNI development.
|
||||
The list below is not complete, and we advise to get the current project state from the [milestones defined in GitHub](https://github.com/containernetworking/cni/milestones).
|
||||
|
||||
## CNI Milestones
|
||||
|
||||
### [v0.2.0](https://github.com/containernetworking/cni/milestones/v0.2.0)
|
||||
|
||||
* Signed release binaries
|
||||
* Introduction of a testing strategy/framework
|
||||
|
||||
### [v0.3.0](https://github.com/containernetworking/cni/milestones/v0.3.0)
|
||||
|
||||
* Further increase test coverage
|
||||
* Simpler default route handling in bridge plugin
|
||||
* Clarify project description, documentation and contribution guidelines
|
||||
|
||||
### [v0.4.0](https://github.com/containernetworking/cni/milestones/v0.4.0)
|
||||
|
||||
* Further increase test coverage
|
||||
* Simpler bridging of host interface
|
||||
* Improve IPAM allocator predictability
|
||||
* Allow in- and output of arbitrary K/V pairs for plugins
|
||||
|
||||
### [v1.0.0](https://github.com/containernetworking/cni/milestones/v1.0.0)
|
||||
|
||||
- Plugin composition functionality
|
||||
- IPv6 support
|
||||
- Stable SPEC
|
||||
- Strategy and tooling for backwards compatibility
|
||||
- Complete test coverage
|
||||
- Integrate build artefact generation with CI
|
267
vendor/github.com/containernetworking/cni/SPEC.md
generated
vendored
267
vendor/github.com/containernetworking/cni/SPEC.md
generated
vendored
@ -1,267 +0,0 @@
|
||||
# Container Networking Interface Proposal
|
||||
|
||||
## Overview
|
||||
|
||||
This document proposes a generic plugin-based networking solution for application containers on Linux, the _Container Networking Interface_, or _CNI_.
|
||||
It is derived from the [rkt Networking Proposal][rkt-networking-proposal], which aimed to satisfy many of the [design considerations][rkt-networking-design] for networking in [rkt][rkt-github].
|
||||
|
||||
For the purposes of this proposal, we define two terms very specifically:
|
||||
- _container_ can be considered synonymous with a [Linux _network namespace_][namespaces]. What unit this corresponds to depends on a particular container runtime implementation: for example, in implementations of the [App Container Spec][appc-github] like rkt, each _pod_ runs in a unique network namespace. In [Docker][docker], on the other hand, network namespaces generally exist for each separate Docker container.
|
||||
- _network_ refers to a group of entities that are uniquely addressable that can communicate amongst each other. This could be either an individual container (as specified above), a machine, or some other network device (e.g. a router). Containers can be conceptually _added to_ or _removed from_ one or more networks.
|
||||
|
||||
[rkt-networking-proposal]: https://docs.google.com/a/coreos.com/document/d/1PUeV68q9muEmkHmRuW10HQ6cHgd4819_67pIxDRVNlM/edit#heading=h.ievko3xsjwxd
|
||||
[rkt-networking-design]:
|
||||
https://docs.google.com/a/coreos.com/document/d/1CTAL4gwqRofjxyp4tTkbgHtAwb2YCcP14UEbHNizd8g
|
||||
[rkt-github]: https://github.com/coreos/rkt
|
||||
[namespaces]: http://man7.org/linux/man-pages/man7/namespaces.7.html
|
||||
[appc-github]: https://github.com/appc/spec
|
||||
[docker]: https://docker.com
|
||||
|
||||
## General considerations
|
||||
|
||||
The intention is for the container runtime to first create a new network namespace for the container.
|
||||
It then determines which networks this container should belong to and for each network, which plugin must be executed.
|
||||
The network configuration is in JSON format and can easily be stored in a file.
|
||||
The network configuration includes mandatory fields such as "name" and "type" as well as plugin (type) specific ones.
|
||||
The network configuration allows for fields to change values between invocations. For this purpose there is an optional field "args" which should contain the varying information.
|
||||
The container runtime sequentially sets up the networks by executing the corresponding plugin for each network.
|
||||
Upon completion of the container lifecycle, the runtime executes the plugins in reverse order (relative to the order in which they were added) to disconnect them from the networks.
|
||||
|
||||
## CNI Plugin
|
||||
|
||||
### Overview
|
||||
|
||||
Each CNI plugin is implemented as an executable that is invoked by the container management system (e.g. rkt or Docker).
|
||||
|
||||
A CNI plugin is responsible for inserting a network interface into the container network namespace (e.g. one end of a veth pair) and making any necessary changes on the host (e.g. attaching other end of veth into a bridge).
|
||||
It should then assign the IP to the interface and setup the routes consistent with IP Address Management section by invoking appropriate IPAM plugin.
|
||||
|
||||
### Parameters
|
||||
|
||||
The operations that the CNI plugin needs to support are:
|
||||
|
||||
|
||||
- Add container to network
|
||||
- Parameters:
|
||||
- **Version**. The version of CNI spec that the caller is using (container management system or the invoking plugin).
|
||||
- **Container ID**. This is optional but recommended, and should be unique across an administrative domain while the container is live (it may be reused in the future). For example, an environment with an IPAM system may require that each container is allocated a unique ID and that each IP allocation can thus be correlated back to a particular container. As another example, in appc implementations this would be the _pod ID_.
|
||||
- **Network namespace path**. This represents the path to the network namespace to be added, i.e. /proc/[pid]/ns/net or a bind-mount/link to it.
|
||||
- **Network configuration**. This is a JSON document describing a network to which a container can be joined. The schema is described below.
|
||||
- **Extra arguments**. This provides an alternative mechanism to allow simple configuration of CNI plugins on a per-container basis.
|
||||
- **Name of the interface inside the container**. This is the name that should be assigned to the interface created inside the container (network namespace); consequently it must comply with the standard Linux restrictions on interface names.
|
||||
- Result:
|
||||
- **IPs assigned to the interface**. This is either an IPv4 address, an IPv6 address, or both.
|
||||
- **DNS information**. Dictionary that includes DNS information for nameservers, domain, search domains and options.
|
||||
|
||||
- Delete container from network
|
||||
- Parameters:
|
||||
- **Version**. The version of CNI spec that the caller is using (container management system or the invoking plugin).
|
||||
- **Container ID**, as defined above.
|
||||
- **Network namespace path**, as defined above.
|
||||
- **Network configuration**, as defined above.
|
||||
- **Extra arguments**, as defined above.
|
||||
- **Name of the interface inside the container**, as defined above.
|
||||
|
||||
The executable command-line API uses the type of network (see [Network Configuration](#network-configuration) below) as the name of the executable to invoke.
|
||||
It will then look for this executable in a list of predefined directories. Once found, it will invoke the executable using the following environment variables for argument passing:
|
||||
- `CNI_VERSION`: [Semantic Version 2.0](http://semver.org) of CNI specification. This effectively versions the CNI_XXX environment variables.
|
||||
- `CNI_COMMAND`: indicates the desired operation; either `ADD` or `DEL`
|
||||
- `CNI_CONTAINERID`: Container ID
|
||||
- `CNI_NETNS`: Path to network namespace file
|
||||
- `CNI_IFNAME`: Interface name to set up
|
||||
- `CNI_ARGS`: Extra arguments passed in by the user at invocation time. Alphanumeric key-value pairs separated by semicolons; for example, "FOO=BAR;ABC=123"
|
||||
- `CNI_PATH`: Colon-separated list of paths to search for CNI plugin executables
|
||||
|
||||
Network configuration in JSON format is streamed to the plugin through stdin. This means it is not tied to a particular file on disk and can contain information which changes between invocations.
|
||||
|
||||
|
||||
### Result
|
||||
|
||||
Success is indicated by a return code of zero and the following JSON printed to stdout in the case of the ADD command. This should be the same output as was returned by the IPAM plugin (see [IP Allocation](#ip-allocation) for details).
|
||||
|
||||
```
|
||||
{
|
||||
"cniVersion": "0.1.0",
|
||||
"ip4": {
|
||||
"ip": <ipv4-and-subnet-in-CIDR>,
|
||||
"gateway": <ipv4-of-the-gateway>, (optional)
|
||||
"routes": <list-of-ipv4-routes> (optional)
|
||||
},
|
||||
"ip6": {
|
||||
"ip": <ipv6-and-subnet-in-CIDR>,
|
||||
"gateway": <ipv6-of-the-gateway>, (optional)
|
||||
"routes": <list-of-ipv6-routes> (optional)
|
||||
},
|
||||
"dns": {
|
||||
"nameservers": <list-of-nameservers> (optional)
|
||||
"domain": <name-of-local-domain> (optional)
|
||||
"search": <list-of-additional-search-domains> (optional)
|
||||
"options": <list-of-options> (optional)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cniVersion` specifies a [Semantic Version 2.0](http://semver.org) of CNI specification used by the plugin.
|
||||
`dns` field contains a dictionary consisting of common DNS information that this network is aware of.
|
||||
The result is returned in the same format as specified in the [configuration](#network-configuration).
|
||||
The specification does not declare how this information must be processed by CNI consumers.
|
||||
Examples include generating an `/etc/resolv.conf` file to be injected into the container filesystem or running a DNS forwarder on the host.
|
||||
|
||||
Errors are indicated by a non-zero return code and the following JSON being printed to stdout:
|
||||
```
|
||||
{
|
||||
"cniVersion": "0.1.0",
|
||||
"code": <numeric-error-code>,
|
||||
"msg": <short-error-message>,
|
||||
"details": <long-error-message> (optional)
|
||||
}
|
||||
```
|
||||
|
||||
`cniVersion` specifies a [Semantic Version 2.0](http://semver.org) of CNI specification used by the plugin.
|
||||
Error codes 0-99 are reserved for well-known errors (see [Well-known Error Codes](#well-known-error-codes) section).
|
||||
Values of 100+ can be freely used for plugin specific errors.
|
||||
|
||||
In addition, stderr can be used for unstructured output such as logs.
|
||||
|
||||
### Network Configuration
|
||||
|
||||
The network configuration is described in JSON form. The configuration can be stored on disk or generated from other sources by the container runtime. The following fields are well-known and have the following meaning:
|
||||
- `cniVersion` (string): [Semantic Version 2.0](http://semver.org) of CNI specification to which this configuration conforms.
|
||||
- `name` (string): Network name. This should be unique across all containers on the host (or other administrative domain).
|
||||
- `type` (string): Refers to the filename of the CNI plugin executable.
|
||||
- `args` (dictionary): Optional additional arguments provided by the container runtime. For example a dictionary of labels could be passed to CNI plugins by adding them to a labels field under `args`.
|
||||
- `ipMasq` (boolean): Optional (if supported by the plugin). Set up an IP masquerade on the host for this network. This is necessary if the host will act as a gateway to subnets that are not able to route to the IP assigned to the container.
|
||||
- `ipam`: Dictionary with IPAM specific values:
|
||||
- `type` (string): Refers to the filename of the IPAM plugin executable.
|
||||
- `routes` (list): List of subnets (in CIDR notation) that the CNI plugin should ensure are reachable by routing them through the network. Each entry is a dictionary containing:
|
||||
- `dst` (string): subnet in CIDR notation
|
||||
- `gw` (string): IP address of the gateway to use. If not specified, the default gateway for the subnet is assumed (as determined by the IPAM plugin).
|
||||
- `dns`: Dictionary with DNS specific values:
|
||||
- `nameservers` (list of strings): list of a priority-ordered list of DNS nameservers that this network is aware of. Each entry in the list is a string containing either an IPv4 or an IPv6 address.
|
||||
- `domain` (string): the local domain used for short hostname lookups.
|
||||
- `search` (list of strings): list of priority ordered search domains for short hostname lookups. Will be preferred over `domain` by most resolvers.
|
||||
- `options` (list of strings): list of options that can be passed to the resolver
|
||||
|
||||
Plugins may define additional fields that they accept and may generate an error if called with unknown fields. The exception to this is the `args` field may be used to pass arbitrary data which may be ignored by plugins.
|
||||
### Example configurations
|
||||
|
||||
```json
|
||||
{
|
||||
"cniVersion": "0.1.0",
|
||||
"name": "dbnet",
|
||||
"type": "bridge",
|
||||
// type (plugin) specific
|
||||
"bridge": "cni0",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
// ipam specific
|
||||
"subnet": "10.1.0.0/16",
|
||||
"gateway": "10.1.0.1"
|
||||
},
|
||||
"dns": {
|
||||
"nameservers": [ "10.1.0.1" ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"cniVersion": "0.1.0",
|
||||
"name": "pci",
|
||||
"type": "ovs",
|
||||
// type (plugin) specific
|
||||
"bridge": "ovs0",
|
||||
"vxlanID": 42,
|
||||
"ipam": {
|
||||
"type": "dhcp",
|
||||
"routes": [ { "dst": "10.3.0.0/16" }, { "dst": "10.4.0.0/16" } ]
|
||||
}
|
||||
// args may be ignored by plugins
|
||||
"args": {
|
||||
"labels" : {
|
||||
"appVersion" : "1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"cniVersion": "0.1",
|
||||
"name": "wan",
|
||||
"type": "macvlan",
|
||||
// ipam specific
|
||||
"ipam": {
|
||||
"type": "dhcp",
|
||||
"routes": [ { "dst": "10.0.0.0/8", "gw": "10.0.0.1" } ]
|
||||
},
|
||||
"dns": {
|
||||
"nameservers": [ "10.0.0.1" ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### IP Allocation
|
||||
|
||||
As part of its operation, a CNI plugin is expected to assign (and maintain) an IP address to the interface and install any necessary routes relevant for that interface. This gives the CNI plugin great flexibility but also places a large burden on it. Many CNI plugins would need to have the same code to support several IP management schemes that users may desire (e.g. dhcp, host-local).
|
||||
|
||||
To lessen the burden and make IP management strategy be orthogonal to the type of CNI plugin, we define a second type of plugin -- IP Address Management Plugin (IPAM plugin). It is however the responsibility of the CNI plugin to invoke the IPAM plugin at the proper moment in its execution. The IPAM plugin is expected to determine the interface IP/subnet, Gateway and Routes and return this information to the "main" plugin to apply. The IPAM plugin may obtain the information via a protocol (e.g. dhcp), data stored on a local filesystem, the "ipam" section of the Network Configuration file or a combination of the above.
|
||||
|
||||
#### IP Address Management (IPAM) Interface
|
||||
|
||||
Like CNI plugins, the IPAM plugins are invoked by running an executable. The executable is searched for in a predefined list of paths, indicated to the CNI plugin via `CNI_PATH`. The IPAM Plugin receives all the same environment variables that were passed in to the CNI plugin. Just like the CNI plugin, IPAM receives the network configuration via stdin.
|
||||
|
||||
Success is indicated by a zero return code and the following JSON being printed to stdout (in the case of the ADD command):
|
||||
|
||||
```
|
||||
{
|
||||
"cniVersion": "0.1.0",
|
||||
"ip4": {
|
||||
"ip": <ipv4-and-subnet-in-CIDR>,
|
||||
"gateway": <ipv4-of-the-gateway>, (optional)
|
||||
"routes": <list-of-ipv4-routes> (optional)
|
||||
},
|
||||
"ip6": {
|
||||
"ip": <ipv6-and-subnet-in-CIDR>,
|
||||
"gateway": <ipv6-of-the-gateway>, (optional)
|
||||
"routes": <list-of-ipv6-routes> (optional)
|
||||
},
|
||||
"dns": {
|
||||
"nameservers": <list-of-nameservers> (optional)
|
||||
"domain": <name-of-local-domain> (optional)
|
||||
"search": <list-of-search-domains> (optional)
|
||||
"options": <list-of-options> (optional)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`cniVersion` specifies a [Semantic Version 2.0](http://semver.org) of CNI specification used by the plugin.
|
||||
`gateway` is the default gateway for this subnet, if one exists.
|
||||
It does not instruct the CNI plugin to add any routes with this gateway: routes to add are specified separately via the `routes` field.
|
||||
An example use of this value is for the CNI plugin to add this IP address to the linux-bridge to make it a gateway.
|
||||
|
||||
Each route entry is a dictionary with the following fields:
|
||||
- `dst` (string): Destination subnet specified in CIDR notation.
|
||||
- `gw` (string): IP of the gateway. If omitted, a default gateway is assumed (as determined by the CNI plugin).
|
||||
|
||||
The "dns" field contains a dictionary consisting of common DNS information.
|
||||
- `nameservers` (list of strings): list of a priority-ordered list of DNS nameservers that this network is aware of. Each entry in the list is a string containing either an IPv4 or an IPv6 address.
|
||||
- `domain` (string): the local domain used for short hostname lookups.
|
||||
- `search` (list of strings): list of priority ordered search domains for short hostname lookups. Will be preferred over `domain` by most resolvers.
|
||||
- `options` (list of strings): list of options that can be passed to the resolver
|
||||
See [CNI Plugin Result](#result) section for more information.
|
||||
|
||||
Errors and logs are communicated in the same way as the CNI plugin. See [CNI Plugin Result](#result) section for details.
|
||||
|
||||
IPAM plugin examples:
|
||||
- **host-local**: Select an unused (by other containers on the same host) IP within the specified range.
|
||||
- **dhcp**: Use DHCP protocol to acquire and maintain a lease. The DHCP requests will be sent via the created container interface; therefore, the associated network must support broadcast.
|
||||
|
||||
#### Notes
|
||||
- Routes are expected to be added with a 0 metric.
|
||||
- A default route may be specified via "0.0.0.0/0". Since another network might have already configured the default route, the CNI plugin should be prepared to skip over its default route definition.
|
||||
|
||||
## Well-known Error Codes
|
||||
- `1` - Incompatible CNI version
|
||||
- `2` - Unsupported field in network configuration. The error message must contain the key and value of the unsupported field.
|
30
vendor/github.com/containernetworking/cni/build
generated
vendored
30
vendor/github.com/containernetworking/cni/build
generated
vendored
@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
ORG_PATH="github.com/containernetworking"
|
||||
REPO_PATH="${ORG_PATH}/cni"
|
||||
|
||||
if [ ! -h gopath/src/${REPO_PATH} ]; then
|
||||
mkdir -p gopath/src/${ORG_PATH}
|
||||
ln -s ../../../.. gopath/src/${REPO_PATH} || exit 255
|
||||
fi
|
||||
|
||||
export GO15VENDOREXPERIMENT=1
|
||||
export GOBIN=${PWD}/bin
|
||||
export GOPATH=${PWD}/gopath
|
||||
|
||||
echo "Building API"
|
||||
go build "$@" ${REPO_PATH}/libcni
|
||||
|
||||
echo "Building reference CLI"
|
||||
go install "$@" ${REPO_PATH}/cnitool
|
||||
|
||||
echo "Building plugins"
|
||||
PLUGINS="plugins/meta/* plugins/main/* plugins/ipam/*"
|
||||
for d in $PLUGINS; do
|
||||
if [ -d $d ]; then
|
||||
plugin=$(basename $d)
|
||||
echo " " $plugin
|
||||
go install "$@" ${REPO_PATH}/$d
|
||||
fi
|
||||
done
|
73
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
73
vendor/github.com/containernetworking/cni/libcni/api.go
generated
vendored
@ -1,73 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package libcni
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
type RuntimeConf struct {
|
||||
ContainerID string
|
||||
NetNS string
|
||||
IfName string
|
||||
Args [][2]string
|
||||
}
|
||||
|
||||
type NetworkConfig struct {
|
||||
Network *types.NetConf
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
type CNI interface {
|
||||
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error)
|
||||
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
||||
}
|
||||
|
||||
type CNIConfig struct {
|
||||
Path []string
|
||||
}
|
||||
|
||||
func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error) {
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
|
||||
}
|
||||
|
||||
func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
|
||||
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
|
||||
}
|
||||
|
||||
// =====
|
||||
func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
|
||||
return &invoke.Args{
|
||||
Command: action,
|
||||
ContainerID: rt.ContainerID,
|
||||
NetNS: rt.NetNS,
|
||||
PluginArgs: rt.Args,
|
||||
IfName: rt.IfName,
|
||||
Path: strings.Join(c.Path, ":"),
|
||||
}
|
||||
}
|
85
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
85
vendor/github.com/containernetworking/cni/libcni/conf.go
generated
vendored
@ -1,85 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package libcni
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func ConfFromBytes(bytes []byte) (*NetworkConfig, error) {
|
||||
conf := &NetworkConfig{Bytes: bytes}
|
||||
if err := json.Unmarshal(bytes, &conf.Network); err != nil {
|
||||
return nil, fmt.Errorf("error parsing configuration: %s", err)
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func ConfFromFile(filename string) (*NetworkConfig, error) {
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading %s: %s", filename, err)
|
||||
}
|
||||
return ConfFromBytes(bytes)
|
||||
}
|
||||
|
||||
func ConfFiles(dir string) ([]string, error) {
|
||||
// In part, adapted from rkt/networking/podenv.go#listFiles
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
switch {
|
||||
case err == nil: // break
|
||||
case os.IsNotExist(err):
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confFiles := []string{}
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
continue
|
||||
}
|
||||
if filepath.Ext(f.Name()) == ".conf" {
|
||||
confFiles = append(confFiles, filepath.Join(dir, f.Name()))
|
||||
}
|
||||
}
|
||||
return confFiles, nil
|
||||
}
|
||||
|
||||
func LoadConf(dir, name string) (*NetworkConfig, error) {
|
||||
files, err := ConfFiles(dir)
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case len(files) == 0:
|
||||
return nil, fmt.Errorf("no net configurations found")
|
||||
}
|
||||
sort.Strings(files)
|
||||
|
||||
for _, confFile := range files {
|
||||
conf, err := ConfFromFile(confFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if conf.Network.Name == name {
|
||||
return conf, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf(`no net configuration with name "%s" in %s`, name, dir)
|
||||
}
|
76
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
76
vendor/github.com/containernetworking/cni/pkg/invoke/args.go
generated
vendored
@ -1,76 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CNIArgs interface {
|
||||
// For use with os/exec; i.e., return nil to inherit the
|
||||
// environment from this process
|
||||
AsEnv() []string
|
||||
}
|
||||
|
||||
type inherited struct{}
|
||||
|
||||
var inheritArgsFromEnv inherited
|
||||
|
||||
func (_ *inherited) AsEnv() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ArgsFromEnv() CNIArgs {
|
||||
return &inheritArgsFromEnv
|
||||
}
|
||||
|
||||
type Args struct {
|
||||
Command string
|
||||
ContainerID string
|
||||
NetNS string
|
||||
PluginArgs [][2]string
|
||||
PluginArgsStr string
|
||||
IfName string
|
||||
Path string
|
||||
}
|
||||
|
||||
func (args *Args) AsEnv() []string {
|
||||
env := os.Environ()
|
||||
pluginArgsStr := args.PluginArgsStr
|
||||
if pluginArgsStr == "" {
|
||||
pluginArgsStr = stringify(args.PluginArgs)
|
||||
}
|
||||
|
||||
env = append(env,
|
||||
"CNI_COMMAND="+args.Command,
|
||||
"CNI_CONTAINERID="+args.ContainerID,
|
||||
"CNI_NETNS="+args.NetNS,
|
||||
"CNI_ARGS="+pluginArgsStr,
|
||||
"CNI_IFNAME="+args.IfName,
|
||||
"CNI_PATH="+args.Path)
|
||||
return env
|
||||
}
|
||||
|
||||
// taken from rkt/networking/net_plugin.go
|
||||
func stringify(pluginArgs [][2]string) string {
|
||||
entries := make([]string, len(pluginArgs))
|
||||
|
||||
for i, kv := range pluginArgs {
|
||||
entries[i] = strings.Join(kv[:], "=")
|
||||
}
|
||||
|
||||
return strings.Join(entries, ";")
|
||||
}
|
53
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
53
vendor/github.com/containernetworking/cni/pkg/invoke/delegate.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
func DelegateAdd(delegatePlugin string, netconf []byte) (*types.Result, error) {
|
||||
if os.Getenv("CNI_COMMAND") != "ADD" {
|
||||
return nil, fmt.Errorf("CNI_COMMAND is not ADD")
|
||||
}
|
||||
|
||||
paths := strings.Split(os.Getenv("CNI_PATH"), ":")
|
||||
|
||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ExecPluginWithResult(pluginPath, netconf, ArgsFromEnv())
|
||||
}
|
||||
|
||||
func DelegateDel(delegatePlugin string, netconf []byte) error {
|
||||
if os.Getenv("CNI_COMMAND") != "DEL" {
|
||||
return fmt.Errorf("CNI_COMMAND is not DEL")
|
||||
}
|
||||
|
||||
paths := strings.Split(os.Getenv("CNI_PATH"), ":")
|
||||
|
||||
pluginPath, err := FindInPath(delegatePlugin, paths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ExecPluginWithoutResult(pluginPath, netconf, ArgsFromEnv())
|
||||
}
|
75
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
75
vendor/github.com/containernetworking/cni/pkg/invoke/exec.go
generated
vendored
@ -1,75 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
func pluginErr(err error, output []byte) error {
|
||||
if _, ok := err.(*exec.ExitError); ok {
|
||||
emsg := types.Error{}
|
||||
if perr := json.Unmarshal(output, &emsg); perr != nil {
|
||||
return fmt.Errorf("netplugin failed but error parsing its diagnostic message %q: %v", string(output), perr)
|
||||
}
|
||||
details := ""
|
||||
if emsg.Details != "" {
|
||||
details = fmt.Sprintf("; %v", emsg.Details)
|
||||
}
|
||||
return fmt.Errorf("%v%v", emsg.Msg, details)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func ExecPluginWithResult(pluginPath string, netconf []byte, args CNIArgs) (*types.Result, error) {
|
||||
stdoutBytes, err := execPlugin(pluginPath, netconf, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &types.Result{}
|
||||
err = json.Unmarshal(stdoutBytes, res)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func ExecPluginWithoutResult(pluginPath string, netconf []byte, args CNIArgs) error {
|
||||
_, err := execPlugin(pluginPath, netconf, args)
|
||||
return err
|
||||
}
|
||||
|
||||
func execPlugin(pluginPath string, netconf []byte, args CNIArgs) ([]byte, error) {
|
||||
stdout := &bytes.Buffer{}
|
||||
|
||||
c := exec.Cmd{
|
||||
Env: args.AsEnv(),
|
||||
Path: pluginPath,
|
||||
Args: []string{pluginPath},
|
||||
Stdin: bytes.NewBuffer(netconf),
|
||||
Stdout: stdout,
|
||||
Stderr: os.Stderr,
|
||||
}
|
||||
if err := c.Run(); err != nil {
|
||||
return nil, pluginErr(err, stdout.Bytes())
|
||||
}
|
||||
|
||||
return stdout.Bytes(), nil
|
||||
}
|
47
vendor/github.com/containernetworking/cni/pkg/invoke/find.go
generated
vendored
47
vendor/github.com/containernetworking/cni/pkg/invoke/find.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package invoke
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// FindInPath returns the full path of the plugin by searching in the provided path
|
||||
func FindInPath(plugin string, paths []string) (string, error) {
|
||||
if plugin == "" {
|
||||
return "", fmt.Errorf("no plugin name provided")
|
||||
}
|
||||
|
||||
if len(paths) == 0 {
|
||||
return "", fmt.Errorf("no paths provided")
|
||||
}
|
||||
|
||||
var fullpath string
|
||||
for _, path := range paths {
|
||||
full := filepath.Join(path, plugin)
|
||||
if fi, err := os.Stat(full); err == nil && fi.Mode().IsRegular() {
|
||||
fullpath = full
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if fullpath == "" {
|
||||
return "", fmt.Errorf("failed to find plugin %q in path %s", plugin, paths)
|
||||
}
|
||||
|
||||
return fullpath, nil
|
||||
}
|
51
vendor/github.com/containernetworking/cni/pkg/ip/cidr.go
generated
vendored
51
vendor/github.com/containernetworking/cni/pkg/ip/cidr.go
generated
vendored
@ -1,51 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"net"
|
||||
)
|
||||
|
||||
// NextIP returns IP incremented by 1
|
||||
func NextIP(ip net.IP) net.IP {
|
||||
i := ipToInt(ip)
|
||||
return intToIP(i.Add(i, big.NewInt(1)))
|
||||
}
|
||||
|
||||
// PrevIP returns IP decremented by 1
|
||||
func PrevIP(ip net.IP) net.IP {
|
||||
i := ipToInt(ip)
|
||||
return intToIP(i.Sub(i, big.NewInt(1)))
|
||||
}
|
||||
|
||||
func ipToInt(ip net.IP) *big.Int {
|
||||
if v := ip.To4(); v != nil {
|
||||
return big.NewInt(0).SetBytes(v)
|
||||
}
|
||||
return big.NewInt(0).SetBytes(ip.To16())
|
||||
}
|
||||
|
||||
func intToIP(i *big.Int) net.IP {
|
||||
return net.IP(i.Bytes())
|
||||
}
|
||||
|
||||
// Network masks off the host portion of the IP
|
||||
func Network(ipn *net.IPNet) *net.IPNet {
|
||||
return &net.IPNet{
|
||||
IP: ipn.IP.Mask(ipn.Mask),
|
||||
Mask: ipn.Mask,
|
||||
}
|
||||
}
|
31
vendor/github.com/containernetworking/cni/pkg/ip/ipforward.go
generated
vendored
31
vendor/github.com/containernetworking/cni/pkg/ip/ipforward.go
generated
vendored
@ -1,31 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func EnableIP4Forward() error {
|
||||
return echo1("/proc/sys/net/ipv4/ip_forward")
|
||||
}
|
||||
|
||||
func EnableIP6Forward() error {
|
||||
return echo1("/proc/sys/net/ipv6/conf/all/forwarding")
|
||||
}
|
||||
|
||||
func echo1(f string) error {
|
||||
return ioutil.WriteFile(f, []byte("1"), 0644)
|
||||
}
|
66
vendor/github.com/containernetworking/cni/pkg/ip/ipmasq.go
generated
vendored
66
vendor/github.com/containernetworking/cni/pkg/ip/ipmasq.go
generated
vendored
@ -1,66 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
)
|
||||
|
||||
// SetupIPMasq installs iptables rules to masquerade traffic
|
||||
// coming from ipn and going outside of it
|
||||
func SetupIPMasq(ipn *net.IPNet, chain string, comment string) error {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to locate iptables: %v", err)
|
||||
}
|
||||
|
||||
if err = ipt.NewChain("nat", chain); err != nil {
|
||||
if err.(*iptables.Error).ExitStatus() != 1 {
|
||||
// TODO(eyakubovich): assumes exit status 1 implies chain exists
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = ipt.AppendUnique("nat", chain, "-d", ipn.String(), "-j", "ACCEPT", "-m", "comment", "--comment", comment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ipt.AppendUnique("nat", chain, "!", "-d", "224.0.0.0/4", "-j", "MASQUERADE", "-m", "comment", "--comment", comment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ipt.AppendUnique("nat", "POSTROUTING", "-s", ipn.String(), "-j", chain, "-m", "comment", "--comment", comment)
|
||||
}
|
||||
|
||||
// TeardownIPMasq undoes the effects of SetupIPMasq
|
||||
func TeardownIPMasq(ipn *net.IPNet, chain string, comment string) error {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to locate iptables: %v", err)
|
||||
}
|
||||
|
||||
if err = ipt.Delete("nat", "POSTROUTING", "-s", ipn.String(), "-j", chain, "-m", "comment", "--comment", comment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ipt.ClearChain("nat", chain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ipt.DeleteChain("nat", chain)
|
||||
}
|
153
vendor/github.com/containernetworking/cni/pkg/ip/link.go
generated
vendored
153
vendor/github.com/containernetworking/cni/pkg/ip/link.go
generated
vendored
@ -1,153 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/ns"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func makeVethPair(name, peer string, mtu int) (netlink.Link, error) {
|
||||
veth := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: name,
|
||||
Flags: net.FlagUp,
|
||||
MTU: mtu,
|
||||
},
|
||||
PeerName: peer,
|
||||
}
|
||||
if err := netlink.LinkAdd(veth); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return veth, nil
|
||||
}
|
||||
|
||||
func makeVeth(name string, mtu int) (peerName string, veth netlink.Link, err error) {
|
||||
for i := 0; i < 10; i++ {
|
||||
peerName, err = RandomVethName()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
veth, err = makeVethPair(name, peerName, mtu)
|
||||
switch {
|
||||
case err == nil:
|
||||
return
|
||||
|
||||
case os.IsExist(err):
|
||||
continue
|
||||
|
||||
default:
|
||||
err = fmt.Errorf("failed to make veth pair: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// should really never be hit
|
||||
err = fmt.Errorf("failed to find a unique veth name")
|
||||
return
|
||||
}
|
||||
|
||||
// RandomVethName returns string "veth" with random prefix (hashed from entropy)
|
||||
func RandomVethName() (string, error) {
|
||||
entropy := make([]byte, 4)
|
||||
_, err := rand.Reader.Read(entropy)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to generate random veth name: %v", err)
|
||||
}
|
||||
|
||||
// NetworkManager (recent versions) will ignore veth devices that start with "veth"
|
||||
return fmt.Sprintf("veth%x", entropy), nil
|
||||
}
|
||||
|
||||
// SetupVeth sets up a virtual ethernet link.
|
||||
// Should be in container netns, and will switch back to hostNS to set the host
|
||||
// veth end up.
|
||||
func SetupVeth(contVethName string, mtu int, hostNS ns.NetNS) (hostVeth, contVeth netlink.Link, err error) {
|
||||
var hostVethName string
|
||||
hostVethName, contVeth, err = makeVeth(contVethName, mtu)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = netlink.LinkSetUp(contVeth); err != nil {
|
||||
err = fmt.Errorf("failed to set %q up: %v", contVethName, err)
|
||||
return
|
||||
}
|
||||
|
||||
hostVeth, err = netlink.LinkByName(hostVethName)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = netlink.LinkSetNsFd(hostVeth, int(hostNS.Fd())); err != nil {
|
||||
err = fmt.Errorf("failed to move veth to host netns: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = hostNS.Do(func(_ ns.NetNS) error {
|
||||
hostVeth, err := netlink.LinkByName(hostVethName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup %q in %q: %v", hostVethName, hostNS.Path(), err)
|
||||
}
|
||||
|
||||
if err = netlink.LinkSetUp(hostVeth); err != nil {
|
||||
return fmt.Errorf("failed to set %q up: %v", hostVethName, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// DelLinkByName removes an interface link.
|
||||
func DelLinkByName(ifName string) error {
|
||||
iface, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
if err = netlink.LinkDel(iface); err != nil {
|
||||
return fmt.Errorf("failed to delete %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DelLinkByNameAddr remove an interface returns its IP address
|
||||
// of the specified family
|
||||
func DelLinkByNameAddr(ifName string, family int) (*net.IPNet, error) {
|
||||
iface, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
addrs, err := netlink.AddrList(iface, family)
|
||||
if err != nil || len(addrs) == 0 {
|
||||
return nil, fmt.Errorf("failed to get IP addresses for %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
if err = netlink.LinkDel(iface); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
return addrs[0].IPNet, nil
|
||||
}
|
47
vendor/github.com/containernetworking/cni/pkg/ip/route.go
generated
vendored
47
vendor/github.com/containernetworking/cni/pkg/ip/route.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ip
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// AddDefaultRoute sets the default route on the given gateway.
|
||||
func AddDefaultRoute(gw net.IP, dev netlink.Link) error {
|
||||
_, defNet, _ := net.ParseCIDR("0.0.0.0/0")
|
||||
return AddRoute(defNet, gw, dev)
|
||||
}
|
||||
|
||||
// AddRoute adds a universally-scoped route to a device.
|
||||
func AddRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error {
|
||||
return netlink.RouteAdd(&netlink.Route{
|
||||
LinkIndex: dev.Attrs().Index,
|
||||
Scope: netlink.SCOPE_UNIVERSE,
|
||||
Dst: ipn,
|
||||
Gw: gw,
|
||||
})
|
||||
}
|
||||
|
||||
// AddHostRoute adds a host-scoped route to a device.
|
||||
func AddHostRoute(ipn *net.IPNet, gw net.IP, dev netlink.Link) error {
|
||||
return netlink.RouteAdd(&netlink.Route{
|
||||
LinkIndex: dev.Attrs().Index,
|
||||
Scope: netlink.SCOPE_HOST,
|
||||
Dst: ipn,
|
||||
Gw: gw,
|
||||
})
|
||||
}
|
68
vendor/github.com/containernetworking/cni/pkg/ipam/ipam.go
generated
vendored
68
vendor/github.com/containernetworking/cni/pkg/ipam/ipam.go
generated
vendored
@ -1,68 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ipam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/invoke"
|
||||
"github.com/containernetworking/cni/pkg/ip"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func ExecAdd(plugin string, netconf []byte) (*types.Result, error) {
|
||||
return invoke.DelegateAdd(plugin, netconf)
|
||||
}
|
||||
|
||||
func ExecDel(plugin string, netconf []byte) error {
|
||||
return invoke.DelegateDel(plugin, netconf)
|
||||
}
|
||||
|
||||
// ConfigureIface takes the result of IPAM plugin and
|
||||
// applies to the ifName interface
|
||||
func ConfigureIface(ifName string, res *types.Result) error {
|
||||
link, err := netlink.LinkByName(ifName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetUp(link); err != nil {
|
||||
return fmt.Errorf("failed to set %q UP: %v", ifName, err)
|
||||
}
|
||||
|
||||
// TODO(eyakubovich): IPv6
|
||||
addr := &netlink.Addr{IPNet: &res.IP4.IP, Label: ""}
|
||||
if err = netlink.AddrAdd(link, addr); err != nil {
|
||||
return fmt.Errorf("failed to add IP addr to %q: %v", ifName, err)
|
||||
}
|
||||
|
||||
for _, r := range res.IP4.Routes {
|
||||
gw := r.GW
|
||||
if gw == nil {
|
||||
gw = res.IP4.Gateway
|
||||
}
|
||||
if err = ip.AddRoute(&r.Dst, gw, link); err != nil {
|
||||
// we skip over duplicate routes as we assume the first one wins
|
||||
if !os.IsExist(err) {
|
||||
return fmt.Errorf("failed to add route '%v via %v dev %v': %v", r.Dst, gw, ifName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
31
vendor/github.com/containernetworking/cni/pkg/ns/README.md
generated
vendored
31
vendor/github.com/containernetworking/cni/pkg/ns/README.md
generated
vendored
@ -1,31 +0,0 @@
|
||||
### Namespaces, Threads, and Go
|
||||
On Linux each OS thread can have a different network namespace. Go's thread scheduling model switches goroutines between OS threads based on OS thread load and whether the goroutine would block other goroutines. This can result in a goroutine switching network namespaces without notice and lead to errors in your code.
|
||||
|
||||
### Namespace Switching
|
||||
Switching namespaces with the `ns.Set()` method is not recommended without additional strategies to prevent unexpected namespace changes when your goroutines switch OS threads.
|
||||
|
||||
Go provides the `runtime.LockOSThread()` function to ensure a specific goroutine executes on its current OS thread and prevents any other goroutine from running in that thread until the locked one exits. Careful usage of `LockOSThread()` and goroutines can provide good control over which network namespace a given goroutine executes in.
|
||||
|
||||
For example, you cannot rely on the `ns.Set()` namespace being the current namespace after the `Set()` call unless you do two things. First, the goroutine calling `Set()` must have previously called `LockOSThread()`. Second, you must ensure `runtime.UnlockOSThread()` is not called somewhere in-between. You also cannot rely on the initial network namespace remaining the current network namespace if any other code in your program switches namespaces, unless you have already called `LockOSThread()` in that goroutine. Note that `LockOSThread()` prevents the Go scheduler from optimally scheduling goroutines for best performance, so `LockOSThread()` should only be used in small, isolated goroutines that release the lock quickly.
|
||||
|
||||
### Do() The Recommended Thing
|
||||
The `ns.Do()` method provides control over network namespaces for you by implementing these strategies. All code dependent on a particular network namespace should be wrapped in the `ns.Do()` method to ensure the correct namespace is selected for the duration of your code. For example:
|
||||
|
||||
```go
|
||||
targetNs, err := ns.NewNS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = targetNs.Do(func(hostNs ns.NetNS) error {
|
||||
dummy := &netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: "dummy0",
|
||||
},
|
||||
}
|
||||
return netlink.LinkAdd(dummy)
|
||||
})
|
||||
```
|
||||
|
||||
### Further Reading
|
||||
- https://github.com/golang/go/wiki/LockOSThread
|
||||
- http://morsmachine.dk/go-scheduler
|
315
vendor/github.com/containernetworking/cni/pkg/ns/ns.go
generated
vendored
315
vendor/github.com/containernetworking/cni/pkg/ns/ns.go
generated
vendored
@ -1,315 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ns
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type NetNS interface {
|
||||
// Executes the passed closure in this object's network namespace,
|
||||
// attempting to restore the original namespace before returning.
|
||||
// However, since each OS thread can have a different network namespace,
|
||||
// and Go's thread scheduling is highly variable, callers cannot
|
||||
// guarantee any specific namespace is set unless operations that
|
||||
// require that namespace are wrapped with Do(). Also, no code called
|
||||
// from Do() should call runtime.UnlockOSThread(), or the risk
|
||||
// of executing code in an incorrect namespace will be greater. See
|
||||
// https://github.com/golang/go/wiki/LockOSThread for further details.
|
||||
Do(toRun func(NetNS) error) error
|
||||
|
||||
// Sets the current network namespace to this object's network namespace.
|
||||
// Note that since Go's thread scheduling is highly variable, callers
|
||||
// cannot guarantee the requested namespace will be the current namespace
|
||||
// after this function is called; to ensure this wrap operations that
|
||||
// require the namespace with Do() instead.
|
||||
Set() error
|
||||
|
||||
// Returns the filesystem path representing this object's network namespace
|
||||
Path() string
|
||||
|
||||
// Returns a file descriptor representing this object's network namespace
|
||||
Fd() uintptr
|
||||
|
||||
// Cleans up this instance of the network namespace; if this instance
|
||||
// is the last user the namespace will be destroyed
|
||||
Close() error
|
||||
}
|
||||
|
||||
type netNS struct {
|
||||
file *os.File
|
||||
mounted bool
|
||||
closed bool
|
||||
}
|
||||
|
||||
func getCurrentThreadNetNSPath() string {
|
||||
// /proc/self/ns/net returns the namespace of the main thread, not
|
||||
// of whatever thread this goroutine is running on. Make sure we
|
||||
// use the thread's net namespace since the thread is switching around
|
||||
return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
|
||||
}
|
||||
|
||||
// Returns an object representing the current OS thread's network namespace
|
||||
func GetCurrentNS() (NetNS, error) {
|
||||
return GetNS(getCurrentThreadNetNSPath())
|
||||
}
|
||||
|
||||
const (
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h
|
||||
NSFS_MAGIC = 0x6e736673
|
||||
PROCFS_MAGIC = 0x9fa0
|
||||
)
|
||||
|
||||
type NSPathNotExistErr struct{ msg string }
|
||||
|
||||
func (e NSPathNotExistErr) Error() string { return e.msg }
|
||||
|
||||
type NSPathNotNSErr struct{ msg string }
|
||||
|
||||
func (e NSPathNotNSErr) Error() string { return e.msg }
|
||||
|
||||
func IsNSorErr(nspath string) error {
|
||||
stat := syscall.Statfs_t{}
|
||||
if err := syscall.Statfs(nspath, &stat); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)}
|
||||
} else {
|
||||
err = fmt.Errorf("failed to Statfs %q: %v", nspath, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
switch stat.Type {
|
||||
case PROCFS_MAGIC:
|
||||
// Kernel < 3.19
|
||||
|
||||
validPathContent := "ns/"
|
||||
validName := strings.Contains(nspath, validPathContent)
|
||||
if !validName {
|
||||
return NSPathNotNSErr{msg: fmt.Sprintf("path %q doesn't contain %q", nspath, validPathContent)}
|
||||
}
|
||||
|
||||
return nil
|
||||
case NSFS_MAGIC:
|
||||
// Kernel >= 3.19
|
||||
|
||||
return nil
|
||||
default:
|
||||
return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an object representing the namespace referred to by @path
|
||||
func GetNS(nspath string) (NetNS, error) {
|
||||
err := IsNSorErr(nspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fd, err := os.Open(nspath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &netNS{file: fd}, nil
|
||||
}
|
||||
|
||||
// Creates a new persistent network namespace and returns an object
|
||||
// representing that namespace, without switching to it
|
||||
func NewNS() (NetNS, error) {
|
||||
const nsRunDir = "/var/run/netns"
|
||||
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Reader.Read(b)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate random netns name: %v", err)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(nsRunDir, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// create an empty file at the mount point
|
||||
nsName := fmt.Sprintf("cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
nsPath := path.Join(nsRunDir, nsName)
|
||||
mountPointFd, err := os.Create(nsPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mountPointFd.Close()
|
||||
|
||||
// Ensure the mount point is cleaned up on errors; if the namespace
|
||||
// was successfully mounted this will have no effect because the file
|
||||
// is in-use
|
||||
defer os.RemoveAll(nsPath)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
// do namespace work in a dedicated goroutine, so that we can safely
|
||||
// Lock/Unlock OSThread without upsetting the lock/unlock state of
|
||||
// the caller of this function
|
||||
var fd *os.File
|
||||
go (func() {
|
||||
defer wg.Done()
|
||||
runtime.LockOSThread()
|
||||
|
||||
var origNS NetNS
|
||||
origNS, err = GetNS(getCurrentThreadNetNSPath())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer origNS.Close()
|
||||
|
||||
// create a new netns on the current thread
|
||||
err = unix.Unshare(unix.CLONE_NEWNET)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer origNS.Set()
|
||||
|
||||
// bind mount the new netns from the current thread onto the mount point
|
||||
err = unix.Mount(getCurrentThreadNetNSPath(), nsPath, "none", unix.MS_BIND, "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fd, err = os.Open(nsPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})()
|
||||
wg.Wait()
|
||||
|
||||
if err != nil {
|
||||
unix.Unmount(nsPath, unix.MNT_DETACH)
|
||||
return nil, fmt.Errorf("failed to create namespace: %v", err)
|
||||
}
|
||||
|
||||
return &netNS{file: fd, mounted: true}, nil
|
||||
}
|
||||
|
||||
func (ns *netNS) Path() string {
|
||||
return ns.file.Name()
|
||||
}
|
||||
|
||||
func (ns *netNS) Fd() uintptr {
|
||||
return ns.file.Fd()
|
||||
}
|
||||
|
||||
func (ns *netNS) errorIfClosed() error {
|
||||
if ns.closed {
|
||||
return fmt.Errorf("%q has already been closed", ns.file.Name())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ns *netNS) Close() error {
|
||||
if err := ns.errorIfClosed(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ns.file.Close(); err != nil {
|
||||
return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err)
|
||||
}
|
||||
ns.closed = true
|
||||
|
||||
if ns.mounted {
|
||||
if err := unix.Unmount(ns.file.Name(), unix.MNT_DETACH); err != nil {
|
||||
return fmt.Errorf("Failed to unmount namespace %s: %v", ns.file.Name(), err)
|
||||
}
|
||||
if err := os.RemoveAll(ns.file.Name()); err != nil {
|
||||
return fmt.Errorf("Failed to clean up namespace %s: %v", ns.file.Name(), err)
|
||||
}
|
||||
ns.mounted = false
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ns *netNS) Do(toRun func(NetNS) error) error {
|
||||
if err := ns.errorIfClosed(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
containedCall := func(hostNS NetNS) error {
|
||||
threadNS, err := GetNS(getCurrentThreadNetNSPath())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open current netns: %v", err)
|
||||
}
|
||||
defer threadNS.Close()
|
||||
|
||||
// switch to target namespace
|
||||
if err = ns.Set(); err != nil {
|
||||
return fmt.Errorf("error switching to ns %v: %v", ns.file.Name(), err)
|
||||
}
|
||||
defer threadNS.Set() // switch back
|
||||
|
||||
return toRun(hostNS)
|
||||
}
|
||||
|
||||
// save a handle to current network namespace
|
||||
hostNS, err := GetNS(getCurrentThreadNetNSPath())
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to open current namespace: %v", err)
|
||||
}
|
||||
defer hostNS.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
var innerError error
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
runtime.LockOSThread()
|
||||
innerError = containedCall(hostNS)
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
return innerError
|
||||
}
|
||||
|
||||
func (ns *netNS) Set() error {
|
||||
if err := ns.errorIfClosed(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, _, err := unix.Syscall(unix.SYS_SETNS, ns.Fd(), uintptr(unix.CLONE_NEWNET), 0); err != 0 {
|
||||
return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithNetNSPath executes the passed closure under the given network
|
||||
// namespace, restoring the original namespace afterwards.
|
||||
func WithNetNSPath(nspath string, toRun func(NetNS) error) error {
|
||||
ns, err := GetNS(nspath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ns.Close()
|
||||
return ns.Do(toRun)
|
||||
}
|
161
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
161
vendor/github.com/containernetworking/cni/pkg/skel/skel.go
generated
vendored
@ -1,161 +0,0 @@
|
||||
// Copyright 2014 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package skel provides skeleton code for a CNI plugin.
|
||||
// In particular, it implements argument parsing and validation.
|
||||
package skel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
// CmdArgs captures all the arguments passed in to the plugin
|
||||
// via both env vars and stdin
|
||||
type CmdArgs struct {
|
||||
ContainerID string
|
||||
Netns string
|
||||
IfName string
|
||||
Args string
|
||||
Path string
|
||||
StdinData []byte
|
||||
}
|
||||
|
||||
type reqForCmdEntry map[string]bool
|
||||
|
||||
// PluginMain is the "main" for a plugin. It accepts
|
||||
// two callback functions for add and del commands.
|
||||
func PluginMain(cmdAdd, cmdDel func(_ *CmdArgs) error) {
|
||||
var cmd, contID, netns, ifName, args, path string
|
||||
|
||||
vars := []struct {
|
||||
name string
|
||||
val *string
|
||||
reqForCmd reqForCmdEntry
|
||||
}{
|
||||
{
|
||||
"CNI_COMMAND",
|
||||
&cmd,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_CONTAINERID",
|
||||
&contID,
|
||||
reqForCmdEntry{
|
||||
"ADD": false,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_NETNS",
|
||||
&netns,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_IFNAME",
|
||||
&ifName,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_ARGS",
|
||||
&args,
|
||||
reqForCmdEntry{
|
||||
"ADD": false,
|
||||
"DEL": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
"CNI_PATH",
|
||||
&path,
|
||||
reqForCmdEntry{
|
||||
"ADD": true,
|
||||
"DEL": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
argsMissing := false
|
||||
for _, v := range vars {
|
||||
*v.val = os.Getenv(v.name)
|
||||
if v.reqForCmd[cmd] && *v.val == "" {
|
||||
log.Printf("%v env variable missing", v.name)
|
||||
argsMissing = true
|
||||
}
|
||||
}
|
||||
|
||||
if argsMissing {
|
||||
dieMsg("required env variables missing")
|
||||
}
|
||||
|
||||
stdinData, err := ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
dieMsg("error reading from stdin: %v", err)
|
||||
}
|
||||
|
||||
cmdArgs := &CmdArgs{
|
||||
ContainerID: contID,
|
||||
Netns: netns,
|
||||
IfName: ifName,
|
||||
Args: args,
|
||||
Path: path,
|
||||
StdinData: stdinData,
|
||||
}
|
||||
|
||||
switch cmd {
|
||||
case "ADD":
|
||||
err = cmdAdd(cmdArgs)
|
||||
|
||||
case "DEL":
|
||||
err = cmdDel(cmdArgs)
|
||||
|
||||
default:
|
||||
dieMsg("unknown CNI_COMMAND: %v", cmd)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if e, ok := err.(*types.Error); ok {
|
||||
// don't wrap Error in Error
|
||||
dieErr(e)
|
||||
}
|
||||
dieMsg(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func dieMsg(f string, args ...interface{}) {
|
||||
e := &types.Error{
|
||||
Code: 100,
|
||||
Msg: fmt.Sprintf(f, args...),
|
||||
}
|
||||
dieErr(e)
|
||||
}
|
||||
|
||||
func dieErr(e *types.Error) {
|
||||
if err := e.Print(); err != nil {
|
||||
log.Print("Error writing error JSON to stdout: ", err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
101
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
101
vendor/github.com/containernetworking/cni/pkg/types/args.go
generated
vendored
@ -1,101 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UnmarshallableBool typedef for builtin bool
|
||||
// because builtin type's methods can't be declared
|
||||
type UnmarshallableBool bool
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
// Returns boolean true if the string is "1" or "[Tt]rue"
|
||||
// Returns boolean false if the string is "0" or "[Ff]alse"
|
||||
func (b *UnmarshallableBool) UnmarshalText(data []byte) error {
|
||||
s := strings.ToLower(string(data))
|
||||
switch s {
|
||||
case "1", "true":
|
||||
*b = true
|
||||
case "0", "false":
|
||||
*b = false
|
||||
default:
|
||||
return fmt.Errorf("Boolean unmarshal error: invalid input %s", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshallableString typedef for builtin string
|
||||
type UnmarshallableString string
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
// Returns the string
|
||||
func (s *UnmarshallableString) UnmarshalText(data []byte) error {
|
||||
*s = UnmarshallableString(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommonArgs contains the IgnoreUnknown argument
|
||||
// and must be embedded by all Arg structs
|
||||
type CommonArgs struct {
|
||||
IgnoreUnknown UnmarshallableBool `json:"ignoreunknown,omitempty"`
|
||||
}
|
||||
|
||||
// GetKeyField is a helper function to receive Values
|
||||
// Values that represent a pointer to a struct
|
||||
func GetKeyField(keyString string, v reflect.Value) reflect.Value {
|
||||
return v.Elem().FieldByName(keyString)
|
||||
}
|
||||
|
||||
// LoadArgs parses args from a string in the form "K=V;K2=V2;..."
|
||||
func LoadArgs(args string, container interface{}) error {
|
||||
if args == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
containerValue := reflect.ValueOf(container)
|
||||
|
||||
pairs := strings.Split(args, ";")
|
||||
unknownArgs := []string{}
|
||||
for _, pair := range pairs {
|
||||
kv := strings.Split(pair, "=")
|
||||
if len(kv) != 2 {
|
||||
return fmt.Errorf("ARGS: invalid pair %q", pair)
|
||||
}
|
||||
keyString := kv[0]
|
||||
valueString := kv[1]
|
||||
keyField := GetKeyField(keyString, containerValue)
|
||||
if !keyField.IsValid() {
|
||||
unknownArgs = append(unknownArgs, pair)
|
||||
continue
|
||||
}
|
||||
|
||||
u := keyField.Addr().Interface().(encoding.TextUnmarshaler)
|
||||
err := u.UnmarshalText([]byte(valueString))
|
||||
if err != nil {
|
||||
return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
|
||||
}
|
||||
}
|
||||
|
||||
isIgnoreUnknown := GetKeyField("IgnoreUnknown", containerValue).Bool()
|
||||
if len(unknownArgs) > 0 && !isIgnoreUnknown {
|
||||
return fmt.Errorf("ARGS: unknown args %q", unknownArgs)
|
||||
}
|
||||
return nil
|
||||
}
|
191
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
191
vendor/github.com/containernetworking/cni/pkg/types/types.go
generated
vendored
@ -1,191 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// like net.IPNet but adds JSON marshalling and unmarshalling
|
||||
type IPNet net.IPNet
|
||||
|
||||
// ParseCIDR takes a string like "10.2.3.1/24" and
|
||||
// return IPNet with "10.2.3.1" and /24 mask
|
||||
func ParseCIDR(s string) (*net.IPNet, error) {
|
||||
ip, ipn, err := net.ParseCIDR(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ipn.IP = ip
|
||||
return ipn, nil
|
||||
}
|
||||
|
||||
func (n IPNet) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal((*net.IPNet)(&n).String())
|
||||
}
|
||||
|
||||
func (n *IPNet) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmp, err := ParseCIDR(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*n = IPNet(*tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetConf describes a network.
|
||||
type NetConf struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
IPAM struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
} `json:"ipam,omitempty"`
|
||||
DNS DNS `json:"dns"`
|
||||
}
|
||||
|
||||
// Result is what gets returned from the plugin (via stdout) to the caller
|
||||
type Result struct {
|
||||
IP4 *IPConfig `json:"ip4,omitempty"`
|
||||
IP6 *IPConfig `json:"ip6,omitempty"`
|
||||
DNS DNS `json:"dns,omitempty"`
|
||||
}
|
||||
|
||||
func (r *Result) Print() error {
|
||||
return prettyPrint(r)
|
||||
}
|
||||
|
||||
// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where
|
||||
// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the
|
||||
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
|
||||
func (r *Result) String() string {
|
||||
var str string
|
||||
if r.IP4 != nil {
|
||||
str = fmt.Sprintf("IP4:%+v, ", *r.IP4)
|
||||
}
|
||||
if r.IP6 != nil {
|
||||
str += fmt.Sprintf("IP6:%+v, ", *r.IP6)
|
||||
}
|
||||
return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
|
||||
}
|
||||
|
||||
// IPConfig contains values necessary to configure an interface
|
||||
type IPConfig struct {
|
||||
IP net.IPNet
|
||||
Gateway net.IP
|
||||
Routes []Route
|
||||
}
|
||||
|
||||
// DNS contains values interesting for DNS resolvers
|
||||
type DNS struct {
|
||||
Nameservers []string `json:"nameservers,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Search []string `json:"search,omitempty"`
|
||||
Options []string `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
type Route struct {
|
||||
Dst net.IPNet
|
||||
GW net.IP
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Code uint `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Details string `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return e.Msg
|
||||
}
|
||||
|
||||
func (e *Error) Print() error {
|
||||
return prettyPrint(e)
|
||||
}
|
||||
|
||||
// net.IPNet is not JSON (un)marshallable so this duality is needed
|
||||
// for our custom IPNet type
|
||||
|
||||
// JSON (un)marshallable types
|
||||
type ipConfig struct {
|
||||
IP IPNet `json:"ip"`
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
Routes []Route `json:"routes,omitempty"`
|
||||
}
|
||||
|
||||
type route struct {
|
||||
Dst IPNet `json:"dst"`
|
||||
GW net.IP `json:"gw,omitempty"`
|
||||
}
|
||||
|
||||
func (c *IPConfig) MarshalJSON() ([]byte, error) {
|
||||
ipc := ipConfig{
|
||||
IP: IPNet(c.IP),
|
||||
Gateway: c.Gateway,
|
||||
Routes: c.Routes,
|
||||
}
|
||||
|
||||
return json.Marshal(ipc)
|
||||
}
|
||||
|
||||
func (c *IPConfig) UnmarshalJSON(data []byte) error {
|
||||
ipc := ipConfig{}
|
||||
if err := json.Unmarshal(data, &ipc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.IP = net.IPNet(ipc.IP)
|
||||
c.Gateway = ipc.Gateway
|
||||
c.Routes = ipc.Routes
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Route) UnmarshalJSON(data []byte) error {
|
||||
rt := route{}
|
||||
if err := json.Unmarshal(data, &rt); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Dst = net.IPNet(rt.Dst)
|
||||
r.GW = rt.GW
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Route) MarshalJSON() ([]byte, error) {
|
||||
rt := route{
|
||||
Dst: IPNet(r.Dst),
|
||||
GW: r.GW,
|
||||
}
|
||||
|
||||
return json.Marshal(rt)
|
||||
}
|
||||
|
||||
func prettyPrint(obj interface{}) error {
|
||||
data, err := json.MarshalIndent(obj, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
return err
|
||||
}
|
41
vendor/github.com/containernetworking/cni/pkg/utils/utils.go
generated
vendored
41
vendor/github.com/containernetworking/cni/pkg/utils/utils.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright 2016 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
maxChainLength = 28
|
||||
chainPrefix = "CNI-"
|
||||
prefixLength = len(chainPrefix)
|
||||
)
|
||||
|
||||
// Generates a chain name to be used with iptables.
|
||||
// Ensures that the generated chain name is exactly
|
||||
// maxChainLength chars in length
|
||||
func FormatChainName(name string, id string) string {
|
||||
chainBytes := sha512.Sum512([]byte(name + id))
|
||||
chain := fmt.Sprintf("%s%x", chainPrefix, chainBytes)
|
||||
return chain[:maxChainLength]
|
||||
}
|
||||
|
||||
// FormatComment returns a comment used for easier
|
||||
// rule identification within iptables.
|
||||
func FormatComment(name string, id string) string {
|
||||
return fmt.Sprintf("name: %q id: %q", name, id)
|
||||
}
|
86
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/README.md
generated
vendored
86
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/README.md
generated
vendored
@ -1,86 +0,0 @@
|
||||
# host-local IP address manager
|
||||
|
||||
host-local IPAM allocates IPv4 and IPv6 addresses out of a specified address range.
|
||||
|
||||
## Usage
|
||||
|
||||
### Obtain an IP
|
||||
|
||||
Given the following network configuration:
|
||||
|
||||
```
|
||||
{
|
||||
"name": "default",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "203.0.113.0/24"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Using the command line interface
|
||||
|
||||
```
|
||||
$ export CNI_COMMAND=ADD
|
||||
$ export CNI_CONTAINERID=f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
||||
$ ./host-local < $conf
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
"ip4": {
|
||||
"ip": "203.0.113.1/24"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Backends
|
||||
|
||||
By default ipmanager stores IP allocations on the local filesystem using the IP address as the file name and the ID as contents. For example:
|
||||
|
||||
```
|
||||
$ ls /var/lib/cni/networks/default
|
||||
```
|
||||
```
|
||||
203.0.113.1 203.0.113.2
|
||||
```
|
||||
|
||||
```
|
||||
$ cat /var/lib/cni/networks/default/203.0.113.1
|
||||
```
|
||||
```
|
||||
f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
||||
```
|
||||
|
||||
## Configuration Files
|
||||
|
||||
|
||||
```
|
||||
{
|
||||
"name": "ipv6",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "3ffe:ffff:0:01ff::/64",
|
||||
"range-start": "3ffe:ffff:0:01ff::0010",
|
||||
"range-end": "3ffe:ffff:0:01ff::0020",
|
||||
"routes": [
|
||||
{ "dst": "3ffe:ffff:0:01ff::1/64" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
"name": "ipv4",
|
||||
"ipam": {
|
||||
"type": "host-local",
|
||||
"subnet": "203.0.113.1/24",
|
||||
"range-start": "203.0.113.10",
|
||||
"range-end": "203.0.113.20",
|
||||
"routes": [
|
||||
{ "dst": "203.0.113.0/24" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
202
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/allocator.go
generated
vendored
202
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/allocator.go
generated
vendored
@ -1,202 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hostlocal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/ip"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/plugins/ipam/host-local/backend"
|
||||
)
|
||||
|
||||
type IPAllocator struct {
|
||||
start net.IP
|
||||
end net.IP
|
||||
conf *IPAMConfig
|
||||
store backend.Store
|
||||
}
|
||||
|
||||
func NewIPAllocator(conf *IPAMConfig, store backend.Store) (*IPAllocator, error) {
|
||||
var (
|
||||
start net.IP
|
||||
end net.IP
|
||||
err error
|
||||
)
|
||||
start, end, err = networkRange((*net.IPNet)(&conf.Subnet))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip the .0 address
|
||||
start = ip.NextIP(start)
|
||||
|
||||
if conf.RangeStart != nil {
|
||||
if err := validateRangeIP(conf.RangeStart, (*net.IPNet)(&conf.Subnet)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start = conf.RangeStart
|
||||
}
|
||||
if conf.RangeEnd != nil {
|
||||
if err := validateRangeIP(conf.RangeEnd, (*net.IPNet)(&conf.Subnet)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// RangeEnd is inclusive
|
||||
end = ip.NextIP(conf.RangeEnd)
|
||||
}
|
||||
return &IPAllocator{start, end, conf, store}, nil
|
||||
}
|
||||
|
||||
func validateRangeIP(ip net.IP, ipnet *net.IPNet) error {
|
||||
if !ipnet.Contains(ip) {
|
||||
return fmt.Errorf("%s not in network: %s", ip, ipnet)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Returns newly allocated IP along with its config
|
||||
func (a *IPAllocator) Get(id string) (*types.IPConfig, error) {
|
||||
a.store.Lock()
|
||||
defer a.store.Unlock()
|
||||
|
||||
gw := a.conf.Gateway
|
||||
if gw == nil {
|
||||
gw = ip.NextIP(a.conf.Subnet.IP)
|
||||
}
|
||||
|
||||
var requestedIP net.IP
|
||||
if a.conf.Args != nil {
|
||||
requestedIP = a.conf.Args.IP
|
||||
}
|
||||
|
||||
if requestedIP != nil {
|
||||
if gw != nil && gw.Equal(a.conf.Args.IP) {
|
||||
return nil, fmt.Errorf("requested IP must differ gateway IP")
|
||||
}
|
||||
|
||||
subnet := net.IPNet{
|
||||
IP: a.conf.Subnet.IP,
|
||||
Mask: a.conf.Subnet.Mask,
|
||||
}
|
||||
err := validateRangeIP(requestedIP, &subnet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reserved, err := a.store.Reserve(id, requestedIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if reserved {
|
||||
return &types.IPConfig{
|
||||
IP: net.IPNet{IP: requestedIP, Mask: a.conf.Subnet.Mask},
|
||||
Gateway: gw,
|
||||
Routes: a.conf.Routes,
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("requested IP address %q is not available in network: %s", requestedIP, a.conf.Name)
|
||||
}
|
||||
|
||||
startIP, endIP := a.getSearchRange()
|
||||
for cur := startIP; !cur.Equal(endIP); cur = a.nextIP(cur) {
|
||||
// don't allocate gateway IP
|
||||
if gw != nil && cur.Equal(gw) {
|
||||
continue
|
||||
}
|
||||
|
||||
reserved, err := a.store.Reserve(id, cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if reserved {
|
||||
return &types.IPConfig{
|
||||
IP: net.IPNet{IP: cur, Mask: a.conf.Subnet.Mask},
|
||||
Gateway: gw,
|
||||
Routes: a.conf.Routes,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("no IP addresses available in network: %s", a.conf.Name)
|
||||
}
|
||||
|
||||
// Releases all IPs allocated for the container with given ID
|
||||
func (a *IPAllocator) Release(id string) error {
|
||||
a.store.Lock()
|
||||
defer a.store.Unlock()
|
||||
|
||||
return a.store.ReleaseByID(id)
|
||||
}
|
||||
|
||||
func networkRange(ipnet *net.IPNet) (net.IP, net.IP, error) {
|
||||
if ipnet.IP == nil {
|
||||
return nil, nil, fmt.Errorf("missing field %q in IPAM configuration", "subnet")
|
||||
}
|
||||
ip := ipnet.IP.To4()
|
||||
if ip == nil {
|
||||
ip = ipnet.IP.To16()
|
||||
if ip == nil {
|
||||
return nil, nil, fmt.Errorf("IP not v4 nor v6")
|
||||
}
|
||||
}
|
||||
|
||||
if len(ip) != len(ipnet.Mask) {
|
||||
return nil, nil, fmt.Errorf("IPNet IP and Mask version mismatch")
|
||||
}
|
||||
|
||||
var end net.IP
|
||||
for i := 0; i < len(ip); i++ {
|
||||
end = append(end, ip[i]|^ipnet.Mask[i])
|
||||
}
|
||||
return ipnet.IP, end, nil
|
||||
}
|
||||
|
||||
// nextIP returns the next ip of curIP within ipallocator's subnet
|
||||
func (a *IPAllocator) nextIP(curIP net.IP) net.IP {
|
||||
if curIP.Equal(a.end) {
|
||||
return a.start
|
||||
}
|
||||
return ip.NextIP(curIP)
|
||||
}
|
||||
|
||||
// getSearchRange returns the start and end ip based on the last reserved ip
|
||||
func (a *IPAllocator) getSearchRange() (net.IP, net.IP) {
|
||||
var startIP net.IP
|
||||
var endIP net.IP
|
||||
startFromLastReservedIP := false
|
||||
lastReservedIP, err := a.store.LastReservedIP()
|
||||
if err != nil {
|
||||
log.Printf("Error retriving last reserved ip: %v", err)
|
||||
} else if lastReservedIP != nil {
|
||||
subnet := net.IPNet{
|
||||
IP: a.conf.Subnet.IP,
|
||||
Mask: a.conf.Subnet.Mask,
|
||||
}
|
||||
err := validateRangeIP(lastReservedIP, &subnet)
|
||||
if err == nil {
|
||||
startFromLastReservedIP = true
|
||||
}
|
||||
}
|
||||
if startFromLastReservedIP {
|
||||
startIP = a.nextIP(lastReservedIP)
|
||||
endIP = lastReservedIP
|
||||
} else {
|
||||
startIP = a.start
|
||||
endIP = a.end
|
||||
}
|
||||
return startIP, endIP
|
||||
}
|
107
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk/backend.go
generated
vendored
107
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk/backend.go
generated
vendored
@ -1,107 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const lastIPFile = "last_reserved_ip"
|
||||
|
||||
var defaultDataDir = "/var/lib/cni/networks"
|
||||
|
||||
type Store struct {
|
||||
FileLock
|
||||
dataDir string
|
||||
}
|
||||
|
||||
func New(network string) (*Store, error) {
|
||||
dir := filepath.Join(defaultDataDir, network)
|
||||
if err := os.MkdirAll(dir, 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lk, err := NewFileLock(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Store{*lk, dir}, nil
|
||||
}
|
||||
|
||||
func (s *Store) Reserve(id string, ip net.IP) (bool, error) {
|
||||
fname := filepath.Join(s.dataDir, ip.String())
|
||||
f, err := os.OpenFile(fname, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644)
|
||||
if os.IsExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if _, err := f.WriteString(id); err != nil {
|
||||
f.Close()
|
||||
os.Remove(f.Name())
|
||||
return false, err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
os.Remove(f.Name())
|
||||
return false, err
|
||||
}
|
||||
// store the reserved ip in lastIPFile
|
||||
ipfile := filepath.Join(s.dataDir, lastIPFile)
|
||||
err = ioutil.WriteFile(ipfile, []byte(ip.String()), 0644)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// LastReservedIP returns the last reserved IP if exists
|
||||
func (s *Store) LastReservedIP() (net.IP, error) {
|
||||
ipfile := filepath.Join(s.dataDir, lastIPFile)
|
||||
data, err := ioutil.ReadFile(ipfile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to retrieve last reserved ip: %v", err)
|
||||
}
|
||||
return net.ParseIP(string(data)), nil
|
||||
}
|
||||
|
||||
func (s *Store) Release(ip net.IP) error {
|
||||
return os.Remove(filepath.Join(s.dataDir, ip.String()))
|
||||
}
|
||||
|
||||
// N.B. This function eats errors to be tolerant and
|
||||
// release as much as possible
|
||||
func (s *Store) ReleaseByID(id string) error {
|
||||
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil || info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if string(data) == id {
|
||||
if err := os.Remove(path); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
50
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk/lock.go
generated
vendored
50
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk/lock.go
generated
vendored
@ -1,50 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package disk
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// FileLock wraps os.File to be used as a lock using flock
|
||||
type FileLock struct {
|
||||
f *os.File
|
||||
}
|
||||
|
||||
// NewFileLock opens file/dir at path and returns unlocked FileLock object
|
||||
func NewFileLock(path string) (*FileLock, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &FileLock{f}, nil
|
||||
}
|
||||
|
||||
// Close closes underlying file
|
||||
func (l *FileLock) Close() error {
|
||||
return l.f.Close()
|
||||
}
|
||||
|
||||
// Lock acquires an exclusive lock
|
||||
func (l *FileLock) Lock() error {
|
||||
return syscall.Flock(int(l.f.Fd()), syscall.LOCK_EX)
|
||||
}
|
||||
|
||||
// Unlock releases the lock
|
||||
func (l *FileLock) Unlock() error {
|
||||
return syscall.Flock(int(l.f.Fd()), syscall.LOCK_UN)
|
||||
}
|
27
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/store.go
generated
vendored
27
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/backend/store.go
generated
vendored
@ -1,27 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package backend
|
||||
|
||||
import "net"
|
||||
|
||||
type Store interface {
|
||||
Lock() error
|
||||
Unlock() error
|
||||
Close() error
|
||||
Reserve(id string, ip net.IP) (bool, error)
|
||||
LastReservedIP() (net.IP, error)
|
||||
Release(ip net.IP) error
|
||||
ReleaseByID(id string) error
|
||||
}
|
70
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/config.go
generated
vendored
70
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/config.go
generated
vendored
@ -1,70 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hostlocal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
// IPAMConfig represents the IP related network configuration.
|
||||
type IPAMConfig struct {
|
||||
Name string
|
||||
Type string `json:"type"`
|
||||
RangeStart net.IP `json:"rangeStart"`
|
||||
RangeEnd net.IP `json:"rangeEnd"`
|
||||
Subnet types.IPNet `json:"subnet"`
|
||||
Gateway net.IP `json:"gateway"`
|
||||
Routes []types.Route `json:"routes"`
|
||||
Args *IPAMArgs `json:"-"`
|
||||
}
|
||||
|
||||
type IPAMArgs struct {
|
||||
types.CommonArgs
|
||||
IP net.IP `json:"ip,omitempty"`
|
||||
}
|
||||
|
||||
type Net struct {
|
||||
Name string `json:"name"`
|
||||
IPAM *IPAMConfig `json:"ipam"`
|
||||
}
|
||||
|
||||
// NewIPAMConfig creates a NetworkConfig from the given network name.
|
||||
func LoadIPAMConfig(bytes []byte, args string) (*IPAMConfig, error) {
|
||||
n := Net{}
|
||||
if err := json.Unmarshal(bytes, &n); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if args != "" {
|
||||
n.IPAM.Args = &IPAMArgs{}
|
||||
err := types.LoadArgs(args, n.IPAM.Args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if n.IPAM == nil {
|
||||
return nil, fmt.Errorf("IPAM config missing 'ipam' key")
|
||||
}
|
||||
|
||||
// Copy net name into IPAM so not to drag Net struct around
|
||||
n.IPAM.Name = n.Name
|
||||
|
||||
return n.IPAM, nil
|
||||
}
|
74
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/main.go
generated
vendored
74
vendor/github.com/containernetworking/cni/plugins/ipam/host-local/main.go
generated
vendored
@ -1,74 +0,0 @@
|
||||
// Copyright 2015 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hostlocal
|
||||
|
||||
import (
|
||||
"github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
func Main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel)
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
ipamConf, err := LoadIPAMConfig(args.StdinData, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
store, err := disk.New(ipamConf.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
allocator, err := NewIPAllocator(ipamConf, store)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ipConf, err := allocator.Get(args.ContainerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := &types.Result{
|
||||
IP4: ipConf,
|
||||
}
|
||||
return r.Print()
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
ipamConf, err := LoadIPAMConfig(args.StdinData, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
store, err := disk.New(ipamConf.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer store.Close()
|
||||
|
||||
allocator, err := NewIPAllocator(ipamConf, store)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return allocator.Release(args.ContainerID)
|
||||
}
|
319
vendor/github.com/containernetworking/cni/plugins/main/bridge/bridge.go
generated
vendored
319
vendor/github.com/containernetworking/cni/plugins/main/bridge/bridge.go
generated
vendored
@ -1,319 +0,0 @@
|
||||
// Copyright 2014 CNI authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/ip"
|
||||
"github.com/containernetworking/cni/pkg/ipam"
|
||||
"github.com/containernetworking/cni/pkg/ns"
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/utils"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const defaultBrName = "cni0"
|
||||
|
||||
type NetConf struct {
|
||||
types.NetConf
|
||||
BrName string `json:"bridge"`
|
||||
IsGW bool `json:"isGateway"`
|
||||
IsDefaultGW bool `json:"isDefaultGateway"`
|
||||
IPMasq bool `json:"ipMasq"`
|
||||
MTU int `json:"mtu"`
|
||||
HairpinMode bool `json:"hairpinMode"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// this ensures that main runs only on main thread (thread group leader).
|
||||
// since namespace ops (unshare, setns) are done for a single thread, we
|
||||
// must ensure that the goroutine does not jump from OS thread to thread
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
func loadNetConf(bytes []byte) (*NetConf, error) {
|
||||
n := &NetConf{
|
||||
BrName: defaultBrName,
|
||||
}
|
||||
if err := json.Unmarshal(bytes, n); err != nil {
|
||||
return nil, fmt.Errorf("failed to load netconf: %v", err)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet) error {
|
||||
addrs, err := netlink.AddrList(br, syscall.AF_INET)
|
||||
if err != nil && err != syscall.ENOENT {
|
||||
return fmt.Errorf("could not get list of IP addresses: %v", err)
|
||||
}
|
||||
|
||||
// if there're no addresses on the bridge, it's ok -- we'll add one
|
||||
if len(addrs) > 0 {
|
||||
ipnStr := ipn.String()
|
||||
for _, a := range addrs {
|
||||
// string comp is actually easiest for doing IPNet comps
|
||||
if a.IPNet.String() == ipnStr {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("%q already has an IP address different from %v", br.Name, ipn.String())
|
||||
}
|
||||
|
||||
addr := &netlink.Addr{IPNet: ipn, Label: ""}
|
||||
if err := netlink.AddrAdd(br, addr); err != nil {
|
||||
return fmt.Errorf("could not add IP address to %q: %v", br.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func bridgeByName(name string) (*netlink.Bridge, error) {
|
||||
l, err := netlink.LinkByName(name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not lookup %q: %v", name, err)
|
||||
}
|
||||
br, ok := l.(*netlink.Bridge)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%q already exists but is not a bridge", name)
|
||||
}
|
||||
return br, nil
|
||||
}
|
||||
|
||||
func ensureBridge(brName string, mtu int) (*netlink.Bridge, error) {
|
||||
br := &netlink.Bridge{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: brName,
|
||||
MTU: mtu,
|
||||
// Let kernel use default txqueuelen; leaving it unset
|
||||
// means 0, and a zero-length TX queue messes up FIFO
|
||||
// traffic shapers which use TX queue length as the
|
||||
// default packet limit
|
||||
TxQLen: -1,
|
||||
},
|
||||
}
|
||||
|
||||
if err := netlink.LinkAdd(br); err != nil {
|
||||
if err != syscall.EEXIST {
|
||||
return nil, fmt.Errorf("could not add %q: %v", brName, err)
|
||||
}
|
||||
|
||||
// it's ok if the device already exists as long as config is similar
|
||||
br, err = bridgeByName(brName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := netlink.LinkSetUp(br); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return br, nil
|
||||
}
|
||||
|
||||
func setupVeth(netns ns.NetNS, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool) error {
|
||||
var hostVethName string
|
||||
|
||||
err := netns.Do(func(hostNS ns.NetNS) error {
|
||||
// create the veth pair in the container and move host end into host netns
|
||||
hostVeth, _, err := ip.SetupVeth(ifName, mtu, hostNS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hostVethName = hostVeth.Attrs().Name
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// need to lookup hostVeth again as its index has changed during ns move
|
||||
hostVeth, err := netlink.LinkByName(hostVethName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to lookup %q: %v", hostVethName, err)
|
||||
}
|
||||
|
||||
// connect host veth end to the bridge
|
||||
if err = netlink.LinkSetMaster(hostVeth, br); err != nil {
|
||||
return fmt.Errorf("failed to connect %q to bridge %v: %v", hostVethName, br.Attrs().Name, err)
|
||||
}
|
||||
|
||||
// set hairpin mode
|
||||
if err = netlink.LinkSetHairpin(hostVeth, hairpinMode); err != nil {
|
||||
return fmt.Errorf("failed to setup hairpin mode for %v: %v", hostVethName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func calcGatewayIP(ipn *net.IPNet) net.IP {
|
||||
nid := ipn.IP.Mask(ipn.Mask)
|
||||
return ip.NextIP(nid)
|
||||
}
|
||||
|
||||
func setupBridge(n *NetConf) (*netlink.Bridge, error) {
|
||||
// create bridge if necessary
|
||||
br, err := ensureBridge(n.BrName, n.MTU)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create bridge %q: %v", n.BrName, err)
|
||||
}
|
||||
|
||||
return br, nil
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
n, err := loadNetConf(args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n.IsDefaultGW {
|
||||
n.IsGW = true
|
||||
}
|
||||
|
||||
br, err := setupBridge(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
netns, err := ns.GetNS(args.Netns)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
|
||||
}
|
||||
defer netns.Close()
|
||||
|
||||
if err = setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// run the IPAM plugin and get back the config to apply
|
||||
result, err := ipam.ExecAdd(n.IPAM.Type, args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: make this optional when IPv6 is supported
|
||||
if result.IP4 == nil {
|
||||
return errors.New("IPAM plugin returned missing IPv4 config")
|
||||
}
|
||||
|
||||
if result.IP4.Gateway == nil && n.IsGW {
|
||||
result.IP4.Gateway = calcGatewayIP(&result.IP4.IP)
|
||||
}
|
||||
|
||||
if err := netns.Do(func(_ ns.NetNS) error {
|
||||
// set the default gateway if requested
|
||||
if n.IsDefaultGW {
|
||||
_, defaultNet, err := net.ParseCIDR("0.0.0.0/0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, route := range result.IP4.Routes {
|
||||
if defaultNet.String() == route.Dst.String() {
|
||||
if route.GW != nil && !route.GW.Equal(result.IP4.Gateway) {
|
||||
return fmt.Errorf(
|
||||
"isDefaultGateway ineffective because IPAM sets default route via %q",
|
||||
route.GW,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.IP4.Routes = append(
|
||||
result.IP4.Routes,
|
||||
types.Route{Dst: *defaultNet, GW: result.IP4.Gateway},
|
||||
)
|
||||
|
||||
// TODO: IPV6
|
||||
}
|
||||
|
||||
return ipam.ConfigureIface(args.IfName, result)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n.IsGW {
|
||||
gwn := &net.IPNet{
|
||||
IP: result.IP4.Gateway,
|
||||
Mask: result.IP4.IP.Mask,
|
||||
}
|
||||
|
||||
if err = ensureBridgeAddr(br, gwn); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ip.EnableIP4Forward(); err != nil {
|
||||
return fmt.Errorf("failed to enable forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if n.IPMasq {
|
||||
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
||||
comment := utils.FormatComment(n.Name, args.ContainerID)
|
||||
if err = ip.SetupIPMasq(ip.Network(&result.IP4.IP), chain, comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
result.DNS = n.DNS
|
||||
return result.Print()
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
n, err := loadNetConf(args.StdinData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Netns == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var ipn *net.IPNet
|
||||
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
|
||||
var err error
|
||||
ipn, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n.IPMasq {
|
||||
chain := utils.FormatChainName(n.Name, args.ContainerID)
|
||||
comment := utils.FormatComment(n.Name, args.ContainerID)
|
||||
if err = ip.TeardownIPMasq(ipn, chain, comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel)
|
||||
}
|
80
vendor/github.com/containernetworking/cni/test
generated
vendored
80
vendor/github.com/containernetworking/cni/test
generated
vendored
@ -1,80 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Run all CNI tests
|
||||
# ./test
|
||||
# ./test -v
|
||||
#
|
||||
# Run tests for one package
|
||||
# PKG=./plugins/ipam/dhcp ./test
|
||||
#
|
||||
set -e
|
||||
|
||||
source ./build
|
||||
|
||||
TESTABLE="plugins/ipam/dhcp plugins/ipam/host-local plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/utils plugins/main/ipvlan plugins/main/macvlan plugins/main/bridge"
|
||||
FORMATTABLE="$TESTABLE libcni pkg/ip pkg/ipam pkg/testutils plugins/ipam/host-local plugins/main/bridge plugins/meta/flannel plugins/meta/tuning"
|
||||
|
||||
# user has not provided PKG override
|
||||
if [ -z "$PKG" ]; then
|
||||
TEST=$TESTABLE
|
||||
FMT=$FORMATTABLE
|
||||
|
||||
# user has provided PKG override
|
||||
else
|
||||
# strip out slashes and dots from PKG=./foo/
|
||||
TEST=${PKG//\//}
|
||||
TEST=${TEST//./}
|
||||
|
||||
# only run gofmt on packages provided by user
|
||||
FMT="$TEST"
|
||||
fi
|
||||
|
||||
# split TEST into an array and prepend REPO_PATH to each local package
|
||||
split=(${TEST// / })
|
||||
TEST=${split[@]/#/${REPO_PATH}/}
|
||||
|
||||
echo -n "Running tests "
|
||||
function testrun {
|
||||
sudo -E bash -c "umask 0; PATH=$GOROOT/bin:$GOBIN:$PATH go test -covermode set $@"
|
||||
}
|
||||
if [ ! -z "${COVERALLS}" ]; then
|
||||
echo "with coverage profile generation..."
|
||||
i=0
|
||||
for t in ${TEST}; do
|
||||
testrun "-coverprofile ${i}.coverprofile ${t}"
|
||||
i=$((i+1))
|
||||
done
|
||||
gover
|
||||
goveralls -service=travis-ci -coverprofile=gover.coverprofile -repotoken=$COVERALLS_TOKEN
|
||||
else
|
||||
echo "without coverage profile generation..."
|
||||
testrun "${TEST}"
|
||||
fi
|
||||
|
||||
echo "Checking gofmt..."
|
||||
fmtRes=$(gofmt -l $FMT)
|
||||
if [ -n "${fmtRes}" ]; then
|
||||
echo -e "gofmt checking failed:\n${fmtRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Checking govet..."
|
||||
vetRes=$(go vet $TEST)
|
||||
if [ -n "${vetRes}" ]; then
|
||||
echo -e "govet checking failed:\n${vetRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
echo "Checking license header..."
|
||||
licRes=$(
|
||||
for file in $(find . -type f -iname '*.go' ! -path './vendor/*'); do
|
||||
head -n1 "${file}" | grep -Eq "(Copyright|generated)" || echo -e " ${file}"
|
||||
done
|
||||
)
|
||||
if [ -n "${licRes}" ]; then
|
||||
echo -e "license header checking failed:\n${licRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
|
||||
echo "Success"
|
25
vendor/github.com/coreos/go-iptables/.travis.yml
generated
vendored
25
vendor/github.com/coreos/go-iptables/.travis.yml
generated
vendored
@ -1,25 +0,0 @@
|
||||
language: go
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.5.3
|
||||
- 1.6
|
||||
- tip
|
||||
|
||||
env:
|
||||
global:
|
||||
- TOOLS_CMD=golang.org/x/tools/cmd
|
||||
- PATH=$GOROOT/bin:$PATH
|
||||
- SUDO_PERMITTED=1
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
|
||||
script:
|
||||
- ./test
|
191
vendor/github.com/coreos/go-iptables/LICENSE
generated
vendored
191
vendor/github.com/coreos/go-iptables/LICENSE
generated
vendored
@ -1,191 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
9
vendor/github.com/coreos/go-iptables/README.md
generated
vendored
9
vendor/github.com/coreos/go-iptables/README.md
generated
vendored
@ -1,9 +0,0 @@
|
||||
# go-iptables
|
||||
|
||||
[](https://travis-ci.org/coreos/go-iptables)
|
||||
|
||||
Go bindings for iptables utility.
|
||||
|
||||
In-kernel netfilter does not have a good userspace API. The tables are manipulated via setsockopt that sets/replaces the entire table. Changes to existing table need to be resolved by userspace code which is difficult and error-prone. Netfilter developers heavily advocate using iptables utlity for programmatic manipulation.
|
||||
|
||||
go-iptables wraps invokation of iptables utility with functions to append and delete rules; create, clear and delete chains.
|
22
vendor/github.com/coreos/go-iptables/build
generated
vendored
22
vendor/github.com/coreos/go-iptables/build
generated
vendored
@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
ORG_PATH="github.com/coreos"
|
||||
REPO_PATH="${ORG_PATH}/go-iptables"
|
||||
|
||||
if [ ! -h gopath/src/${REPO_PATH} ]; then
|
||||
mkdir -p gopath/src/${ORG_PATH}
|
||||
ln -s ../../../.. gopath/src/${REPO_PATH} || exit 255
|
||||
fi
|
||||
|
||||
export GOBIN=${PWD}/bin
|
||||
export GOPATH=${PWD}/gopath
|
||||
|
||||
eval $(go env)
|
||||
|
||||
if [ ${GOOS} = "linux" ]; then
|
||||
echo "Building go-iptables..."
|
||||
go build ${REPO_PATH}/iptables
|
||||
else
|
||||
echo "Not on Linux"
|
||||
fi
|
295
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
295
vendor/github.com/coreos/go-iptables/iptables/iptables.go
generated
vendored
@ -1,295 +0,0 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Adds the output of stderr to exec.ExitError
|
||||
type Error struct {
|
||||
exec.ExitError
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e *Error) ExitStatus() int {
|
||||
return e.Sys().(syscall.WaitStatus).ExitStatus()
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("exit status %v: %v", e.ExitStatus(), e.msg)
|
||||
}
|
||||
|
||||
type IPTables struct {
|
||||
path string
|
||||
hasCheck bool
|
||||
hasWait bool
|
||||
}
|
||||
|
||||
func New() (*IPTables, error) {
|
||||
path, err := exec.LookPath("iptables")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checkPresent, waitPresent, err := getIptablesCommandSupport()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking iptables version: %v", err)
|
||||
}
|
||||
ipt := IPTables{
|
||||
path: path,
|
||||
hasCheck: checkPresent,
|
||||
hasWait: waitPresent,
|
||||
}
|
||||
return &ipt, nil
|
||||
}
|
||||
|
||||
// Exists checks if given rulespec in specified table/chain exists
|
||||
func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) {
|
||||
if !ipt.hasCheck {
|
||||
return ipt.existsForOldIptables(table, chain, rulespec)
|
||||
|
||||
}
|
||||
cmd := append([]string{"-t", table, "-C", chain}, rulespec...)
|
||||
err := ipt.run(cmd...)
|
||||
eerr, eok := err.(*Error)
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
case eok && eerr.ExitStatus() == 1:
|
||||
return false, nil
|
||||
default:
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Insert inserts rulespec to specified table/chain (in specified pos)
|
||||
func (ipt *IPTables) Insert(table, chain string, pos int, rulespec ...string) error {
|
||||
cmd := append([]string{"-t", table, "-I", chain, strconv.Itoa(pos)}, rulespec...)
|
||||
return ipt.run(cmd...)
|
||||
}
|
||||
|
||||
// Append appends rulespec to specified table/chain
|
||||
func (ipt *IPTables) Append(table, chain string, rulespec ...string) error {
|
||||
cmd := append([]string{"-t", table, "-A", chain}, rulespec...)
|
||||
return ipt.run(cmd...)
|
||||
}
|
||||
|
||||
// AppendUnique acts like Append except that it won't add a duplicate
|
||||
func (ipt *IPTables) AppendUnique(table, chain string, rulespec ...string) error {
|
||||
exists, err := ipt.Exists(table, chain, rulespec...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return ipt.Append(table, chain, rulespec...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes rulespec in specified table/chain
|
||||
func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error {
|
||||
cmd := append([]string{"-t", table, "-D", chain}, rulespec...)
|
||||
return ipt.run(cmd...)
|
||||
}
|
||||
|
||||
// List rules in specified table/chain
|
||||
func (ipt *IPTables) List(table, chain string) ([]string, error) {
|
||||
args := []string{"-t", table, "-S", chain}
|
||||
var stdout bytes.Buffer
|
||||
if err := ipt.runWithOutput(args, &stdout); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := strings.Split(stdout.String(), "\n")
|
||||
if len(rules) > 0 && rules[len(rules)-1] == "" {
|
||||
rules = rules[:len(rules)-1]
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (ipt *IPTables) NewChain(table, chain string) error {
|
||||
return ipt.run("-t", table, "-N", chain)
|
||||
}
|
||||
|
||||
// ClearChain flushed (deletes all rules) in the specified table/chain.
|
||||
// If the chain does not exist, a new one will be created
|
||||
func (ipt *IPTables) ClearChain(table, chain string) error {
|
||||
err := ipt.NewChain(table, chain)
|
||||
|
||||
eerr, eok := err.(*Error)
|
||||
switch {
|
||||
case err == nil:
|
||||
return nil
|
||||
case eok && eerr.ExitStatus() == 1:
|
||||
// chain already exists. Flush (clear) it.
|
||||
return ipt.run("-t", table, "-F", chain)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// RenameChain renames the old chain to the new one.
|
||||
func (ipt *IPTables) RenameChain(table, oldChain, newChain string) error {
|
||||
return ipt.run("-t", table, "-E", oldChain, newChain)
|
||||
}
|
||||
|
||||
// DeleteChain deletes the chain in the specified table.
|
||||
// The chain must be empty
|
||||
func (ipt *IPTables) DeleteChain(table, chain string) error {
|
||||
return ipt.run("-t", table, "-X", chain)
|
||||
}
|
||||
|
||||
// run runs an iptables command with the given arguments, ignoring
|
||||
// any stdout output
|
||||
func (ipt *IPTables) run(args ...string) error {
|
||||
return ipt.runWithOutput(args, nil)
|
||||
}
|
||||
|
||||
// runWithOutput runs an iptables command with the given arguments,
|
||||
// writing any stdout output to the given writer
|
||||
func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
|
||||
args = append([]string{ipt.path}, args...)
|
||||
if ipt.hasWait {
|
||||
args = append(args, "--wait")
|
||||
} else {
|
||||
fmu, err := newXtablesFileLock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ul, err := fmu.tryLock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ul.Unlock()
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
cmd := exec.Cmd{
|
||||
Path: ipt.path,
|
||||
Args: args,
|
||||
Stdout: stdout,
|
||||
Stderr: &stderr,
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return &Error{*(err.(*exec.ExitError)), stderr.String()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Checks if iptables has the "-C" and "--wait" flag
|
||||
func getIptablesCommandSupport() (bool, bool, error) {
|
||||
vstring, err := getIptablesVersionString()
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
v1, v2, v3, err := extractIptablesVersion(vstring)
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
}
|
||||
|
||||
return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), nil
|
||||
}
|
||||
|
||||
// getIptablesVersion returns the first three components of the iptables version.
|
||||
// e.g. "iptables v1.3.66" would return (1, 3, 66, nil)
|
||||
func extractIptablesVersion(str string) (int, int, int, error) {
|
||||
versionMatcher := regexp.MustCompile("v([0-9]+)\\.([0-9]+)\\.([0-9]+)")
|
||||
result := versionMatcher.FindStringSubmatch(str)
|
||||
if result == nil {
|
||||
return 0, 0, 0, fmt.Errorf("no iptables version found in string: %s", str)
|
||||
}
|
||||
|
||||
v1, err := strconv.Atoi(result[1])
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
v2, err := strconv.Atoi(result[2])
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
v3, err := strconv.Atoi(result[3])
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
return v1, v2, v3, nil
|
||||
}
|
||||
|
||||
// Runs "iptables --version" to get the version string
|
||||
func getIptablesVersionString() (string, error) {
|
||||
cmd := exec.Command("iptables", "--version")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return out.String(), nil
|
||||
}
|
||||
|
||||
// Checks if an iptables version is after 1.4.11, when --check was added
|
||||
func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool {
|
||||
if v1 > 1 {
|
||||
return true
|
||||
}
|
||||
if v1 == 1 && v2 > 4 {
|
||||
return true
|
||||
}
|
||||
if v1 == 1 && v2 == 4 && v3 >= 11 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks if an iptables version is after 1.4.20, when --wait was added
|
||||
func iptablesHasWaitCommand(v1 int, v2 int, v3 int) bool {
|
||||
if v1 > 1 {
|
||||
return true
|
||||
}
|
||||
if v1 == 1 && v2 > 4 {
|
||||
return true
|
||||
}
|
||||
if v1 == 1 && v2 == 4 && v3 >= 20 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Checks if a rule specification exists for a table
|
||||
func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string) (bool, error) {
|
||||
rs := strings.Join(append([]string{"-A", chain}, rulespec...), " ")
|
||||
args := []string{"-t", table, "-S"}
|
||||
var stdout bytes.Buffer
|
||||
err := ipt.runWithOutput(args, &stdout)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.Contains(stdout.String(), rs), nil
|
||||
}
|
84
vendor/github.com/coreos/go-iptables/iptables/lock.go
generated
vendored
84
vendor/github.com/coreos/go-iptables/iptables/lock.go
generated
vendored
@ -1,84 +0,0 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package iptables
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
// In earlier versions of iptables, the xtables lock was implemented
|
||||
// via a Unix socket, but now flock is used via this lockfile:
|
||||
// http://git.netfilter.org/iptables/commit/?id=aa562a660d1555b13cffbac1e744033e91f82707
|
||||
// Note the LSB-conforming "/run" directory does not exist on old
|
||||
// distributions, so assume "/var" is symlinked
|
||||
xtablesLockFilePath = "/var/run/xtables.lock"
|
||||
|
||||
defaultFilePerm = 0600
|
||||
)
|
||||
|
||||
type Unlocker interface {
|
||||
Unlock() error
|
||||
}
|
||||
|
||||
type nopUnlocker struct{}
|
||||
|
||||
func (_ nopUnlocker) Unlock() error { return nil }
|
||||
|
||||
type fileLock struct {
|
||||
// mu is used to protect against concurrent invocations from within this process
|
||||
mu sync.Mutex
|
||||
fd int
|
||||
}
|
||||
|
||||
// tryLock takes an exclusive lock on the xtables lock file without blocking.
|
||||
// This is best-effort only: if the exclusive lock would block (i.e. because
|
||||
// another process already holds it), no error is returned. Otherwise, any
|
||||
// error encountered during the locking operation is returned.
|
||||
// The returned Unlocker should be used to release the lock when the caller is
|
||||
// done invoking iptables commands.
|
||||
func (l *fileLock) tryLock() (Unlocker, error) {
|
||||
l.mu.Lock()
|
||||
err := syscall.Flock(l.fd, syscall.LOCK_EX|syscall.LOCK_NB)
|
||||
switch err {
|
||||
case syscall.EWOULDBLOCK:
|
||||
l.mu.Unlock()
|
||||
return nopUnlocker{}, nil
|
||||
case nil:
|
||||
return l, nil
|
||||
default:
|
||||
l.mu.Unlock()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock closes the underlying file, which implicitly unlocks it as well. It
|
||||
// also unlocks the associated mutex.
|
||||
func (l *fileLock) Unlock() error {
|
||||
defer l.mu.Unlock()
|
||||
return syscall.Close(l.fd)
|
||||
}
|
||||
|
||||
// newXtablesFileLock opens a new lock on the xtables lockfile without
|
||||
// acquiring the lock
|
||||
func newXtablesFileLock() (*fileLock, error) {
|
||||
fd, err := syscall.Open(xtablesLockFilePath, os.O_CREATE, defaultFilePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fileLock{fd: fd}, nil
|
||||
}
|
55
vendor/github.com/coreos/go-iptables/test
generated
vendored
55
vendor/github.com/coreos/go-iptables/test
generated
vendored
@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Run all go-iptables tests
|
||||
# ./test
|
||||
# ./test -v
|
||||
#
|
||||
# Run tests for one package
|
||||
# PKG=./unit ./test
|
||||
# PKG=ssh ./test
|
||||
#
|
||||
set -e
|
||||
|
||||
# Invoke ./cover for HTML output
|
||||
COVER=${COVER:-"-cover"}
|
||||
|
||||
source ./build
|
||||
|
||||
TESTABLE="iptables"
|
||||
FORMATTABLE="$TESTABLE"
|
||||
|
||||
# user has not provided PKG override
|
||||
if [ -z "$PKG" ]; then
|
||||
TEST=$TESTABLE
|
||||
FMT=$FORMATTABLE
|
||||
|
||||
# user has provided PKG override
|
||||
else
|
||||
# strip out slashes and dots from PKG=./foo/
|
||||
TEST=${PKG//\//}
|
||||
TEST=${TEST//./}
|
||||
|
||||
# only run gofmt on packages provided by user
|
||||
FMT="$TEST"
|
||||
fi
|
||||
|
||||
echo "Checking gofmt..."
|
||||
fmtRes=$(gofmt -l $FMT)
|
||||
if [ -n "${fmtRes}" ]; then
|
||||
echo -e "gofmt checking failed:\n${fmtRes}"
|
||||
exit 255
|
||||
fi
|
||||
|
||||
# split TEST into an array and prepend REPO_PATH to each local package
|
||||
split=(${TEST// / })
|
||||
TEST=${split[@]/#/${REPO_PATH}/}
|
||||
|
||||
echo "Running tests..."
|
||||
go test -i ${TEST}
|
||||
if [[ -z "$SUDO_PERMITTED" ]]; then
|
||||
echo "Test aborted for safety reasons. Please set the SUDO_PERMITTED variable."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo -E bash -c "PATH=\$GOROOT/bin:\$PATH go test ${COVER} $@ ${TEST}"
|
||||
echo "Success"
|
4
vendor/github.com/rancher/cniglue/.dockerignore
generated
vendored
4
vendor/github.com/rancher/cniglue/.dockerignore
generated
vendored
@ -1,4 +0,0 @@
|
||||
./bin
|
||||
./.dapper
|
||||
./dist
|
||||
./.trash-cache
|
4
vendor/github.com/rancher/cniglue/.drone.yml
generated
vendored
4
vendor/github.com/rancher/cniglue/.drone.yml
generated
vendored
@ -1,4 +0,0 @@
|
||||
image: rancher/dind:v1.10.0-rancher1
|
||||
script:
|
||||
- wrapdocker
|
||||
- make ci
|
4
vendor/github.com/rancher/cniglue/.gitignore
generated
vendored
4
vendor/github.com/rancher/cniglue/.gitignore
generated
vendored
@ -1,4 +0,0 @@
|
||||
/.dapper
|
||||
/bin
|
||||
*.swp
|
||||
/.trash-cache
|
15
vendor/github.com/rancher/cniglue/Dockerfile.dapper
generated
vendored
15
vendor/github.com/rancher/cniglue/Dockerfile.dapper
generated
vendored
@ -1,15 +0,0 @@
|
||||
FROM golang:1.6.2
|
||||
RUN go get github.com/rancher/trash
|
||||
RUN go get github.com/golang/lint/golint
|
||||
RUN curl -sL https://get.docker.com/builds/Linux/x86_64/docker-1.9.1 > /usr/bin/docker && \
|
||||
chmod +x /usr/bin/docker
|
||||
ENV PATH /go/bin:$PATH
|
||||
ENV DAPPER_SOURCE /go/src/github.com/rancher/cniglue
|
||||
ENV DAPPER_OUTPUT bin
|
||||
ENV DAPPER_DOCKER_SOCKET true
|
||||
ENV DAPPER_ENV TAG REPO
|
||||
ENV GO15VENDOREXPERIMENT 1
|
||||
ENV TRASH_CACHE ${DAPPER_SOURCE}/.trash-cache
|
||||
WORKDIR ${DAPPER_SOURCE}
|
||||
ENTRYPOINT ["./scripts/entry"]
|
||||
CMD ["ci"]
|
177
vendor/github.com/rancher/cniglue/LICENSE
generated
vendored
177
vendor/github.com/rancher/cniglue/LICENSE
generated
vendored
@ -1,177 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
23
vendor/github.com/rancher/cniglue/Makefile
generated
vendored
23
vendor/github.com/rancher/cniglue/Makefile
generated
vendored
@ -1,23 +0,0 @@
|
||||
TARGETS := $(shell ls scripts)
|
||||
|
||||
.dapper:
|
||||
@echo Downloading dapper
|
||||
@curl -sL https://releases.rancher.com/dapper/latest/dapper-`uname -s`-`uname -m` > .dapper.tmp
|
||||
@@chmod +x .dapper.tmp
|
||||
@./.dapper.tmp -v
|
||||
@mv .dapper.tmp .dapper
|
||||
|
||||
$(TARGETS): .dapper
|
||||
./.dapper $@
|
||||
|
||||
trash: .dapper
|
||||
./.dapper -m bind trash
|
||||
|
||||
trash-keep: .dapper
|
||||
./.dapper -m bind trash -k
|
||||
|
||||
deps: trash
|
||||
|
||||
.DEFAULT_GOAL := ci
|
||||
|
||||
.PHONY: $(TARGETS)
|
28
vendor/github.com/rancher/cniglue/README.md
generated
vendored
28
vendor/github.com/rancher/cniglue/README.md
generated
vendored
@ -1,28 +0,0 @@
|
||||
CNI Glue
|
||||
========
|
||||
|
||||
Simple binding to plug CNI into Rancher and runc hooks.
|
||||
|
||||
## Building
|
||||
|
||||
`make`
|
||||
|
||||
|
||||
## Running
|
||||
|
||||
`./bin/cniglue`
|
||||
|
||||
## License
|
||||
Copyright (c) 2014-2016 [Rancher Labs, Inc.](http://rancher.com)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
123
vendor/github.com/rancher/cniglue/cni.go
generated
vendored
123
vendor/github.com/rancher/cniglue/cni.go
generated
vendored
@ -1,123 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/libcni"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
)
|
||||
|
||||
var (
|
||||
cniDir = "/etc/docker/cni/%s.d"
|
||||
cniPath = []string{
|
||||
"/var/lib/cni/bin",
|
||||
"/usr/local/sbin",
|
||||
"/usr/sbin",
|
||||
"/sbin",
|
||||
"/usr/local/bin",
|
||||
"/usr/bin",
|
||||
"/bin",
|
||||
}
|
||||
)
|
||||
|
||||
type CNIExec struct {
|
||||
confs []*libcni.NetworkConfig
|
||||
runtimeConf libcni.RuntimeConf
|
||||
cninet libcni.CNIConfig
|
||||
}
|
||||
|
||||
func (c *CNIExec) Add(index int) (*types.Result, error) {
|
||||
return c.cninet.AddNetwork(c.confs[index], &c.runtimeConf)
|
||||
}
|
||||
|
||||
func (c *CNIExec) Del(index int) error {
|
||||
rt := c.runtimeConf
|
||||
rt.NetNS = ""
|
||||
return c.cninet.DelNetwork(c.confs[index], &rt)
|
||||
}
|
||||
|
||||
func NewCNIExec(state *DockerPluginState) (*CNIExec, error) {
|
||||
if state.HostConfig.NetworkMode.IsContainer() ||
|
||||
state.HostConfig.NetworkMode.IsHost() ||
|
||||
state.HostConfig.NetworkMode.IsNone() {
|
||||
return &CNIExec{}, nil
|
||||
}
|
||||
|
||||
c := &CNIExec{
|
||||
runtimeConf: libcni.RuntimeConf{
|
||||
ContainerID: state.ContainerID,
|
||||
NetNS: fmt.Sprintf("/proc/%d/ns/net", state.State.Pid),
|
||||
IfName: "eth0",
|
||||
Args: [][2]string{
|
||||
{"IgnoreUnknown", "1"},
|
||||
{"DOCKER", "true"},
|
||||
},
|
||||
},
|
||||
cninet: libcni.CNIConfig{
|
||||
Path: cniPath,
|
||||
},
|
||||
}
|
||||
|
||||
network := state.HostConfig.NetworkMode.NetworkName()
|
||||
if network == "" {
|
||||
network = "default"
|
||||
}
|
||||
|
||||
dir := fmt.Sprintf(cniDir, network)
|
||||
files, err := libcni.ConfFiles(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sort.Strings(files)
|
||||
|
||||
os.Setenv("PATH", strings.Join(cniPath, ":"))
|
||||
|
||||
for _, file := range files {
|
||||
netConf, err := libcni.ConfFromFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.confs = append(c.confs, netConf)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func CNIAdd(state *DockerPluginState) (*types.Result, error) {
|
||||
c, err := NewCNIExec(state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result *types.Result
|
||||
for i := range c.confs {
|
||||
pluginResult, err := c.Add(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pluginResult.IP4 != nil {
|
||||
result = pluginResult
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func CNIDel(state *DockerPluginState) error {
|
||||
c, err := NewCNIExec(state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
for i := len(c.confs) - 1; i >= 0; i-- {
|
||||
if err := c.Del(i); err != nil {
|
||||
lastErr = err
|
||||
}
|
||||
}
|
||||
|
||||
return lastErr
|
||||
}
|
43
vendor/github.com/rancher/cniglue/conf.go
generated
vendored
43
vendor/github.com/rancher/cniglue/conf.go
generated
vendored
@ -1,43 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/docker/engine-api/types/container"
|
||||
"github.com/opencontainers/specs/specs-go"
|
||||
)
|
||||
|
||||
type DockerPluginState struct {
|
||||
ContainerID string
|
||||
State specs.State
|
||||
Spec specs.Spec
|
||||
HostConfig container.HostConfig
|
||||
Config container.Config
|
||||
}
|
||||
|
||||
func ReadState() (*DockerPluginState, error) {
|
||||
pluginState := DockerPluginState{}
|
||||
config := struct {
|
||||
ID string
|
||||
Config container.Config
|
||||
}{}
|
||||
|
||||
if err := json.NewDecoder(os.Stdin).Decode(&pluginState.State); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := readJSONFile(os.Getenv("DOCKER_HOST_CONFIG"), &pluginState.HostConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := readJSONFile(os.Getenv("DOCKER_CONFIG"), &config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pluginState.Config = config.Config
|
||||
pluginState.ContainerID = config.ID
|
||||
|
||||
return &pluginState, readJSONFile(path.Join(pluginState.State.BundlePath, "config.json"), &pluginState.Spec)
|
||||
}
|
46
vendor/github.com/rancher/cniglue/glue.go
generated
vendored
46
vendor/github.com/rancher/cniglue/glue.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
func Main() {
|
||||
var err error
|
||||
if len(os.Args) < 2 || os.Args[1] == "prestart" {
|
||||
err = Prestart()
|
||||
} else if os.Args[1] == "poststop" {
|
||||
err = Poststop()
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Prestart() error {
|
||||
state, err := ReadState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := SetupResolvConf(state); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cniResult, err := CNIAdd(state)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SetupHosts(state, cniResult)
|
||||
}
|
||||
|
||||
func Poststop() error {
|
||||
state, err := ReadState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return CNIDel(state)
|
||||
}
|
67
vendor/github.com/rancher/cniglue/hosts.go
generated
vendored
67
vendor/github.com/rancher/cniglue/hosts.go
generated
vendored
@ -1,67 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
hostsFile = "/etc/hosts"
|
||||
defaultHosts = []byte(`127.0.0.1 localhost
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
`)
|
||||
)
|
||||
|
||||
func SetupHosts(state *DockerPluginState, cniResult *types.Result) error {
|
||||
targetFile := path.Join(state.Spec.Root.Path, hostsFile)
|
||||
mode := state.HostConfig.NetworkMode
|
||||
|
||||
if !isZero(targetFile) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if mode.IsHost() {
|
||||
return copyToExistingFile(targetFile, hostsFile)
|
||||
} else if mode.IsNone() {
|
||||
return writeHosts(targetFile, "", "")
|
||||
} else if mode.IsContainer() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ip := ""
|
||||
if cniResult != nil && cniResult.IP4 != nil {
|
||||
ip = cniResult.IP4.IP.String()
|
||||
}
|
||||
|
||||
return writeHosts(targetFile, ip, state.Config.Hostname)
|
||||
}
|
||||
|
||||
func writeHosts(file, ip, hostname string) error {
|
||||
f, err := os.OpenFile(file, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "opening "+file)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err := f.Write(defaultHosts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ip != "" && hostname != "" {
|
||||
_, err := io.WriteString(f, fmt.Sprintf("%s %s\n", ip, hostname))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
51
vendor/github.com/rancher/cniglue/io.go
generated
vendored
51
vendor/github.com/rancher/cniglue/io.go
generated
vendored
@ -1,51 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func isZero(path string) bool {
|
||||
stat, err := os.Stat(path)
|
||||
if os.IsNotExist(err) {
|
||||
return true
|
||||
}
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return stat.Size() == 0
|
||||
}
|
||||
|
||||
func copyToExistingFile(to, from string) error {
|
||||
src, err := os.Open(from)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "opening file "+from)
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dest, err := os.OpenFile(to, os.O_RDWR|os.O_TRUNC, 0666)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "opening file "+to)
|
||||
}
|
||||
defer dest.Close()
|
||||
|
||||
_, err = io.Copy(dest, src)
|
||||
return err
|
||||
}
|
||||
|
||||
func readJSONFile(file string, obj interface{}) error {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "opening "+file)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := json.NewDecoder(f).Decode(obj); err != nil {
|
||||
return errors.Wrap(err, "unmarshaling "+file)
|
||||
}
|
||||
return nil
|
||||
}
|
83
vendor/github.com/rancher/cniglue/resolvconf.go
generated
vendored
83
vendor/github.com/rancher/cniglue/resolvconf.go
generated
vendored
@ -1,83 +0,0 @@
|
||||
package glue
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var resolvConf = "/etc/resolv.conf"
|
||||
|
||||
func SetupResolvConf(state *DockerPluginState) error {
|
||||
root := state.Spec.Root.Path
|
||||
mode := state.HostConfig.NetworkMode
|
||||
targetFile := path.Join(root, resolvConf)
|
||||
|
||||
if !isZero(targetFile) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if mode.IsHost() || mode.IsNone() {
|
||||
return copyToExistingFile(targetFile, resolvConf)
|
||||
}
|
||||
|
||||
if mode.IsContainer() {
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(resolvConf, os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
ignoreNameserver := false
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
line := s.Text()
|
||||
copyLine := true
|
||||
switch {
|
||||
case strings.HasPrefix(line, "nameserver"):
|
||||
copyLine = false
|
||||
if ignoreNameserver {
|
||||
break
|
||||
}
|
||||
for _, dns := range state.HostConfig.DNS {
|
||||
ignoreNameserver = true
|
||||
buf.WriteString(fmt.Sprintf("nameserver %s\n", dns))
|
||||
}
|
||||
if !ignoreNameserver && strings.Contains(line, "127.0.") {
|
||||
ignoreNameserver = true
|
||||
buf.WriteString(fmt.Sprintf("nameserver 8.8.8.8\n"))
|
||||
buf.WriteString(fmt.Sprintf("nameserver 8.8.4.4\n"))
|
||||
} else {
|
||||
copyLine = true
|
||||
}
|
||||
case strings.HasPrefix(line, "search"):
|
||||
if len(state.HostConfig.DNSSearch) > 0 {
|
||||
buf.WriteString(fmt.Sprintf("search %s\n", strings.Join(state.HostConfig.DNSSearch, " ")))
|
||||
}
|
||||
case strings.HasPrefix(line, "options"):
|
||||
if len(state.HostConfig.DNSOptions) > 0 {
|
||||
buf.WriteString(fmt.Sprintf("options %s\n", strings.Join(state.HostConfig.DNSOptions, " ")))
|
||||
}
|
||||
}
|
||||
|
||||
if copyLine {
|
||||
buf.WriteString(line)
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(targetFile, buf.Bytes(), 0666)
|
||||
}
|
7
vendor/github.com/rancher/cniglue/trash.conf
generated
vendored
7
vendor/github.com/rancher/cniglue/trash.conf
generated
vendored
@ -1,7 +0,0 @@
|
||||
github.com/containernetworking/cni b8e92ed030588120f9fda47dd359e17a3234142d
|
||||
github.com/docker/engine-api f90ecdb1e989f834dabbd91807e891094aa069fe
|
||||
github.com/docker/go-connections 990a1a1a70b0da4c4cb70e117971a4f0babfbf1a
|
||||
github.com/docker/go-units f2d77a61e3c169b43402a0a1e84f06daf29b8190
|
||||
github.com/opencontainers/specs b45aa77484bb771fc50498020063abcbc9b5f4c2
|
||||
github.com/pkg/errors d62207b3dc916c342cd6a7180fa861d898cf42ee
|
||||
github.com/Sirupsen/logrus 446d1c146faa8ed3f4218f056fcd165f6bcfda81
|
Loading…
Reference in New Issue
Block a user