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 +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
|