simple_provision 0.99.2
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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +116 -0
- data/Rakefile +6 -0
- data/bin/simpro +28 -0
- data/lib/ext/fog.rb +61 -0
- data/lib/simple_provision/cli.rb +30 -0
- data/lib/simple_provision/configuration.rb +49 -0
- data/lib/simple_provision/connection.rb +25 -0
- data/lib/simple_provision/scp.rb +42 -0
- data/lib/simple_provision/server.rb +55 -0
- data/lib/simple_provision/version.rb +3 -0
- data/lib/simple_provision.rb +14 -0
- data/simple_provision.gemspec +25 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3b9054da4fdd261531b7c333a4e58768defe18e5
|
4
|
+
data.tar.gz: 4d15973d1f36b144cfa1be8df14b1fc447068e45
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa8c47134f34cce7813461ac5c768abd708382b9717ef6e8c503f72727cf4ecdd59dfa4c13d06b0ca48a6198475ce975804ac66c54fdc6dd66acdf20df86d84f
|
7
|
+
data.tar.gz: bb5e2fe6f4428809a95a0a57c399a029af5851126375ebcd623ad474e5c59b317ae6315e392539cd8e947b3d1180e52dfad7fd43f0f31efce19f271d09ab4dfa
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Brandon Hilkert
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Introduction
|
2
|
+
This is based on the work that brandonhilkert initally carried to automate
|
3
|
+
EC2 deployment with YAML and SHELL script. It tries to bring the good spirit: SIMPLE,
|
4
|
+
and JUST WORK to the world of Digital Ocean. So you own a Digital Ocean?
|
5
|
+
|
6
|
+
If you have suffer days of headache with Chef and Puppet, time for a new
|
7
|
+
simple way of provision. Let's rock.
|
8
|
+
|
9
|
+
### Recipes repo
|
10
|
+
|
11
|
+
Don't forget to also checkout the recipes collection
|
12
|
+
https://github.com/phuongnd08/simple_privision_recipes
|
13
|
+
|
14
|
+
# How it works
|
15
|
+
This gem carries the provision by uploading a set of scripts (and
|
16
|
+
files) to the server and execute there.
|
17
|
+
|
18
|
+
It's up to you to choose the language you want. I often use a mix of
|
19
|
+
SHELL and RUBY scripts to accomplish the task. SHELL for some simple stuff
|
20
|
+
like install a package on the server and RUBY when I need to complete
|
21
|
+
some tricky part of the configuration.
|
22
|
+
|
23
|
+
Just remember that you need to use a shell script to install ruby/python first,
|
24
|
+
and then you can start use ruby/python. The install of ruby and python can be
|
25
|
+
as simple as create a bash contains "yum install ruby(python) -y" and include
|
26
|
+
it in the top of the `scripts` section in your server definition file.
|
27
|
+
|
28
|
+
# Project Structure
|
29
|
+
As simple as it could: One or few servers definition written in YAML + setup scripts written in
|
30
|
+
SHELL, RUBY and PYTHON + text files as resource.
|
31
|
+
It's up to you to use ERB, HAML or any kind of template processors.
|
32
|
+
|
33
|
+
```
|
34
|
+
./provisions
|
35
|
+
├── files
|
36
|
+
│ ├── keys
|
37
|
+
│ │ └── deploy_key
|
38
|
+
│ └── rails_config
|
39
|
+
│ └── database.yml
|
40
|
+
├── scripts
|
41
|
+
│ ├── apt.sh
|
42
|
+
│ ├── deploy_key.sh
|
43
|
+
│ ├── git.sh
|
44
|
+
│ ├── redis.rb
|
45
|
+
│ ├── ruby2.sh
|
46
|
+
│ ├── rubygems.sh
|
47
|
+
│ ├── install_tornado.py
|
48
|
+
│ ├── search_service_code.sh
|
49
|
+
│ └── search_service_env.sh
|
50
|
+
└── servers
|
51
|
+
├── defaults.yml
|
52
|
+
└── search-service.yml
|
53
|
+
```
|
54
|
+
|
55
|
+
So: You put definition of each type of server in `servers/type.yml`.
|
56
|
+
In `files` and `scripts` folder, you place files and scripts that will be
|
57
|
+
uploaded to the Digital Ocean droplet and executed.
|
58
|
+
|
59
|
+
## Installation
|
60
|
+
|
61
|
+
Add this line to your application's Gemfile:
|
62
|
+
|
63
|
+
gem 'simple_provision'
|
64
|
+
|
65
|
+
And then execute:
|
66
|
+
|
67
|
+
$ bundle
|
68
|
+
|
69
|
+
Or install it yourself as:
|
70
|
+
|
71
|
+
$ gem install simple_provision
|
72
|
+
|
73
|
+
## Servers Configuration
|
74
|
+
|
75
|
+
### Server Definition
|
76
|
+
To define a server type, create a yaml file in the `./servers` directory with the following format:
|
77
|
+
|
78
|
+
`./servers/my-awesome-server.yml`
|
79
|
+
|
80
|
+
```yaml
|
81
|
+
files:
|
82
|
+
- files/credentials.yml
|
83
|
+
scripts:
|
84
|
+
- scripts/git.sh
|
85
|
+
- scripts/ruby.sh
|
86
|
+
- scripts/rubygems.sh
|
87
|
+
- scripts/redis.sh
|
88
|
+
env:
|
89
|
+
DBNAME: my_db_name
|
90
|
+
WEBROOT: /var/www/app
|
91
|
+
```
|
92
|
+
|
93
|
+
### Shared Definitions
|
94
|
+
|
95
|
+
You can share definitions across server types with `./servers/defaults.yml`
|
96
|
+
|
97
|
+
```yaml
|
98
|
+
private_key_path: /Users/bhilkert/.ssh/pd-app-server
|
99
|
+
```
|
100
|
+
|
101
|
+
|
102
|
+
### Passing variables to scripts
|
103
|
+
Variables defined in `env` will be exposed to scripts during execution.
|
104
|
+
That way you can use the same scripts for different type of server and
|
105
|
+
still be able to produce different outcomes.
|
106
|
+
|
107
|
+
## Provision your Digital Ocean server:
|
108
|
+
`simpro y-awesome-server --droplet-name YOUR_DROPLET_NAME`
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
1. Fork it
|
113
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
114
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
115
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
116
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/simpro
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require_relative '../lib/simple_provision'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: fss [options] type"
|
10
|
+
|
11
|
+
opts.on('--droplet-name NAME', 'An exiting Droplet Name' ) do |name|
|
12
|
+
options[:droplet_name] = name
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('-h', '--help', 'Display this screen' ) do
|
16
|
+
puts opts
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('-v', '--version', 'Show version' ) do
|
21
|
+
puts SimpleProvision::Version
|
22
|
+
end
|
23
|
+
end.parse!
|
24
|
+
|
25
|
+
options.merge!(type: ARGV.first)
|
26
|
+
|
27
|
+
cli = SimpleProvision::CLI.new(options)
|
28
|
+
cli.configure
|
data/lib/ext/fog.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'fog/core/ssh'
|
3
|
+
|
4
|
+
# Monkey-patch Fog 1.3.1 to stream SSH output
|
5
|
+
# (in real time) to stdout.
|
6
|
+
class Fog::SSH::Real
|
7
|
+
def run(commands)
|
8
|
+
commands = [*commands]
|
9
|
+
results = []
|
10
|
+
begin
|
11
|
+
Net::SSH.start(@address, @username, @options) do |ssh|
|
12
|
+
commands.each do |command|
|
13
|
+
result = Fog::SSH::Result.new(command)
|
14
|
+
ssh.open_channel do |ssh_channel|
|
15
|
+
ssh_channel.request_pty
|
16
|
+
ssh_channel.exec(command) do |channel, success|
|
17
|
+
unless success
|
18
|
+
raise "Could not execute command: #{command.inspect}"
|
19
|
+
end
|
20
|
+
|
21
|
+
channel.on_data do |ch, data|
|
22
|
+
result.stdout << data
|
23
|
+
puts data
|
24
|
+
end
|
25
|
+
|
26
|
+
channel.on_extended_data do |ch, type, data|
|
27
|
+
next unless type == 1
|
28
|
+
result.stderr << data
|
29
|
+
puts data
|
30
|
+
end
|
31
|
+
|
32
|
+
channel.on_request('exit-status') do |ch, data|
|
33
|
+
result.status = data.read_long
|
34
|
+
end
|
35
|
+
|
36
|
+
channel.on_request('exit-signal') do |ch, data|
|
37
|
+
result.status = 255
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ssh.loop
|
42
|
+
results << result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue Net::SSH::HostKeyMismatch => exception
|
46
|
+
exception.remember_host!
|
47
|
+
sleep 0.2
|
48
|
+
retry
|
49
|
+
end
|
50
|
+
results
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
require "fog/digitalocean/models/compute/server"
|
55
|
+
|
56
|
+
# Monkey patch Digital Ocean to properly return public_ip_address to used in scp
|
57
|
+
Fog::Compute::DigitalOcean::Server.class_eval do
|
58
|
+
def public_ip_address
|
59
|
+
ip_address
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SimpleProvision
|
2
|
+
class CLI
|
3
|
+
def initialize(opts = {})
|
4
|
+
@opts = opts
|
5
|
+
@connection = SimpleProvision::Connection.new(options).connection
|
6
|
+
end
|
7
|
+
|
8
|
+
def bootstrap
|
9
|
+
server.bootstrap
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
server.build
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure
|
17
|
+
server.configure
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def server
|
23
|
+
SimpleProvision::Server.new(@connection, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def options
|
27
|
+
@options ||= SimpleProvision::Configuration.new(@opts).options
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module SimpleProvision
|
4
|
+
class Configuration
|
5
|
+
MissingServerType = Class.new(StandardError)
|
6
|
+
MissingServerConfiguration = Class.new(StandardError)
|
7
|
+
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
def initialize(command_line_options = {})
|
11
|
+
@command_line_options = command_line_options
|
12
|
+
|
13
|
+
read_and_parse_server_options
|
14
|
+
|
15
|
+
raise MissingServerType, "Please specify a type of server you want to create using the --type option" unless options[:type]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def default_options
|
21
|
+
begin
|
22
|
+
YAML.load(File.read('servers/defaults.yml'))
|
23
|
+
rescue Errno::ENOENT
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def server_options
|
29
|
+
begin
|
30
|
+
YAML.load(File.read(server_file))
|
31
|
+
rescue Errno::ENOENT
|
32
|
+
raise MissingServerConfiguration, "Please create a configuration file './servers/#{type}.yml'"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def server_file
|
37
|
+
"servers/#{type}.yml"
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_and_parse_server_options
|
41
|
+
options_string_hash = default_options.merge(server_options).merge(@command_line_options)
|
42
|
+
@options = Hash[options_string_hash.map{ |(k,v)| [k.to_sym, v] }]
|
43
|
+
end
|
44
|
+
|
45
|
+
def type
|
46
|
+
@command_line_options[:type]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'fog'
|
2
|
+
|
3
|
+
module SimpleProvision
|
4
|
+
class Connection
|
5
|
+
MissingDigitalOceanCredentials = Class.new(StandardError)
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@opts = opts
|
9
|
+
|
10
|
+
if ENV["DIGITAL_OCEAN_API_KEY"].nil? || ENV["DIGITAL_OCEAN_CLIENT_ID"].nil?
|
11
|
+
raise SimpleProvision::Connection::MissingDigitalOceanCredentials, "Make sure DIGITAL_OCEAN_API_KEY and DIGITAL_OCEAN_CLIENT_ID are environmental variables with your credentials"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def connection
|
16
|
+
@connection ||= begin
|
17
|
+
Fog::Compute.new(
|
18
|
+
provider: "DigitalOcean",
|
19
|
+
digitalocean_client_id: ENV["DIGITAL_OCEAN_CLIENT_ID"],
|
20
|
+
digitalocean_api_key: ENV["DIGITAL_OCEAN_API_KEY"]
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SimpleProvision
|
2
|
+
class SCP
|
3
|
+
FILENAME = "fss.tar.gz"
|
4
|
+
|
5
|
+
def initialize(server, opts)
|
6
|
+
@server, @opts = server, opts
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_server
|
10
|
+
create_local_archive
|
11
|
+
scp_files_to_server
|
12
|
+
extract_remote_archive
|
13
|
+
remove_local_archive
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def create_local_archive
|
19
|
+
files = @opts[:files] || []
|
20
|
+
scripts = @opts[:scripts] || []
|
21
|
+
includes = files + scripts
|
22
|
+
|
23
|
+
if includes.empty?
|
24
|
+
raise "Both files and scripts are empty. You should provide some"
|
25
|
+
end
|
26
|
+
|
27
|
+
`tar -czf #{FILENAME} #{includes.join(" ")}`
|
28
|
+
end
|
29
|
+
|
30
|
+
def scp_files_to_server
|
31
|
+
@server.scp(FILENAME, ".")
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract_remote_archive
|
35
|
+
@server.ssh("tar -xzf #{FILENAME}")
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_local_archive
|
39
|
+
`rm -f #{FILENAME}`
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module SimpleProvision
|
4
|
+
class Server
|
5
|
+
ServerNotFound = Class.new(StandardError)
|
6
|
+
MissingDropletName = Class.new(StandardError)
|
7
|
+
|
8
|
+
attr_reader :server
|
9
|
+
|
10
|
+
def initialize(connection, options)
|
11
|
+
@connection, @options = connection, options
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure
|
15
|
+
get(options[:droplet_name]) if server.nil?
|
16
|
+
raise ServerNotFound, "Unable to find server with Droplet name #{options[:droplet_name]}." if server.nil?
|
17
|
+
|
18
|
+
SimpleProvision::SCP.new(server, options).to_server
|
19
|
+
scripts = options.fetch(:scripts).map do |script|
|
20
|
+
"#{environment_exports} bash -c '#{script}'"
|
21
|
+
end
|
22
|
+
server.ssh(scripts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def environment_exports
|
26
|
+
@environment_exports ||= begin
|
27
|
+
if options[:env].nil?
|
28
|
+
""
|
29
|
+
else
|
30
|
+
options[:env].map { |k, v| [k, Shellwords.escape(v)].join("=") }.join(" ")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :options, :connection
|
38
|
+
|
39
|
+
def get(droplet_name)
|
40
|
+
if droplet_name.nil?
|
41
|
+
raise SimpleProvision::Server::MissingDropletName ,
|
42
|
+
"Please specify the Droplet Name using the --droplet-name option."
|
43
|
+
end
|
44
|
+
@server = connection.servers.detect { |server| server.name == droplet_name }
|
45
|
+
if options.has_key?(:private_key_path)
|
46
|
+
@server.private_key_path = options.fetch(:private_key_path)
|
47
|
+
end
|
48
|
+
@server
|
49
|
+
end
|
50
|
+
|
51
|
+
def name
|
52
|
+
"#{options.fetch(:name).downcase.sub(/ /, '-')}-#{Time.now.strftime("%y-%m-%d-%H-%M")}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "simple_provision/version"
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'pry'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
require_relative 'simple_provision/cli'
|
9
|
+
require_relative 'simple_provision/configuration'
|
10
|
+
require_relative 'simple_provision/connection'
|
11
|
+
require_relative 'simple_provision/scp'
|
12
|
+
require_relative 'simple_provision/server'
|
13
|
+
|
14
|
+
require_relative 'ext/fog'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'simple_provision/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "simple_provision"
|
8
|
+
spec.version = SimpleProvision::VERSION
|
9
|
+
spec.authors = ["Phuong Gia Su", "Brandon Hilkert"]
|
10
|
+
spec.email = ["phuongnd08@gmail.com", "brandonhilkert@gmail.com"]
|
11
|
+
spec.description = %q{The easiest, most common sense server provision tool.}
|
12
|
+
spec.summary = %q{The easiest, most common sense server provision tool.}
|
13
|
+
spec.homepage = "https://github.com/phuongnd08/simple_provision"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_dependency "fog", "~> 1.14.0"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_provision
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.99.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Phuong Gia Su
|
8
|
+
- Brandon Hilkert
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.3'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: fog
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ~>
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 1.14.0
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.14.0
|
56
|
+
description: The easiest, most common sense server provision tool.
|
57
|
+
email:
|
58
|
+
- phuongnd08@gmail.com
|
59
|
+
- brandonhilkert@gmail.com
|
60
|
+
executables:
|
61
|
+
- simpro
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- Gemfile
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.md
|
69
|
+
- Rakefile
|
70
|
+
- bin/simpro
|
71
|
+
- lib/ext/fog.rb
|
72
|
+
- lib/simple_provision.rb
|
73
|
+
- lib/simple_provision/cli.rb
|
74
|
+
- lib/simple_provision/configuration.rb
|
75
|
+
- lib/simple_provision/connection.rb
|
76
|
+
- lib/simple_provision/scp.rb
|
77
|
+
- lib/simple_provision/server.rb
|
78
|
+
- lib/simple_provision/version.rb
|
79
|
+
- simple_provision.gemspec
|
80
|
+
homepage: https://github.com/phuongnd08/simple_provision
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - '>='
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.0.3
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: The easiest, most common sense server provision tool.
|
104
|
+
test_files: []
|