dployr 0.0.2 → 0.0.3

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.
@@ -5,94 +5,93 @@ module Dployr
5
5
  module Compute
6
6
  class AWS
7
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
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
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
18
+ def get_instance(name, states)
19
+ servers = @compute.servers.all
20
+ servers.each do |instance|
21
+ if instance.tags["Name"] == name and states.include? instance.state
22
+ return instance
25
23
  end
26
- return nil
27
24
  end
25
+ nil
26
+ end
28
27
 
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
28
+ def get_ip(name)
29
+ instance = get_instance(name, ["running"])
30
+ instance.private_ip_address if instance
31
+ end
32
+
33
+ def destroy(name)
34
+ instance = get_instance(name, ["running", "stopped", "stopping"])
35
+ if instance
36
+ instance.destroy
37
+ else
41
38
  raise "Instance #{name} not found"
42
39
  end
43
-
44
- def halt(name)
45
- instance = get_instance(name, ["running"])
46
- if instance
47
- return instance.stop
48
- end
40
+ end
41
+
42
+ def halt(name)
43
+ instance = get_instance(name, ["running"])
44
+ if instance
45
+ instance.stop
46
+ else
49
47
  raise "Instance #{name} not found"
50
48
  end
49
+ end
51
50
 
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
51
+ def start(attributes, region)
52
+ server = get_instance(attributes["name"], ["stopped", "stopping"])
53
+ if server
54
+ puts "Starting stopped instance for #{attributes["name"]} in #{region}...".yellow
55
+ server.start
56
+ else
57
+ puts "Creating new instance for #{attributes["name"]} in #{region}...".yellow
58
+ options = {
59
+ availability_zone: region,
60
+ flavor_id: attributes["instance_type"],
61
+ image_id: attributes["ami"],
62
+ key_name: attributes["keypair"],
63
+ subnet_id: attributes["subnet_id"],
64
+ security_group_ids: attributes["security_groups"],
65
+ tags: { Name: attributes["name"] }
66
+ #private_ip_address : private_ip_address,
67
+ #user_data : user_data,
68
+ #elastic_ip : elastic_ip,
69
+ #allocate_elastic_ip : allocate_elastic_ip,
70
+ #block_device_mapping : block_device_mapping,
71
+ #instance_initiated_shutdown_behavior : terminate_on_shutdown == true ? "terminate" : nil,
72
+ #monitoring : monitoring,
73
+ #ebs_optimized : ebs_optimized
74
+ }
75
+ puts options.to_yaml
76
+ server = @compute.servers.create(options)
77
+ end
78
+ print "Wait for instance to get online".yellow
79
+ server.wait_for { print ".".yellow; ready? }
80
+
81
+ print "\nWait for ssh to get ready...".yellow
82
+ while true
83
+ begin
84
+ Net::SSH.start(server.private_ip_address, attributes["username"], :keys => attributes["private_key_path"]) do |ssh|
85
+ print "\n"
86
+ return server.private_ip_address
92
87
  end
88
+ rescue Exception => e
89
+ print ".".yellow
90
+ sleep 2
93
91
  end
94
- print "\n"
95
- return null
92
+ end
93
+ print "\n"
94
+ nil
96
95
  end
97
96
 
98
97
  end
