1
0
mirror of https://github.com/rancher/os.git synced 2025-09-01 14:48:55 +00:00

move dependencies to vendor

This commit is contained in:
Ivan Mikushin
2015-11-26 17:37:01 +05:00
parent 63d7de67cd
commit 1d691cd8d6
2232 changed files with 154499 additions and 9037 deletions

2
vendor/github.com/docker/machine/.dockerignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
docker-machine*
.git

2
vendor/github.com/docker/machine/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
docker-machine*
*.log

1
vendor/github.com/docker/machine/.godir generated vendored Normal file
View File

@@ -0,0 +1 @@
github.com/docker/machine

14
vendor/github.com/docker/machine/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,14 @@
language: go
sudo: false
go:
- 1.3
install:
- export GOPATH=${TRAVIS_BUILD_DIR}/Godeps/_workspace:$GOPATH
- export PATH=${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$PATH
- go get -t -v ./...
- go get code.google.com/p/go.tools/cmd/cover
script:
- script/validate-dco
- script/validate-gofmt
- go test -v -short ./...
- script/generate-coverage

164
vendor/github.com/docker/machine/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,164 @@
Changelog
==========
# 0.3.0 (2015-06-18)
## Features
- Engine option configuration (ability to configure all engine options)
- Swarm option configuration (ability to configure all swarm options)
- New Provisioning system to allow for greater flexibility and stability for installing and configuring Docker
- New Provisioners
- Rancher OS
- RedHat Enterprise Linux 7.0+ (experimental)
- Fedora 21+ (experimental)
- Debian 8+ (experimental)
- PowerShell support (configure Windows Docker CLI)
- Command Prompt (cmd.exe) support (configure Windows Docker CLI)
- Filter command help by driver
- Ability to import Boot2Docker instances
- Boot2Docker CLI migration guide (experimental)
- Format option for `inspect` command
- New logging output format to improve readability and display across platforms
- Updated "active" machine concept - now is implicit according to `DOCKER_HOST` environment variable. Note: this removes the implicit "active" machine and can no longer be specified with the `active` command. You change the "active" host by using the `env` command instead.
- Specify Swarm version (`--swarm-image` flag)
## Drivers
- New: Exoscale Driver
- New: Generic Driver (provision any host with supported base OS and SSH)
- Amazon EC2
- SSH user is configurable
- Support for Spot instances
- Add option to use private address only
- Base AMI updated to 20150417
- Google
- Support custom disk types
- Updated base image to v20150316
- Openstack
- Support for Keystone v3 domains
- Rackspace
- Misc fixes including environment variable for Flavor Id and stability
- Softlayer
- Enable local disk as provisioning option
- Fixes for SSH access errors
- Fixed bug where public IP would always be returned when requesting private
- Add support for specifying public and private VLAN IDs
- VirtualBox
- Use Intel network interface driver (adds great stability)
- Stability fixes for NAT access
- Use DNS pass through
- Default CPU to single core for improved performance
- Enable shared folder support for Windows hosts
- VMware Fusion
- Boot2Docker ISO updated
- Shared folder support
## Fixes
- Provisioning improvements to ensure Docker is available
- SSH improvements for provisioning stability
- Fixed SSH key generation bug on Windows
- Help formatting for improved readability
## Breaking Changes
- "Short-Form" name reference no longer supported Instead of "docker-machine " implying the active host you must now use docker-machine
- VMware shared folders require Boot2Docker 1.7
## Special Thanks
We would like to thank all contributors. Machine would not be where it is
without you. We would also like to give special thanks to the following
contributors for outstanding contributions to the project:
- @frapposelli for VMware updates and fixes
- @hairyhenderson for several improvements to Softlayer driver, inspect formatting and lots of fixes
- @ibuildthecloud for rancher os provisioning
- @sthulb for portable SSH library
- @vincentbernat for exoscale
- @zchee for Amazon updates and great doc updates
# 0.2.0 (2015-04-16)
Core Stability and Driver Updates
## Core
- Support for system proxy environment
- New command to regenerate TLS certificates
- Note: this will restart the Docker engine to apply
- Updates to driver operations (create, start, stop, etc) for better reliability
- New internal `libmachine` package for internal api (not ready for public usage)
- Updated Driver Interface
- [Driver Spec](https://github.com/docker/machine/blob/master/docs/DRIVER_SPEC.md)
- Removed host provisioning from Drivers to enable a more consistent install
- Removed SSH commands from each Driver for more consistent operations
- Swarm: machine now uses Swarm default binpacking strategy
## Driver Updates
- All drivers updated to new Driver interface
- Amazon EC2
- Better checking for subnets on creation
- Support for using Private IPs in VPC
- Fixed bug with duplicate security group authorization with Swarm
- Support for IAM instance profile
- Fixed bug where IP was not properly detected upon stop
- DigitalOcean
- IPv6 support
- Backup option
- Private Networking
- Openstack / Rackspace
- Gophercloud updated to latest version
- New insecure flag to disable TLS (use with caution)
- Google
- Google source image updated
- Ability to specify auth token via file
- VMware Fusion
- Paravirtualized driver for disk (pvscsi)
- Enhanced paravirtualized NIC (vmxnet3)
- Power option updates
- SSH keys persistent across reboots
- Stop now gracefully stops VM
- vCPUs now match host CPUs
- SoftLayer
- Fixed provision bug where `curl` was not present
- VirtualBox
- Correct power operations with Saved VM state
- Fixed bug where image option was ignored
## CLI
- Auto-regeneration of TLS certificates when TLS error is detected
- Note: this will restart the Docker engine to apply
- Minor UI updates including improved sorting and updated command docs
- Bug with `config` and `env` with spaces fixed
- Note: you now must use `eval $(docker-machine env machine)` to load environment settings
- Updates to better support `fish` shell
- Use `--tlsverify` for both `config` and `env` commands
- Commands now use eval for better interoperability with shell
## Testing
- New integration test framework (bats)
# 0.1.0 (2015-02-26)
Initial beta release.
- Provision Docker Engines using multiple drivers
- Provide light management for the machines
- Create, Start, Stop, Restart, Kill, Remove, SSH
- Configure the Docker Engine for secure communication (TLS)
- Easily switch target machine for fast configuration of Docker Engine client
- Provision Swarm clusters (experimental)
## Included drivers
- Amazon EC2
- Digital Ocean
- Google
- Microsoft Azure
- Microsoft Hyper-V
- Openstack
- Rackspace
- VirtualBox
- VMware Fusion
- VMware vCloud Air
- VMware vSphere

227
vendor/github.com/docker/machine/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,227 @@
# Contributing to machine
[![GoDoc](https://godoc.org/github.com/docker/machine?status.png)](https://godoc.org/github.com/docker/machine)
[![Build Status](https://travis-ci.org/docker/machine.svg?branch=master)](https://travis-ci.org/docker/machine)
Want to hack on Machine? Awesome! Here are instructions to get you
started.
Machine is a part of the [Docker](https://www.docker.com) project, and follows
the same rules and principles. If you're already familiar with the way
Docker does things, you'll feel right at home.
Otherwise, go read
[Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md).
The requirements to build Machine are:
1. A running instance of Docker
2. The `bash` shell
To build, run:
$ script/build
From the Machine repository's root. Machine will run the build inside of a
Docker container and the compiled binaries will appear in the project directory
on the host.
By default, Machine will run a build which cross-compiles binaries for a variety
of architectures and operating systems. If you know that you are only compiling
for a particular architecture and/or operating system, you can speed up
compilation by overriding the default argument that the build script passes
to [gox](https://github.com/mitchellh/gox). This is very useful if you want
to iterate quickly on a new feature, bug fix, etc.
For instance, if you only want to compile for use on OS X with the x86_64 arch,
run:
$ script/build -osarch="darwin/amd64"
If you don't need to run the `docker build` to generate the image on each
compile, i.e. if you have built the image already, you can skip the image build
using the `SKIP_BUILD` environment variable, for instance:
$ SKIP_BUILD=1 script/build -osarch="darwin/amd64"
If you have any questions we're in #docker-machine on Freenode.
## Unit Tests
To run the unit tests for the whole project, using the following script:
$ script/test
This will run the unit tests inside of a container, so you don't have to worry
about configuring your environment properly before doing so.
To run the unit tests for only a specific subdirectory of the project, you can
pass an argument to that script to specify which directory, e.g.:
$ script/test ./drivers/amazonec2
If you make a pull request, it is highly encouraged that you submit tests for
the code that you have added or modified in the same pull request.
## Code Coverage
Machine includes a script to check for missing `*_test.go` files and to generate
an [HTML-based representation of which code is covered by tests](http://blog.golang.org/cover#TOC_5.).
To run the code coverage script, execute:
```console
$ ./script/coverage serve
```
You will see the results of the code coverage check as they come in.
This will also generate the code coverage website and serve it from a container
on port 8000. By default, `/` will show you the source files from the base
directory, and you can navigate to the coverage for any particular subdirectory
of the Docker Machine repo's root by going to that path. For instance, to see
the coverage for the VirtualBox driver's package, browse to `/drivers/virtualbox`.
![](/docs/img/coverage.png)
You can hit `CTRL+C` to stop the server.
## Integration Tests
### Setup
We utilize [BATS](https://github.com/sstephenson/bats) for integration testing.
This runs tests against the generated binary. To use, first make sure to
[install BATS](https://github.com/sstephenson/bats). Then run `./script/build`
to generate the binary for your system.
### Basic Usage
Once you have the binary, the integration tests can be invoked using the
`test/integration/run-bats.sh` wrapper script.
Using this wrapper script, you can invoke a test or subset of tests for a
particular driver. To set the driver, use the `DRIVER` environment variable.
The following examples are all shown relative to the project's root directory,
but you should be able to invoke them from any directory without issue.
To invoke just one test:
```console
$ DRIVER=virtualbox ./test/integration/run-bats.sh test/integration/core/core-commands.bats
✓ virtualbox: machine should not exist
✓ virtualbox: create
✓ virtualbox: ls
✓ virtualbox: run busybox container
✓ virtualbox: url
✓ virtualbox: ip
✓ virtualbox: ssh
✓ virtualbox: docker commands with the socket should work
✓ virtualbox: stop
✓ virtualbox: machine should show stopped after stop
✓ virtualbox: machine should now allow upgrade when stopped
✓ virtualbox: start
✓ virtualbox: machine should show running after start
✓ virtualbox: kill
✓ virtualbox: machine should show stopped after kill
✓ virtualbox: restart
✓ virtualbox: machine should show running after restart
17 tests, 0 failures
Cleaning up machines...
Successfully removed bats-virtualbox-test
```
To invoke a shared test with a different driver:
```console
$ DRIVER=digitalocean ./test/integration/run-bats.sh test/integration/core/core-commands.bats
...
```
To invoke a directory of tests recursively:
```console
$ DRIVER=virtualbox ./test/integration/run-bats.sh test/integration/core/
...
```
If you want to invoke a group of tests across two or more different drivers at
once (e.g. every test in the `drivers` directory), at the time of writing there
is no first-class support to do so - you will have to write your own wrapper
scripts, bash loops, etc. However, in the future, this may gain first-class
support as usage patterns become more clear.
### Extra Create Arguments
In some cases, for instance to test the creation of a specific base OS (e.g.
RHEL) as opposed to the default with the common tests, you may want to run
common tests with different create arguments than you get out of the box.
Keep in mind that Machine supports environment variables for many of these
flags. So, for instance, you could run the command (substituting, of course,
the proper secrets):
```
$ DRIVER=amazonec2 \
AWS_VPC_ID=vpc-xxxxxxx \
AWS_SECRET_ACCESS_KEY=yyyyyyyyyyyyy \
AWS_ACCESS_KEY_ID=zzzzzzzzzzzzzzzz \
AWS_AMI=ami-12663b7a \
AWS_SSH_USER=ec2-user \
./test/integration/run-bats.sh test/integration/core
```
in order to run the core tests on Red Hat Enterprise Linux on Amazon.
### Layout
The `test/integration` directory is layed out to divide up tests based on the
areas which the test. If you are uncertain where to put yours, we are happy to
guide you.
At the time of writing, there is:
1. A `core` directory which contains tests that are applicable to all drivers.
2. A `drivers` directory which contains tests that are applicable only to
specific drivers with sub-directories for each provider.
3. A `cli` directory which is meant for testing functionality of the command
line interface, without much regard for driver-specific details.
### Guidelines
The best practices for writing integration tests on Docker Machine are still a
work in progress, but here are some general guidelines from the maintainers:
1. Ideally, each test file should have only one concern.
2. Tests generally should not spin up more than one machine unless the test is
deliberately testing something which involves multiple machines, such as an `ls`
test which involves several machines, or a test intended to create and check
some property of a Swarm cluster.
3. BATS will print the output of commands executed during a test if the test
fails. This can be useful, for instance to dump the magic `$output` variable
that BATS provides and/or to get debugging information.
4. It is not strictly needed to clean up the machines as part of the test. The
BATS wrapper script has a hook to take care of cleaning up all created machines
after each test.
# Drivers
Docker Machine has several included drivers that supports provisioning hosts
in various providers. If you wish to contribute a driver, we ask the following
to ensure we keep the driver in a consistent and stable state:
- Address issues filed against this driver in a timely manner
- Review PRs for the driver
- Be responsible for maintaining the infrastructure to run unit tests
and integration tests on the new supported environment
- Participate in a weekly driver maintainer meeting
If you can commit to those, the next step is to make sure the driver adheres
to the [spec](https://github.com/docker/machine/blob/master/docs/DRIVER_SPEC.md).
Once you have created and tested the driver, you can open a PR.
Note: even if those are met does not guarantee a driver will be accepted.
If you have questions, please do not hesitate to contact us on IRC.

15
vendor/github.com/docker/machine/Dockerfile generated vendored Normal file
View File

@@ -0,0 +1,15 @@
FROM golang:1.4.2-cross
# TODO: Vendor these `go get` commands using Godep.
RUN go get github.com/mitchellh/gox
RUN go get github.com/aktau/github-release
RUN go get github.com/tools/godep
RUN go get golang.org/x/tools/cmd/cover
ENV GOPATH /go/src/github.com/docker/machine/Godeps/_workspace:/go
ENV MACHINE_BINARY /go/src/github.com/docker/machine/docker-machine
ENV USER root
WORKDIR /go/src/github.com/docker/machine
ADD . /go/src/github.com/docker/machine

191
vendor/github.com/docker/machine/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,191 @@
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
Copyright 2014 Docker, 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.

3
vendor/github.com/docker/machine/MAINTAINERS generated vendored Normal file
View File

@@ -0,0 +1,3 @@
Ben Firshman <ben@firshman.co.uk> (@bfirsh)
Evan Hazlett <ejhazlett@gmail.com> (@ehazlett)
Nathan LeClaire <nathan.leclaire@docker.com> (@nathanleclaire)

18
vendor/github.com/docker/machine/Makefile generated vendored Normal file
View File

@@ -0,0 +1,18 @@
.PHONY: all test validate-dco validate-gofmt validate build
all: validate test build
test:
script/test
validate-dco:
script/validate-dco
validate-gofmt:
script/validate-gofmt
validate: validate-dco validate-gofmt
build:
script/build

56
vendor/github.com/docker/machine/README.md generated vendored Normal file
View File

@@ -0,0 +1,56 @@
# Docker Machine
![](/docs/img/logo.png)
Machine lets you create Docker hosts on your computer, on cloud providers, and
inside your own data center. It creates servers, installs Docker on them, then
configures the Docker client to talk to them.
It works a bit like this:
```console
$ docker-machine create -d virtualbox dev
Creating CA: /home/username/.docker/machine/certs/ca.pem
Creating client certificate: /home/username/.docker/machine/certs/cert.pem
Image cache does not exist, creating it at /home/username/.docker/machine/cache...
No default boot2docker iso found locally, downloading the latest release...
Downloading https://github.com/boot2docker/boot2docker/releases/download/v1.6.2/boot2docker.iso to /home/username/.docker/machine/cache/boot2docker.iso...
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env dev
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
dev * virtualbox Running tcp://192.168.99.127:2376
$ eval "$(docker-machine env dev)"
$ docker run busybox echo hello world
Unable to find image 'busybox:latest' locally
511136ea3c5a: Pull complete
df7546f9f060: Pull complete
ea13149945cb: Pull complete
4986bf8c1536: Pull complete
hello world
$ docker-machine create -d digitalocean --digitalocean-access-token=secret staging
Creating SSH key...
Creating Digital Ocean droplet...
To see how to connect Docker to this machine, run: docker-machine env staging
$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
dev virtualbox Running tcp://192.168.99.127:2376
staging * digitalocean Running tcp://104.236.253.181:2376
```
## Installation and documentation
Full documentation [is available here](https://docs.docker.com/machine/).
## Contributing
Want to hack on Machine? Please start with the [Contributing Guide](https://github.com/docker/machine/blob/master/CONTRIBUTING.md).

31
vendor/github.com/docker/machine/ROADMAP.md generated vendored Normal file
View File

@@ -0,0 +1,31 @@
# Machine Roadmap
Machine currently works really well for development and test environments. The
goal is to make it work better for provisioning and managing production
environments.
This is not a simple task -- production is inherently far more complex than
development -- but there are three things which are big steps towards that goal:
**client/server architecture**, **swarm integration** and **flexible
provisioning**.
(Note: this document is a high-level overview of where we are taking Machine.
For what is coming in specific releases, see our [upcoming
milestones](https://github.com/docker/machine/milestones).)
### Docker Engine / Swarm Configuration
Currently there are only a few things that can be configured in the Docker Engine and Swarm. This will enable more operations such as Engine labels and Swarm strategies.
### Boot2Docker Migration Support
Currently both Machine and Boot2Docker provider similar functionality. This will enable users to migrate from boot2docker to machine.
### Expand Provisioner
Machine currently supports running Boot2Docker for "local" providers and Ubuntu for "remote" providers. This will expand the provisioning capabilities to include other base operating systems such as Red Hat-like distributions and possibly other "just enough" operating systems.
### Windows Experience
Currently, the Machine on Windows experience is not as good as the Mac / Linux. There is no "recommended" path to use Machine and there are several inconsistencies on Windows such as logging and output formatting.
Project Planning
================
An [Open-Source Planning Process](https://github.com/docker/machine/wiki/Open-Source-Planning-Process) is used to define the Roadmap. [Project Pages](https://github.com/docker/machine/wiki) define the goals for each Milestone and identify current progress.

123
vendor/github.com/docker/machine/log/log.go generated vendored Normal file
View File

@@ -0,0 +1,123 @@
package log
import (
"fmt"
"os"
"strconv"
)
// Why the interface? We may only want to print to STDOUT and STDERR for now,
// but it won't neccessarily be that way forever. This interface is intended
// to provide a "framework" for a variety of different logging types in the
// future (log to file, log to logstash, etc.) There could be a driver model
// similar to what is done with OS or machine providers.
type Logger interface {
Debug(...interface{})
Debugf(string, ...interface{})
Error(...interface{})
Errorf(string, ...interface{})
Errorln(...interface{})
Info(...interface{})
Infof(string, ...interface{})
Infoln(...interface{})
Fatal(...interface{})
Fatalf(string, ...interface{})
Print(...interface{})
Printf(string, ...interface{})
Warn(...interface{})
Warnf(string, ...interface{})
WithFields(Fields) Logger
}
var (
l = TerminalLogger{}
)
// TODO: I think this is superflous and can be replaced by one check for if
// debug is on that sets a variable in this module.
func isDebug() bool {
debugEnv := os.Getenv("DEBUG")
if debugEnv != "" {
showDebug, err := strconv.ParseBool(debugEnv)
if err != nil {
fmt.Fprintln(os.Stderr, "Error parsing boolean value from DEBUG: %s", err)
os.Exit(1)
}
return showDebug
}
return false
}
type Fields map[string]interface{}
func Debug(args ...interface{}) {
l.Debug(args...)
}
func Debugf(fmtString string, args ...interface{}) {
l.Debugf(fmtString, args...)
}
func Error(args ...interface{}) {
l.Error(args...)
}
func Errorf(fmtString string, args ...interface{}) {
l.Errorf(fmtString, args...)
}
func Errorln(args ...interface{}) {
l.Errorln(args...)
}
func Info(args ...interface{}) {
l.Info(args...)
}
func Infof(fmtString string, args ...interface{}) {
l.Infof(fmtString, args...)
}
func Infoln(args ...interface{}) {
l.Infoln(args...)
}
func Fatal(args ...interface{}) {
l.Fatal(args...)
}
func Fatalf(fmtString string, args ...interface{}) {
l.Fatalf(fmtString, args...)
}
func Print(args ...interface{}) {
l.Print(args...)
}
func Printf(fmtString string, args ...interface{}) {
l.Printf(fmtString, args...)
}
func Warn(args ...interface{}) {
l.Warn(args...)
}
func Warnf(fmtString string, args ...interface{}) {
l.Warnf(fmtString, args...)
}
func WithField(fieldName string, field interface{}) Logger {
return l.WithFields(Fields{
fieldName: field,
})
}
func WithFields(fields Fields) Logger {
return l.WithFields(fields)
}

19
vendor/github.com/docker/machine/log/log_test.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package log
import "testing"
func TestTerminalLoggerWithFields(t *testing.T) {
logger := TerminalLogger{}
withFieldsLogger := logger.WithFields(Fields{
"foo": "bar",
"spam": "eggs",
})
withFieldsTerminalLogger, ok := withFieldsLogger.(TerminalLogger)
if !ok {
t.Fatal("Type assertion to TerminalLogger failed")
}
expectedOutFields := "\t\t foo=bar spam=eggs"
if withFieldsTerminalLogger.fieldOut != expectedOutFields {
t.Fatalf("Expected %q, got %q", expectedOutFields, withFieldsTerminalLogger.fieldOut)
}
}

129
vendor/github.com/docker/machine/log/terminal.go generated vendored Normal file
View File

@@ -0,0 +1,129 @@
package log
import (
"fmt"
"os"
"sort"
)
type TerminalLogger struct {
// fieldOut is used to do log.WithFields correctly
fieldOut string
}
func (t TerminalLogger) log(args ...interface{}) {
fmt.Print(args...)
fmt.Print(t.fieldOut, "\n")
t.fieldOut = ""
}
func (t TerminalLogger) logf(fmtString string, args ...interface{}) {
fmt.Printf(fmtString, args...)
fmt.Print(t.fieldOut, "\n")
t.fieldOut = ""
}
func (t TerminalLogger) err(args ...interface{}) {
fmt.Fprint(os.Stderr, args...)
fmt.Fprint(os.Stderr, t.fieldOut, "\n")
t.fieldOut = ""
}
func (t TerminalLogger) errf(fmtString string, args ...interface{}) {
fmt.Fprintf(os.Stderr, fmtString, args...)
fmt.Fprint(os.Stderr, t.fieldOut, "\n")
t.fieldOut = ""
}
func (t TerminalLogger) Debug(args ...interface{}) {
if isDebug() {
t.log(args...)
}
}
func (t TerminalLogger) Debugf(fmtString string, args ...interface{}) {
if isDebug() {
t.logf(fmtString, args...)
}
}
func (t TerminalLogger) Error(args ...interface{}) {
t.err(args...)
}
func (t TerminalLogger) Errorf(fmtString string, args ...interface{}) {
t.errf(fmtString, args...)
}
func (t TerminalLogger) Errorln(args ...interface{}) {
t.err(args...)
}
func (t TerminalLogger) Info(args ...interface{}) {
t.log(args...)
}
func (t TerminalLogger) Infof(fmtString string, args ...interface{}) {
t.logf(fmtString, args...)
}
func (t TerminalLogger) Infoln(args ...interface{}) {
t.log(args...)
}
func (t TerminalLogger) Fatal(args ...interface{}) {
t.err(args...)
os.Exit(1)
}
func (t TerminalLogger) Fatalf(fmtString string, args ...interface{}) {
t.errf(fmtString, args...)
os.Exit(1)
}
func (t TerminalLogger) Print(args ...interface{}) {
t.log(args...)
}
func (t TerminalLogger) Printf(fmtString string, args ...interface{}) {
t.logf(fmtString, args...)
}
func (t TerminalLogger) Warn(args ...interface{}) {
t.log(args...)
}
func (t TerminalLogger) Warnf(fmtString string, args ...interface{}) {
t.logf(fmtString, args...)
}
func (t TerminalLogger) WithFields(fields Fields) Logger {
// When the user calls WithFields, we make a string which gets appended
// to the output of the final [Info|Warn|Error] call for the
// descriptive fields. Because WithFields returns the proper Logger
// (with the fieldOut string set correctly), the logrus syntax will
// still work.
kvpairs := []string{}
// Why the string slice song and dance? Because Go's map iteration
// order is random, we will get inconsistent results if we don't sort
// the fields (or their resulting string K/V pairs, like we have here).
// Otherwise, we couldn't test this reliably.
for k, v := range fields {
kvpairs = append(kvpairs, fmt.Sprintf("%s=%v", k, v))
}
sort.Strings(kvpairs)
// TODO:
// 1. Is this thread-safe?
// 2. Add more tabs?
t.fieldOut = "\t\t"
for _, s := range kvpairs {
// TODO: Is %v the correct format string here?
t.fieldOut = fmt.Sprintf("%s %s", t.fieldOut, s)
}
return t
}

125
vendor/github.com/docker/machine/main.go generated vendored Normal file
View File

@@ -0,0 +1,125 @@
package main
import (
"os"
"path"
"github.com/codegangsta/cli"
"github.com/docker/machine/commands"
"github.com/docker/machine/log"
"github.com/docker/machine/ssh"
"github.com/docker/machine/utils"
"github.com/docker/machine/version"
)
var AppHelpTemplate = `Usage: {{.Name}} {{if .Flags}}[OPTIONS] {{end}}COMMAND [arg...]
{{.Usage}}
Version: {{.Version}}{{if or .Author .Email}}
Author:{{if .Author}}
{{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}}
{{.Email}}{{end}}{{end}}
{{if .Flags}}
Options:
{{range .Flags}}{{.}}
{{end}}{{end}}
Commands:
{{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
{{end}}
Run '{{.Name}} COMMAND --help' for more information on a command.
`
var CommandHelpTemplate = `Usage: docker-machine {{.Name}}{{if .Flags}} [OPTIONS]{{end}} [arg...]
{{.Usage}}{{if .Description}}
Description:
{{.Description}}{{end}}{{if .Flags}}
Options:
{{range .Flags}}
{{.}}{{end}}{{ end }}
`
func main() {
for _, f := range os.Args {
if f == "-D" || f == "--debug" || f == "-debug" {
os.Setenv("DEBUG", "1")
}
}
cli.AppHelpTemplate = AppHelpTemplate
cli.CommandHelpTemplate = CommandHelpTemplate
app := cli.NewApp()
app.Name = path.Base(os.Args[0])
app.Author = "Docker Machine Contributors"
app.Email = "https://github.com/docker/machine"
app.Before = func(c *cli.Context) error {
os.Setenv("MACHINE_STORAGE_PATH", c.GlobalString("storage-path"))
if c.GlobalBool("native-ssh") {
ssh.SetDefaultClient(ssh.Native)
}
return nil
}
app.Commands = commands.Commands
app.CommandNotFound = cmdNotFound
app.Usage = "Create and manage machines running Docker."
app.Version = version.VERSION + " (" + version.GITCOMMIT + ")"
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug, D",
Usage: "Enable debug mode",
},
cli.StringFlag{
EnvVar: "MACHINE_STORAGE_PATH",
Name: "s, storage-path",
Value: utils.GetBaseDir(),
Usage: "Configures storage path",
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CA_CERT",
Name: "tls-ca-cert",
Usage: "CA to verify remotes against",
Value: "",
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CA_KEY",
Name: "tls-ca-key",
Usage: "Private key to generate certificates",
Value: "",
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CLIENT_CERT",
Name: "tls-client-cert",
Usage: "Client cert to use for TLS",
Value: "",
},
cli.StringFlag{
EnvVar: "MACHINE_TLS_CLIENT_KEY",
Name: "tls-client-key",
Usage: "Private key used in client TLS auth",
Value: "",
},
cli.BoolFlag{
EnvVar: "MACHINE_NATIVE_SSH",
Name: "native-ssh",
Usage: "Use the native (Go-based) SSH implementation.",
},
}
app.Run(os.Args)
}
func cmdNotFound(c *cli.Context, command string) {
log.Fatalf(
"%s: '%s' is not a %s command. See '%s --help'.",
c.App.Name,
command,
c.App.Name,
c.App.Name,
)
}

1
vendor/github.com/docker/machine/main_test.go generated vendored Normal file
View File

@@ -0,0 +1 @@
package main

238
vendor/github.com/docker/machine/utils/b2d.go generated vendored Normal file
View File

@@ -0,0 +1,238 @@
package utils
import (
//"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"time"
"github.com/docker/machine/log"
)
const (
timeout = time.Second * 5
)
func defaultTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
func getClient() *http.Client {
transport := http.Transport{
DisableKeepAlives: true,
Proxy: http.ProxyFromEnvironment,
Dial: defaultTimeout,
}
client := http.Client{
Transport: &transport,
}
return &client
}
type B2dUtils struct {
isoFilename string
commonIsoPath string
imgCachePath string
githubApiBaseUrl string
githubBaseUrl string
}
func NewB2dUtils(githubApiBaseUrl, githubBaseUrl, isoFilename string) *B2dUtils {
defaultBaseApiUrl := "https://api.github.com"
defaultBaseUrl := "https://github.com"
imgCachePath := GetMachineCacheDir()
if githubApiBaseUrl == "" {
githubApiBaseUrl = defaultBaseApiUrl
}
if githubBaseUrl == "" {
githubBaseUrl = defaultBaseUrl
}
return &B2dUtils{
isoFilename: isoFilename,
imgCachePath: GetMachineCacheDir(),
commonIsoPath: filepath.Join(imgCachePath, isoFilename),
githubApiBaseUrl: githubApiBaseUrl,
githubBaseUrl: githubBaseUrl,
}
}
// Get the latest boot2docker release tag name (e.g. "v0.6.0").
// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL() (string, error) {
//client := getClient()
//apiUrl := fmt.Sprintf("%s/repos/boot2docker/boot2docker/releases", b.githubApiBaseUrl)
//rsp, err := client.Get(apiUrl)
//if err != nil {
// return "", err
//}
//defer rsp.Body.Close()
//var t []struct {
// TagName string `json:"tag_name"`
// PreRelease bool `json:"prerelease"`
//}
//if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil {
// return "", fmt.Errorf("Error demarshaling the Github API response: %s\nYou may be getting rate limited by Github.", err)
//}
//if len(t) == 0 {
// return "", fmt.Errorf("no releases found")
//}
//// find the latest "released" release (i.e. not pre-release)
//isoUrl := ""
//for _, r := range t {
// if !r.PreRelease {
// tag := r.TagName
// isoUrl = fmt.Sprintf("%s/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", b.githubBaseUrl, tag)
// break
// }
//}
//return isoUrl, nil
// TODO: once we decide on the final versioning and location we will
// enable the above "check for latest"
u := fmt.Sprintf("https://s3.amazonaws.com/docker-mcn/public/b2d-next/%s", b.isoFilename)
return u, nil
}
func removeFileIfExists(name string) error {
if _, err := os.Stat(name); err == nil {
if err := os.Remove(name); err != nil {
log.Fatalf("Error removing temporary download file: %s", err)
}
}
return nil
}
// Download boot2docker ISO image for the given tag and save it at dest.
func (b *B2dUtils) DownloadISO(dir, file, isoUrl string) error {
u, err := url.Parse(isoUrl)
var src io.ReadCloser
if u.Scheme == "file" || u.Scheme == "" {
s, err := os.Open(u.Path)
if err != nil {
return err
}
src = s
} else {
client := getClient()
s, err := client.Get(isoUrl)
if err != nil {
return err
}
src = s.Body
}
defer src.Close()
// Download to a temp file first then rename it to avoid partial download.
f, err := ioutil.TempFile(dir, file+".tmp")
if err != nil {
return err
}
defer func() {
if err := removeFileIfExists(f.Name()); err != nil {
log.Fatalf("Error removing file: %s", err)
}
}()
if _, err := io.Copy(f, src); err != nil {
// TODO: display download progress?
return err
}
if err := f.Close(); err != nil {
return err
}
// Dest is the final path of the boot2docker.iso file.
dest := filepath.Join(dir, file)
// Windows can't rename in place, so remove the old file before
// renaming the temporary downloaded file.
if err := removeFileIfExists(dest); err != nil {
return err
}
if err := os.Rename(f.Name(), dest); err != nil {
return err
}
return nil
}
func (b *B2dUtils) DownloadLatestBoot2Docker() error {
latestReleaseUrl, err := b.GetLatestBoot2DockerReleaseURL()
if err != nil {
return err
}
return b.DownloadISOFromURL(latestReleaseUrl)
}
func (b *B2dUtils) DownloadISOFromURL(latestReleaseUrl string) error {
log.Infof("Downloading %s to %s...", latestReleaseUrl, b.commonIsoPath)
if err := b.DownloadISO(b.imgCachePath, b.isoFilename, latestReleaseUrl); err != nil {
return err
}
return nil
}
func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error {
machinesDir := GetMachineDir()
machineIsoPath := filepath.Join(machinesDir, machineName, b.isoFilename)
// just in case the cache dir has been manually deleted,
// check for it and recreate it if it's gone
if _, err := os.Stat(b.imgCachePath); os.IsNotExist(err) {
log.Infof("Image cache does not exist, creating it at %s...", b.imgCachePath)
if err := os.Mkdir(b.imgCachePath, 0700); err != nil {
return err
}
}
// By default just copy the existing "cached" iso to
// the machine's directory...
if isoURL == "" {
if err := b.copyDefaultIsoToMachine(machineIsoPath); err != nil {
return err
}
} else {
// But if ISO is specified go get it directly
log.Infof("Downloading %s from %s...", b.isoFilename, isoURL)
if err := b.DownloadISO(filepath.Join(machinesDir, machineName), b.isoFilename, isoURL); err != nil {
return err
}
}
return nil
}
func (b *B2dUtils) copyDefaultIsoToMachine(machineIsoPath string) error {
if _, err := os.Stat(b.commonIsoPath); os.IsNotExist(err) {
log.Info("No default boot2docker iso found locally, downloading the latest release...")
if err := b.DownloadLatestBoot2Docker(); err != nil {
return err
}
}
if err := CopyFile(b.commonIsoPath, machineIsoPath); err != nil {
return err
}
return nil
}

63
vendor/github.com/docker/machine/utils/b2d_test.go generated vendored Normal file
View File

@@ -0,0 +1,63 @@
package utils
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"path/filepath"
"testing"
)
func TestGetLatestBoot2DockerReleaseUrl(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
respText := `[{"tag_name": "0.2", "prerelease": true, "tag_name": "0.1", "prerelease": false}]`
w.Write([]byte(respText))
}))
defer ts.Close()
b := NewB2dUtils(ts.URL, ts.URL, "virtualbox")
isoUrl, err := b.GetLatestBoot2DockerReleaseURL()
if err != nil {
t.Fatal(err)
}
// TODO: update to release URL once we get the releases worked
// out for b2d-ng
//expectedUrl := fmt.Sprintf("%s/boot2docker/boot2docker/releases/download/0.1/boot2docker.iso", ts.URL)
//if isoUrl != expectedUrl {
// t.Fatalf("expected url %s; received %s", isoUrl)
//}
if isoUrl == "" {
t.Fatalf("expected a url for the iso")
}
}
func TestDownloadIso(t *testing.T) {
testData := "test-download"
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(testData))
}))
defer ts.Close()
filename := "test"
tmpDir, err := ioutil.TempDir("", "machine-test-")
if err != nil {
t.Fatal(err)
}
b := NewB2dUtils(ts.URL, ts.URL, "")
if err := b.DownloadISO(tmpDir, filename, ts.URL); err != nil {
t.Fatal(err)
}
data, err := ioutil.ReadFile(filepath.Join(tmpDir, filename))
if err != nil {
t.Fatal(err)
}
if string(data) != testData {
t.Fatalf("expected data \"%s\"; received \"%s\"", testData, string(data))
}
}

202
vendor/github.com/docker/machine/utils/certs.go generated vendored Normal file
View File

@@ -0,0 +1,202 @@
package utils
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"io/ioutil"
"math/big"
"net"
"os"
"time"
)
func getTLSConfig(caCert, cert, key []byte, allowInsecure bool) (*tls.Config, error) {
// TLS config
var tlsConfig tls.Config
tlsConfig.InsecureSkipVerify = allowInsecure
certPool := x509.NewCertPool()
certPool.AppendCertsFromPEM(caCert)
tlsConfig.RootCAs = certPool
keypair, err := tls.X509KeyPair(cert, key)
if err != nil {
return &tlsConfig, err
}
tlsConfig.Certificates = []tls.Certificate{keypair}
if allowInsecure {
tlsConfig.InsecureSkipVerify = true
}
return &tlsConfig, nil
}
func newCertificate(org string) (*x509.Certificate, error) {
now := time.Now()
// need to set notBefore slightly in the past to account for time
// skew in the VMs otherwise the certs sometimes are not yet valid
notBefore := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute()-5, 0, 0, time.Local)
notAfter := notBefore.Add(time.Hour * 24 * 1080)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, err
}
return &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{org},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement,
BasicConstraintsValid: true,
}, nil
}
// GenerateCACertificate generates a new certificate authority from the specified org
// and bit size and stores the resulting certificate and key file
// in the arguments.
func GenerateCACertificate(certFile, keyFile, org string, bits int) error {
template, err := newCertificate(org)
if err != nil {
return err
}
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign
template.KeyUsage |= x509.KeyUsageKeyEncipherment
template.KeyUsage |= x509.KeyUsageKeyAgreement
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}
// GenerateCert generates a new certificate signed using the provided
// certificate authority files and stores the result in the certificate
// file and key provided. The provided host names are set to the
// appropriate certificate fields.
func GenerateCert(hosts []string, certFile, keyFile, caFile, caKeyFile, org string, bits int) error {
template, err := newCertificate(org)
if err != nil {
return err
}
// client
if len(hosts) == 1 && hosts[0] == "" {
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
template.KeyUsage = x509.KeyUsageDigitalSignature
} else { // server
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}
}
tlsCert, err := tls.LoadX509KeyPair(caFile, caKeyFile)
if err != nil {
return err
}
priv, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
x509Cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
if err != nil {
return err
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, x509Cert, &priv.PublicKey, tlsCert.PrivateKey)
if err != nil {
return err
}
certOut, err := os.Create(certFile)
if err != nil {
return err
}
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
certOut.Close()
keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
keyOut.Close()
return nil
}
func ValidateCertificate(addr, caCertPath, serverCertPath, serverKeyPath string) (bool, error) {
caCert, err := ioutil.ReadFile(caCertPath)
if err != nil {
return false, err
}
serverCert, err := ioutil.ReadFile(serverCertPath)
if err != nil {
return false, err
}
serverKey, err := ioutil.ReadFile(serverKeyPath)
if err != nil {
return false, err
}
tlsConfig, err := getTLSConfig(caCert, serverCert, serverKey, false)
if err != nil {
return false, err
}
dialer := &net.Dialer{
Timeout: time.Second * 2,
}
_, err = tls.DialWithDialer(dialer, "tcp", addr, tlsConfig)
if err != nil {
return false, nil
}
return true, nil
}

74
vendor/github.com/docker/machine/utils/certs_test.go generated vendored Normal file
View File

@@ -0,0 +1,74 @@
package utils
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
)
func TestGenerateCACertificate(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "machine-test-")
if err != nil {
t.Fatal(err)
}
// cleanup
defer os.RemoveAll(tmpDir)
os.Setenv("MACHINE_DIR", tmpDir)
caCertPath := filepath.Join(tmpDir, "ca.pem")
caKeyPath := filepath.Join(tmpDir, "key.pem")
testOrg := "test-org"
bits := 2048
if err := GenerateCACertificate(caCertPath, caKeyPath, testOrg, bits); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(caCertPath); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(caKeyPath); err != nil {
t.Fatal(err)
}
os.Setenv("MACHINE_DIR", "")
}
func TestGenerateCert(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "machine-test-")
if err != nil {
t.Fatal(err)
}
// cleanup
defer os.RemoveAll(tmpDir)
os.Setenv("MACHINE_DIR", tmpDir)
caCertPath := filepath.Join(tmpDir, "ca.pem")
caKeyPath := filepath.Join(tmpDir, "key.pem")
certPath := filepath.Join(tmpDir, "cert.pem")
keyPath := filepath.Join(tmpDir, "cert-key.pem")
testOrg := "test-org"
bits := 2048
if err := GenerateCACertificate(caCertPath, caKeyPath, testOrg, bits); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(caCertPath); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(caKeyPath); err != nil {
t.Fatal(err)
}
os.Setenv("MACHINE_DIR", "")
if err := GenerateCert([]string{}, certPath, keyPath, caCertPath, caKeyPath, testOrg, bits); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(certPath); err != nil {
t.Fatalf("certificate not created at %s", certPath)
}
if _, err := os.Stat(keyPath); err != nil {
t.Fatalf("key not created at %s", keyPath)
}
}

