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.
@@ -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