@@ -0,0 +1,134 @@
1
+ require 'fog'
2
+ require 'net/ssh'
3
+
4
+ module Dployr
5
+ module Compute
6
+ class GCE
7
+
8
+ def initialize(region)
9
+ @options = {
10
+ provider: 'Google',
11
+ google_project: ENV["GOOGLE_PROJECT_ID"],
12
+ google_client_email: ENV["GOOGLE_CLIENT_EMAIL"],
13
+ google_key_location: ENV["GOOGLE_KEY_LOCATION"]
14
+ }
15
+ @compute = Fog::Compute.new @options
16
+ end
17
+
18
+ # https://developers.google.com/compute/docs/instances
19
+ # private
20
+ def get_instance(name, states)
21
+ servers = @compute.servers.all
22
+ servers.each do |instance|
23
+ if instance.name == name and states.include? instance.state
24
+ return instance
25
+ end
26
+ end
27
+ return nil
28
+ end
29
+
30
+ def get_ip(name)
31
+ instance = get_instance(name, ["PROVISIONING", "STAGING", "RUNNING"])
32
+ if instance
33
+ return instance.private_ip_address
34
+ end
35
+ end
36
+
37
+ def destroy(name)
38
+ instance = get_instance(name, ["RUNNING", "STOPPED"])
39
+ if instance
40
+ puts "Destroying instance #{name}...".yellow
41
+ instance.destroy(async = false)
42
+ puts "Destroying disk #{name}...".yellow
43
+ disk = @compute.disks.get(name)
44
+ disk.destroy
45
+ # Bug in fog. It return "persistent-disk-0" instead of boot disk name (usually the same name of the machine)
46
+ # instance.disks.each do |disk|
47
+ # gdisk = @compute.disks.get(disk["deviceName"])
48
+ # gdisk.destroy
49
+ # end
50
+ return
51
+ end
52
+ raise "Instance #{name} not found"
53
+ end
54
+
55
+ def halt(name)
56
+ instance = get_instance(name, ["RUNNING"])
57
+ if instance
58
+ instance.disks.each do |disk|
59
+ if disk["autoDelete"] == true
60
+ raise "Cannot halt instance with autoDelete disks"
61
+ end
62
+ end
63
+ return instance.destroy
64
+ end
65
+ raise "Instance #{name} not found"
66
+ end
67
+
68
+ def create_disk(name, size_gb, zone_name, image_name)
69
+ disk = @compute.disks.get(name)
70
+ if disk != nil
71
+ puts "Disk #{name} already created. Reusing it.".yellow
72
+ return disk
73
+ else
74
+ puts "Creating new boot disk #{name}...".yellow
75
+ disk = @compute.disks.create(
76
+ name: name,
77
+ size_gb: size_gb,
78
+ zone_name: zone_name,
79
+ source_image: image_name
80
+ )
81
+
82
+ disk.wait_for { disk.ready? }
83
+ return disk
84
+ end
85
+ end
86
+
87
+ def start(attributes, region)
88
+ server = get_instance(attributes["name"], ["stopped", "stopping"])
89
+ if server
90
+ puts "Starting stopped instance for #{attributes["name"]} in #{region}...".yellow
91
+ server.start
92
+ else
93
+ disks = create_disk(attributes["name"], 10, region, attributes["image_name"])
94
+ if defined? attributes["autodelete_disk"]
95
+ autodelete_disk = attributes["autodelete_disk"]
96
+ else
97
+ autodelete_disk = false
98
+ end
99
+
100
+ puts "Creating new instance for #{attributes["name"]} in #{region}...".yellow
101
+
102
+ options = {
103
+ name: attributes["name"],
104
+ zone_name: region,
105
+ machine_type: attributes["instance_type"],
106
+ network: attributes["network"],
107
+ disks: [disks.get_as_boot_disk(true, autodelete_disk)],
108
+ }
109
+
110
+ puts options.to_yaml
111
+ server = @compute.servers.create(options)
112
+ end
113
+ print "Wait for instance to get online".yellow
114
+ server.wait_for { print ".".yellow; ready? }
115
+
116
+ print "\nWait for ssh to get ready...".yellow
117
+ while true
118
+ begin
119
+ Net::SSH.start(server.private_ip_address, attributes["username"], :keys => attributes["private_key_path"]) do |ssh|
120
+ print "\n"
121
+ return server.private_ip_address
122
+ end
123
+ rescue Exception => e
124
+ print ".".yellow
125
+ sleep 2
126
+ end
127
+ end
128
+ print "\n"
129
+ return nil
130
+ end
131
+
132
+ end
133
+ end
134
+ end
@@ -18,18 +18,16 @@ module Dployr
18
18
  end
19
19
 
20
20
  def discover(dir = Dir.pwd)
21
- [nil].concat(EXTENSIONS).each do |ext|
22
- (0..5).each do |n|
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
21
+ (0..5).each do |n|
22
+ FILENAMES.each do |file|
23
+ [nil].concat(EXTENSIONS).each do |ext|
24
+ file_name = "#{file}.#{ext}" if ext
25
+ file_path = File.join dir, ('../' * n), (file_name or file)
26
+ return File.expand_path file_path, dir if File.file? file_path
29
27
  end
30
28
  end
31
29
  end
32
- return nil
30
+ nil
33
31
  end
34
32
 
35
33
  end
@@ -7,11 +7,12 @@ module Dployr
7
7
 
8
8
  attr_reader :default, :instances
9
9
 
10
- def initialize
10
+ def initialize(attributes = {})
11
11
  @default = nil
12
12
  @config = nil
13
13
  @instances = []
14
14
  @merged = false
15
+ @attributes = attributes.is_a?(Hash) ? attributes : {}
15
16
  yield self if block_given?
16
17
  end
17
18
 
@@ -35,6 +36,7 @@ module Dployr
35
36
 
36
37
  def get_config(name, attributes = {})
37
38
  instance = get_instance name
39
+ attributes = @attributes.merge (attributes or {})
38
40
  raise ArgumentError.new "Instance '#{name.to_s}' do not exists" if instance.nil?
39
41
  replace_variables merge_config(instance), replace_variables(attributes)
40
42
  end
data/lib/dployr/init.rb CHANGED
@@ -34,8 +34,7 @@ module Dployr
34
34
 
35
35
  def initialize(attributes = {})
36
36
  @@instance = self