170
vendor/github.com/docker/machine/utils/utils.go generated vendored Normal file
View File

@@ -0,0 +1,170 @@
package utils
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net"
"os"
"path/filepath"
"runtime"
"strconv"
"time"
"github.com/docker/machine/log"
)
func GetHomeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}
func GetBaseDir() string {
baseDir := os.Getenv("MACHINE_STORAGE_PATH")
if baseDir == "" {
baseDir = filepath.Join(GetHomeDir(), ".docker", "machine")
}
return baseDir
}
func GetDockerDir() string {
return filepath.Join(GetHomeDir(), ".docker")
}
func GetMachineDir() string {
return filepath.Join(GetBaseDir(), "machines")
}
func GetMachineCertDir() string {
return filepath.Join(GetBaseDir(), "certs")
}
func GetMachineCacheDir() string {
return filepath.Join(GetBaseDir(), "cache")
}
func GetUsername() string {
u := "unknown"
osUser := ""
switch runtime.GOOS {
case "darwin", "linux":
osUser = os.Getenv("USER")
case "windows":
osUser = os.Getenv("USERNAME")
}
if osUser != "" {
u = osUser
}
return u
}
func CopyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
if _, err = io.Copy(out, in); err != nil {
return err
}
fi, err := os.Stat(src)
if err != nil {
return err
}
if err := os.Chmod(dst, fi.Mode()); err != nil {
return err
}
return nil
}
func WaitForSpecificOrError(f func() (bool, error), maxAttempts int, waitInterval time.Duration) error {
for i := 0; i < maxAttempts; i++ {
stop, err := f()
if err != nil {
return err
}
if stop {
return nil
}
time.Sleep(waitInterval)
}
return fmt.Errorf("Maximum number of retries (%d) exceeded", maxAttempts)
}
func WaitForSpecific(f func() bool, maxAttempts int, waitInterval time.Duration) error {
return WaitForSpecificOrError(func() (bool, error) {
return f(), nil
}, maxAttempts, waitInterval)
}
func WaitFor(f func() bool) error {
return WaitForSpecific(f, 60, 3*time.Second)
}
func WaitForDocker(ip string, daemonPort int) error {
return WaitFor(func() bool {
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ip, daemonPort))
if err != nil {
log.Debugf("Daemon not responding yet: %s", err)
return false
}
conn.Close()
return true
})
}
func DumpVal(vals ...interface{}) {
for _, val := range vals {
prettyJSON, err := json.MarshalIndent(val, "", " ")
if err != nil {
log.Fatal(err)
}
log.Debug(string(prettyJSON))
}
}
// Following two functions are from github.com/docker/docker/utils module. It
// was way overkill to include the whole module, so we just have these bits
// that we're using here.
func TruncateID(id string) string {
shortLen := 12
if len(id) < shortLen {
shortLen = len(id)
}
return id[:shortLen]
}
// GenerateRandomID returns an unique id
func GenerateRandomID() string {
for {
id := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, id); err != nil {
panic(err) // This shouldn't happen
}
value := hex.EncodeToString(id)
// if we try to parse the truncated for as an int and we don't have
// an error then the value is all numberic and causes issues when
// used as a hostname. ref #3869
if _, err := strconv.ParseInt(TruncateID(value), 10, 64); err == nil {
continue
}
return value
}
}

