orca 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- orca (0.3.0)
4
+ orca (0.3.1)
5
5
  colored
6
6
  net-sftp
7
7
  net-ssh
data/README.md CHANGED
@@ -87,6 +87,7 @@ Options, all commands support the following optional parameters...
87
87
  --sequential | dont attempt to run commands accross multiple nodes in parrallel
88
88
  --throw | throw a stack trace rather than pretty printing errors
89
89
  --file | path to the orca.rb file to load, defaults to ./orca/orca.rb
90
+ --verbose | print all SSH output, useful for debugging but can be rather long
90
91
  --skip-dependancies | Don't validate and run dependancies, only the pkg in question
91
92
 
92
93
 
@@ -123,6 +124,7 @@ Orca packages are written in a Ruby based DSL. It's really simple to learn in le
123
124
  end
124
125
  end
125
126
 
127
+ A more complete WIP example can be found in this gist... https://gist.github.com/andykent/5814997
126
128
 
127
129
 
128
130
  Extensions
@@ -3,6 +3,12 @@ require 'colored'
3
3
  require 'thor'
4
4
 
5
5
  module Orca
6
+ def verbose(val=nil)
7
+ @verbose = val unless val.nil?
8
+ @verbose || false
9
+ end
10
+ module_function :verbose
11
+
6
12
  def root
7
13
  File.dirname(ENV['ORCA_FILE'])
8
14
  end
@@ -7,6 +7,7 @@ class Orca::Cli < Thor
7
7
  class_option :file, :banner => 'ORCA_FILE', :desc => "path to the orca.rb file to load, defaults to ./orca/orca.rb"
8
8
  class_option :throw, :type => :boolean, :desc => "Don't pretty print errors, raise with a stack trace."
9
9
  class_option :sequential, :type => :boolean, :desc => "Don't run tasks in parrallel across nodes."
10
+ class_option :verbose, :type => :boolean, :desc => "print all SSH output, useful for debugging"
10
11
  class_option :'skip-dependancies', :type => :boolean, :desc => "Don't validate and run dependancies."
11
12
 
12
13
  desc "apply PACKAGE_NAME GROUP_OR_NODE_NAME", "apply the given package onto the given named group"
@@ -37,6 +38,7 @@ class Orca::Cli < Thor
37
38
  private
38
39
 
39
40
  def run_command(package, group, cmd)
41
+ Orca.verbose(options[:verbose] || false)
40
42
  begin
41
43
  suite = Orca::Suite.new(options)
42
44
  suite.load_file(orca_file)
@@ -47,6 +49,8 @@ class Orca::Cli < Thor
47
49
  else
48
50
  puts "!!! ERROR !!! [#{e.class.name}] #{e.message}".red.bold
49
51
  end
52
+ ensure
53
+ suite.cleanup
50
54
  end
51
55
  end
52
56
 
@@ -9,16 +9,16 @@ class Orca::ExecutionContext
9
9
  instance_eval(&blk)
10
10
  end
11
11
 
12
- def run(cmd)
13
- @node.execute(cmd)
12
+ def run(cmd, opts={})
13
+ @node.execute(cmd, opts)
14
14
  end
15
15
 
16
16
  def log(msg)
17
17
  @node.log('log', msg)
18
18
  end
19
19
 
20
- def sudo(cmd)
21
- @node.sudo(cmd)
20
+ def sudo(cmd, opts={})
21
+ @node.sudo(cmd, opts)
22
22
  end
23
23
 
24
24
  def upload(from, to)
@@ -1,25 +1,38 @@
1
1
  Orca.extension :apt do
2
+
3
+ # supports three formats
4
+ # apt_package 'git-core' - create a package 'git-core' that installs 'git-core'
5
+ # apt_package 'git', 'git-core' - creates a package 'git' that installs 'git-core'
6
+ # apt_package 'git', package:'git-core', version:'1.7.2' - creates a package 'git' that installs 'git-core=1.7.2'
2
7
  module_function
3
- def apt_package(pkg_name, apt_name=pkg_name, &blk)
8
+ def apt_package(pkg_name, opts=pkg_name, &blk)
9
+ apt_name = opts
10
+ version = nil
11
+ if opts.is_a? Hash
12
+ version = opts[:version]
13
+ apt_name = opts[:package] || pkg_name
14
+ end
4
15
  package pkg_name do
5
- depends_on 'apt'
6
- validate { trigger 'apt:exists', apt_name }
7
- apply do
8
- trigger 'apt:update'
9
- trigger 'apt:install', apt_name
16
+ depends_on('apt')
17
+ validate { trigger('apt:exists', apt_name, version) }
18
+ apply do
19
+ trigger('apt:update')
20
+ trigger('apt:install', apt_name, version)
10
21
  end
11
- remove { trigger 'apt:remove', apt_name }
22
+ remove { trigger('apt:remove', apt_name, version) }
12
23
  instance_eval(&blk) if blk
13
24
  end
14
25
  end
15
26
 
16
27
  package 'apt' do
17
- action 'install' do |package_name|
18
- sudo "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq #{package_name}"
28
+ action 'install' do |package_name, version=nil|
29
+ package_description = [package_name, version].compact.join('=')
30
+ sudo "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq #{package_description}"
19
31
  end