37
- @attributes = attributes
38
- @config = Dployr::Configuration.new
37
+ @config = Dployr::Configuration.new attributes
39
38
  @file_path = nil
40
39
  end
41
40
 
@@ -1,19 +1,12 @@
1
- require 'logger'
2
- require 'dployr/utils'
3
- require 'colorize'
4
-
5
1
  module Dployr
6
2
  module Scripts
7
3
  class Default_Hooks
8
4
 
9
- include Dployr::Utils
10
-
11
5
  def initialize(ip, config, stage, command)
12
- @log = Logger.new STDOUT
13
6
  @config = config
14
7
  @ip = ip
15
8
  @stage = stage
16
-
9
+
17
10
  if @config[:scripts]["pre-#{@stage}"]
18
11
  Dployr::Scripts::Hook.new @ip, config, "pre-#{@stage}"
19
12
  end
@@ -25,7 +18,7 @@ module Dployr
25
18
  Dployr::Scripts::Hook.new @ip, config, "#{@stage}"
26
19
  end
27
20
  end
28
-
21
+
29
22
  end
30
23
  end
31
24
  end
@@ -1,15 +1,8 @@
1
- require 'logger'
2
- require 'dployr/utils'
3
- require 'colorize'
4
-
5
1
  module Dployr
6
2
  module Scripts
7
3
  class Hook
8
4
 
9
- include Dployr::Utils
10
-
11
5
  def initialize(ip, instance, stage)
12
- @log = Logger.new STDOUT
13
6
  @ip = ip
14
7
  @instance = instance
15
8
  @stage = stage
@@ -24,12 +17,14 @@ module Dployr
24
17
  username = attrs["username"]
25
18
  private_key_path = attrs["private_key_path"]
26
19
 
27
- puts "STAGE '#{@stage}':".yellow
20
+ puts "Running stage '#{@stage}':".yellow
28
21
  @instance[:scripts][@stage].each do |script|
29
22
  if script["target"]
30
23
  Dployr::Scripts::Scp.new @ip, host, username, private_key_path, script
31
- else
24
+ elsif script["remote_path"]
32
25
  Dployr::Scripts::Shell.new @ip, host, username, private_key_path, script
26
+ elsif script["local_path"]
27
+ Dployr::Scripts::Local_Shell.new script
33
28
  end
34
29
  end
35
30
  end
@@ -0,0 +1,29 @@
1
+ require 'net/ssh'
2
+
3
+ module Dployr
4
+ module Scripts
5
+ class Local_Shell
6
+
7
+ def initialize(script)
8
+ @script = script
9
+ start
10
+ end
11
+
12
+ private
13
+
14
+ def start
15
+ command = @script["local_path"]
16
+ arguments = @script["args"]
17
+
18
+ puts "Running local script '#{command} #{arguments}'".yellow
19
+ result = system(command + ' ' + arguments)
20
+ if result == false
21
+ raise "Exit code non zero when running local script '#{command} #{arguments}'".yellow
22
+ else
23
+ puts "Local script '#{command} #{arguments}' finished succesfully".yellow
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -1,18 +1,11 @@
1
- require 'logger'
2
1
  require 'net/scp'
3
- require 'colorize'
4
- require 'dployr/utils'
5
2
 
6
3
  module Dployr
7
4
  module Scripts
8
5
  class Scp
9
6
 
10
- include Dployr::Utils
11
-
12
7
  def initialize(ip, host, username, private_key_path, script)
13
-
14
8
  begin
15
- @log = Logger.new STDOUT
16
9
  puts "Connecting to #{host} (SCP)...".yellow
17
10
  Net::SCP.start(ip, username, :keys => [private_key_path]) do |scp|
18
11
  source = script["source"]
@@ -20,12 +13,11 @@ module Dployr
20
13
  puts "Coping #{source} -> #{target}".yellow
21
14
  scp.upload(source, target, :recursive => true, :preserve => true)
22
15
  end
23
-
24
16
  rescue Exception => e
25
- @log.error e
26
17
  raise Error.new "Cannot copy to remote: #{e}"
27
18
  end
28
19
  end
20
+
29
21
  end
30
22
  end
31
23
  end
@@ -1,28 +1,16 @@
1
- require 'logger'
2
1
  require 'net/ssh'
3
- require 'colorize'
4
- require 'dployr/utils'
5
2
 
6
3
  module Dployr
7
4
  module Scripts
8
5
  class Shell
9
6
 
10
- include Dployr::Utils
11
-
12
7
  def initialize(ip, host, username, private_key_path, script)
13
- @log = Logger.new STDOUT
14
8
  @ip = ip
15
9
  @host = host
16
10
  @username = username
17
11
  @private_key_path = private_key_path
18
12
  @script = script
19
-
20
- begin
21
- start
22
- rescue Exception => e
23
- @log.error e
24
- Process.exit! false
25
- end
13
+ start
26
14
  end