139
vendor/github.com/docker/machine/utils/utils_test.go generated vendored Normal file
View File

@@ -0,0 +1,139 @@
package utils
import (
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"testing"
)
func TestGetBaseDir(t *testing.T) {
// reset any override env var
homeDir := GetHomeDir()
baseDir := GetBaseDir()
if strings.Index(baseDir, homeDir) != 0 {
t.Fatalf("expected base dir with prefix %s; received %s", homeDir, baseDir)
}
}
func TestGetCustomBaseDir(t *testing.T) {
root := "/tmp"
os.Setenv("MACHINE_STORAGE_PATH", root)
baseDir := GetBaseDir()
if strings.Index(baseDir, root) != 0 {
t.Fatalf("expected base dir with prefix %s; received %s", root, baseDir)
}
os.Setenv("MACHINE_STORAGE_PATH", "")
}
func TestGetDockerDir(t *testing.T) {
homeDir := GetHomeDir()
baseDir := GetBaseDir()
if strings.Index(baseDir, homeDir) != 0 {
t.Fatalf("expected base dir with prefix %s; received %s", homeDir, baseDir)
}
}
func TestGetMachineDir(t *testing.T) {
root := "/tmp"
os.Setenv("MACHINE_STORAGE_PATH", root)
machineDir := GetMachineDir()
if strings.Index(machineDir, root) != 0 {
t.Fatalf("expected machine dir with prefix %s; received %s", root, machineDir)
}
path, filename := path.Split(machineDir)
if strings.Index(path, root) != 0 {
t.Fatalf("expected base path of %s; received %s", root, path)
}
if filename != "machines" {
t.Fatalf("expected machine dir \"machines\"; received %s", filename)
}
os.Setenv("MACHINE_STORAGE_PATH", "")
}
func TestGetMachineCertDir(t *testing.T) {
root := "/tmp"
os.Setenv("MACHINE_STORAGE_PATH", root)
clientDir := GetMachineCertDir()
if strings.Index(clientDir, root) != 0 {
t.Fatalf("expected machine client cert dir with prefix %s; received %s", root, clientDir)
}
path, filename := path.Split(clientDir)
if strings.Index(path, root) != 0 {
t.Fatalf("expected base path of %s; received %s", root, path)
}
if filename != "certs" {
t.Fatalf("expected machine client dir \"certs\"; received %s", filename)
}
os.Setenv("MACHINE_STORAGE_PATH", "")
}
func TestCopyFile(t *testing.T) {
testStr := "test-machine"
srcFile, err := ioutil.TempFile("", "machine-test-")
if err != nil {
t.Fatal(err)
}
srcFi, err := srcFile.Stat()
if err != nil {
t.Fatal(err)
}
srcFile.Write([]byte(testStr))
srcFile.Close()
srcFilePath := filepath.Join(os.TempDir(), srcFi.Name())
destFile, err := ioutil.TempFile("", "machine-copy-test-")
if err != nil {
t.Fatal(err)
}
destFi, err := destFile.Stat()
if err != nil {
t.Fatal(err)
}
destFile.Close()
destFilePath := filepath.Join(os.TempDir(), destFi.Name())
if err := CopyFile(srcFilePath, destFilePath); err != nil {
t.Fatal(err)
}
data, err := ioutil.ReadFile(destFilePath)
if err != nil {
t.Fatal(err)
}
if string(data) != testStr {
t.Fatalf("expected data \"%s\"; received \"%\"", testStr, string(data))
}
}
func TestGetUsername(t *testing.T) {
currentUser := "unknown"
switch runtime.GOOS {
case "darwin", "linux":
currentUser = os.Getenv("USER")
case "windows":
currentUser = os.Getenv("USERNAME")
}
username := GetUsername()
if username != currentUser {
t.Fatalf("expected username %s; received %s", currentUser, username)
}
}