dployr 0.0.1 → 0.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b382202193f87d485df3e630d80d00fe16757356
4
- data.tar.gz: 84199d78c073963b72f65d641442bbf32e2cdf2c
3
+ metadata.gz: 901f079e84371186e545d8c438b618e84ff8d711
4
+ data.tar.gz: 4abb4a9493c968a60b52337d4a92c0fa83de4128
5
5
  SHA512:
6
- metadata.gz: 7fe63977dac1afc5eaa20966a9500dee3c25af05ddbce63f9056d7376779f9b3a72ab2f72db8d190e5c62b486d0af13ac09e7f78890c8c3fc51cea0bf750ab28
7
- data.tar.gz: 67406e12e53495591bb9e83066519adaf7d9a66c208e6d79c3e2b9a9bc1c324461f382bb664a9e76d90c57378525d6dc0ef145f1376e0222ba3a953b003bd5cb
6
+ metadata.gz: f8f663dcc49d7d2cd944d9001ca96d9f75b80989add9ce2fc0c529723f656f81516cc23da40026afb2b93aeb397438163a79327b84fe45539f4f1df12f4d7f67
7
+ data.tar.gz: 2f946f5046e40ca1acd16410df0731276dc08a5561ccff27b166146cc1c3d3bae5c736ddfe12ecc8a8f4a9157d22072b60848ad6814689539ebc79aa72dadad0
data/.gitignore CHANGED
@@ -4,4 +4,5 @@ Gemfile.lock
4
4
  pkg/*
5
5
  .rvmrc
6
6
  .ruby-version
7
- coverage/*
7
+ coverage/*
8
+ .project
data/README.md CHANGED
@@ -37,78 +37,15 @@ spec.add_dependency 'dployr', '>= 0.0.1'
37
37
  gem 'dployr', '>= 0.0.1'
38
38
  ```
39
39
 
40
- ## Usage
40
+ ## Documentation
41
41
 
42
- ### Command-line interface
43
-
44
- ```
45
- Usage: dployr <command> [options]
46
-
47
- Commands
48
-
49
- up start instances
50
- halt stop instances
51
- status retrieve the instances status
52
- test run remote test in instances
53
- deploy start, provision and test running instances
54
- provision instance provisioning
55
- config generate configuration in YAML format
56
- init create a sample Dployrfile
57
-
58
- Options
59
-
60
- -e, --environment ENV environment to pass to the instances
61
- -n, --name NAME template name identifier to load
62
- -a, --attributes ATTRS aditional attributes to pass to the configuration in matrix query format
63
- -p, --provider provider to use (allow multiple values comma-separated)
64
- -r, --region region to use (allow multiple values comma-separated)
65
- -h, --help help
66
-
67
- ```
68
-
69
- ### Programmatic API
70
-
71
- ```ruby
72
- Dployr::configure do |dployr|
73
-
74
- dployr.config.add_instance({
75
- attributes: {
76
- name: "example",
77
- instance_type: "m1.small",
78
- version: "${VERSION}"
79
- },
80
- scripts: [
81
- { path: "configure.sh" }
82
- ],
83
- providers: {
84
- aws: {
85
- attributes: {
86
- network_id: "be457fca",
87
- instance_type: "m1.small",
88
- "type-%{name}" => "small"
89
- },
90
- regions: {
91
- "eu-west-1a" => {
92
- attributes: {
93
- keypair: "vagrant-aws-ireland"
94
- },
95
- scripts: [
96
- { path: "router.sh", args: ["%{name}", "${region}", "${provider}"] }
97
- ]
98
- }
99
- }
100
- }
101
- }
102
- })
103
-
104
- end
105
- ```
42
+ Dployr documentation and API is available from [RubyDoc][rubydoc]
106
43
 
107
44
  ## Features
108
45
 
109
46
  `To do! but all will be cool :)`
110
47
 
111
- ## Configuration file
48
+ ## Configuration
112
49
 
113
50
  Configuration file must be called `Dployrfile`. It can be also a standard Ruby file
114
51
  or a YAML file (adding the `.yml` or `.yaml` extension)
@@ -238,6 +175,71 @@ custom:
238
175
 
239
176
  ```
240
177
 
178
+ ## Command-line interface
179
+
180
+ ```
181
+ Usage: dployr <command> [options]
182
+
183
+ Commands
184
+
185
+ up start instances
186
+ halt stop instances
187
+ status retrieve the instances status
188
+ test run remote test in instances
189
+ deploy start, provision and test running instances
190
+ provision instance provisioning
191
+ config generate configuration in YAML format
192
+ init create a sample Dployrfile
193
+
194
+ Options
195
+
196
+ -e, --environment ENV environment to pass to the instances
197
+ -n, --name NAME template name identifier to load
198
+ -a, --attributes ATTRS aditional attributes to pass to the configuration in matrix query format
199
+ -p, --provider provider to use (allow multiple values comma-separated)
200
+ -r, --region region to use (allow multiple values comma-separated)
201
+ -h, --help help
202
+
203
+ ```
204
+
205
+ ## Programmatic API
206
+
207
+ ```ruby
208
+ Dployr::configure do |dployr|
209
+
210
+ dployr.config.add_instance({
211
+ attributes: {
212
+ name: "example",
213
+ instance_type: "m1.small",
214
+ version: "${VERSION}"
215
+ },
216
+ scripts: [
217
+ { path: "configure.sh" }
218
+ ],
219
+ providers: {
220
+ aws: {
221
+ attributes: {
222
+ network_id: "be457fca",
223
+ instance_type: "m1.small",
224
+ "type-%{name}" => "small"
225
+ },
226
+ regions: {
227
+ "eu-west-1a" => {
228
+ attributes: {
229
+ keypair: "vagrant-aws-ireland"
230
+ },
231
+ scripts: [
232
+ { path: "router.sh", args: ["%{name}", "${region}", "${provider}"] }
233
+ ]
234
+ }
235
+ }
236
+ }
237
+ }
238
+ })
239
+
240
+ end
241
+ ```
242
+
241
243
  ## Contributing
242
244
 
243
245
  Feel free to report any issue you experiment via Github issues.
@@ -291,4 +293,5 @@ $ rake release
291
293
  [gemnasium]: https://gemnasium.com/innotech/dployr
292
294
  [gem]: http://rubygems.org/gems/dployr
293
295
  [ruby-guide]: https://github.com/bbatsov/ruby-style-guide
294
- [rspec-test]: http://betterspecs.org/
296
+ [rspec-best]: http://betterspecs.org/
297
+ [rubydoc]: http://www.rubydoc.info/gems/dployr/
data/bin/dployr CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  $LOAD_PATH.push File.expand_path("../../lib", __FILE__)
4
- require 'dployr/cli/cli'
4
+ require 'dployr/cli'
@@ -0,0 +1,30 @@
1
+ german-dployr:
2
+ attributes:
3
+ name: "german-dployr"
4
+ prefix: dev
5
+ private_key_path: ~/pems/innotechdev.pem
6
+ username: innotechdev
7
+ scripts:
8
+ pre-provision:
9
+ -
10
+ source: ./hello
11
+ target: /tmp
12
+ provision:
13
+ -
14
+ args: ""
15
+ path: "/tmp/hello/hello.sh"
16
+ -
17
+ args: ""
18
+ path: "ls -l /tmp"
19
+ providers:
20
+ aws:
21
+ attributes:
22
+ instance_type: t1.micro
23
+ regions:
24
+ sa-east-1a:
25
+ attributes:
26
+ ami: ami-370daf2a # centos-base-v7
27
+ keypair: vagrant-aws-saopaulo
28
+ security_groups:
29
+ - sg-3cf3e45e # lib_aws_saopaulo
30
+ subnet_id: subnet-1eebe07c
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+ echo hello
3
+ echo hola >&2
4
+ exit 0
data/dployr.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.version = Dployr::VERSION
7
7
  s.summary = "Multicloud management and deployment with asteroids made simple"
8
8
  s.description = "Multicloud management and deployment with asteroids made simple with a rich programmatic API and featured CLI"
9
- s.authors = ["Tomas Aparicio"]
9
+ s.authors = ["Tomas Aparicio", "German Ramos"]
10
10
  s.email = ["nerds@innotechapp.com"]
11
11
  s.homepage = "https://github.com/innotech/dployr"
12
12
  s.license = "MIT"
@@ -21,6 +21,9 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency "fog", "~> 1.21"
23
23
  s.add_dependency "deep_merge", "~> 1.0"
24
+ s.add_dependency "net-ssh", "~> 2.8.0"
25
+ s.add_dependency "net-scp", "~> 1.2.0"
26
+ s.add_dependency "colorize", "~> 0.7.2"
24
27
 
25
28
  s.add_development_dependency "rake", "~> 10"
26
29
  s.add_development_dependency "rspec", "~> 2"
@@ -1,7 +1,6 @@
1
1
  require 'optparse'
2
2
  require 'dployr'
3
3
  require 'dployr/version'
4
- require 'dployr/cli/commands'
5
4
 
6
5
  command = ARGV[0]
7
6
  options = {}
@@ -11,37 +10,38 @@ opt_parser = OptionParser.new do |opt|
11
10
  opt.separator ""
12
11
  opt.separator " Commands"
13
12
  opt.separator ""
14
- opt.separator " up start instances"
13
+ opt.separator " start start instances"
15
14
  opt.separator " halt stop instances"
16
15
  opt.separator " destroy destroy instances"
17
16
  opt.separator " status retrieve the instances status"
18
17
  opt.separator " test run remote test in instances"
19
18
  opt.separator " deploy start, provision and test running instances"
20
19
  opt.separator " provision instance provisioning"
21
- opt.separator " config generate configuration in YAML format"
20
+ opt.separator " config generate configuration in YAML from Dployrfile"
21
+ opt.separator " execute run custom stages"
22
22
  opt.separator " init create a sample Dployrfile"
23
23
  opt.separator ""
24
24
  opt.separator " Options"
25
25
  opt.separator ""
26
26
 
27
- opt.on("-e", "--environment ENV", "environment to pass to the instances") do |v|
28
- options[:environment] = v
29
- end
30
-
31
27
  opt.on("-n", "--name NAME", "template name identifier to load") do |v|
32
28
  options[:name] = v
33
29
  end
34
30
 
31
+ opt.on("-f", "--file PATH", "custom config file path to load") do |v|
32
+ options[:file] = v
33
+ end
34
+
35
35
  opt.on("-a", "--attributes ATTRS", "aditional attributes to pass to the configuration in matrix query format") do |v|
36
36
  options[:attributes] = v
37
37
  end
38
38
 
39
- opt.on("-p", "--provider", "provider to use (allow multiple values comma-separated)") do |v|
39
+ opt.on("-p", "--provider VALUES", "provider to use (allow multiple values comma-separated)") do |v|
40
40
  options[:provider] = v
41
41
  end
42
42
 
43
- opt.on("-r", "--region", "region to use (allow multiple values comma-separated)") do |v|
44
- options[:provider] = v
43
+ opt.on("-r", "--region REGION", "region to use (allow multiple values comma-separated)") do |v|
44
+ options[:region] = v
45
45
  end
46
46
 
47
47
  opt.on("-v", "-V", "--version", "version") do
@@ -50,6 +50,7 @@ opt_parser = OptionParser.new do |opt|
50
50
 
51
51
  opt.on("-h", "--help", "help") do
52
52
  puts opt_parser
53
+ exit 0
53
54
  end
54
55
 
55
56
  opt.separator ""
@@ -57,21 +58,35 @@ end
57
58
 
58
59
  opt_parser.parse!
59
60
 
61
+ dployr = Dployr::Init.new @attributes
62
+ dployr.load_config options[:file]
63
+ config = dployr.config.get_region(options[:name], options[:provider], options[:region])
64
+
60
65
  case command
61
- when "up"
62
- puts "Command currently not available"
66
+ when "start"
67
+ Dployr::Commands::Start.new(config, options)
63
68
  when "halt"
64
- puts "Command currently not available"
69
+ Dployr::Commands::Stop_Destroy.new(config, options, "halt")
70
+ when "destroy"
71
+ Dployr::Commands::Stop_Destroy.new(config, options, "destroy")
65
72
  when "status"
66
73
  puts "Command currently not available"
67
74
  when "provision"
68
- puts "Command currently not available"
75
+ Dployr::Commands::Provision_Test.new(config, options, "provision")
69
76
  when "test"
70
- puts "Command currently not available"
77
+ Dployr::Commands::Provision_Test.new(config, options, "test")
71
78
  when "deploy"
72
- puts "Command currently not available"
79
+ Dployr::Commands::Start.new(config, options)
80
+ Dployr::Commands::Provision_Test.new(config, options, "provision")
81
+ Dployr::Commands::Provision_Test.new(config, options, "test")
82
+ when "execute"
83
+ Dployr::Commands::Execute.new(config, options, ARGV[1..-1])
73
84
  when "config"
74
- Dployr::CLI::Config.new options
85
+ Dployr::Commands::Config.new(config, options)
75
86
  when "init"
76
87
  Dployr::Config::Create.write_file
88
+ when '-h', '--help', 'help'
89
+ # help already showed by option
90
+ else
91
+ puts opt_parser
77
92
  end
@@ -0,0 +1,24 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'dployr/compute/aws'
4
+ require 'colorize'
5
+
6
+ module Dployr
7
+ module Commands
8
+ class Config
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(config, options)
13
+ begin
14
+ puts "Options:", options.to_yaml
15
+ puts "\nConfig:", config.to_yaml
16
+ rescue Exception => e
17
+ @log.error e
18
+ Process.exit! false
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'dployr/compute/aws'
4
+ require 'colorize'
5
+
6
+ module Dployr
7
+ module Commands
8
+ class Execute
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(config, options, stages)
13
+ begin
14
+ @log = Logger.new STDOUT
15
+ @name = config[:attributes]["name"]
16
+ @provider = options[:provider].upcase
17
+ @region = options[:region]
18
+ @attributes = config[:attributes]
19
+
20
+ puts "Connecting to #{@provider}...".yellow
21
+ @client = Dployr::Compute.const_get(@provider.to_sym).new(@region)
22
+
23
+ puts "Looking for #{@name} in #{@region}...".yellow
24
+ @ip = @client.get_ip(@name)
25
+ if @ip
26
+ puts "#{@name} found with IP #{@ip}".yellow
27
+ else
28
+ raise "#{@name} not found"
29
+ end
30
+
31
+ stages.each do |stage|
32
+ Dployr::Scripts::Hook.new @ip, config, stage
33
+ end
34
+
35
+ rescue Exception => e
36
+ @log.error e
37
+ Process.exit! false
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'dployr/compute/aws'
4
+ require 'colorize'
5
+
6
+ module Dployr
7
+ module Commands
8
+ class Provision_Test
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(config, options, action)
13
+ begin
14
+ @log = Logger.new STDOUT
15
+ @name = config[:attributes]["name"]
16
+ @provider = options[:provider].upcase
17
+ @region = options[:region]
18
+ @attributes = config[:attributes]
19
+ @action = action
20
+
21
+ puts "Connecting to #{@provider}...".yellow
22
+ @client = Dployr::Compute.const_get(@provider.to_sym).new(@region)
23
+
24
+ puts "Looking for #{@name} in #{@region}...".yellow
25
+ @ip = @client.get_ip(@name)
26
+ if @ip
27
+ puts "#{@name} found with IP #{@ip}".yellow
28
+ else
29
+ raise "#{@name} not found"
30
+ end
31
+
32
+ Dployr::Scripts::Default_Hooks.new @ip, config, @action, self
33
+
34
+ rescue Exception => e
35
+ @log.error e
36
+ Process.exit! false
37
+ end
38
+ end
39
+
40
+ def action
41
+ return @ip
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'dployr/compute/aws'
4
+ require 'colorize'
5
+
6
+ module Dployr
7
+ module Commands
8
+ class Start
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(config, options)
13
+ begin
14
+ @log = Logger.new STDOUT
15
+ @name = config[:attributes]["name"]
16
+ @provider = options[:provider].upcase
17
+ @region = options[:region]
18
+ @attributes = config[:attributes]
19
+
20
+ puts "Connecting to #{@provider}...".yellow
21
+ @client = Dployr::Compute.const_get(@provider.to_sym).new(@region)
22
+
23
+ puts "Looking for #{@name} in #{@region}...".yellow
24
+ @ip = @client.get_ip(@name)
25
+
26
+ Dployr::Scripts::Default_Hooks.new @ip, config, "start", self
27
+
28
+ rescue Exception => e
29
+ @log.error e
30
+ Process.exit! false
31
+ end
32
+ end
33
+
34
+ def action
35
+ if @ip
36
+ puts "#{@name} found with IP #{@ip}".yellow
37
+ else
38
+ @ip = @client.start(@attributes, @region)
39
+ puts "Startded instance for #{@name} in #{@region} with IP #{@ip} succesfully".yellow
40
+ end
41
+ return @ip
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,49 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'dployr/compute/aws'
4
+ require 'colorize'
5
+
6
+ module Dployr
7
+ module Commands
8
+ class Stop_Destroy
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(config, options, action)
13
+ begin
14
+ @log = Logger.new STDOUT
15
+ @name = config[:attributes]["name"]
16
+ @provider = options[:provider].upcase
17
+ @region = options[:region]
18
+ @attributes = config[:attributes]
19
+ @action = action
20
+
21
+ puts "Connecting to #{@provider}...".yellow
22
+ @client = Dployr::Compute.const_get(@provider.to_sym).new(@region)
23
+
24
+ puts "Looking for #{@name} in #{@region}...".yellow
25
+ @ip = @client.get_ip(@name)
26
+ if @ip
27
+ puts "#{@name} found with IP #{@ip}".yellow
28
+ else
29
+ puts "#{@name} not found".yellow
30
+ end
31
+
32
+ Dployr::Scripts::Default_Hooks.new @ip, config, @action, self
33
+
34
+ rescue Exception => e
35
+ @log.error e
36
+ Process.exit! false
37
+ end
38
+ end
39
+
40
+ def action
41
+ puts "#{@action.capitalize}ing #{@name} in #{@region}...".yellow
42
+ @client.send(@action.to_sym, @name)
43
+ puts "#{@name} #{@action}ed sucesfully".yellow
44
+ return @ip
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,100 @@
1
+ require 'fog'
2
+ require 'net/ssh'
3
+
4
+ module Dployr
5
+ module Compute
6
+ class AWS
7
+
8
+ def initialize(region)
9
+ @options = {
10
+ region: region[0..-2],
11
+ provider: 'AWS',
12
+ aws_access_key_id: ENV["AWS_ACCESS_KEY"],
13
+ aws_secret_access_key: ENV["AWS_SECRET_KEY"]
14
+ }
15
+ @compute = Fog::Compute.new @options
16
+ end
17
+
18
+ # private
19
+ def get_instance(name, states)
20
+ servers = @compute.servers.all
21
+ servers.each do |instance|
22
+ if instance.tags["Name"] == name and states.include? instance.state
23
+ return instance
24
+ end
25
+ end
26
+ return nil
27
+ end
28
+
29
+ def get_ip(name)
30
+ instance = get_instance(name, ["running"])
31
+ if instance
32
+ return instance.private_ip_address
33
+ end
34
+ end
35
+
36
+ def destroy(name)
37
+ instance = get_instance(name, ["running", "stopped", "stopping"])
38
+ if instance
39
+ return instance.destroy
40
+ end
41
+ raise "Instance #{name} not found"
42
+ end
43
+
44
+ def halt(name)
45
+ instance = get_instance(name, ["running"])
46
+ if instance
47
+ return instance.stop
48
+ end
49
+ raise "Instance #{name} not found"
50
+ end
51
+
52
+ def start(attributes, region)
53
+ server = get_instance(attributes["name"], ["stopped", "stopping"])
54
+ if server
55
+ puts "Starting stopped instance for #{attributes["name"]} in #{region}...".yellow
56
+ server.start
57
+ else
58
+ puts "Creating new instance for #{attributes["name"]} in #{region}...".yellow
59
+ options = {
60
+ availability_zone: region,
61
+ flavor_id: attributes["instance_type"],
62
+ image_id: attributes["ami"],
63
+ key_name: attributes["keypair"],
64
+ subnet_id: attributes["subnet_id"],
65
+ security_group_ids: attributes["security_groups"],
66
+ tags: { Name: attributes["name"] }
67
+ #private_ip_address : private_ip_address,
68
+ #user_data : user_data,
69
+ #elastic_ip : elastic_ip,
70
+ #allocate_elastic_ip : allocate_elastic_ip,
71
+ #block_device_mapping : block_device_mapping,
72
+ #instance_initiated_shutdown_behavior : terminate_on_shutdown == true ? "terminate" : nil,
73
+ #monitoring : monitoring,
74
+ #ebs_optimized : ebs_optimized
75
+ }
76
+ puts options.to_yaml
77
+ server = @compute.servers.create(options)
78
+ end
79
+ print "Wait for instance to get online".yellow
80
+ server.wait_for { print ".".yellow; ready? }
81
+
82
+ print "\nWait for ssh to get ready...".yellow
83
+ while true
84
+ begin
85
+ Net::SSH.start(server.private_ip_address, attributes["username"], :keys => attributes["private_key_path"]) do |ssh|
86
+ print "\n"
87
+ return server.private_ip_address
88
+ end
89
+ rescue Exception => e
90
+ print ".".yellow
91
+ sleep 2
92
+ end
93
+ end
94
+ print "\n"
95
+ return null
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -2,7 +2,10 @@ module Dployr
2
2
  module Config
3
3
  module Constants
4
4
 
5
- FILENAME = "Dployrfile"
5
+ FILENAME = 'Dployrfile'
6
+
7
+ FILENAMES = [FILENAME, 'dployrfile', 'dployr', 'Dployr']
8
+
6
9
  EXTENSIONS = ['rb', 'yml', 'yaml']
7
10
 
8
11
  end
@@ -1,8 +1,10 @@
1
+ require 'dployr/config/constants'
2
+
1
3
  module Dployr
2
4
  module Config
3
5
  module Create
4
6
 
5
- FILENAME = 'Dployrfile'
7
+ include Dployr::Config::Constants
6
8
 
7
9
  RB_CONTENT = <<-EOS
8
10
  Dployr::configure do |dployr|
@@ -20,15 +20,16 @@ module Dployr
20
20
  def discover(dir = Dir.pwd)
21
21
  [nil].concat(EXTENSIONS).each do |ext|
22
22
  (0..5).each do |n|
23
- file_name = FILENAME
24
- file_name += ".#{ext}" if ext
25
- file_path = File.join dir, ('../' * n), file_name
26
- if File.exists? file_path
27
- return File.expand_path file_path, dir
23
+ FILENAMES.each do |file|
24
+ file += ".#{ext}" if ext
25
+ file_path = File.join dir, ('../' * n), file
26
+ if File.file? file_path
27
+ return File.expand_path file_path, dir
28
+ end
28
29
  end
29
30
  end
30
31
  end
31
- nil
32
+ return nil
32
33
  end
33
34
 
34
35
  end
@@ -82,7 +82,7 @@ module Dployr
82
82
  end
83
83
 
84
84
  def set_scripts(scripts)
85
- @scripts = scripts if scripts.is_a? Array
85
+ @scripts = scripts if scripts.is_a? Hash or scripts.is_a? Array
86
86
  end
87
87
 
88
88
  def set_attributes(attrs)
@@ -20,7 +20,7 @@ module Dployr
20
20
  end
21
21
 
22
22
  def set_default(config)
23
- @default = create_instance('default', config) if config.is_a? Hash
23
+ @default = create_instance 'default', config if config.is_a? Hash
24
24
  end
25
25
 
26
26
  def add_instance(name, config)
@@ -44,7 +44,6 @@ module Dployr
44
44
  @instances.each do |i|
45
45
  config << get_config(i.name, attributes)
46
46
  end
47
- puts config
48
47
  config
49
48
  end
50
49
 
@@ -137,7 +136,10 @@ module Dployr
137
136
  keys.each do |type|
138
137
  current = deep_copy get_by_key(parent, type)
139
138
  source = get_by_key child, type
140
- if type == :scripts
139
+ if current and source
140
+ raise Error.new "Cannot merge different types: #{parent}" if current.class != source.class
141
+ end
142
+ if type.to_sym == :scripts and current.is_a? Array
141
143
  current = [] unless current.is_a? Array
142
144
  current.concat source if source.is_a? Array
143
145
  current = current.compact.uniq
@@ -145,7 +147,8 @@ module Dployr
145
147
  current = {} unless current.is_a? Hash
146
148
  current = deep_merge current, source
147
149
  end
148
- child[type] = current if current.length
150
+ child.delete type.to_s unless child[type.to_s].nil?
151
+ child[type.to_sym] = current if current
149
152
  end
150
153
  child
151
154
  end
data/lib/dployr/init.rb CHANGED
@@ -27,7 +27,8 @@ module Dployr
27
27
 
28
28
  include Dployr::Config::FileUtils
29
29
 
30
- attr_reader :file_path, :config
30
+ attr_reader :config
31
+ attr_accessor :file_path
31
32
 
32
33
  @@instance = nil
33
34
 
@@ -35,22 +36,30 @@ module Dployr
35
36
  @@instance = self
36
37
  @attributes = attributes
37
38
  @config = Dployr::Configuration.new
38
- @file_path = discover
39
- load_file @file_path
39
+ @file_path = nil
40
40
  end
41
41
 
42
42
  def self.instance
43
43
  @@instance
44
44
  end
45
45
 
46
+ def load_config(file_path = nil)
47
+ if file_path
48
+ @file_path = file_path
49
+ else
50
+ @file_path = discover
51
+ end
52
+ set_config @file_path
53
+ end
54
+
46
55
  private
47
56
 
48
- def load_file(file_path)
49
- if file_path.is_a? String
50
- if yaml_file? file_path
51
- load_yaml file_path
57
+ def set_config(file_path)
58
+ if @file_path.is_a? String
59
+ if yaml_file? @file_path
60
+ load_yaml @file_path
52
61
  else
53
- load file_path
62
+ load @file_path
54
63
  end
55
64
  end
56
65
  end
@@ -0,0 +1,31 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'colorize'
4
+
5
+ module Dployr
6
+ module Scripts
7
+ class Default_Hooks
8
+
9
+ include Dployr::Utils
10
+
11
+ def initialize(ip, config, stage, command)
12
+ @log = Logger.new STDOUT
13
+ @config = config
14
+ @ip = ip
15
+ @stage = stage
16
+
17
+ if @config[:scripts]["pre-#{@stage}"]
18
+ Dployr::Scripts::Hook.new @ip, config, "pre-#{@stage}"
19
+ end
20
+ @ip = command.action()
21
+ if @config[:scripts][@stage]
22
+ Dployr::Scripts::Hook.new @ip, config, "#{@stage}"
23
+ end
24
+ if @config[:scripts]["post-#{@stage}"]
25
+ Dployr::Scripts::Hook.new @ip, config, "#{@stage}"
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,38 @@
1
+ require 'logger'
2
+ require 'dployr/utils'
3
+ require 'colorize'
4
+
5
+ module Dployr
6
+ module Scripts
7
+ class Hook
8
+
9
+ include Dployr::Utils
10
+
11
+ def initialize(ip, instance, stage)
12
+ @log = Logger.new STDOUT
13
+ @ip = ip
14
+ @instance = instance
15
+ @stage = stage
16
+ run
17
+ end
18
+
19
+ private
20
+
21
+ def run
22
+ attrs = @instance[:attributes]
23
+ host = attrs["name"]
24
+ username = attrs["username"]
25
+ private_key_path = attrs["private_key_path"]
26
+
27
+ puts "STAGE '#{@stage}':".yellow
28
+ @instance[:scripts][@stage].each do |script|
29
+ if script["target"]
30
+ Dployr::Scripts::Scp.new @ip, host, username, private_key_path, script
31
+ else
32
+ Dployr::Scripts::Shell.new @ip, host, username, private_key_path, script
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ require 'logger'
2
+ require 'net/scp'
3
+ require 'colorize'
4
+ require 'dployr/utils'
5
+
6
+ module Dployr
7
+ module Scripts
8
+ class Scp
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(ip, host, username, private_key_path, script)
13
+
14
+ begin
15
+ @log = Logger.new STDOUT
16
+ puts "Connecting to #{host} (SCP)...".yellow
17
+ Net::SCP.start(ip, username, :keys => [private_key_path]) do |scp|
18
+ source = script["source"]
19
+ target = script["target"]
20
+ puts "Coping #{source} -> #{target}".yellow
21
+ scp.upload(source, target, :recursive => true, :preserve => true)
22
+ end
23
+
24
+ rescue Exception => e
25
+ @log.error e
26
+ raise Error.new "Cannot copy to remote: #{e}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,86 @@
1
+ require 'logger'
2
+ require 'net/ssh'
3
+ require 'colorize'
4
+ require 'dployr/utils'
5
+
6
+ module Dployr
7
+ module Scripts
8
+ class Shell
9
+
10
+ include Dployr::Utils
11
+
12
+ def initialize(ip, host, username, private_key_path, script)
13
+ @log = Logger.new STDOUT
14
+ @ip = ip
15
+ @host = host
16
+ @username = username
17
+ @private_key_path = private_key_path
18
+ @script = script
19
+
20
+ begin
21
+ start
22
+ rescue Exception => e
23
+ @log.error e
24
+ Process.exit! false
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def start
31
+ puts "Connecting to #{@host} (SSH)...".yellow
32
+ Net::SSH.start(@ip, @username, :keys => [@private_key_path]) do |ssh|
33
+ command = @script["path"]
34
+ arguments = @script["args"]
35
+
36
+ puts "Running remote script '#{command} #{arguments}'".yellow
37
+ result = ssh_exec!(ssh, command)
38
+ if result[:exit_code] > 0
39
+ raise "Exit code #{result[:exit_code]} when running script '#{command} #{arguments}'".yellow
40
+ else
41
+ puts "Remote script '#{command} #{arguments}' finished succesfully".yellow
42
+ end
43
+ end
44
+ end
45
+
46
+ # http://craiccomputing.blogspot.com.es/2010/08/printing-colored-text-in-unix-terminals.html
47
+ def ssh_exec!(ssh, command)
48
+ stdout_data = ""
49
+ stderr_data = ""
50
+ exit_code = nil
51
+ exit_signal = nil
52
+ ssh.open_channel do |channel|
53
+ channel.exec(command) do |ch, success|
54
+ unless success
55
+ abort "FAILED: couldn't execute command (ssh.channel.exec)"
56
+ end
57
+ channel.on_data do |ch,data|
58
+ stdout_data+=data
59
+ print "[#{@host}] #{data}".green
60
+ end
61
+
62
+ channel.on_extended_data do |ch,type,data|
63
+ stderr_data+=data
64
+ print "[#{@host}] #{data}".red
65
+ end
66
+
67
+ channel.on_request("exit-status") do |ch,data|
68
+ exit_code = data.read_long
69
+ end
70
+
71
+ channel.on_request("exit-signal") do |ch, data|
72
+ exit_signal = data.read_long
73
+ end
74
+ end
75
+ end
76
+ ssh.loop
77
+ {
78
+ stdout_data: stdout_data,
79
+ stderr_data: stderr_data,
80
+ exit_code: exit_code,
81
+ exit_signal: exit_signal
82
+ }
83
+ end
84
+ end
85
+ end
86
+ end
data/lib/dployr/utils.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'deep_merge'
2
+
1
3
  module Dployr
2
4
  module Utils
3
5
 
@@ -17,7 +19,7 @@ module Dployr
17
19
  end
18
20
 
19
21
  def get_real_key(hash, key)
20
- if hash.is_a? Hash
22
+ if key and hash.is_a? Hash
21
23
  if hash.key? key
22
24
  key
23
25
  elsif hash.key? key.to_sym
@@ -1,3 +1,3 @@
1
1
  module Dployr
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/lib/dployr.rb CHANGED
@@ -1,8 +1,15 @@
1
- require 'yaml'
2
- require 'deep_merge'
3
1
  require 'dployr/version'
4
2
  require 'dployr/init'
5
3
  require 'dployr/configuration'
6
4
  require 'dployr/config/create'
7
5
  require 'dployr/config/file_utils'
8
6
  require 'dployr/config/instance'
7
+ require 'dployr/commands/provision_test'
8
+ require 'dployr/commands/start'
9
+ require 'dployr/commands/stop_destroy'
10
+ require 'dployr/commands/config'
11
+ require 'dployr/commands/execute'
12
+ require 'dployr/scripts/hook'
13
+ require 'dployr/scripts/default_hooks'
14
+ require 'dployr/scripts/shell'
15
+ require 'dployr/scripts/scp'
@@ -359,7 +359,7 @@ describe Dployr::Configuration do
359
359
  zeus[:providers][:aws][:regions]["eu-west-1a"].should be_a Hash
360
360
  end
361
361
 
362
- describe "eu-west-1a" do
362
+ describe "europe-west1-a" do
363
363
  let(:region) {
364
364
  zeus[:providers][:aws][:regions]["eu-west-1a"]
365
365
  }
data/spec/init_spec.rb CHANGED
@@ -7,7 +7,6 @@ describe Dployr::Init do
7
7
 
8
8
  before :all do
9
9
  Dir.chdir fixtures
10
- @dployr = Dployr::Init.new
11
10
  end
12
11
 
13
12
  after :all do
@@ -15,7 +14,13 @@ describe Dployr::Init do
15
14
  end
16
15
 
17
16
  describe "file discovery" do
18
- it "should discover the file" do
17
+
18
+ before :all do
19
+ @dployr = Dployr::Init.new
20
+ @dployr.load_config
21
+ end
22
+
23
+ it "should discover Dployrfile" do
19
24
  @dployr.file_path.should eql "#{fixtures}/Dployrfile"
20
25
  end
21
26
 
@@ -23,5 +28,21 @@ describe Dployr::Init do
23
28
  @dployr.config.should be_instance_of Dployr::Configuration
24
29
  end
25
30
  end
31
+
32
+ describe "custom path" do
33
+
34
+ before :all do
35
+ @dployr = Dployr::Init.new
36
+ @dployr.load_config File.join File.dirname(__FILE__), 'fixtures', 'Dployrfile.yml'
37
+ end
38
+
39
+ it "should load with custom path" do
40
+ @dployr.file_path.should eql "#{fixtures}/Dployrfile.yml"
41
+ end
42
+
43
+ it "should create a new config instance" do
44
+ @dployr.config.should be_instance_of Dployr::Configuration
45
+ end
46
+ end
26
47
  end
27
48
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dployr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomas Aparicio
8
+ - German Ramos
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-04-21 00:00:00.000000000 Z
12
+ date: 2014-04-24 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: fog
@@ -38,6 +39,48 @@ dependencies:
38
39
  - - ~>
39
40
  - !ruby/object:Gem::Version
40
41
  version: '1.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: net-ssh
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: 2.8.0
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 2.8.0
56
+ - !ruby/object:Gem::Dependency
57
+ name: net-scp
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 1.2.0
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.2.0
70
+ - !ruby/object:Gem::Dependency
71
+ name: colorize
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.7.2
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: 0.7.2
41
84
  - !ruby/object:Gem::Dependency
42
85
  name: rake
43
86
  requirement: !ruby/object:Gem::Requirement
@@ -84,12 +127,17 @@ files:
84
127
  - README.md
85
128
  - Rakefile
86
129
  - bin/dployr
130
+ - config/Dployrfile.yml
131
+ - config/hello/hello.sh
87
132
  - dployr.gemspec
88
133
  - lib/dployr.rb
89
- - lib/dployr/cli/cli.rb
90
- - lib/dployr/cli/commands.rb
91
- - lib/dployr/cli/commands/config.rb
92
- - lib/dployr/compute/client.rb
134
+ - lib/dployr/cli.rb
135
+ - lib/dployr/commands/config.rb
136
+ - lib/dployr/commands/execute.rb
137
+ - lib/dployr/commands/provision_test.rb
138
+ - lib/dployr/commands/start.rb
139
+ - lib/dployr/commands/stop_destroy.rb
140
+ - lib/dployr/compute/aws.rb
93
141
  - lib/dployr/config/constants.rb
94
142
  - lib/dployr/config/create.rb
95
143
  - lib/dployr/config/file_utils.rb
@@ -97,6 +145,10 @@ files:
97
145
  - lib/dployr/configuration.rb
98
146
  - lib/dployr/init.rb
99
147
  - lib/dployr/logger.rb
148
+ - lib/dployr/scripts/default_hooks.rb
149
+ - lib/dployr/scripts/hook.rb
150
+ - lib/dployr/scripts/scp.rb
151
+ - lib/dployr/scripts/shell.rb
100
152
  - lib/dployr/utils.rb
101
153
  - lib/dployr/version.rb
102
154
  - spec/config_file_utils_spec.rb
@@ -1,66 +0,0 @@
1
- require 'logger'
2
- require 'dployr'
3
- require 'dployr/utils'
4
-
5
- module Dployr
6
- module CLI
7
- class Config
8
-
9
- include Dployr::Utils
10
-
11
- def initialize(options)
12
- @options = options
13
- @name = options[:name]
14
- @log = Logger.new STDOUT
15
- @attributes = parse_attributes @options[:attributes]
16
-
17
- begin
18
- create
19
- render_file
20
- rescue Exception => e
21
- @log.error e
22
- Process.exit! false
23
- end
24
- end
25
-
26
- def create
27
- begin
28
- @dployr = Dployr::Init.new @attributes
29
- rescue Exception => e
30
- raise "Cannot load the config: #{e}"
31
- end
32
- end
33
-
34
- def render_file
35
- raise "Dployrfile was not found" if @dployr.file_path.nil?
36
- raise "Configuration is missing" unless @dployr.config.exists?
37
- begin
38
- if @name
39
- config = @dployr.config.get_config @name, @attributes
40
- else
41
- puts @attributes
42
- config = @dployr.config.get_config_all @attributes
43
- end
44
- unless config.nil?
45
- puts config.to_yaml
46
- else
47
- @log.info "Missing configuration data"
48
- end
49
- rescue Exception => e
50
- raise "Cannot generate the config: #{e}"
51
- end
52
- end
53
-
54
- def parse_attributes(attributes)
55
- if attributes.is_a? String
56
- if @options[:attributes][0] == '-'
57
- parse_flags attributes
58
- else
59
- parse_matrix attributes
60
- end
61
- end
62
- end
63
-
64
- end
65
- end
66
- end
@@ -1 +0,0 @@
1
- require 'dployr/cli/commands/config'
@@ -1,28 +0,0 @@
1
- require 'fog'
2
-
3
- module Dployr
4
- module Compute
5
- class Client
6
-
7
- attr_reader :client
8
-
9
- DEFAULT = {
10
- provider: 'AWS'
11
- }
12
-
13
- def initialize(options)
14
- @options = options
15
- @client = Fog::Compute.new DEFAULT.merge options
16
- end
17
-
18
- def servers
19
- @client.servers
20
- end
21
-
22
- def create_server(options)
23
- @client.servers.create options
24
- end
25
-
26
- end
27
- end
28
- end