simple_provision 0.99.5 → 0.99.6
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 +4 -4
- data/README.md +8 -10
- data/bin/simpro +9 -21
- data/lib/simple_provision.rb +1 -5
- data/lib/simple_provision/cli.rb +28 -10
- data/lib/simple_provision/configuration.rb +6 -11
- data/lib/simple_provision/scp.rb +11 -9
- data/lib/simple_provision/version.rb +1 -1
- data/simple_provision.gemspec +2 -1
- metadata +19 -8
- data/lib/ext/fog.rb +0 -52
- data/lib/simple_provision/connection.rb +0 -25
- data/lib/simple_provision/server.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1ff2a55eb683cc8e6f25b12c8565bd62c93bc99
|
4
|
+
data.tar.gz: 2ac7128c70fde4cac971896fab7132a46e9446f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6fb5a3e387013d6db44ab56e0ba6213f0d762d0ffbcd4dc72afacebe0e6232a3ef4cbf51a3503094af68fbe2a7a026a8959c1a4cb05819d8ee58943a859168a
|
7
|
+
data.tar.gz: 67d345ad0b1fe411acc5c14710025153dde7dc3e91ddc8b1474b00161e824aa42825a3cf4b1eddc0f14a4cafef59b2e6ca1c8d99a86d9996e2117513c2e2c48e
|
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
1
|
# Introduction
|
2
2
|
This is based on the work that brandonhilkert initally carried to automate
|
3
|
-
EC2 instance provision with YAML and SHELL script. It tries to bring the good spirit: SIMPLE, and JUST WORK to the world of
|
3
|
+
EC2 instance provision with YAML and SHELL script. It tries to bring the good spirit: SIMPLE, and JUST WORK to the world of every remote machine.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
With simple_provision, you get your hand dirty in a few minutes and
|
5
|
+
I had been banging my head trying to work with Chef and Puppet in the
|
6
|
+
past, so this is my attempt to make the provision stuff easier to be
|
7
|
+
implemented. With this tool, you get your hand dirty in a few minutes and
|
10
8
|
we have the working provision profile in just half an hour. From that
|
11
9
|
moment, provision another instance is just the matter of kicking off
|
12
10
|
a command from the terminal.
|
@@ -19,7 +17,7 @@ Let's rock.
|
|
19
17
|
### Recipes repo
|
20
18
|
|
21
19
|
Don't forget to also checkout the recipes collection
|
22
|
-
https://github.com/phuongnd08/
|
20
|
+
https://github.com/phuongnd08/simple_provision_recipes
|
23
21
|
|
24
22
|
# How it works
|
25
23
|
This gem carries the provision by uploading a set of scripts (and
|
@@ -64,7 +62,7 @@ It's up to you to use ERB, HAML or any kind of template processors.
|
|
64
62
|
|
65
63
|
So: You put definition of each type of server in `servers/type.yml`.
|
66
64
|
In `files` and `scripts` folder, you place files and scripts that will be
|
67
|
-
uploaded to the
|
65
|
+
uploaded to the server machine and executed there.
|
68
66
|
|
69
67
|
## Installation
|
70
68
|
|
@@ -114,8 +112,8 @@ Variables defined in `env` will be exposed to scripts during execution.
|
|
114
112
|
That way you can use the same scripts for different type of server and
|
115
113
|
still be able to produce different outcomes.
|
116
114
|
|
117
|
-
## Provision your
|
118
|
-
`simpro
|
115
|
+
## Provision your server
|
116
|
+
`simpro my-awesome-server root@my-host`
|
119
117
|
|
120
118
|
## Contributing
|
121
119
|
|
data/bin/simpro
CHANGED
@@ -4,25 +4,13 @@ require 'optparse'
|
|
4
4
|
require_relative '../lib/simple_provision'
|
5
5
|
|
6
6
|
options = {}
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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)
|
7
|
+
invalid_argument = false
|
8
|
+
invalid_argument = true if ARGV.length != 2
|
9
|
+
unless invalid_argument
|
10
|
+
username, host = ARGV.last.split('@')
|
11
|
+
invalid_argument = username.nil? || host.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
cli = SimpleProvision::CLI.new(profile: ARGV.first, username: username, host: host)
|
15
|
+
cli.bootstrap
|
28
16
|
cli.configure
|
data/lib/simple_provision.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "simple_provision/version"
|
2
2
|
|
3
3
|
begin
|
4
4
|
require 'pry'
|
@@ -7,8 +7,4 @@ end
|
|
7
7
|
|
8
8
|
require_relative 'simple_provision/cli'
|
9
9
|
require_relative 'simple_provision/configuration'
|
10
|
-
require_relative 'simple_provision/connection'
|
11
10
|
require_relative 'simple_provision/scp'
|
12
|
-
require_relative 'simple_provision/server'
|
13
|
-
|
14
|
-
require_relative 'ext/fog'
|
data/lib/simple_provision/cli.rb
CHANGED
@@ -1,30 +1,48 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
|
1
3
|
module SimpleProvision
|
2
4
|
class CLI
|
3
|
-
|
4
|
-
|
5
|
-
@
|
5
|
+
attr_reader :profile, :username, :host
|
6
|
+
def initialize(args)
|
7
|
+
@profile = args[:profile]
|
8
|
+
@username = args[:username]
|
9
|
+
@host = args[:host]
|
6
10
|
end
|
7
11
|
|
8
12
|
def bootstrap
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def build
|
13
|
-
server.build
|
13
|
+
SimpleProvision::SCP.new(username, host, options).copy_files
|
14
14
|
end
|
15
15
|
|
16
16
|
def configure
|
17
|
-
|
17
|
+
Net::SSH.start(host, username) do |ssh|
|
18
|
+
ssh.exec! "tar -xzf #{SimpleProvision::SCP::FILENAME}"
|
19
|
+
scripts = options.fetch(:scripts).each do |script|
|
20
|
+
puts "Execute #{script}"
|
21
|
+
ssh.exec!("#{environment_exports} bash -c '#{script}'") do |channel, stream, data|
|
22
|
+
print data
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
28
|
private
|
21
29
|
|
30
|
+
def environment_exports
|
31
|
+
@environment_exports ||= begin
|
32
|
+
if options[:env].nil?
|
33
|
+
""
|
34
|
+
else
|
35
|
+
options[:env].map { |k, v| [k, Shellwords.escape(v)].join("=") }.join(" ")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
22
40
|
def server
|
23
41
|
SimpleProvision::Server.new(@connection, options)
|
24
42
|
end
|
25
43
|
|
26
44
|
def options
|
27
|
-
@options ||= SimpleProvision::Configuration.new(@
|
45
|
+
@options ||= SimpleProvision::Configuration.new(@profile).options
|
28
46
|
end
|
29
47
|
end
|
30
48
|
end
|
@@ -6,13 +6,12 @@ module SimpleProvision
|
|
6
6
|
MissingServerConfiguration = Class.new(StandardError)
|
7
7
|
|
8
8
|
attr_reader :options
|
9
|
+
attr_reader :profile
|
9
10
|
|
10
|
-
def initialize(
|
11
|
-
@
|
11
|
+
def initialize(profile)
|
12
|
+
@profile = profile
|
12
13
|
|
13
14
|
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
15
|
end
|
17
16
|
|
18
17
|
private
|
@@ -29,21 +28,17 @@ module SimpleProvision
|
|
29
28
|
begin
|
30
29
|
YAML.load(File.read(server_file))
|
31
30
|
rescue Errno::ENOENT
|
32
|
-
raise MissingServerConfiguration, "Please create a configuration file './servers/#{
|
31
|
+
raise MissingServerConfiguration, "Please create a configuration file './servers/#{profile}.yml'"
|
33
32
|
end
|
34
33
|
end
|
35
34
|
|
36
35
|
def server_file
|
37
|
-
"servers/#{
|
36
|
+
"servers/#{profile}.yml"
|
38
37
|
end
|
39
38
|
|
40
39
|
def read_and_parse_server_options
|
41
|
-
options_string_hash = default_options.merge(server_options)
|
40
|
+
options_string_hash = default_options.merge(server_options)
|
42
41
|
@options = Hash[options_string_hash.map{ |(k,v)| [k.to_sym, v] }]
|
43
42
|
end
|
44
|
-
|
45
|
-
def type
|
46
|
-
@command_line_options[:type]
|
47
|
-
end
|
48
43
|
end
|
49
44
|
end
|
data/lib/simple_provision/scp.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
require 'net/scp'
|
2
|
+
require 'byebug'
|
3
|
+
|
1
4
|
module SimpleProvision
|
2
5
|
class SCP
|
3
6
|
FILENAME = "simpro.tar.gz"
|
4
7
|
|
5
|
-
def initialize(
|
6
|
-
@
|
8
|
+
def initialize(username, host, opts)
|
9
|
+
@username, @host, @opts = username, host, opts
|
7
10
|
end
|
8
11
|
|
9
|
-
def
|
12
|
+
def copy_files
|
10
13
|
create_local_archive
|
11
14
|
scp_files_to_server
|
12
|
-
extract_remote_archive
|
13
15
|
remove_local_archive
|
14
16
|
end
|
15
17
|
|
@@ -38,11 +40,11 @@ module SimpleProvision
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def scp_files_to_server
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
Net::SCP.start(@host, @username) do |scp|
|
44
|
+
scp.upload!("tmp/#{FILENAME}", ".")
|
45
|
+
end
|
46
|
+
rescue Net::SSH::HostKeyMismatch
|
47
|
+
puts "Please run ssh #{@username}@#{@host} to verify the fingerprint first"
|
46
48
|
end
|
47
49
|
|
48
50
|
def remove_local_archive
|
data/simple_provision.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_provision
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.99.
|
4
|
+
version: 0.99.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phuong Gia Su
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-07-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -40,19 +40,33 @@ dependencies:
|
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: net-scp
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - '>='
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
48
|
+
version: '0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - '>='
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version:
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: net-ssh
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
56
70
|
description: The easiest, most common sense server provision tool.
|
57
71
|
email:
|
58
72
|
- phuongnd08@gmail.com
|
@@ -68,13 +82,10 @@ files:
|
|
68
82
|
- README.md
|
69
83
|
- Rakefile
|
70
84
|
- bin/simpro
|
71
|
-
- lib/ext/fog.rb
|
72
85
|
- lib/simple_provision.rb
|
73
86
|
- lib/simple_provision/cli.rb
|
74
87
|
- lib/simple_provision/configuration.rb
|
75
|
-
- lib/simple_provision/connection.rb
|
76
88
|
- lib/simple_provision/scp.rb
|
77
|
-
- lib/simple_provision/server.rb
|
78
89
|
- lib/simple_provision/version.rb
|
79
90
|
- simple_provision.gemspec
|
80
91
|
homepage: https://github.com/phuongnd08/simple_provision
|
data/lib/ext/fog.rb
DELETED
@@ -1,52 +0,0 @@
|
|
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
|
@@ -1,25 +0,0 @@
|
|
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
|
@@ -1,55 +0,0 @@
|
|
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
|