machine_configure 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +5 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +21 -0
- data/README.md +100 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/rdoc +9 -0
- data/bin/setup +8 -0
- data/exe/maccon +7 -0
- data/lib/machine_configure/cli.rb +92 -0
- data/lib/machine_configure/cli_constants.rb +81 -0
- data/lib/machine_configure/exporter.rb +84 -0
- data/lib/machine_configure/helpers/message.rb +77 -0
- data/lib/machine_configure/helpers/shared.rb +31 -0
- data/lib/machine_configure/importer.rb +71 -0
- data/lib/machine_configure/meta.rb +4 -0
- data/lib/machine_configure/validator.rb +220 -0
- data/lib/machine_configure.rb +56 -0
- data/machine_configure.gemspec +36 -0
- data/vimrc +1 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1ccd8db9cf4911d7c39b8a1a60e2aef90f38798437bcb1e6f463c9977fcc369f
|
4
|
+
data.tar.gz: 073d2219e21ec95877111f79cc430da279dd1fb8551e94f82f072d3478fc8d6e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a9ef77ddcef9d115d2e796fe0493a4f1623ac65adb5e46dac1f7f138a23bc5c8b24e66060c682041b11414d3aea6236d8eff298b89b66332dbf5ec5dc82fc9a
|
7
|
+
data.tar.gz: 3ea90114839e8c543de8ee78678a0e97d8e8e3384cdc5970ea636a1ad90888775b52c8d46a588b791c48cd4214374c48657e0af51d0b885cf0abd0ce1335af3c
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/Noah2610/ArgumentParser
|
3
|
+
revision: 3ac5b0083fd42ae8740d1d22d988f56c74a29470
|
4
|
+
specs:
|
5
|
+
argument_parser (1.0.0)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: .
|
9
|
+
specs:
|
10
|
+
machine_configure (0.0.1)
|
11
|
+
rubyzip (~> 1.2)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
minitest (5.11.3)
|
17
|
+
rake (10.5.0)
|
18
|
+
rdoc (6.0.4)
|
19
|
+
rubyzip (1.2.1)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
argument_parser!
|
26
|
+
bundler (~> 1.16)
|
27
|
+
machine_configure!
|
28
|
+
minitest (~> 5.0)
|
29
|
+
rake (~> 10.0)
|
30
|
+
rdoc
|
31
|
+
|
32
|
+
BUNDLED WITH
|
33
|
+
1.16.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Noah Rosenzweig
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# MachineConfigure
|
2
|
+
Export or import your docker-machine's configuration files,
|
3
|
+
and share them with others.
|
4
|
+
|
5
|
+
## Table of Contents _(Generated)_
|
6
|
+
- [Description](#description)
|
7
|
+
- [Installation](#installation)
|
8
|
+
- [Install manually](#install-manually)
|
9
|
+
- [Usage](#usage)
|
10
|
+
- [Exporting](#exporting)
|
11
|
+
- [Example](#example)
|
12
|
+
- [Importing](#importing)
|
13
|
+
- [Example](#example)
|
14
|
+
- [TODO](#todo)
|
15
|
+
- [License](#license)
|
16
|
+
|
17
|
+
## Description
|
18
|
+
This gem is heavily inspired by [machine-share][machine-share-site],
|
19
|
+
a nodejs package, which does basically the same thing as this gem.
|
20
|
+
I just had some minor inconveniences with it,
|
21
|
+
so I decided I would write my own version in Ruby.
|
22
|
+
|
23
|
+
If you use [docker-machine][docker-machine-site], this might come in handy,
|
24
|
+
if you ever want to share your remote docker-machine instance
|
25
|
+
with a collegue or across multiple machines.
|
26
|
+
|
27
|
+
With this gem, you can export your configuration files for a specific
|
28
|
+
docker-machine instance into a zip file. You can then share the created
|
29
|
+
zip file with others / other computers and import it again.
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
__ATTENTION:
|
33
|
+
The gem is not yet available on rubygems.org, this is still a todo.__
|
34
|
+
|
35
|
+
Install from [rubygems][rubygems-site] with ...
|
36
|
+
|
37
|
+
```
|
38
|
+
$ gem install machine_configure
|
39
|
+
```
|
40
|
+
|
41
|
+
### Install manually
|
42
|
+
If you want to install the gem manually from this repository directly,
|
43
|
+
you'll need to:
|
44
|
+
|
45
|
+
- Clone the repository,
|
46
|
+
- install all dependencies,
|
47
|
+
- build the gem, and
|
48
|
+
- install it.
|
49
|
+
|
50
|
+
Here's a command to copy/paste, it does all of the above ...
|
51
|
+
|
52
|
+
```
|
53
|
+
git clone https://github.com/Noah2610/MachineConfigure.git && \
|
54
|
+
cd MachineConfigure && \
|
55
|
+
bundle install --with development && \
|
56
|
+
rake build && \
|
57
|
+
gems=($(ls pkg/machine_configure-*)); \
|
58
|
+
gem install "${gems[-1]}"; \
|
59
|
+
unset gems
|
60
|
+
```
|
61
|
+
|
62
|
+
Once this completes, you should have the gem installed.
|
63
|
+
You can try using it by executing `maccon`.
|
64
|
+
|
65
|
+
## Usage
|
66
|
+
### Exporting
|
67
|
+
To export the configurations of an existing docker-machine instance,
|
68
|
+
use the `export` keyword, pass the machine's name,
|
69
|
+
and optionally, the output zip file.
|
70
|
+
#### Example
|
71
|
+
|
72
|
+
```
|
73
|
+
$ maccon export my_machine # Creates my_machine.zip
|
74
|
+
$ maccon export my_machine my_machine_configs.zip # Creates my_machine_configs.zip
|
75
|
+
```
|
76
|
+
|
77
|
+
### Importing
|
78
|
+
To import a docker-machine's configuration files from a zip file,
|
79
|
+
use the `import` keyword, and pass the target zip file.
|
80
|
+
#### Example
|
81
|
+
|
82
|
+
```
|
83
|
+
$ maccon import my_machine_configs.zip
|
84
|
+
```
|
85
|
+
|
86
|
+
For all command-line options, see `--help`.
|
87
|
+
|
88
|
+
---
|
89
|
+
|
90
|
+
## TODO
|
91
|
+
See the [Trello Board][trello-site] for open tasks.
|
92
|
+
|
93
|
+
## License
|
94
|
+
The gem is available as open source under the terms of the [MIT License][mit-site].
|
95
|
+
|
96
|
+
[machine-share-site]: https://github.com/bhurlow/machine-share
|
97
|
+
[docker-machine-site]: https://docs.docker.com/machine
|
98
|
+
[rubygems-site]: https://rubygems.org/gems/machine_configure
|
99
|
+
[trello-site]: https://trello.com/b/ZVdArdrk
|
100
|
+
[mit-site]: https://opensource.org/licenses/MIT
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'machine_configure'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require 'pry'
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/rdoc
ADDED
data/bin/setup
ADDED
data/exe/maccon
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
class CLI
|
3
|
+
include Helpers::Message
|
4
|
+
include CLIConstants
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
Helpers::Message.error_no_stack_trace!
|
8
|
+
@arguments = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parses given command-line arguments,
|
12
|
+
# and sets proper settings.
|
13
|
+
def run
|
14
|
+
@arguments = ArgumentParser.get_arguments VALID_ARGUMENTS
|
15
|
+
print_help if (@arguments[:options][:help])
|
16
|
+
print_version if (@arguments[:options][:version])
|
17
|
+
if (@arguments[:keywords][:export])
|
18
|
+
handle_export
|
19
|
+
elsif (@arguments[:keywords][:import])
|
20
|
+
handle_import
|
21
|
+
else
|
22
|
+
print_help
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def print_help
|
29
|
+
puts HELP_TEXT
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
|
33
|
+
def print_version
|
34
|
+
puts "#{GEM_NAME} v#{VERSION}"
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_export
|
39
|
+
verify_keywords_export
|
40
|
+
dm_name = @arguments[:keywords][:export][1]
|
41
|
+
zipfile = @arguments[:keywords][:export][2]
|
42
|
+
zipfile = get_zipfile_from_name dm_name unless (zipfile)
|
43
|
+
exporter = Exporter.new dm_name
|
44
|
+
exporter.export_to zipfile
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_import
|
48
|
+
verify_keywords_import
|
49
|
+
zipfile = @arguments[:keywords][:import][1]
|
50
|
+
importer = Importer.new
|
51
|
+
importer.import_from zipfile
|
52
|
+
end
|
53
|
+
|
54
|
+
def verify_options *option_names
|
55
|
+
option_names.flatten.each do |option_name|
|
56
|
+
error(
|
57
|
+
"Option `--#{VALID_ARGUMENTS[:double][option_name].first.first}' must be given."
|
58
|
+
) unless (@arguments[:options][option_name])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def verify_keywords_export
|
63
|
+
error(
|
64
|
+
"Missing argument DOCKER_MACHINE_NAME for #{VALID_ARGUMENTS[:keywords][:export].first.first}."
|
65
|
+
) unless (@arguments[:keywords][:export][1])
|
66
|
+
verify_keyword_size_for :export
|
67
|
+
end
|
68
|
+
|
69
|
+
def verify_keywords_import
|
70
|
+
error(
|
71
|
+
"Missing argument ZIP_FILE for #{VALID_ARGUMENTS[:keywords][:import].first.first}.",
|
72
|
+
"See --help for more information."
|
73
|
+
) unless (@arguments[:keywords][:import][1])
|
74
|
+
verify_keyword_size_for :import
|
75
|
+
end
|
76
|
+
|
77
|
+
def verify_keyword_size_for keyword_name
|
78
|
+
target_size = VALID_ARGUMENTS[:keywords][keyword_name].size
|
79
|
+
given_size = @arguments[:keywords][keyword_name].size
|
80
|
+
if (given_size > target_size)
|
81
|
+
extra_arguments = @arguments[:keywords][keyword_name][target_size .. -1]
|
82
|
+
error(
|
83
|
+
"Invalid argument#{extra_arguments.size > 1 ? ?s : ''} `#{extra_arguments.join(', ')}'"
|
84
|
+
)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_zipfile_from_name dm_name
|
89
|
+
return "#{dm_name}.zip"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
module CLIConstants
|
3
|
+
# Hash containing all valid arguments,
|
4
|
+
# which may be passed to the CLI.
|
5
|
+
VALID_ARGUMENTS = {
|
6
|
+
single: {
|
7
|
+
help: [
|
8
|
+
[?h],
|
9
|
+
false
|
10
|
+
],
|
11
|
+
version: [
|
12
|
+
[?v],
|
13
|
+
false
|
14
|
+
],
|
15
|
+
name: [
|
16
|
+
[?n],
|
17
|
+
true
|
18
|
+
],
|
19
|
+
zipfile: [
|
20
|
+
[?z],
|
21
|
+
true
|
22
|
+
]
|
23
|
+
},
|
24
|
+
double: {
|
25
|
+
help: [
|
26
|
+
['help'],
|
27
|
+
false
|
28
|
+
],
|
29
|
+
version: [
|
30
|
+
['version'],
|
31
|
+
false
|
32
|
+
],
|
33
|
+
name: [
|
34
|
+
['name'],
|
35
|
+
true
|
36
|
+
],
|
37
|
+
zipfile: [
|
38
|
+
['zip'],
|
39
|
+
true
|
40
|
+
]
|
41
|
+
},
|
42
|
+
keywords: {
|
43
|
+
export: [['export', ?e], :INPUT, :INPUTS],
|
44
|
+
import: [['import', ?i], :INPUTS]
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
# The <tt>--help</tt> text.
|
49
|
+
cli_name = DIR[:caller].basename
|
50
|
+
HELP_TEXT = <<-END_HELP_TEXT
|
51
|
+
USAGE
|
52
|
+
$ #{cli_name} [--help|--version]
|
53
|
+
$ #{cli_name} export DOCKER_MACHINE_NAME [ZIP_FILE]
|
54
|
+
$ #{cli_name} import ZIP_FILE
|
55
|
+
|
56
|
+
KEYWORDS
|
57
|
+
export
|
58
|
+
Export existing configuration files from
|
59
|
+
the docker-machine instance DOCKER_MACHINE_NAME.
|
60
|
+
Optionally, add a ZIP_FILE name.
|
61
|
+
import
|
62
|
+
Import an exported ZIP_FILE.
|
63
|
+
|
64
|
+
OPTIONS
|
65
|
+
--help -h
|
66
|
+
Print this text and exit.
|
67
|
+
--version -v
|
68
|
+
Print the current version number and exit.
|
69
|
+
|
70
|
+
EXAMPLES
|
71
|
+
Export an existing docker-machine instance with the name "my_machine",
|
72
|
+
to a new zip file "my_machine.zip":
|
73
|
+
$ #{cli_name} export my_machine
|
74
|
+
The same as above, but specify the output zip file name:
|
75
|
+
$ #{cli_name} export my_machine my_machine_configs
|
76
|
+
Import a new docker-machine instance from
|
77
|
+
the zip file "my_machine_configs.zip":
|
78
|
+
$ #{cli_name} import my_machine_configs.zip
|
79
|
+
END_HELP_TEXT
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
# The Exporter is responsible for finding all
|
3
|
+
# necessary certificates for a given docker-machine,
|
4
|
+
# and bundle them all into a single zip archive.
|
5
|
+
class Exporter
|
6
|
+
include Helpers::Message
|
7
|
+
include Helpers::Shared
|
8
|
+
|
9
|
+
# Initialize with a docker-machine <tt>name</tt>.
|
10
|
+
def initialize name
|
11
|
+
@machine_name = name
|
12
|
+
VALIDATOR.validate_machine_name name
|
13
|
+
@dir = {
|
14
|
+
machine: DM_MACHINES_PATH.join(@machine_name),
|
15
|
+
certs: DM_CERTS_PATH.join(@machine_name)
|
16
|
+
}
|
17
|
+
VALIDATOR.validate_directories @dir[:machine]
|
18
|
+
@contents = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Export certificates for the machine.
|
22
|
+
def export_to zip_file
|
23
|
+
zip_file = Pathname.new "#{zip_file.to_s}#{zip_file.to_s.match(/\.zip\z/i) ? '' : '.zip'}"
|
24
|
+
VALIDATOR.validate_zip_file_export zip_file
|
25
|
+
files = get_files
|
26
|
+
@contents = get_contents_from_files(*files)
|
27
|
+
config_json_path = get_config_json_path
|
28
|
+
@contents[config_json_path] = remove_home_in @contents[config_json_path]
|
29
|
+
@contents[MACHINE_NAME_FILENAME] = @machine_name
|
30
|
+
write_zip_file_to zip_file
|
31
|
+
message(
|
32
|
+
"Successfully created zip archive",
|
33
|
+
" `#{zip_file.to_s}'",
|
34
|
+
"with the keys and certificates from docker-machine",
|
35
|
+
" `#{@machine_name}'"
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Returns all necessary filepaths.
|
42
|
+
def get_files
|
43
|
+
return @dir.values.map do |dir|
|
44
|
+
next get_files_recursively_from dir
|
45
|
+
end .reject { |x| !x } .flatten
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns all filepaths from <tt>directory</tt>, recursively.
|
49
|
+
def get_files_recursively_from directory
|
50
|
+
dir = Pathname.new directory
|
51
|
+
return nil unless (dir.directory?)
|
52
|
+
return dir.each_child.map do |file|
|
53
|
+
next file.realpath.to_path if (file.file?)
|
54
|
+
next get_files_recursively_from file if (file.directory?)
|
55
|
+
end .flatten
|
56
|
+
end
|
57
|
+
|
58
|
+
# Reads contents from <tt>files</tt>, and returns
|
59
|
+
# a Hash with the file's filepath as the key and
|
60
|
+
# the file's content as the value.
|
61
|
+
# The filepath key is the absolute path to the file,
|
62
|
+
# but _without_ the DM_STORAGE_PATH.
|
63
|
+
def get_contents_from_files *files
|
64
|
+
return files.flatten.map do |filename|
|
65
|
+
file = Pathname.new filename
|
66
|
+
content = file.read
|
67
|
+
path = remove_storage_path_from file.to_path
|
68
|
+
next [path, content]
|
69
|
+
end .to_h
|
70
|
+
end
|
71
|
+
|
72
|
+
# Write the processed <tt>@contents</tt> to
|
73
|
+
# a zip archive using Zip.
|
74
|
+
def write_zip_file_to zip_file
|
75
|
+
Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
|
76
|
+
@contents.each do |filepath, content|
|
77
|
+
zip.get_output_stream(filepath) do |zipfile|
|
78
|
+
zipfile.write content
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
module Helpers
|
3
|
+
# This helper provides useful error methods,
|
4
|
+
# which may abort the script with an error message
|
5
|
+
# and a stack traceback.
|
6
|
+
module Message
|
7
|
+
MESSAGE_PADDING = ' '
|
8
|
+
STACK_TRACE_SIZE = 20
|
9
|
+
STACK_TRACE_PADDING = 1
|
10
|
+
@@_error_stack_trace = true
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Disable stack trace output on #error method.
|
14
|
+
def error_no_stack_trace!
|
15
|
+
@@_error_stack_trace = false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Enable stack trace output on #error method,
|
19
|
+
# if it was disabled.
|
20
|
+
def error_yes_stack_trace!
|
21
|
+
@@_error_stack_trace = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def error *messages #:doc:
|
28
|
+
message = messages.flatten.join(?\n).gsub(/^/, MESSAGE_PADDING)
|
29
|
+
output = [
|
30
|
+
"#{_get_message_header} ERROR:",
|
31
|
+
message,
|
32
|
+
"#{MESSAGE_PADDING}Exiting."
|
33
|
+
]
|
34
|
+
if (@@_error_stack_trace)
|
35
|
+
stack_trace = caller[STACK_TRACE_PADDING ... (STACK_TRACE_SIZE + STACK_TRACE_PADDING)].map do |line|
|
36
|
+
next "#{MESSAGE_PADDING}#{line}"
|
37
|
+
end .reverse
|
38
|
+
output.unshift([
|
39
|
+
"Stack traceback (most recent call last):",
|
40
|
+
stack_trace,
|
41
|
+
])
|
42
|
+
end
|
43
|
+
abort output.flatten.join(?\n)
|
44
|
+
end
|
45
|
+
|
46
|
+
def warning *messages #:doc:
|
47
|
+
message = _get_warning_message_from(*messages.flatten)
|
48
|
+
puts message
|
49
|
+
end
|
50
|
+
|
51
|
+
def warning_print *messages #:doc:
|
52
|
+
message = _get_warning_message_from(*messages.flatten)
|
53
|
+
print message
|
54
|
+
end
|
55
|
+
|
56
|
+
def message *messages #:doc:
|
57
|
+
message = messages.flatten.join(?\n).gsub(/^/, MESSAGE_PADDING)
|
58
|
+
puts([
|
59
|
+
"#{_get_message_header}",
|
60
|
+
message
|
61
|
+
].flatten.join(?\n))
|
62
|
+
end
|
63
|
+
|
64
|
+
def _get_warning_message_from *messages
|
65
|
+
message = messages.flatten.join(?\n).gsub(/^/, MESSAGE_PADDING)
|
66
|
+
return [
|
67
|
+
"#{_get_message_header} WARNING:",
|
68
|
+
message
|
69
|
+
].flatten.join(?\n)
|
70
|
+
end
|
71
|
+
|
72
|
+
def _get_message_header
|
73
|
+
return DIR[:caller].basename
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
module Helpers
|
3
|
+
module Shared
|
4
|
+
private
|
5
|
+
|
6
|
+
# Returns the path to the docker-machine's <tt>'config.json'</tt> file,
|
7
|
+
# but without the prefixed path leading to the DM_MACHINES_PATH.
|
8
|
+
def get_config_json_path
|
9
|
+
return nil unless (@machine_name)
|
10
|
+
config_json_path = remove_storage_path_from DM_MACHINES_PATH.join(@machine_name, 'config.json').to_path
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the <tt>filepath</tt> without DM_STORAGE_PATH.
|
14
|
+
def remove_storage_path_from filepath
|
15
|
+
return filepath.to_s.sub("#{DM_STORAGE_PATH.to_path}/", '')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Replaces any occurences of the user's
|
19
|
+
# home directory path with HOME_REPLACE_STRING.
|
20
|
+
def remove_home_in string
|
21
|
+
return string.gsub(HOME, HOME_REPLACE_STRING)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Replaces any occurences of HOME_REPLACE_STRING
|
25
|
+
# with the user's home directory path.
|
26
|
+
def insert_home_in string
|
27
|
+
return string.gsub(HOME_REPLACE_STRING, HOME)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
# The Importer takes a zip file,
|
3
|
+
# processes the files,
|
4
|
+
# and extracts them into the proper directories.
|
5
|
+
class Importer
|
6
|
+
include Helpers::Message
|
7
|
+
include Helpers::Shared
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@contents = nil
|
11
|
+
@machine_name = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
# Import given <tt>zip_file</tt>
|
15
|
+
# as a new docker-machine.
|
16
|
+
def import_from zip_file
|
17
|
+
VALIDATOR.validate_zip_file_import zip_file
|
18
|
+
@contents = get_contents_from_zip zip_file
|
19
|
+
@machine_name = @contents[MACHINE_NAME_FILENAME]
|
20
|
+
@contents.delete MACHINE_NAME_FILENAME
|
21
|
+
@dir = {
|
22
|
+
machine: DM_MACHINES_PATH.join(@machine_name),
|
23
|
+
certs: DM_CERTS_PATH.join(@machine_name)
|
24
|
+
}
|
25
|
+
#VALIDATOR.validate_directories_dont_exist *@dir.values
|
26
|
+
VALIDATOR.validate_no_machine_name @machine_name
|
27
|
+
config_json_path = get_config_json_path
|
28
|
+
@contents[config_json_path] = insert_home_in @contents[config_json_path]
|
29
|
+
write_contents
|
30
|
+
# Finally, check that the newly imported machine is recognized by docker-machine.
|
31
|
+
VALIDATOR.validate_machine_name @machine_name
|
32
|
+
message(
|
33
|
+
"Successfully imported docker-machine configuration files from archive",
|
34
|
+
" `#{zip_file.to_s}'",
|
35
|
+
"for docker-machine",
|
36
|
+
" `#{@machine_name}'"
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Reads the <tt>zip_file</tt> and returns
|
43
|
+
# a Hash with each file's path as the key
|
44
|
+
# and the file's content as the value.
|
45
|
+
def get_contents_from_zip zip_file
|
46
|
+
contents = {}
|
47
|
+
Zip::File.open(zip_file) do |zip|
|
48
|
+
zip.each_entry do |entry|
|
49
|
+
entry.get_input_stream do |entryfile|
|
50
|
+
contents[entry.name] = entryfile.read
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
return contents
|
55
|
+
end
|
56
|
+
|
57
|
+
# Write <tt>@contents</tt> to proper paths.
|
58
|
+
def write_contents
|
59
|
+
@contents.each do |relative_filepath, content|
|
60
|
+
filepath = DM_STORAGE_PATH.join relative_filepath
|
61
|
+
filedir = filepath.dirname
|
62
|
+
filedir.mkpath unless (filedir.directory?)
|
63
|
+
permission = 0644
|
64
|
+
permission = 0600 if (filepath.basename.to_path == 'id_rsa')
|
65
|
+
file = File.open filepath.to_path, ?w, permission
|
66
|
+
file.write content
|
67
|
+
file.close
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
module MachineConfigure
|
2
|
+
# This class should validate that dependencies are installed (docker-machine).
|
3
|
+
class Validator
|
4
|
+
include Helpers::Message
|
5
|
+
# Default command-line apps,
|
6
|
+
# which need to be available.
|
7
|
+
BASE_APPS = [
|
8
|
+
'docker-machine'
|
9
|
+
]
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@validated_apps = []
|
13
|
+
end
|
14
|
+
|
15
|
+
# Calls #validate_apps for BASE_APPS.
|
16
|
+
def validate_base_apps
|
17
|
+
validate_apps *BASE_APPS
|
18
|
+
end
|
19
|
+
|
20
|
+
# Check if given <tt>apps</tt> (or default BASE_APPS),
|
21
|
+
# are available from the command-line.
|
22
|
+
# Throw an error and exit if any aren't available.
|
23
|
+
def validate_apps *apps
|
24
|
+
apps.flatten.each do |appname|
|
25
|
+
validate_app appname
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check that the given <tt>name</tt>
|
30
|
+
# exists for docker-machine.
|
31
|
+
def validate_machine_name name
|
32
|
+
validate_app 'docker-machine'
|
33
|
+
error(
|
34
|
+
"Docker machine `#{name}' is not available."
|
35
|
+
) unless (docker_machine_exists? name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Check that the given <tt>name</tt>
|
39
|
+
# does _not_ exist for docker-machine.
|
40
|
+
def validate_no_machine_name name
|
41
|
+
validate_app 'docker-machine'
|
42
|
+
prompt_to_replace_docker_machine name if (docker_machine_exists? name)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Check that the given <tt>directories</tt> exist,
|
46
|
+
# and are directories.
|
47
|
+
def validate_directories *directories
|
48
|
+
directories.flatten.each do |directory|
|
49
|
+
validate_directory directory
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Check that the given <tt>directories</tt> do *NOT* exist.
|
54
|
+
def validate_directories_dont_exist *directories
|
55
|
+
directories.flatten.each do |directory|
|
56
|
+
validate_directory_doesnt_exist directory
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Check that the given <tt>zip_file</tt>
|
61
|
+
# doesn't exist already but that the path leading
|
62
|
+
# to the file does exist.
|
63
|
+
def validate_zip_file_export zip_file
|
64
|
+
path = File.dirname zip_file
|
65
|
+
error(
|
66
|
+
"The path to the zip file `#{path.to_path}' doesn't exist."
|
67
|
+
) unless (is_directory? path)
|
68
|
+
prompt_to_replace_file zip_file if (is_file? zip_file)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Similar to #validate_zip_file_export,
|
72
|
+
# but don't prompt for overwriting, etc.
|
73
|
+
# The zip file _has_ to exist in this case.
|
74
|
+
def validate_zip_file_import zip_file
|
75
|
+
error(
|
76
|
+
"The zip file `#{zip_file.to_s}' doesn't exist or is a directory."
|
77
|
+
) unless (is_file? zip_file)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def validate_app appname
|
83
|
+
return if (@validated_apps.include? appname)
|
84
|
+
if (app_available? appname)
|
85
|
+
@validated_apps << appname
|
86
|
+
return
|
87
|
+
end
|
88
|
+
error(
|
89
|
+
"`#{appname}' is not available.",
|
90
|
+
"Please make sure you have it installed."
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
def app_available? name
|
95
|
+
return system("which #{name} &> /dev/null")
|
96
|
+
end
|
97
|
+
|
98
|
+
def docker_machine_exists? name
|
99
|
+
return system("docker-machine inspect #{name} &> /dev/null")
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate_directory directory
|
103
|
+
return if (is_directory? directory)
|
104
|
+
error(
|
105
|
+
"Directory `#{directory.to_s}' does not exist or is a file."
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_directory_doesnt_exist directory
|
110
|
+
error(
|
111
|
+
"Directory `#{directory.to_s}' already exists."
|
112
|
+
) if (is_directory?(directory) || is_file?(directory))
|
113
|
+
end
|
114
|
+
|
115
|
+
def is_directory? directory
|
116
|
+
return File.directory? directory
|
117
|
+
end
|
118
|
+
|
119
|
+
def is_file? file
|
120
|
+
return File.file? file
|
121
|
+
end
|
122
|
+
|
123
|
+
def prompt_to_replace_file file
|
124
|
+
options = {
|
125
|
+
overwrite: ?o,
|
126
|
+
append: ?a,
|
127
|
+
nothing: ?N
|
128
|
+
}
|
129
|
+
warning_print(
|
130
|
+
"File `#{file.to_s}' already exists. What do you want to do?",
|
131
|
+
" Overwrite file? (Remove existing and create new archive.) [#{options[:overwrite]}]",
|
132
|
+
" Append content to existing archive? [#{options[:append]}]",
|
133
|
+
" Do nothing, abort. [#{options[:nothing]}]",
|
134
|
+
"[#{options.values.join(?/)}] "
|
135
|
+
)
|
136
|
+
answer = STDIN.gets[0].strip.downcase
|
137
|
+
case answer
|
138
|
+
when options[:overwrite].downcase
|
139
|
+
message "Overwriting archive `#{file.to_s}'."
|
140
|
+
File.delete file
|
141
|
+
when options[:append].downcase
|
142
|
+
message "Appending to archive `#{file.to_s}'."
|
143
|
+
when options[:nothing].downcase, ''
|
144
|
+
message "Exiting."
|
145
|
+
abort
|
146
|
+
else
|
147
|
+
prompt_to_replace_file file
|
148
|
+
return
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def prompt_to_replace_docker_machine name
|
153
|
+
options = {
|
154
|
+
backup: ?B,
|
155
|
+
overwrite: ?o,
|
156
|
+
nothing: ?n
|
157
|
+
}
|
158
|
+
warning_print(
|
159
|
+
"Docker machine `#{name}' already exists. What do you want to do?",
|
160
|
+
" Backup current configurations and create new one from import? [#{options[:backup]}]",
|
161
|
+
" (Backup to #{DM_BACKUP_PATH})",
|
162
|
+
" Overwrite existing files? [#{options[:overwrite]}]",
|
163
|
+
" Do nothing, abort. [#{options[:nothing]}]",
|
164
|
+
"[#{options.values.join(?/)}] "
|
165
|
+
)
|
166
|
+
answer = STDIN.gets[0].strip.downcase
|
167
|
+
case answer
|
168
|
+
when options[:overwrite].downcase
|
169
|
+
message "Overwriting existing configuration files for `#{name}'."
|
170
|
+
when options[:backup].downcase, ''
|
171
|
+
backup_docker_machine name
|
172
|
+
when options[:nothing].downcase
|
173
|
+
message "Exiting."
|
174
|
+
abort
|
175
|
+
else
|
176
|
+
prompt_to_replace_docker_machine name
|
177
|
+
return
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def backup_docker_machine name
|
182
|
+
backup_name_date = "#{name}.#{Time.now.strftime('%Y-%m-%d')}"
|
183
|
+
mk_backup_directories
|
184
|
+
machine_path = DM_MACHINES_PATH.join name
|
185
|
+
cert_path = DM_CERTS_PATH.join name
|
186
|
+
|
187
|
+
#backup_machine_path = DM_BACKUP_MACHINES_PATH.join backup_name_date
|
188
|
+
#backup_cert_path = DM_BACKUP_CERTS_PATH.join backup_name_date
|
189
|
+
|
190
|
+
backup_machine_path = backup_cert_path = nil
|
191
|
+
backup_machine_path = get_backup_directory_for DM_BACKUP_MACHINES_PATH.join(backup_name_date) if (machine_path.directory?)
|
192
|
+
backup_cert_path = get_backup_directory_for DM_BACKUP_CERTS_PATH.join(backup_name_date) if (cert_path.directory?)
|
193
|
+
|
194
|
+
msg = [ "Backing-up configuration files for `#{name}' to" ]
|
195
|
+
msg << " `#{backup_machine_path}'" if (backup_machine_path)
|
196
|
+
msg[-1] += ', and' if (backup_machine_path && backup_cert_path)
|
197
|
+
msg << " `#{backup_cert_path}'" if (backup_cert_path)
|
198
|
+
message msg
|
199
|
+
FileUtils.mv machine_path, backup_machine_path if (backup_machine_path)
|
200
|
+
FileUtils.mv cert_path, backup_cert_path if (backup_cert_path)
|
201
|
+
end
|
202
|
+
|
203
|
+
def mk_backup_directories
|
204
|
+
DM_BACKUP_MACHINES_PATH.mkpath unless (DM_BACKUP_MACHINES_PATH.directory?)
|
205
|
+
DM_BACKUP_CERTS_PATH.mkpath unless (DM_BACKUP_CERTS_PATH.directory?)
|
206
|
+
end
|
207
|
+
|
208
|
+
def get_backup_directory_for base_backup_directory
|
209
|
+
base_backup_directory = Pathname.new base_backup_directory unless (base_backup_directory.is_a? Pathname)
|
210
|
+
return base_backup_directory unless (base_backup_directory.directory?)
|
211
|
+
base_backup_directory_tmp = base_backup_directory.dup
|
212
|
+
counter = 0
|
213
|
+
while (base_backup_directory_tmp.directory?)
|
214
|
+
counter += 1
|
215
|
+
base_backup_directory_tmp = Pathname.new "#{base_backup_directory.to_path}_#{counter}"
|
216
|
+
end
|
217
|
+
return base_backup_directory_tmp
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'argument_parser'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
require 'zip'
|
6
|
+
|
7
|
+
module MachineConfigure
|
8
|
+
entry_file = Pathname.new(__FILE__).realpath
|
9
|
+
root = entry_file.dirname
|
10
|
+
|
11
|
+
HOME = Dir.home.chomp ?/
|
12
|
+
DIR = {
|
13
|
+
caller: Pathname.new($0).realpath,
|
14
|
+
entry: entry_file,
|
15
|
+
root: root,
|
16
|
+
src: root.join('machine_configure'),
|
17
|
+
helpers: root.join('machine_configure/helpers')
|
18
|
+
}
|
19
|
+
|
20
|
+
# This constant will replace any occurences of
|
21
|
+
# the user's home directory path in the
|
22
|
+
# docker-machine's config.json file.
|
23
|
+
HOME_REPLACE_STRING = '<REPLACE_WITH_HOME>'
|
24
|
+
|
25
|
+
# This string will be used as the filename for an
|
26
|
+
# additional file, which will only have the machine name in it.
|
27
|
+
MACHINE_NAME_FILENAME = 'MACHINE_NAME'
|
28
|
+
|
29
|
+
# The path to the docker-machine storage directory.
|
30
|
+
# <tt>$MACHINE_STORAGE_PATH</tt> or <tt>'~/.docker/machine'</tt>.
|
31
|
+
DM_STORAGE_PATH = (ENV['MACHINE_STORAGE_PATH'] ? (
|
32
|
+
Pathname.new(ENV['MACHINE_STORAGE_PATH'].chomp(?/)).realpath
|
33
|
+
) : (
|
34
|
+
Pathname.new(File.join(HOME, '.docker/machine'))
|
35
|
+
))
|
36
|
+
# The path to the docker-machine <tt>'machines'</tt> directory.
|
37
|
+
DM_MACHINES_PATH = DM_STORAGE_PATH.join 'machines'
|
38
|
+
# The path to the docker-machine <tt>'certs'</tt> directory.
|
39
|
+
DM_CERTS_PATH = DM_STORAGE_PATH.join 'certs'
|
40
|
+
# The paths for the machines backup directories <em>(Created by this script.)</em>.
|
41
|
+
DM_BACKUP_PATH = DM_STORAGE_PATH.join("#{DIR[:caller].basename}.backup")
|
42
|
+
DM_BACKUP_MACHINES_PATH = DM_BACKUP_PATH.join('machines')
|
43
|
+
DM_BACKUP_CERTS_PATH = DM_BACKUP_PATH.join('certs')
|
44
|
+
|
45
|
+
require DIR[:src].join 'meta'
|
46
|
+
require DIR[:helpers].join 'shared'
|
47
|
+
require DIR[:helpers].join 'message'
|
48
|
+
require DIR[:src].join 'validator'
|
49
|
+
require DIR[:src].join 'exporter'
|
50
|
+
require DIR[:src].join 'importer'
|
51
|
+
require DIR[:src].join 'cli_constants'
|
52
|
+
require DIR[:src].join 'cli'
|
53
|
+
|
54
|
+
VALIDATOR = Validator.new
|
55
|
+
VALIDATOR.validate_base_apps
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'machine_configure/meta'
|
4
|
+
github_url = 'https://github.com/Noah2610/MachineConfigure'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = MachineConfigure::GEM_NAME
|
8
|
+
spec.version = MachineConfigure::VERSION
|
9
|
+
spec.authors = ['Noah Rosenzweig']
|
10
|
+
spec.email = ['rosenzweig.noah@gmail.com']
|
11
|
+
spec.summary = 'Manage your docker-machines\' configuration files.'
|
12
|
+
spec.description = <<-END
|
13
|
+
This gem can import or export the necessary configuration files
|
14
|
+
for your docker-machine configuration.
|
15
|
+
Use it to share your machine instances with others.
|
16
|
+
END
|
17
|
+
spec.homepage = github_url
|
18
|
+
spec.license = 'MIT'
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split(?\x0).reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = 'exe'
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ['lib']
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
30
|
+
#spec.add_development_dependency 'byebug'
|
31
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
32
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
33
|
+
spec.add_development_dependency 'rdoc'
|
34
|
+
|
35
|
+
spec.add_dependency 'rubyzip', '~> 1.2'
|
36
|
+
end
|
data/vimrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
nmap <leader>rd :!bin/rdoc<CR>
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: machine_configure
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Noah Rosenzweig
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-07-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rdoc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubyzip
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.2'
|
83
|
+
description: |2
|
84
|
+
This gem can import or export the necessary configuration files
|
85
|
+
for your docker-machine configuration.
|
86
|
+
Use it to share your machine instances with others.
|
87
|
+
email:
|
88
|
+
- rosenzweig.noah@gmail.com
|
89
|
+
executables:
|
90
|
+
- maccon
|
91
|
+
extensions: []
|
92
|
+
extra_rdoc_files: []
|
93
|
+
files:
|
94
|
+
- ".gitignore"
|
95
|
+
- ".travis.yml"
|
96
|
+
- Gemfile
|
97
|
+
- Gemfile.lock
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- bin/console
|
102
|
+
- bin/rdoc
|
103
|
+
- bin/setup
|
104
|
+
- exe/maccon
|
105
|
+
- lib/machine_configure.rb
|
106
|
+
- lib/machine_configure/cli.rb
|
107
|
+
- lib/machine_configure/cli_constants.rb
|
108
|
+
- lib/machine_configure/exporter.rb
|
109
|
+
- lib/machine_configure/helpers/message.rb
|
110
|
+
- lib/machine_configure/helpers/shared.rb
|
111
|
+
- lib/machine_configure/importer.rb
|
112
|
+
- lib/machine_configure/meta.rb
|
113
|
+
- lib/machine_configure/validator.rb
|
114
|
+
- machine_configure.gemspec
|
115
|
+
- vimrc
|
116
|
+
homepage: https://github.com/Noah2610/MachineConfigure
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.7.7
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Manage your docker-machines' configuration files.
|
140
|
+
test_files: []
|