orca 0.2.0 → 0.3.0

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.
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'rake'
6
+ gem 'minitest'
6
7
  gem 'mocha', :require => false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- orca (0.2.0)
4
+ orca (0.3.0)
5
5
  colored
6
6
  net-sftp
7
7
  net-ssh
@@ -12,6 +12,7 @@ GEM
12
12
  specs:
13
13
  colored (1.2)
14
14
  metaclass (0.0.1)
15
+ minitest (4.7.5)
15
16
  mocha (0.13.1)
16
17
  metaclass (~> 0.0.1)
17
18
  net-sftp (2.1.2)
@@ -24,6 +25,7 @@ PLATFORMS
24
25
  ruby
25
26
 
26
27
  DEPENDENCIES
28
+ minitest
27
29
  mocha
28
30
  orca!
29
31
  rake
data/README.md CHANGED
@@ -76,7 +76,18 @@ So here are some examples (assuming you have a package called "app" and a node c
76
76
 
77
77
  orca apply app server
78
78
  orca remove app server
79
- orca demonstrate app server
79
+
80
+ You can also directly trigger actions from the CLI like so...
81
+
82
+ orca trigger nginx:reload web-1
83
+
84
+ Options, all commands support the following optional parameters...
85
+
86
+ --demonstrate | dont actually run the commands on the server just pretend like you are
87
+ --sequential | dont attempt to run commands accross multiple nodes in parrallel
88
+ --throw | throw a stack trace rather than pretty printing errors
89
+ --file | path to the orca.rb file to load, defaults to ./orca/orca.rb
90
+ --skip-dependancies | Don't validate and run dependancies, only the pkg in question
80
91
 
81
92
 
82
93
  The Orca DSL
data/lib/orca.rb CHANGED
@@ -37,6 +37,7 @@ require_relative "./orca/package_index"
37
37
  require_relative "./orca/node"
38
38
  require_relative "./orca/group"
39
39
  require_relative "./orca/runner"
40
+ require_relative "./orca/trigger_runner"
40
41
  require_relative "./orca/resolver"
41
42
  require_relative "./orca/execution_context"
42
43
  require_relative "./orca/local_file"
data/lib/orca/cli.rb CHANGED
@@ -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 :'skip-dependancies', :type => :boolean, :desc => "Don't validate and run dependancies."
10
11
 
11
12
  desc "apply PACKAGE_NAME GROUP_OR_NODE_NAME", "apply the given package onto the given named group"
12
13
  def apply(package, group)
@@ -28,6 +29,11 @@ class Orca::Cli < Thor
28
29
  directory('template', 'orca')
29
30
  end
30
31
 
32
+ desc "trigger ACTION_REF GROUP_OR_NODE_NAME", "trigger an action directly e.g. `orca trigger nginx:reload web-1`"
33
+ def trigger(action_ref, group)
34
+ run_command(action_ref, group, :trigger)
35
+ end
36
+
31
37
  private
32
38
 
33
39
  def run_command(package, group, cmd)
@@ -1,4 +1,6 @@
1
1
  class Orca::ExecutionContext
2
+ attr_reader :node
3
+
2
4
  def initialize(node)
3
5
  @node = node
4
6
  end
@@ -11,6 +13,10 @@ class Orca::ExecutionContext
11
13
  @node.execute(cmd)
12
14
  end
13
15
 
16
+ def log(msg)
17
+ @node.log('log', msg)
18
+ end
19
+
14
20
  def sudo(cmd)
15
21
  @node.sudo(cmd)
16
22
  end
@@ -47,7 +53,7 @@ class Orca::ExecutionContext
47
53
  pkg_name, action_name = *action_ref.split(':', 2)
48
54
  pkg = Orca::PackageIndex.default.get(pkg_name)
49
55
  action = pkg.actions[action_name]
50
- raise "Action #{action_ref} could not be found." unless action
56
+ raise Orca::MissingActionError.new(action_ref) unless action
51
57
  instance_exec(*args, &action)
52
58
  end
53
59
 
@@ -56,6 +62,16 @@ class Orca::ExecutionContext
56
62
  end
57
63
  end
58
64
 
65
+ class Orca::MissingActionError < StandardError
66
+ def initialize(action_ref)
67
+ @action_ref = action_ref
68
+ end
69
+
70
+ def message
71
+ "Action '#{@action_ref}' could not be found."
72
+ end
73
+ end
74
+
59
75
  class Orca::MockExecutionContext < Orca::ExecutionContext
60
76
  def run(cmd)
61
77
  @node.log 'mock-execute', cmd
@@ -1,15 +1,16 @@
1
1
  Orca.extension :file_sync do
2
2
  class Orca::Package
3
- def file(config)
4
- Orca::FileSync.new(self, config).configure
3
+ def file(config, &blk)
4
+ Orca::FileSync.new(self, config, &blk).configure
5
5
  end
6
6
  end
7
7
  end
8
8
 
9
9
  class Orca::FileSync
10
- def initialize(parent, config)
10
+ def initialize(parent, config, &blk)
11
11
  @parent = parent
12
12
  @config = config
13
+ @after_apply = blk
13
14
  raise ArgumentError.new('A file :source must be provided') unless local_path
14
15
  raise ArgumentError.new('A file :destination must be provided') unless remote_path
15
16
  end
@@ -48,6 +49,10 @@ class Orca::FileSync
48
49
  add_permissions_package unless permissions.nil? and user.nil? and group.nil?
49
50
  end
50
51
 
52
+ def run_after_apply(context)
53
+ context.instance_eval(&@after_apply)
54
+ end
55
+
51
56
  def add_content_package
52
57
  fs = self
53
58
  add_package('content') do |package|
@@ -61,6 +66,7 @@ class Orca::FileSync
61
66
  tmp_path = "orca-upload-#{local_file.hash}"
62
67
  local_file.copy_to(remote(tmp_path))
63
68
  sudo("mv #{tmp_path} #{fs.remote_path}")
69
+ fs.run_after_apply(self)
64
70
  end
65
71
 
66
72
  package.command :remove do
@@ -79,6 +85,7 @@ class Orca::FileSync
79
85
  package.command :apply do
80
86
  remote(fs.remote_path).set_owner(fs.user, fs.group) unless fs.user.nil? and fs.group.nil?
81
87
  remote(fs.remote_path).set_permissions(fs.permissions) unless fs.permissions.nil?
88
+ fs.run_after_apply(self)
82
89
  end
83
90
 
84
91
  package.command :validate do
data/lib/orca/node.rb CHANGED
@@ -23,6 +23,14 @@ class Orca::Node
23
23
  Orca::Node.register(self)
24
24
  end
25
25
 
26
+ def get(option)
27
+ @options[option]
28
+ end
29
+
30
+ def method_missing(meth, *args)
31
+ get(meth)
32
+ end
33
+
26
34
  def upload(from, to)
27
35
  log('sftp', "UPLOAD: #{from} => #{to}")
28
36
  sftp.upload!(from, to)
@@ -71,14 +79,25 @@ class Orca::Node
71
79
 
72
80
  def log(context, msg)
73
81
  Thread.exclusive { puts "#{self.to_s} [#{context.to_s.bold}] #{msg}" }
82
+ msg
74
83
  end
75
84
 
76
85
  def connection
77
86
  return @connection if @connection
78
- @connetion = Net::SSH.start(@host, (@options[:user] || 'root'), @options)
87
+ @connetion = Net::SSH.start(@host, (@options[:user] || 'root'), options_for_ssh)
79
88
  end
80
89
 
81
90
  def to_s
82
91
  "#{name}(#{host})"
83
92
  end
93
+
94
+ private
95
+
96
+ def options_for_ssh
97
+ opts = [:auth_methods, :compression, :compression_level, :config, :encryption , :forward_agent , :global_known_hosts_file , :hmac , :host_key , :host_key_alias , :host_name, :kex , :keys , :key_data , :keys_only , :logger , :paranoid , :passphrase , :password , :port , :properties , :proxy , :rekey_blocks_limit , :rekey_limit , :rekey_packet_limit , :timeout , :user , :user_known_hosts_file , :verbose ]
98
+ @options.reduce({}) do |hsh, (k,v)|
99
+ hsh[k] = v if opts.include?(k)
100
+ hsh
101
+ end
102
+ end
84
103
  end
@@ -55,7 +55,7 @@ class Orca::RemoteFile
55
55
  end
56
56
 
57
57
  def delete!
58
- @context.remove(path)
58
+ @context.remove(path) if exists?
59
59
  invalidate!
60
60
  self
61
61
  end
data/lib/orca/runner.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  class Orca::Runner
2
- def initialize(node, package)
2
+ def initialize(node, package, skip_dependancies=false)
3
3
  @node = node
4
4
  @package = package
5
5
  @perform = true
6
+ @skip_dependancies = skip_dependancies
6
7
  end
7
8
 
8
9
  def packages
10
+ return [@package] if @skip_dependancies
9
11
  resolver = Orca::Resolver.new(@package)
10
12
  resolver.resolve
11
13
  resolver.packages
data/lib/orca/suite.rb CHANGED
@@ -3,6 +3,7 @@ class Orca::Suite
3
3
  def initialize(options={})
4
4
  @sequential = options[:sequential]
5
5
  @demonstrate = options[:demonstrate]
6
+ @skip_dependancies = options[:'skip-dependancies'] || false
6
7
  end
7
8
 
8
9
  def load_file(file)
@@ -11,8 +12,14 @@ class Orca::Suite
11
12
 
12
13
  def run(group_name, pkg_name, command, sequential=false)
13
14
  group = Orca::Group.find(group_name)
14
- pkg = Orca::PackageIndex.default.get(pkg_name)
15
- runners = group.nodes.map { |node| Orca::Runner.new(node, pkg) }
15
+ runners = group.nodes.map do |node|
16
+ if command == :trigger
17
+ Orca::TriggerRunner.new(node, pkg_name)
18
+ else
19
+ pkg = Orca::PackageIndex.default.get(pkg_name)
20
+ Orca::Runner.new(node, pkg, @skip_dependancies)
21
+ end
22
+ end
16
23
  if @sequential
17
24
  runners.each {|runner| exec(runner, command) }
18
25
  else
@@ -0,0 +1,14 @@
1
+ class Orca::TriggerRunner
2
+ def initialize(node, action_ref)
3
+ @node = node
4
+ @action_ref = action_ref
5
+ end
6
+
7
+ def execute(_)
8
+ Orca::ExecutionContext.new(@node).trigger(@action_ref)
9
+ end
10
+
11
+ def demonstrate(_)
12
+ Orca::MockExecutionContext.new(@node).trigger(@action_ref)
13
+ end
14
+ end
data/orca.gemspec CHANGED
@@ -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.2.0'
13
+ gem.version = '0.3.0'
14
14
  gem.add_dependency('colored')
15
15
  gem.add_dependency('net-ssh')
16
16
  gem.add_dependency('net-sftp')
@@ -75,9 +75,20 @@ describe Orca::RemoteFile do
75
75
 
76
76
  describe 'delete!' do
77
77
  it "removes the file from the remote server" do
78
+ @context.expects(:run)
79
+ .with(%[if [ -f #{@remote_file_path} ]; then echo "true"; else echo "false"; fi])
80
+ .returns("true\n")
78
81
  @context.expects(:remove).with(@remote_file.path)
79
82
  @remote_file.delete!
80
83
  end
84
+
85
+ it "doesn't delete missing files" do
86
+ @context.expects(:run)
87
+ .with(%[if [ -f #{@remote_file_path} ]; then echo "true"; else echo "false"; fi])
88
+ .returns("false\n")
89
+ @context.expects(:remove).with(@remote_file.path).never
90
+ @remote_file.delete!
91
+ end
81
92
  end
82
93
 
83
94
  describe 'set_permissions' do
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.2.0
4
+ version: 0.3.0
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-24 00:00:00.000000000 Z
12
+ date: 2013-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colored
@@ -107,6 +107,7 @@ files:
107
107
  - lib/orca/resolver.rb
108
108
  - lib/orca/runner.rb
109
109
  - lib/orca/suite.rb
110
+ - lib/orca/trigger_runner.rb
110
111
  - orca.gemspec
111
112
  - test/dsl_test.rb
112
113
  - test/fixtures/example.txt
@@ -131,7 +132,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
132
  version: '0'
132
133
  segments:
133
134
  - 0
134
- hash: 1672503668912245797
135
+ hash: 1540904086341919600
135
136
  required_rubygems_version: !ruby/object:Gem::Requirement
136
137
  none: false
137
138
  requirements:
@@ -140,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  version: '0'
141
142
  segments:
142
143
  - 0
143
- hash: 1672503668912245797
144
+ hash: 1540904086341919600
144
145
  requirements: []
145
146
  rubyforge_project:
146
147
  rubygems_version: 1.8.23