27
15
 
28
16
  private
@@ -30,11 +18,11 @@ module Dployr
30
18
  def start
31
19
  puts "Connecting to #{@host} (SSH)...".yellow
32
20
  Net::SSH.start(@ip, @username, :keys => [@private_key_path]) do |ssh|
33
- command = @script["path"]
21
+ command = @script["remote_path"]
34
22
  arguments = @script["args"]
35
23
 
36
24
  puts "Running remote script '#{command} #{arguments}'".yellow
37
- result = ssh_exec!(ssh, command)
25
+ result = ssh_exec!(ssh, command + ' ' + arguments)
38
26
  if result[:exit_code] > 0
39
27
  raise "Exit code #{result[:exit_code]} when running script '#{command} #{arguments}'".yellow
40
28
  else
@@ -50,35 +38,35 @@ module Dployr
50
38
  exit_code = nil
51
39
  exit_signal = nil
52
40
  ssh.open_channel do |channel|
41
+ @channel = channel
53
42
  channel.exec(command) do |ch, success|
54
43
  unless success
55
44
  abort "FAILED: couldn't execute command (ssh.channel.exec)"
56
45
  end
57
46
  channel.on_data do |ch,data|
58
47
  stdout_data+=data
59
- print "[#{@host}] #{data}".green
48
+ #print "[#{@host}] #{data}".green
49
+ print "#{data}".green
60
50
  end
61
51
 
62
52
  channel.on_extended_data do |ch,type,data|
63
53
  stderr_data+=data
64
- print "[#{@host}] #{data}".red
54
+ #print "[#{@host}] #{data}".red
55
+ print "#{data}".red
65
56
  end
66
57
 
67
58
  channel.on_request("exit-status") do |ch,data|
68
59
  exit_code = data.read_long
60
+ @channel.close
69
61
  end
70
-
71
- channel.on_request("exit-signal") do |ch, data|
72
- exit_signal = data.read_long
73
- end
62
+
74
63
  end
75
64
  end
76
65
  ssh.loop
77
66
  {
78
67
  stdout_data: stdout_data,
79
68
  stderr_data: stderr_data,
80
- exit_code: exit_code,
81
- exit_signal: exit_signal
69
+ exit_code: exit_code
82
70
  }
83
71
  end
84
72
  end
@@ -0,0 +1,23 @@
1
+ require 'net/ssh'
2
+
3
+ module Dployr
4
+ module Scripts
5
+ class Ssh
6
+
7
+ def initialize(ip, instance)
8
+ @ip = ip
9
+ @username = instance[:attributes]["username"]
10
+ @private_key_path = instance[:attributes]["private_key_path"]
11
+ run
12
+ end
13
+
14
+ private
15
+
16
+ def run
17
+ puts "ssh -i #{@private_key_path} #{@username}@#{@ip}"
18
+ system("ssh -i #{@private_key_path} #{@username}@#{@ip}")
19
+ end
20
+
21
+ end
22
+ end
23
+ end
data/lib/dployr/utils.rb CHANGED
@@ -46,27 +46,6 @@ module Dployr
46
46
  Marshal.load Marshal.dump o
47
47
  end
48
48
 
49
- def parse_matrix(str)
50
- hash = {}
51
- str.split(';').each do |val|
52
- val = val.split '='
53
- hash[val.first.strip] = val.last.strip
54
- end if str.is_a? String
55
- hash
56
- end
57
-
58
- def parse_flags(str)
59
- hash = {}
60
- str.gsub(/\s+/, ' ').strip.split(' ').each_slice(2) do |val|
61
- key = val.first
62
- if val.first.is_a? String
63
- key = key.gsub(/^\-+/, '').strip
64
- hash[key] = (val.last or '').strip
65
- end
66
- end if str.is_a? String
67
- hash
68
- end
69
-
70
49
  def replace_vars(str)
71
50
  str.gsub(/\%\{(\w+)\}/) { yield $1 }
72
51
  end
@@ -1,3 +1,3 @@
1
1
  module Dployr
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/dployr.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'colorize'
1
2
  require 'dployr/version'
2
3
  require 'dployr/init'
3
4
  require 'dployr/configuration'
@@ -9,7 +10,10 @@ require 'dployr/commands/start'
9
10
  require 'dployr/commands/stop_destroy'
10
11
  require 'dployr/commands/config'
11
12
  require 'dployr/commands/execute'
13
+ require 'dployr/commands/ssh'
12
14
  require 'dployr/scripts/hook'
13
15
  require 'dployr/scripts/default_hooks'
14
16
  require 'dployr/scripts/shell'
17
+ require 'dployr/scripts/local_shell'
18
+ require 'dployr/scripts/ssh'
15
19
  require 'dployr/scripts/scp'