dployr 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'