canzea 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.idea/compiler.xml +22 -0
- data/.idea/copyright/profiles_settings.xml +3 -0
- data/.idea/misc.xml +39 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +10 -0
- data/bin/canzea +6 -0
- data/bin/setup +8 -0
- data/canzea.gemspec +35 -0
- data/cli.iml +9 -0
- data/lib/canzea/config.rb +23 -0
- data/lib/canzea/version.rb +3 -0
- data/lib/canzea.rb +123 -0
- data/lib/commands/config-git-commit.rb +38 -0
- data/lib/commands/get-catalog.rb +17 -0
- data/lib/commands/remote-run.rb +12 -0
- data/lib/helper-run-class.rb +53 -0
- data/lib/plan-step-class.rb +136 -0
- data/lib/prepare-environment.rb +121 -0
- data/lib/registry.rb +120 -0
- data/lib/ssh-base-cmd-class.rb +72 -0
- data/lib/template-runner.rb +37 -0
- data/lib/trace-component.rb +177 -0
- data/lib/trace-runner.rb +139 -0
- metadata +201 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'logger'
|
3
|
+
require 'trace-component'
|
4
|
+
require 'helper-run-class'
|
5
|
+
|
6
|
+
class PlanStep
|
7
|
+
def runPhaseInstall (role, solution, test, task)
|
8
|
+
|
9
|
+
log = Logger.new(Canzea::config[:logging_root] + '/plans.log')
|
10
|
+
|
11
|
+
# ruby plan.rb <plan description> <test run> <start>
|
12
|
+
|
13
|
+
plan = JSON.parse("{ \"plan\": [ { \"role\": \"#{role}\", \"solution\": \"#{solution}\" } ] }")
|
14
|
+
|
15
|
+
n = Worker.new
|
16
|
+
|
17
|
+
|
18
|
+
n.test ( test )
|
19
|
+
|
20
|
+
start = Integer(task)
|
21
|
+
lines = 1
|
22
|
+
|
23
|
+
cmd = "TBD"
|
24
|
+
|
25
|
+
|
26
|
+
begin
|
27
|
+
|
28
|
+
plan['plan'].each do |item|
|
29
|
+
log.info(item['solution'])
|
30
|
+
|
31
|
+
root = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}"
|
32
|
+
if File.exist?(root) == false
|
33
|
+
puts "-- ERROR #{root} does not exist!"
|
34
|
+
raise "#{root} does not exist!"
|
35
|
+
end
|
36
|
+
|
37
|
+
cmd = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/install.sh"
|
38
|
+
|
39
|
+
if File.exist?(cmd)
|
40
|
+
lines = n.run cmd, start, lines - 1
|
41
|
+
|
42
|
+
log.info "#{ lines } lines read"
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
rescue => exception
|
48
|
+
log.error(cmd)
|
49
|
+
log.error(exception.to_s)
|
50
|
+
log.error(exception.backtrace)
|
51
|
+
abort()
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def runPhaseConfigure (role, solution, test, task)
|
56
|
+
|
57
|
+
log = Logger.new(Dir.home() + '/plans.log')
|
58
|
+
|
59
|
+
# ruby plan.rb <plan description> <test run> <start>
|
60
|
+
|
61
|
+
plan = JSON.parse("{ \"plan\": [ { \"role\": \"#{role}\", \"solution\": \"#{solution}\" } ] }")
|
62
|
+
|
63
|
+
n = Worker.new
|
64
|
+
|
65
|
+
|
66
|
+
n.test ( test )
|
67
|
+
|
68
|
+
start = Integer(task)
|
69
|
+
lines = 1
|
70
|
+
|
71
|
+
cmd = "TBD"
|
72
|
+
|
73
|
+
|
74
|
+
begin
|
75
|
+
|
76
|
+
plan['plan'].each do |item|
|
77
|
+
log.info(item['solution'])
|
78
|
+
|
79
|
+
root = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}"
|
80
|
+
if File.exist?(root) == false
|
81
|
+
puts "-- ERROR #{root} does not exist!"
|
82
|
+
raise "#{root} does not exist!"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Register the service with Consul, if consul is ready
|
86
|
+
# If metadata.json exists, then use the information to register
|
87
|
+
cmd = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/metadata.json"
|
88
|
+
if File.exist?(cmd)
|
89
|
+
md = File.read(cmd)
|
90
|
+
md = JSON.parse(md)
|
91
|
+
if (md['services'].size() > 0)
|
92
|
+
svc = md['services'][0]
|
93
|
+
adef = {"listener"=>svc['listener'], "serviceName"=>svc['name'], "tags"=>{}, "port"=>svc['port']}
|
94
|
+
h = HelperRun.new
|
95
|
+
h.run "consul", "add_service", JSON.generate(adef)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
envScript = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/environment.json"
|
100
|
+
if File.exist?(envScript)
|
101
|
+
require_relative '../init/prepare_environment'
|
102
|
+
|
103
|
+
envPush = PrepareEnvironment.new
|
104
|
+
envPush.addToEnv "#{envScript}"
|
105
|
+
end
|
106
|
+
|
107
|
+
cmd = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/configure.sh"
|
108
|
+
if File.exist?(cmd)
|
109
|
+
lines = n.run cmd, start, lines - 1
|
110
|
+
|
111
|
+
log.info("#{ lines } lines read")
|
112
|
+
end
|
113
|
+
|
114
|
+
cmd = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/enable.sh"
|
115
|
+
if File.exist?(cmd)
|
116
|
+
lines = n.run cmd, start, lines - 1
|
117
|
+
|
118
|
+
log.info("#{ lines } lines read")
|
119
|
+
end
|
120
|
+
|
121
|
+
cmd = ENV['CANZEA_PLUGINS'] + "ike-environments/environment/production/roles/#{item['role']}/#{item['solution']}/status.sh"
|
122
|
+
if File.exist?(cmd)
|
123
|
+
lines = n.run cmd, start, lines - 1, true
|
124
|
+
|
125
|
+
log.info("#{ lines } lines read")
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
rescue => exception
|
130
|
+
log.error(cmd)
|
131
|
+
log.error(exception.to_s)
|
132
|
+
log.error(exception.backtrace)
|
133
|
+
abort()
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'logger'
|
3
|
+
require 'net/http'
|
4
|
+
require "trace-runner"
|
5
|
+
require "registry"
|
6
|
+
|
7
|
+
|
8
|
+
class PrepareEnvironment
|
9
|
+
|
10
|
+
def addToEnv (envFile)
|
11
|
+
log = Logger.new(Canzea::config[:logging_root] + '/plans.log')
|
12
|
+
|
13
|
+
r = Registry.new
|
14
|
+
|
15
|
+
# ENV["ENV_CONFIG"] instead of a file
|
16
|
+
file = File.read(envFile)
|
17
|
+
|
18
|
+
serviceLookups = JSON.parse(file)
|
19
|
+
|
20
|
+
serviceLookups['keyvalues'].each do |svc|
|
21
|
+
|
22
|
+
log.info("Looking up...#{svc['name']}")
|
23
|
+
|
24
|
+
s = r.getKeyValue(svc['name'])
|
25
|
+
|
26
|
+
if (s.nil? == false)
|
27
|
+
# puts s
|
28
|
+
|
29
|
+
key = "" + svc['name'].upcase
|
30
|
+
key = key.gsub(/\./, '').gsub(/-/, '_').gsub(/\//, '_')
|
31
|
+
log.info("Setting: " + key + " : " + s)
|
32
|
+
ENV.store(key, s)
|
33
|
+
else
|
34
|
+
log.warn("KEY VALUE NOT FOUND! " + svc['name'])
|
35
|
+
puts "-- KEY VALUE NOT FOUND! " + svc['name']
|
36
|
+
abort()
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
serviceLookups['services'].each do |svc|
|
42
|
+
|
43
|
+
puts "Looking up...#{svc['name']}"
|
44
|
+
|
45
|
+
url = ENV["CONSUL_URL"] + '/v1/catalog/service/' + svc['name']
|
46
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
47
|
+
service = JSON.parse(resp.body)
|
48
|
+
|
49
|
+
# s = r.getValue(svc['name'], "publicIp")
|
50
|
+
|
51
|
+
s = service[0]
|
52
|
+
if (s.nil? == false)
|
53
|
+
# puts s
|
54
|
+
|
55
|
+
key = "" + svc['name'].upcase + "_ADDRESS"
|
56
|
+
key = key.gsub(/\./, '')
|
57
|
+
log.info("Setting: " + key + " : " + s["ServiceAddress"])
|
58
|
+
ENV.store(key, s["ServiceAddress"])
|
59
|
+
|
60
|
+
key = "" + svc['name'].upcase + "_PORT"
|
61
|
+
key = key.gsub(/\./, '')
|
62
|
+
log.info("Setting: " + key + " : " + String(s["ServicePort"]))
|
63
|
+
ENV.store(key, String(s["ServicePort"]))
|
64
|
+
|
65
|
+
key = "" + svc['name'].upcase + "_URL"
|
66
|
+
key = key.gsub(/\./, '')
|
67
|
+
val = "http://" + s["ServiceAddress"] + ":" + String(s["ServicePort"])
|
68
|
+
log.info("Setting: " + key + " : " + val)
|
69
|
+
ENV.store(key, val)
|
70
|
+
|
71
|
+
else
|
72
|
+
log.warn("SERVICE NOT FOUND! " + svc['name'])
|
73
|
+
puts "-- SERVICE NOT FOUND! " + svc['name']
|
74
|
+
abort()
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
serviceLookups['secrets'].each do |svc|
|
79
|
+
|
80
|
+
# puts "Looking up secret...#{svc['name']}"
|
81
|
+
|
82
|
+
url = URI(ENV['VAULT_URL'] + '/v1/secret/' + svc['name'])
|
83
|
+
|
84
|
+
req = Net::HTTP::Get.new(url)
|
85
|
+
req['X-Vault-Token'] = ENV["VAULT_TOKEN"]
|
86
|
+
req['Content-type'] = 'application/json'
|
87
|
+
|
88
|
+
resp = Net::HTTP.start(url.hostname, url.port) {|http|
|
89
|
+
http.request(req)
|
90
|
+
}
|
91
|
+
# puts resp.body
|
92
|
+
|
93
|
+
if (Integer(resp.code) == 200)
|
94
|
+
|
95
|
+
data = JSON.parse(resp.body)
|
96
|
+
|
97
|
+
s = data['data']
|
98
|
+
s.each do |k|
|
99
|
+
key = "" + svc['name'].upcase + "_" + k[0].upcase
|
100
|
+
key = key.gsub(/\./, '').gsub(/-/, '_').gsub(/\//, '_')
|
101
|
+
|
102
|
+
log.info("Setting: " + key)
|
103
|
+
ENV.store(key, k[1])
|
104
|
+
end
|
105
|
+
else
|
106
|
+
log.warn( "SECRET NOT FOUND! " + svc['name'])
|
107
|
+
log.warn( "ERROR FROM VAULT " + resp.body)
|
108
|
+
puts "-- SECRET NOT FOUND! " + svc['name']
|
109
|
+
puts "-- ERROR FROM VAULT " + resp.body
|
110
|
+
abort()
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
def print ()
|
117
|
+
ENV.each_pair { |name,value|
|
118
|
+
puts name + " = " + value
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
data/lib/registry.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'patron'
|
2
|
+
require 'json'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
class Registry
|
6
|
+
|
7
|
+
def getKeyValue (key)
|
8
|
+
|
9
|
+
sess = Patron::Session.new do |patron|
|
10
|
+
patron.timeout = 10
|
11
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
12
|
+
# patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
13
|
+
end
|
14
|
+
|
15
|
+
#sess.enable_debug
|
16
|
+
resp = sess.get("/#{key}")
|
17
|
+
|
18
|
+
# puts resp.body
|
19
|
+
|
20
|
+
if resp.status != 200
|
21
|
+
abort("problem #{resp.status_line}")
|
22
|
+
end
|
23
|
+
|
24
|
+
result = JSON.parse(resp.body)
|
25
|
+
return Base64.decode64(result[0]["Value"])
|
26
|
+
end
|
27
|
+
|
28
|
+
def getValue (root, key)
|
29
|
+
|
30
|
+
sess = Patron::Session.new do |patron|
|
31
|
+
patron.timeout = 10
|
32
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
33
|
+
# patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
34
|
+
end
|
35
|
+
|
36
|
+
#sess.enable_debug
|
37
|
+
resp = sess.get("/#{root}/#{key}")
|
38
|
+
|
39
|
+
# puts resp.body
|
40
|
+
|
41
|
+
if resp.status != 200
|
42
|
+
abort("problem #{resp.status_line}")
|
43
|
+
end
|
44
|
+
|
45
|
+
result = JSON.parse(resp.body)
|
46
|
+
return Base64.decode64(result[0]["Value"])
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def exists (root)
|
51
|
+
|
52
|
+
sess = Patron::Session.new do |patron|
|
53
|
+
patron.timeout = 10
|
54
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
55
|
+
patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
56
|
+
end
|
57
|
+
|
58
|
+
# sess.enable_debug
|
59
|
+
resp = sess.get("/#{root}")
|
60
|
+
puts resp.body
|
61
|
+
|
62
|
+
if resp.status == 200
|
63
|
+
abort("problem #{resp.status_line}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def deleteDirectory (root)
|
68
|
+
|
69
|
+
sess = Patron::Session.new do |patron|
|
70
|
+
patron.timeout = 10
|
71
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
72
|
+
patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
73
|
+
end
|
74
|
+
|
75
|
+
# sess.enable_debug
|
76
|
+
resp = sess.delete("/#{root}?&recurse=true")
|
77
|
+
puts resp.body
|
78
|
+
|
79
|
+
if resp.status != 200
|
80
|
+
abort("problem #{resp.status_line}")
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def registerDirectory (root)
|
86
|
+
|
87
|
+
sess = Patron::Session.new do |patron|
|
88
|
+
patron.timeout = 10
|
89
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
90
|
+
patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
91
|
+
end
|
92
|
+
|
93
|
+
# sess.enable_debug
|
94
|
+
resp = sess.put("/#{root}?dir=true", "")
|
95
|
+
puts resp.body
|
96
|
+
|
97
|
+
if resp.status > 202
|
98
|
+
abort("problem #{resp.status_line}")
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def register (root, key, value)
|
104
|
+
|
105
|
+
sess = Patron::Session.new do |patron|
|
106
|
+
patron.timeout = 10
|
107
|
+
patron.base_url = ENV["CONSUL_URL"] + '/v1/kv'
|
108
|
+
patron.headers = {'User-Agent' => 'IKE-Registry/1.0'}
|
109
|
+
end
|
110
|
+
|
111
|
+
#sess.enable_debug
|
112
|
+
resp = sess.put("/#{root}/#{key}", "#{value}")
|
113
|
+
puts resp.body
|
114
|
+
|
115
|
+
if resp.status > 202
|
116
|
+
abort("problem #{resp.status_line}")
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# canzea --role=operatingsystem --solution=centos --remote --hostname=192.34.56.119 --privateKey=/var/go/.ssh/id_rsa_digitalocean
|
2
|
+
|
3
|
+
require 'net/ssh'
|
4
|
+
require 'net/sftp'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
class RemoteCall
|
8
|
+
def init (hostname, privateKey)
|
9
|
+
cmd1 = "yum -y install git"
|
10
|
+
|
11
|
+
cmd2 = "(rm -rf ike-environments && git clone https://IKE_CI:55665566@gitlab.com/ikethecoder/ike-environments.git)"
|
12
|
+
|
13
|
+
cmd3 = 'find /root/ike-environments -name "*.sh" -exec chmod +x {} +'
|
14
|
+
|
15
|
+
cmd4 = '(cd /root/ike-environments/environment/production && ./roles/workarounds/ruby/install.sh)'
|
16
|
+
cmd5 = '(cd /root/ike-environments/environment/production && ./roles/workarounds/ruby-gems/install.sh)'
|
17
|
+
cmd6 = '(cd /root/ike-environments/environment/production && ./roles/workarounds/sshd/configure.sh)'
|
18
|
+
cmd7 = '(cd /root/ike-environments/environment/production && ./roles/workarounds/sshd/enable.sh)'
|
19
|
+
cmd8 = '(cd /root/ike-environments/environment/production && ./roles/workarounds/canzea/install-root.sh)'
|
20
|
+
|
21
|
+
exec hostname, privateKey, cmd1
|
22
|
+
exec hostname, privateKey, cmd2
|
23
|
+
exec hostname, privateKey, cmd3
|
24
|
+
exec hostname, privateKey, cmd4
|
25
|
+
exec hostname, privateKey, cmd5
|
26
|
+
exec hostname, privateKey, cmd6
|
27
|
+
exec hostname, privateKey, cmd7
|
28
|
+
exec hostname, privateKey, cmd8
|
29
|
+
end
|
30
|
+
|
31
|
+
def run (hostname, privateKey, cmd)
|
32
|
+
@cmd = ". .bash_profile && cd .local/bin/ike-environments/environment/production && #{cmd}"
|
33
|
+
exec hostname, privateKey, @cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
def exec (hostname, privateKey, cmd)
|
37
|
+
|
38
|
+
@username = "root"
|
39
|
+
|
40
|
+
Net::SSH.start(hostname, @username, :paranoid => false, :keys => [privateKey]) do |ssh|
|
41
|
+
|
42
|
+
chan = ssh.open_channel do |channel|
|
43
|
+
channel[:data] = ""
|
44
|
+
channel.request_pty
|
45
|
+
channel.env("DIGITAL_OCEAN_API_KEY", ENV['DIGITAL_OCEAN_API_KEY'])
|
46
|
+
channel.env("VAULT_TOKEN", ENV['VAULT_TOKEN'])
|
47
|
+
channel.env("CONSUL_URL", ENV['CONSUL_URL'])
|
48
|
+
channel.env("WORK_DIR", ENV['WORK_DIR'])
|
49
|
+
channel.exec(cmd) do |ch, success|
|
50
|
+
abort "could not execute command" unless success
|
51
|
+
|
52
|
+
channel.on_data do |ch, data|
|
53
|
+
channel[:data] << data
|
54
|
+
end
|
55
|
+
|
56
|
+
channel.on_request("exit-status") do |ch, data|
|
57
|
+
exit_code = data.read_long
|
58
|
+
if (exit_code == 0)
|
59
|
+
else
|
60
|
+
abort(channel[:data])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
channel.on_close do |ch|
|
65
|
+
puts channel[:data]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
chan.wait
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'mustache'
|
3
|
+
|
4
|
+
class Template < Mustache
|
5
|
+
def processAndWriteToFile (template, output, parameters)
|
6
|
+
contents = process template, parameters
|
7
|
+
File.write(output, contents)
|
8
|
+
end
|
9
|
+
|
10
|
+
def process (template, parameters)
|
11
|
+
self.template_file = template
|
12
|
+
ENV.each_pair do |k, v|
|
13
|
+
self[k] = v
|
14
|
+
end
|
15
|
+
parameters.each_pair do |k, v|
|
16
|
+
self[k] = v
|
17
|
+
end
|
18
|
+
return self.render
|
19
|
+
end
|
20
|
+
|
21
|
+
def processString (string, parameters)
|
22
|
+
self.template = string
|
23
|
+
ENV.each_pair do |k, v|
|
24
|
+
self[k] = v
|
25
|
+
end
|
26
|
+
parameters.each_pair do |k, v|
|
27
|
+
self[k] = v
|
28
|
+
end
|
29
|
+
return self.render
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# t = Template.new
|
34
|
+
|
35
|
+
# t.process ARGV[0], ARGV[1], JSON.parse(ARGV[2])
|
36
|
+
|
37
|
+
# puts "Wrote to #{ARGV[1]}"
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open3'
|
3
|
+
require 'stringio'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# Optionally can specify the command to continue from
|
7
|
+
# Exit on first failure
|
8
|
+
#
|
9
|
+
def time_diff_milli(start, finish)
|
10
|
+
(finish - start) * 1000.0
|
11
|
+
end
|
12
|
+
|
13
|
+
def handleIO(stillOpen, ioArray, io, log)
|
14
|
+
if ioArray.include?(io)
|
15
|
+
begin
|
16
|
+
log.write(io.readpartial(4096))
|
17
|
+
rescue EOFError
|
18
|
+
stillOpen.delete_if{|s| s == io}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
class Audit
|
25
|
+
def start (id, cmd)
|
26
|
+
self.log( id, cmd, "start", "", 0, "")
|
27
|
+
end
|
28
|
+
|
29
|
+
def complete (id, cmd, status, msecs, result)
|
30
|
+
self.log( id, cmd, "complete", status, msecs, result)
|
31
|
+
end
|
32
|
+
|
33
|
+
def status (id, cmd, status, msecs, result)
|
34
|
+
data = {
|
35
|
+
"message" => {
|
36
|
+
"id" => id,
|
37
|
+
"cmd" => cmd,
|
38
|
+
"task" => "status",
|
39
|
+
"status" => status,
|
40
|
+
"elapsed" => msecs,
|
41
|
+
"result" => result
|
42
|
+
}
|
43
|
+
}
|
44
|
+
puts data.to_json
|
45
|
+
File.open(Canzea::config[:logging_root] + '/audit.log', 'a') { |file| file.puts(data.to_json) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def log (id, cmd, task, status, msecs, result)
|
49
|
+
data = {
|
50
|
+
"message" => {
|
51
|
+
"id" => id,
|
52
|
+
"cmd" => cmd,
|
53
|
+
"task" => task,
|
54
|
+
"status" => status,
|
55
|
+
"elapsed" => msecs,
|
56
|
+
"result" => result
|
57
|
+
}
|
58
|
+
}
|
59
|
+
summary = {
|
60
|
+
"message" => {
|
61
|
+
"id" => id,
|
62
|
+
"cmd" => cmd,
|
63
|
+
"task" => task,
|
64
|
+
"status" => status,
|
65
|
+
"elapsed" => msecs
|
66
|
+
}
|
67
|
+
}
|
68
|
+
puts summary.to_json
|
69
|
+
File.open(Canzea::config[:logging_root] + '/audit.log', 'a') { |file| file.puts(data.to_json) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class ManagedError < StandardError
|
74
|
+
end
|
75
|
+
|
76
|
+
class Worker
|
77
|
+
@test = false
|
78
|
+
|
79
|
+
|
80
|
+
def test (t)
|
81
|
+
@test = t
|
82
|
+
end
|
83
|
+
|
84
|
+
def run(command, start, lines, statusIndicator = false )
|
85
|
+
audit = Audit.new
|
86
|
+
|
87
|
+
log = Logger.new(Canzea::config[:logging_root] + '/plans.log')
|
88
|
+
|
89
|
+
log.info("HANDLING: " + command)
|
90
|
+
|
91
|
+
File.foreach(command) { |l|
|
92
|
+
if ( l.start_with?('## ') )
|
93
|
+
log.info "#{lines + 1} Label: " + l
|
94
|
+
elsif ( l.start_with?('#') )
|
95
|
+
elsif ( /\S/ !~ l )
|
96
|
+
elsif ( l.chomp.end_with?(".sh") && !l.chomp.end_with?(".atomic.sh") && !l.include?("cp ") && !l.include?("chmod") )
|
97
|
+
log.info("#{lines + 1} RECURSE: " + l)
|
98
|
+
|
99
|
+
lines = run l.chomp, start, lines
|
100
|
+
else
|
101
|
+
|
102
|
+
if ( (lines + 1) < start )
|
103
|
+
log.info("Skipping : #{lines + 1} #{l}")
|
104
|
+
lines += 1
|
105
|
+
next
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
audit.start( "#{lines + 1 }", l.chomp)
|
110
|
+
|
111
|
+
log.info("#{lines + 1} FOUND: " + l)
|
112
|
+
|
113
|
+
if @test == false
|
114
|
+
t1 = Time.now
|
115
|
+
|
116
|
+
begin
|
117
|
+
puts "-- Executing: #{l}"
|
118
|
+
Open3.popen3(l) {|stdin, stdout, stderr, wait_thr|
|
119
|
+
pid = wait_thr.pid # pid of the started process.
|
120
|
+
|
121
|
+
log_w = StringIO.new
|
122
|
+
|
123
|
+
stillOpen = [stdout, stderr]
|
124
|
+
while !stillOpen.empty?
|
125
|
+
fhs = select(stillOpen, nil, nil, nil)
|
126
|
+
handleIO(stillOpen, fhs[0], stdout, log_w)
|
127
|
+
handleIO(stillOpen, fhs[0], stderr, log_w)
|
128
|
+
end
|
129
|
+
|
130
|
+
exit_status = wait_thr.value # wait for it to finish
|
131
|
+
|
132
|
+
log_w.close_write
|
133
|
+
|
134
|
+
output = log_w.string
|
135
|
+
|
136
|
+
output.split(/\n/).each do | line |
|
137
|
+
puts "-- #{line}"
|
138
|
+
end
|
139
|
+
puts "-- Exit Status = #{exit_status}"
|
140
|
+
|
141
|
+
log.info("STDOUT #{output}")
|
142
|
+
|
143
|
+
log.info("Exit Status = #{exit_status}")
|
144
|
+
|
145
|
+
# if exit status is failure then exit right away
|
146
|
+
|
147
|
+
t2 = Time.now
|
148
|
+
|
149
|
+
msecs = time_diff_milli t1, t2
|
150
|
+
|
151
|
+
audit.complete("#{lines + 1}", l.chomp, exit_status.exitstatus, msecs, output)
|
152
|
+
|
153
|
+
if (statusIndicator)
|
154
|
+
audit.status("#{lines + 1}", l.chomp, exit_status.exitstatus, msecs, output)
|
155
|
+
end
|
156
|
+
|
157
|
+
if exit_status.exitstatus != 0
|
158
|
+
abort()
|
159
|
+
end
|
160
|
+
}
|
161
|
+
rescue => exception
|
162
|
+
msecs = time_diff_milli t1, Time.now
|
163
|
+
audit.complete("#{lines + 1}", l.chomp, "-1", msecs, exception.to_s)
|
164
|
+
raise
|
165
|
+
end
|
166
|
+
else
|
167
|
+
puts "-- TEST -- [#{lines + 1}] FOUND: " + l
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
lines += 1
|
173
|
+
}
|
174
|
+
return lines
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|