machine_configure 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|