20
32
 
21
- action 'remove' do |package_name|
22
- sudo "DEBIAN_FRONTEND=noninteractive apt-get remove -y -qq #{package_name}"
33
+ action 'remove' do |package_name, version=nil|
34
+ package_description = [package_name, version].compact.join('=')
35
+ sudo "DEBIAN_FRONTEND=noninteractive apt-get remove -y -qq #{package_description}"
23
36
  end
24
37
 
25
38
  action 'ppa' do |repo|
@@ -30,8 +43,15 @@ Orca.extension :apt do
30
43
  sudo "DEBIAN_FRONTEND=noninteractive apt-get update -y -qq"
31
44
  end
32
45
 
33
- action 'exists' do |package_name|
34
- run("dpkg -s #{package_name} 2>&1 | grep Status") =~ /Status: install ok installed/
46
+ action 'exists' do |package_name, required_version=nil|
47
+ pkg_info = run("dpkg -s #{package_name} 2>&1")
48
+ installed = pkg_info =~ /Status: install ok installed/
49
+ next false unless installed
50
+ next true if required_version.nil?
51
+ version = pkg_info.match(/^Version: (.+?)$/)[1]
52
+ version_matches = (version == required_version)
53
+ log("#{package_name}: expected '#{required_version}' but found '#{version}'") unless version_matches
54
+ version_matches
35
55
  end
36
56
 
37
57
  validate do
@@ -50,7 +50,7 @@ class Orca::FileSync
50
50
  end
51
51
 
52
52
  def run_after_apply(context)
53
- context.instance_eval(&@after_apply)
53
+ context.instance_eval(&@after_apply) if @after_apply
54
54
  end
55
55
 
56
56
  def add_content_package
@@ -60,21 +60,21 @@ class Orca::Node
60
60
  @sftp ||= connection.sftp.connect
61
61
  end
62
62
 
63
- def execute(cmd)
63
+ def execute(cmd, opts={})
64
64
  log('execute', cmd.cyan)
65
65
  output = ""
66
66
  connection.exec! cmd do |channel, stream, data|
67
67
  output += data if stream == :stdout
68
68
  data.split("\n").each do |line|
69
69
  msg = stream == :stdout ? line.green : line.red
70
- log(stream, msg)
70
+ log(stream, msg) if opts[:log] || Orca.verbose
71
71
  end
72
72
  end
73
73
  output
74
74
  end
75
75
 
76
- def sudo(cmd)
77
- execute("sudo #{cmd}")
76
+ def sudo(cmd, opts={})
77
+ execute("sudo #{cmd}", opts)
78
78
  end
79
79
 
80
80
  def log(context, msg)
@@ -84,7 +84,11 @@ class Orca::Node
84
84
 
85
85
  def connection
86
86
  return @connection if @connection
87
- @connetion = Net::SSH.start(@host, (@options[:user] || 'root'), options_for_ssh)
87
+ @connection = Net::SSH.start(@host, (@options[:user] || 'root'), options_for_ssh)
88
+ end
89
+
90
+ def disconnect
91
+ @connection.close if @connection && !@connection.closed?
88
92
  end
89
93
 
90
94
  def to_s
@@ -4,6 +4,7 @@ class Orca::Suite
4
4
  @sequential = options[:sequential]
5
5
  @demonstrate = options[:demonstrate]
6
6
  @skip_dependancies = options[:'skip-dependancies'] || false
7
+ @nodes = []
7
8
  end
8
9
 
9
10
  def load_file(file)
@@ -13,6 +14,7 @@ class Orca::Suite
13
14
  def run(group_name, pkg_name, command, sequential=false)
14
15
  group = Orca::Group.find(group_name)
15
16
  runners = group.nodes.map do |node|
17
+ @nodes << node
16
18
  if command == :trigger
17
19
  Orca::TriggerRunner.new(node, pkg_name)
18
20
  else
@@ -28,6 +30,12 @@ class Orca::Suite
28
30
  end
29
31
  end
30
32
 
33
+ def cleanup
34
+ @nodes.each(&:disconnect)
35
+ end
36
+
37
+ private
38
+
31
39
  def exec(runner, command)
32
40
  if @demonstrate
33
41
  runner.demonstrate(command)
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
11
11
  gem.name = "orca"
12
12
  gem.require_paths = ["lib"]
13
- gem.version = '0.3.0'
13
+ gem.version = '0.3.1'
14
14
  gem.add_dependency('colored')
15
15
  gem.add_dependency('net-ssh')
16
16
  gem.add_dependency('net-sftp')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
12
+ date: 2013-06-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colored
@@ -132,7 +132,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
132
  version: '0'
133
133
  segments:
134
134
  - 0
135
- hash: 1540904086341919600
135
+ hash: -4313409858467376914
136
136
  required_rubygems_version: !ruby/object:Gem::Requirement
137
137
  none: false
138
138
  requirements:
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  version: '0'
142
142
  segments:
143
143
  - 0
144
- hash: 1540904086341919600
144
+ hash: -4313409858467376914
145
145
  requirements: []
146
146
  rubyforge_project:
147
147
  rubygems_version: 1.8.23