orca 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +12 -1
- data/lib/orca.rb +1 -0
- data/lib/orca/cli.rb +6 -0
- data/lib/orca/execution_context.rb +17 -1
- data/lib/orca/extensions/file_sync.rb +10 -3
- data/lib/orca/node.rb +20 -1
- data/lib/orca/remote_file.rb +1 -1
- data/lib/orca/runner.rb +3 -1
- data/lib/orca/suite.rb +9 -2
- data/lib/orca/trigger_runner.rb +14 -0
- data/orca.gemspec +1 -1
- data/test/remote_file_test.rb +11 -0
- metadata +5 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
orca (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
|
-
|
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
|
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'),
|
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
|
data/lib/orca/remote_file.rb
CHANGED
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
|
-
|
15
|
-
|
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.
|
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')
|
data/test/remote_file_test.rb
CHANGED
@@ -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.
|
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-
|
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:
|
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:
|
144
|
+
hash: 1540904086341919600
|
144
145
|
requirements: []
|
145
146
|
rubyforge_project:
|
146
147
|
rubygems_version: 1.8.23
|