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:
2
vendor/github.com/docker/machine/.dockerignore
generated
vendored
Normal file
2
vendor/github.com/docker/machine/.dockerignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
docker-machine*
|
||||
.git
|
2
vendor/github.com/docker/machine/.gitignore
generated
vendored
Normal file
2
vendor/github.com/docker/machine/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
docker-machine*
|
||||
*.log
|
1
vendor/github.com/docker/machine/.godir
generated
vendored
Normal file
1
vendor/github.com/docker/machine/.godir
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github.com/docker/machine
|
14
vendor/github.com/docker/machine/.travis.yml
generated
vendored
Normal file
14
vendor/github.com/docker/machine/.travis.yml
generated
vendored
Normal 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
164
vendor/github.com/docker/machine/CHANGELOG.md
generated
vendored
Normal 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
227
vendor/github.com/docker/machine/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
# Contributing to machine
|
||||
|
||||
[](https://godoc.org/github.com/docker/machine)
|
||||
[](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`.
|
||||
|
||||

|
||||
|
||||
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
15
vendor/github.com/docker/machine/Dockerfile
generated
vendored
Normal 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
191
vendor/github.com/docker/machine/LICENSE
generated
vendored
Normal 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
3
vendor/github.com/docker/machine/MAINTAINERS
generated
vendored
Normal 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
18
vendor/github.com/docker/machine/Makefile
generated
vendored
Normal 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
56
vendor/github.com/docker/machine/README.md
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# Docker Machine
|
||||
|
||||

|
||||
|
||||
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
31
vendor/github.com/docker/machine/ROADMAP.md
generated
vendored
Normal 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
123
vendor/github.com/docker/machine/log/log.go
generated
vendored
Normal 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
19
vendor/github.com/docker/machine/log/log_test.go
generated
vendored
Normal 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
129
vendor/github.com/docker/machine/log/terminal.go
generated
vendored
Normal 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
125
vendor/github.com/docker/machine/main.go
generated
vendored
Normal 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
1
vendor/github.com/docker/machine/main_test.go
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
package main
|
238
vendor/github.com/docker/machine/utils/b2d.go
generated
vendored
Normal file
238
vendor/github.com/docker/machine/utils/b2d.go
generated
vendored
Normal 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
63
vendor/github.com/docker/machine/utils/b2d_test.go
generated
vendored
Normal 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
202
vendor/github.com/docker/machine/utils/certs.go
generated
vendored
Normal 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
74
vendor/github.com/docker/machine/utils/certs_test.go
generated
vendored
Normal 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
170
vendor/github.com/docker/machine/utils/utils.go
generated
vendored
Normal 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
139
vendor/github.com/docker/machine/utils/utils_test.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user