larrow-runner 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +4 -5
- data/larrow-runner.gemspec +0 -3
- data/lib/active_support/core_ext/hash.rb +7 -0
- data/lib/active_support/core_ext/hash/compact.rb +20 -0
- data/lib/active_support/core_ext/hash/deep_merge.rb +38 -0
- data/lib/active_support/core_ext/hash/except.rb +15 -0
- data/lib/active_support/core_ext/hash/indifferent_access.rb +23 -0
- data/lib/active_support/core_ext/hash/keys.rb +162 -0
- data/lib/active_support/core_ext/hash/reverse_merge.rb +22 -0
- data/lib/active_support/core_ext/hash/slice.rb +42 -0
- data/lib/active_support/hash_with_indifferent_access.rb +272 -0
- data/lib/larrow/runner.rb +3 -3
- data/lib/larrow/runner/cli/tools.rb +5 -1
- data/lib/larrow/runner/errors.rb +2 -1
- data/lib/larrow/runner/logger.rb +2 -2
- data/lib/larrow/runner/manager.rb +10 -3
- data/lib/larrow/runner/manifest.rb +15 -4
- data/lib/larrow/runner/manifest/adapter/larrow.rb +28 -26
- data/lib/larrow/runner/manifest/adapter/travis.rb +53 -52
- data/lib/larrow/runner/manifest/base_loader.rb +18 -16
- data/lib/larrow/runner/manifest/configuration.rb +118 -116
- data/lib/larrow/runner/model/app.rb +4 -4
- data/lib/larrow/runner/model/node.rb +56 -56
- data/lib/larrow/runner/service/cloud.rb +10 -4
- data/lib/larrow/runner/session.rb +14 -11
- data/lib/larrow/runner/vcs/base.rb +14 -12
- data/lib/larrow/runner/vcs/github.rb +40 -38
- data/lib/larrow/runner/version.rb +1 -1
- metadata +11 -50
data/lib/larrow/runner.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
1
|
require 'active_support/core_ext/hash'
|
2
|
+
require 'active_support/core_ext/string'
|
3
3
|
|
4
4
|
require "larrow/runner/version"
|
5
5
|
require 'larrow/runner/logger'
|
@@ -18,8 +18,8 @@ module Larrow
|
|
18
18
|
end
|
19
19
|
# global options
|
20
20
|
RunOption = {}.with_indifferent_access
|
21
|
-
#
|
22
|
-
|
21
|
+
# default resource file path
|
22
|
+
ResourcePath = '.larrow.resource'
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -8,7 +8,11 @@ You can save it as .larrow.yml on the project root folder.
|
|
8
8
|
EOF
|
9
9
|
def dump url
|
10
10
|
vcs = Vcs.detect url
|
11
|
-
configuration =
|
11
|
+
configuration = Manifest.configuration(
|
12
|
+
vcs,
|
13
|
+
ignore_base_scripts: true,
|
14
|
+
ignore_larrow: true
|
15
|
+
)
|
12
16
|
puts configuration.dump
|
13
17
|
end
|
14
18
|
|
data/lib/larrow/runner/errors.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
ExecutionError
|
1
|
+
ExecutionError = Class.new StandardError
|
2
|
+
InvalidConfigFile = Class.new StandardError
|
data/lib/larrow/runner/logger.rb
CHANGED
@@ -7,7 +7,7 @@ module Larrow::Runner
|
|
7
7
|
# logger.level(3).title 'hello'
|
8
8
|
# logger.level(3).detail 'hello'
|
9
9
|
class Logger
|
10
|
-
def initialize logger, level:nil, color:'
|
10
|
+
def initialize logger, level:nil, color:'green'
|
11
11
|
@inner_logger = if logger.is_a? ::Logger
|
12
12
|
logger
|
13
13
|
else
|
@@ -44,7 +44,7 @@ module Larrow::Runner
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def detail msg
|
47
|
-
color('
|
47
|
+
color('magenta').info msg
|
48
48
|
end
|
49
49
|
|
50
50
|
def err msg
|
@@ -45,6 +45,11 @@ module Larrow::Runner
|
|
45
45
|
|
46
46
|
def handle_exception
|
47
47
|
yield
|
48
|
+
rescue InvalidConfigFile => e
|
49
|
+
data = eval(e.message)
|
50
|
+
url = "https://github.com/fsword/larrow-runner/wiki/#{data[:wiki]}"
|
51
|
+
RunLogger.err "invalid config file: #{data[:file]}"
|
52
|
+
RunLogger.level(1).err "see: #{url}"
|
48
53
|
rescue => e
|
49
54
|
RunOption[:keep] = true if e.is_a?(ExecutionError)
|
50
55
|
if e.is_a?(ExecutionError) && !debug?
|
@@ -88,7 +93,7 @@ module Larrow::Runner
|
|
88
93
|
|
89
94
|
def self.resource
|
90
95
|
resource_iterator do |clazz, array|
|
91
|
-
RunLogger.
|
96
|
+
RunLogger.info clazz.name.split("::").last
|
92
97
|
clazz.show array, 1
|
93
98
|
end
|
94
99
|
end
|
@@ -101,14 +106,16 @@ module Larrow::Runner
|
|
101
106
|
end
|
102
107
|
|
103
108
|
def self.resource_iterator
|
104
|
-
|
105
|
-
|
109
|
+
RunLogger.title "load resource from #{ResourcePath}"
|
110
|
+
resource = YAML.load(File.read ResourcePath) rescue {}
|
111
|
+
|
106
112
|
resource.each_pair do |k,array|
|
107
113
|
case k
|
108
114
|
when :nodes
|
109
115
|
yield Model::Node, array
|
110
116
|
end
|
111
117
|
end
|
118
|
+
RunLogger.detail "no resource on the file" if resource.empty?
|
112
119
|
end
|
113
120
|
end
|
114
121
|
end
|
@@ -13,11 +13,22 @@ module Larrow
|
|
13
13
|
|
14
14
|
extend self
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
# options:
|
17
|
+
# :ignore_larrow : do not try to use larrow adapter
|
18
|
+
# :ignore_base_scripts : do not merge base scripts
|
19
|
+
def configuration source_accessor, options={}
|
20
|
+
adapters = [Travis, Blank]
|
21
|
+
adapters.unshift Larrow unless options[:ignore_larrow]
|
22
|
+
|
23
|
+
configuration = adapters.each do |clazz|
|
24
|
+
c = clazz.new(source_accessor).load
|
25
|
+
break c if c
|
26
|
+
end
|
27
|
+
|
28
|
+
unless options[:ignore_base_scripts]
|
29
|
+
add_base_scripts(configuration, source_accessor)
|
20
30
|
end
|
31
|
+
configuration
|
21
32
|
end
|
22
33
|
|
23
34
|
def add_base_scripts configuration,source_accessor
|
@@ -1,31 +1,33 @@
|
|
1
|
-
module Larrow::Runner
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
module Larrow::Runner
|
2
|
+
module Manifest
|
3
|
+
class Larrow < BaseLoader
|
4
|
+
def config_file
|
5
|
+
source_accessor.larrow_file || '.larrow.yml'
|
6
|
+
end
|
7
|
+
|
8
|
+
# TODO manifest validation
|
9
|
+
def parse content
|
10
|
+
data = YAML.load(content).with_indifferent_access
|
11
|
+
if data.is_a? Array # stages as a Array
|
12
|
+
# TODO
|
13
|
+
elsif data.is_a? Hash # steps as a Hash
|
14
|
+
configuration.image = data[:image]
|
15
|
+
Configuration::DEFINED_GROUPS[:custom].each do |title|
|
16
|
+
v = data[title]
|
17
|
+
build_step title,v if v
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
|
22
|
+
def build_step title, lines
|
23
|
+
source_dir = if title == :init
|
24
|
+
nil
|
25
|
+
else
|
26
|
+
configuration.source_dir
|
27
|
+
end
|
28
|
+
scripts = lines.map{|s| Script.new s, base_dir: source_dir}
|
29
|
+
configuration.put_to_step title, scripts
|
30
|
+
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -1,43 +1,44 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
-
module Larrow::Runner
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
3
|
+
module Larrow::Runner
|
4
|
+
module Manifest
|
5
|
+
class Travis < BaseLoader
|
6
|
+
CONFIG_FILE='.travis.yml'
|
7
|
+
attr_accessor :data
|
8
|
+
|
9
|
+
def parse content
|
10
|
+
self.data = YAML.load(content).with_indifferent_access
|
11
|
+
build_language
|
12
|
+
map_step :prepare, :before_script
|
13
|
+
map_step :functional_test, :script
|
14
|
+
end
|
15
|
+
|
16
|
+
def map_step title, travis_title
|
17
|
+
source_dir = configuration.source_dir
|
18
|
+
scripts = (data[travis_title] || []).map do |cmd|
|
19
|
+
Script.new cmd, base_dir: source_dir
|
20
|
+
end
|
21
|
+
return nil if scripts.empty?
|
22
|
+
|
23
|
+
configuration.put_to_step title, scripts
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_language
|
27
|
+
return if data[:language].nil?
|
28
|
+
clazz = eval data[:language].camelize
|
29
|
+
clazz.fulfill(data,configuration)
|
19
30
|
end
|
20
|
-
return nil if scripts.empty?
|
21
|
-
|
22
|
-
configuration.put_to_step title, scripts
|
23
|
-
end
|
24
|
-
|
25
|
-
def build_language
|
26
|
-
return if data[:language].nil?
|
27
|
-
clazz = eval data[:language].camelize
|
28
|
-
clazz.fulfill(data,configuration)
|
29
31
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
lines = <<-EOF
|
32
|
+
class Erlang
|
33
|
+
TEMPLATE_PATH='/opt/install/erlang/%s'
|
34
|
+
def self.fulfill data, configuration
|
35
|
+
revision = case data[:otp_release].last
|
36
|
+
when /R15/ then 'R15B03'
|
37
|
+
when /R16/ then 'R16B03'
|
38
|
+
when /17/ then '17.1'
|
39
|
+
end rescue '17'
|
40
|
+
install_dir = sprintf(TEMPLATE_PATH,revision.downcase)
|
41
|
+
lines = <<-EOF
|
41
42
|
echo '-s' >> .curlrc
|
42
43
|
curl https://raw.githubusercontent.com/spawngrid/kerl/master/kerl -o /usr/local/bin/kerl
|
43
44
|
chmod a+x /usr/local/bin/kerl
|
@@ -45,29 +46,29 @@ kerl update releases
|
|
45
46
|
kerl build #{revision} #{revision}
|
46
47
|
kerl install #{revision} #{install_dir}
|
47
48
|
echo 'source #{install_dir}/activate' >> $HOME/.bashrc
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
EOF
|
50
|
+
lines.split(/\n/).each do |line|
|
51
|
+
s = Script.new line
|
52
|
+
configuration.put_to_step :init, s
|
53
|
+
end
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
lines = <<-EOF
|
56
|
+
|
57
|
+
class Ruby
|
58
|
+
def self.fulfill data, configuration
|
59
|
+
return unless data[:rvm] # only rvm is supported for ruby
|
60
|
+
version = data[:rvm].last
|
61
|
+
lines = <<-EOF
|
61
62
|
echo '-s' >> .curlrc
|
62
63
|
curl -sSL https://get.rvm.io | bash -s stable
|
63
64
|
echo 'source /etc/profile.d/rvm.sh' >> .bashrc
|
64
65
|
rvm install #{version}
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
EOF
|
67
|
+
lines.split(/\n/).each do |line|
|
68
|
+
s = Script.new line
|
69
|
+
configuration.put_to_step :init, s
|
70
|
+
end
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
73
|
-
|
@@ -1,21 +1,23 @@
|
|
1
|
-
module Larrow::Runner
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Larrow::Runner
|
2
|
+
module Manifest
|
3
|
+
class BaseLoader
|
4
|
+
attr_accessor :source_accessor,:configuration
|
5
|
+
def initialize source_accessor
|
6
|
+
self.source_accessor = source_accessor
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def load
|
10
|
+
content = source_accessor.get config_file
|
11
|
+
return nil if content.nil?
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
self.configuration = Configuration.new
|
14
|
+
parse content
|
15
|
+
self.configuration
|
16
|
+
end
|
17
|
+
|
18
|
+
def config_file
|
19
|
+
self.class.const_get('CONFIG_FILE')
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
end
|
@@ -1,126 +1,128 @@
|
|
1
|
-
module Larrow::Runner
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
:
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def put_to_step title, *scripts
|
39
|
-
steps[title] ||= CmdStep.new(nil, title)
|
40
|
-
steps[title].scripts += scripts.flatten
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
def insert_to_step title, *scripts
|
45
|
-
steps[title] ||= CmdStep.new(nil, title)
|
46
|
-
steps[title].scripts.unshift *scripts.flatten
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
def add_source_sync source_accessor
|
51
|
-
steps[:source_sync] = FunctionStep.new(:source_sync) do |node|
|
52
|
-
source_accessor.update_source node,source_dir
|
1
|
+
module Larrow::Runner
|
2
|
+
module Manifest
|
3
|
+
# The top of manifest model which store Steps information
|
4
|
+
class Configuration
|
5
|
+
DEFINED_GROUPS = {
|
6
|
+
all:[
|
7
|
+
:init,
|
8
|
+
:source_sync, #inner step
|
9
|
+
:prepare,
|
10
|
+
:compile, :unit_test,
|
11
|
+
:before_install, #inner_step
|
12
|
+
:install, :functional_test,
|
13
|
+
:before_start, #inner_step
|
14
|
+
:start, :integration_test,
|
15
|
+
:after_start, :complete #inner_step
|
16
|
+
],
|
17
|
+
custom: [
|
18
|
+
:init,
|
19
|
+
:prepare,
|
20
|
+
:compile, :unit_test,
|
21
|
+
:install, :functional_test,
|
22
|
+
:start, :integration_test,
|
23
|
+
],
|
24
|
+
deploy: [
|
25
|
+
:init,:source_sync,:prepare,
|
26
|
+
:compile,:before_install,:install,
|
27
|
+
:before_start,:start,:after_start,
|
28
|
+
:complete
|
29
|
+
],
|
30
|
+
image: [:init]
|
31
|
+
}
|
32
|
+
|
33
|
+
attr_accessor :steps, :image, :source_dir
|
34
|
+
def initialize
|
35
|
+
self.steps = {}
|
36
|
+
self.source_dir = '$HOME/source'
|
53
37
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
groups = groups - [:init] if image
|
60
|
-
groups.each do |title|
|
61
|
-
yield steps[title] if steps[title]
|
38
|
+
|
39
|
+
def put_to_step title, *scripts
|
40
|
+
steps[title] ||= CmdStep.new(nil, title)
|
41
|
+
steps[title].scripts += scripts.flatten
|
42
|
+
self
|
62
43
|
end
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
scripts_data = steps[title].scripts.map(&:dump).compact
|
69
|
-
sum.update title.to_s => scripts_data
|
44
|
+
|
45
|
+
def insert_to_step title, *scripts
|
46
|
+
steps[title] ||= CmdStep.new(nil, title)
|
47
|
+
steps[title].scripts.unshift *scripts.flatten
|
48
|
+
self
|
70
49
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
50
|
+
|
51
|
+
def add_source_sync source_accessor
|
52
|
+
steps[:source_sync] = FunctionStep.new(:source_sync) do |node|
|
53
|
+
source_accessor.update_source node,source_dir
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def steps_for type
|
58
|
+
groups = DEFINED_GROUPS[type]
|
59
|
+
# ignore init when image id is specified
|
60
|
+
groups = groups - [:init] if image
|
61
|
+
groups.each do |title|
|
62
|
+
yield steps[title] if steps[title]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def dump
|
67
|
+
data = DEFINED_GROUPS[:all].reduce({}) do |sum,title|
|
68
|
+
next sum if steps[title].nil?
|
69
|
+
scripts_data = steps[title].scripts.map(&:dump).compact
|
70
|
+
sum.update title.to_s => scripts_data
|
71
|
+
end
|
72
|
+
YAML.dump data
|
86
73
|
end
|
87
74
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
block.call node
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# store the real command line
|
107
|
-
# :cannt_fail used to declare `non-zero retcode of current script will be fail`
|
108
|
-
class Script
|
109
|
-
attr_accessor :cmd, :base_dir, :args, :cannt_fail
|
110
|
-
def initialize cmd, base_dir:nil, args:{}, cannt_fail: true
|
111
|
-
self.cmd = cmd
|
112
|
-
self.args = args
|
113
|
-
self.cannt_fail = cannt_fail
|
114
|
-
self.base_dir = base_dir
|
75
|
+
|
76
|
+
# Describe a set of scripts to accomplish a specific goal
|
77
|
+
class CmdStep
|
78
|
+
attr_accessor :scripts, :title
|
79
|
+
def initialize scripts, title
|
80
|
+
self.scripts = scripts || []
|
81
|
+
self.title = title
|
82
|
+
end
|
83
|
+
|
84
|
+
def run_on node
|
85
|
+
scripts.each do |script|
|
86
|
+
node.execute script.actual_command, base_dir: script.base_dir
|
87
|
+
end
|
88
|
+
end
|
115
89
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
90
|
+
|
91
|
+
# An abstract step which bind business logic with block
|
92
|
+
# This class designed for some typically service,eg:
|
93
|
+
# * local file folder sync
|
94
|
+
# * some service invoke
|
95
|
+
class FunctionStep
|
96
|
+
attr_accessor :block, :title
|
97
|
+
def initialize title, &block
|
98
|
+
self.title = title
|
99
|
+
self.block = block
|
100
|
+
end
|
101
|
+
|
102
|
+
def run_on node
|
103
|
+
block.call node
|
104
|
+
end
|
119
105
|
end
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
106
|
+
|
107
|
+
# store the real command line
|
108
|
+
# :cannt_fail used to declare `non-zero retcode of current script will be fail`
|
109
|
+
class Script
|
110
|
+
attr_accessor :cmd, :base_dir, :args, :cannt_fail
|
111
|
+
def initialize cmd, base_dir:nil, args:{}, cannt_fail: true
|
112
|
+
self.cmd = cmd
|
113
|
+
self.args = args
|
114
|
+
self.cannt_fail = cannt_fail
|
115
|
+
self.base_dir = base_dir
|
116
|
+
end
|
117
|
+
|
118
|
+
def actual_command
|
119
|
+
sprintf(cmd, args)
|
120
|
+
end
|
121
|
+
|
122
|
+
def dump
|
123
|
+
return nil if cmd.empty?
|
124
|
+
cmd
|
125
|
+
end
|
124
126
|
end
|
125
127
|
end
|
126
128
|
end
|