chloride 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of chloride might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6de9d1474d03d7012ae1831c35e9a9c572d5117f
4
- data.tar.gz: 592bb951a691a867845ba875d918299cb397e5b7
3
+ metadata.gz: 4745a7cd2b20421818ebf6baf24deed96fca4f72
4
+ data.tar.gz: caf69fb1a91510985ac7cef32ec93304086ba7b6
5
5
  SHA512:
6
- metadata.gz: 191910b3180eaa360b524e90800fac5586c07bb7b63f095ee24f030cc30fb8dbfc20403edcf4b83d52a0b5f6d0d9a0aab63570544b9ec8f5acc35c0c938543ab
7
- data.tar.gz: a2fc72c58079d8829a36606be4612de5818c04efa1f22ca6b1446b758d8a95cb3f96b35df9859216b0e4ce9b153fc2d08fc877a7e6891d22d69c5d790e5fd858
6
+ metadata.gz: 39ca494f094616cbb357d7416e5751aaaa8452b6518187005fd81ac82264dcf74cf02918ae8a62c9a038cc58c9adbbcef8efd992b0ce2d1c42e4c735bbcaa3d5
7
+ data.tar.gz: ee6bc7998b0534ebd52f888e488d26c1d666d6bea4fa852a571581c4494008224bfef08870c027847b58016fe2c393ced62a5737e20f6b210901c472a2c15e05
data/.rubocop.yml CHANGED
@@ -50,13 +50,18 @@ Lint/Void:
50
50
 
51
51
  # Offense count: 6
52
52
  Metrics/AbcSize:
53
+ Enabled: false
53
54
  Max: 70
54
55
 
55
56
  # Offense count: 4
56
57
  # Configuration parameters: CountComments.
57
58
  Metrics/BlockLength:
59
+ Enabled: false
58
60
  Max: 45
59
61
 
62
+ Metrics/BlockNesting:
63
+ Max: 4
64
+
60
65
  # Offense count: 1
61
66
  # Configuration parameters: CountComments.
62
67
  Metrics/ClassLength:
@@ -64,6 +69,7 @@ Metrics/ClassLength:
64
69
 
65
70
  # Offense count: 2
66
71
  Metrics/CyclomaticComplexity:
72
+ Enabled: false
67
73
  Max: 20
68
74
 
69
75
  # Offense count: 90
@@ -75,10 +81,12 @@ Metrics/LineLength:
75
81
  # Offense count: 10
76
82
  # Configuration parameters: CountComments.
77
83
  Metrics/MethodLength:
84
+ Enabled: false
78
85
  Max: 89
79
86
 
80
87
  # Offense count: 2
81
88
  Metrics/PerceivedComplexity:
89
+ Enabled: false
82
90
  Max: 23
83
91
 
84
92
  # Offense count: 10
@@ -119,6 +127,7 @@ Style/BracesAroundHashParameters:
119
127
  # Configuration parameters: EnforcedStyle, SupportedStyles.
120
128
  # SupportedStyles: nested, compact
121
129
  Style/ClassAndModuleChildren:
130
+ Enabled: false
122
131
  Exclude:
123
132
  - 'lib/chloride/action/execute.rb'
124
133
  - 'lib/chloride/action/file_copy.rb'
@@ -154,7 +163,10 @@ Style/Documentation:
154
163
  - 'lib/chloride/errors.rb'
155
164
  - 'lib/chloride/event.rb'
156
165
  - 'lib/chloride/event/message.rb'
166
+ - 'lib/chloride/executor.rb'
157
167
  - 'lib/chloride/host.rb'
168
+ - 'lib/chloride/step.rb'
169
+ - 'lib/chloride/step/noop.rb'
158
170
 
159
171
  # Cop supports --auto-correct.
160
172
  Style/EmptyLines:
@@ -0,0 +1,235 @@
1
+ require 'chloride/errors'
2
+ require 'chloride/action'
3
+
4
+ # Executes a shell command on the hosts provided. Will block until completion.
5
+ class Chloride::Action::DetectPlatform < Chloride::Action
6
+ attr_reader :results, :hosts
7
+
8
+ # TODO: Document args
9
+ def initialize(args)
10
+ super
11
+
12
+ @hosts = args[:hosts] || [args[:host]]
13
+ end
14
+
15
+ # TODO: Document block format
16
+ def go(&stream_block)
17
+ @status = :running
18
+ @results = Hash.new { |h, k| h[k] = {} }
19
+ @hosts.each do |host|
20
+ # First try identifying using lsb_release. This takes care of Ubuntu (lsb-release is part of ubuntu-minimal).
21
+ lsb = exec_and_log(host, 'lsb_release -icr', true, @results[host.hostname], &stream_block)
22
+
23
+ if (lsb[:exit_status]).zero?
24
+ lsb_data = {}
25
+ lsb[:stdout].each_line do |l|
26
+ k, v = l.split(':')
27
+ lsb_data[k.strip] = v.strip if k && v
28
+ end
29
+
30
+ distribution = lsb_data['Distributor ID'].downcase.gsub(/\s+/, '')
31
+ distribution = case distribution
32
+ when /redhatenterpriseserver|redhatenterpriseclient|redhatenterpriseas|redhatenterprisees|enterpriseenterpriseserver|redhatenterpriseworkstation|redhatenterprisecomputenode|oracleserver/
33
+ :rhel
34
+ when /enterprise.*/
35
+ :centos
36
+ when /scientific|scientifics|scientificsl/
37
+ :rhel
38
+ when /amazonami/
39
+ :amazon
40
+ when /suselinux/
41
+ :sles
42
+ else
43
+ distribution.to_sym
44
+ end
45
+
46
+ release = lsb_data['Release'].gsub(/\s+/, '')
47
+ release = case distribution
48
+ when :centos, :rhel
49
+ release.split('.')[0]
50
+ when :debian
51
+ if release == 'testing'
52
+ '7'
53
+ else
54
+ release.split('.')[0]
55
+ end
56
+ else
57
+ release
58
+ end
59
+ end
60
+
61
+ # Check for Redhat
62
+ if !distribution && !release
63
+ redhat_release = exec_and_log(host, 'cat /etc/redhat-release', true, @results[host.hostname], &stream_block)
64
+
65
+ if (redhat_release[:exit_status]).zero?
66
+ stdout = redhat_release[:stdout]
67
+
68
+ distribution = case stdout
69
+ when /red hat enterprise/im
70
+ :rhel
71
+ when /centos/im
72
+ :centos
73
+ when /scientific/im
74
+ :rhel
75
+ end
76
+
77
+ release = /.* release ([[:digit:]]).*/.match(stdout)[1]
78
+ end
79
+ end
80
+
81
+ # Check for Cumulus
82
+ if !distribution && !release
83
+ os_release = exec_and_log(host, 'cat /etc/os-release', true, @results[host.hostname], &stream_block)
84
+
85
+ if (os_release[:exit_status]).zero?
86
+ stdout = os_release[:stdout]
87
+
88
+ distribution = :cumulus if /Cumulus Linux/m =~ stdout
89
+ release = /VERSION_ID=(\d+\.\d)/.match(stdout)[1] if distribution
90
+ end
91
+ end
92
+
93
+ # Check for EOS
94
+ if !distribution && !release
95
+ eos_release = exec_and_log(host, 'cat /etc/Eos-release', true, @results[host.hostname], &stream_block)
96
+
97
+ if (eos_release[:exit_status]).zero?
98
+ stdout = eos_release[:stdout]
99
+
100
+ distribution = :eos if /Arista Networks EOS/m =~ stdout
101
+
102
+ release = /^Arista Networks EOS v*(.*)\..*$/.match(stdout)[1]
103
+ end
104
+ end
105
+
106
+ # Check for Debian
107
+ if !distribution && !release
108
+ debian_version = exec_and_log(host, 'cat /etc/debian_version', true, @results[host.hostname], &stream_block)
109
+
110
+ if (debian_version[:exit_status]).zero?
111
+ stdout = debian_version[:stdout]
112
+ distribution = :debian
113
+
114
+ release = case stdout
115
+ when /^[[:digit:]]/
116
+ stdout.split('.')[0]
117
+ when /^wheezy/.match(stdout)
118
+ '7'
119
+ end
120
+ end
121
+ end
122
+
123
+ # Check for SuSE
124
+ if !distribution && !release
125
+ suse_release = exec_and_log(host, 'cat /etc/SuSE-release', true, @results[host.hostname], &stream_block)
126
+
127
+ if (suse_release[:exit_status]).zero?
128
+ stdout = suse_release[:stdout]
129
+
130
+ if /Enterprise Server/ =~ stdout
131
+ distribution = :sles
132
+ release = /^VERSION = (\d*)/m.match(stdout)[1]
133
+ end
134
+ end
135
+ end
136
+
137
+ # Check for Amazon 6, or fail
138
+ if !distribution && !release
139
+ system_release = exec_and_log(host, 'cat /etc/system-release', true, @results[host.hostname], &stream_block)
140
+
141
+ if (system_release[:exit_status]).zero?
142
+ stdout = system_release[:stdout]
143
+
144
+ if /amazon linux/im =~ stdout
145
+ distribution = :amazon
146
+ # How is this safe to assume?
147
+ release = '6'
148
+ end
149
+ end
150
+ end
151
+
152
+ # Check for Solaris
153
+ if !distribution && !release
154
+ uname = exec_and_log(host, 'uname -s', true, @results[host.hostname], &stream_block)
155
+
156
+ if (uname[:exit_status]).zero?
157
+ distribution = case uname.results[hostname][:stdout].strip
158
+ when 'SunOS'
159
+ unamer = exec_and_log(host, 'uname -r', true, @results[host.hostname], &stream_block)
160
+
161
+ if (unamer[:exit_status]).zero?
162
+ release = unamer.results[hostname][:stdout].split('.')[0]
163
+ end
164
+
165
+ :solaris
166
+ when 'AIX'
167
+ oslevel = exec_and_log(host, 'oslevel', true, @results[host.hostname], &stream_block)
168
+ yield oslevel
169
+
170
+ if (oslevel[:exit_status]).zero?
171
+ release = oslevel.results[hostname][:stdout].split('.')[0..1].join('.')
172
+ end
173
+
174
+ :aix
175
+ end
176
+ end
177
+ end
178
+
179
+ # Architecture
180
+ unamem = exec_and_log(host, 'uname -m', true, @results[host.hostname], &stream_block)
181
+
182
+ if (unamem[:exit_status]).zero?
183
+ architecture = unamem[:stdout].strip
184
+
185
+ architecture = case architecture
186
+ when 'i686'
187
+ 'i386'
188
+ when 'ppc'
189
+ 'powerpc'
190
+ when 'x86_64'
191
+ [:ubuntu, :debian].include?(distribution) ? 'amd64' : 'x86_64'
192
+ else
193
+ architecture
194
+ end
195
+ end
196
+
197
+ host.data[:os] = {}
198
+ # Tag
199
+ @results[host.hostname][:distribution] = host.data[:os][:distribution] = distribution
200
+ @results[host.hostname][:release] = host.data[:os][:release] = release
201
+ @results[host.hostname][:architecture] = host.data[:os][:architecture] = architecture
202
+
203
+ tag_distribution = distribution || 'unknown'
204
+ tag_release = release || 'unknown'
205
+ tag_architecture = architecture || 'unknown'
206
+
207
+ @results[host.hostname][:tag] = host.data[:os][:tag] = case distribution
208
+ when :rhel, :centos, :amazon
209
+ "el-#{tag_release}-#{tag_architecture}"
210
+ else
211
+ "#{tag_distribution}-#{tag_release}-#{tag_architecture}"
212
+ end
213
+ end
214
+
215
+ @results
216
+ end
217
+
218
+ def success?
219
+ @results.all? do |_host, result|
220
+ !(result[:distribution].nil? || result[:release].nil? || result[:architecture].nil?)
221
+ end
222
+ end
223
+
224
+ def error_message(hostname)
225
+ @results[hostname][:stderr].strip if @results.key?(hostname) && @results[hostname].key?(:stderr)
226
+ end
227
+
228
+ def name
229
+ :detect_platform
230
+ end
231
+
232
+ def description
233
+ "Detect OS on #{@hosts.join(', ')}"
234
+ end
235
+ end
@@ -1,4 +1,4 @@
1
- require 'uri'
1
+ require 'cgi'
2
2
 
3
3
  module Chloride
4
4
  class Event
@@ -15,7 +15,7 @@ module Chloride
15
15
  {
16
16
  severity: @severity,
17
17
  hostname: @hostname,
18
- message: URI.escape(remove_ansi(@message))
18
+ message: CGI.escape_html(remove_ansi(@message))
19
19
  }.to_json(*args)
20
20
  end
21
21
 
@@ -0,0 +1,67 @@
1
+ class Chloride::Executor
2
+ def initialize(logger, &stream_block)
3
+ @logger = logger
4
+ @stream_block = stream_block
5
+ end
6
+
7
+ def publish(event, action_id = nil)
8
+ event.action_id = action_id if action_id
9
+ @stream_block.call(event) if @stream_block
10
+ end
11
+
12
+ def execute(steps)
13
+ # Perform the plan given
14
+ skip_remaining_steps = false
15
+
16
+ steps.each do |step|
17
+ # TODO: Check for step.pre
18
+ if skip_remaining_steps
19
+ publish Chloride::Event.new(:step_skip, step.name)
20
+ next
21
+ end
22
+
23
+ publish Chloride::Event.new(:step_start, step.name)
24
+
25
+ begin
26
+ step.perform_step do |action|
27
+ action_id = SecureRandom.uuid
28
+ publish(Chloride::Event.new(:action_start, action.name), action_id)
29
+
30
+ action.go do |event|
31
+ publish(event, action_id)
32
+ end
33
+
34
+ if action.success?
35
+ publish(Chloride::Event.new(:action_success, action.name), action_id)
36
+ else
37
+ publish(Chloride::Event.new(:action_fail, action.name), action_id)
38
+ end
39
+ end
40
+ rescue Exception => e # rubocop:disable Lint/RescueException
41
+ # Treat *any* error like a step failure and proceed accordingly
42
+ @logger.error [e, *e.backtrace].join("\n")
43
+ step.error(step.infra.installer_hostname, "An error occured while performing #{step.name}: #{e.message}")
44
+ end
45
+
46
+ type = case step.status
47
+ when :error
48
+ skip_remaining_steps = step.fail_stop?
49
+ :step_error
50
+ when :warn
51
+ :step_warn
52
+ else
53
+ :step_success
54
+ end
55
+
56
+ Chloride::Event.new(type, step.name).tap do |event|
57
+ step.messages.each { |m| event.add_message(m) }
58
+ publish event
59
+ end
60
+
61
+ # Clear the messages so that revalidation doesn't log them again
62
+ step.reset
63
+
64
+ # TODO: Check for step.post
65
+ end
66
+ end
67
+ end
data/lib/chloride/host.rb CHANGED
@@ -7,7 +7,7 @@ require 'timeout'
7
7
  require 'json'
8
8
 
9
9
  class Chloride::Host
10
- attr_reader :data, :remote_conn, :roles, :hostname, :username, :ssh_key_file, :ssh_key_passphrase, :alt_names, :localhost
10
+ attr_reader :data, :remote_conn, :hostname, :username, :ssh_key_file, :ssh_key_passphrase, :localhost
11
11
  attr_accessor :data
12
12
 
13
13
  def initialize(hostname, config = {})
@@ -0,0 +1,53 @@
1
+ class Chloride::Step
2
+ attr_reader :actions, :hosts, :messages, :status
3
+
4
+ def initialize(data = {}, pre = nil, post = nil)
5
+ @pre = pre
6
+ @post = post
7
+ @data = data
8
+ @hosts = Set.new
9
+
10
+ @actions = []
11
+ @messages = []
12
+
13
+ @status = :success
14
+ @uuid = SecureRandom.uuid
15
+ end
16
+
17
+ def perform_step(_execute_block)
18
+ raise NotImplementedError, "Don't know how to perform this kind of step"
19
+ end
20
+
21
+ def name
22
+ raise NotImplementedError, 'Step name required'
23
+ end
24
+
25
+ def description
26
+ raise NotImplementedError, 'Step description required'
27
+ end
28
+
29
+ def fail_stop?
30
+ false
31
+ end
32
+
33
+ def reset
34
+ @status = :success
35
+ @messages.clear
36
+ end
37
+
38
+ def error(hostname, message)
39
+ @messages << Chloride::Event::Message.new(:error, hostname, message)
40
+ @status = :error
41
+ end
42
+
43
+ def warning(hostname, message)
44
+ @messages << Chloride::Event::Message.new(:warn, hostname, message)
45
+ @status = :warn unless @status == :error
46
+ end
47
+
48
+ def info(hostname, message)
49
+ @messages << Chloride::Event::Message.new(:info, hostname, message)
50
+ end
51
+ end
52
+
53
+ require 'chloride/event'
@@ -0,0 +1,24 @@
1
+ require 'chloride/step'
2
+
3
+ class Chloride::Step::Noop < Chloride::Step
4
+ def initialize(data = {}, pre = nil, post = nil)
5
+ super(data, pre, post)
6
+ @name = data[:name]
7
+ @performed = false
8
+ end
9
+
10
+ def perform_step(_execute_block)
11
+ @performed = true
12
+ # noop
13
+ end
14
+
15
+ def performed?
16
+ @performed
17
+ end
18
+
19
+ attr_reader :name
20
+
21
+ def description
22
+ 'Do basically nothing'
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module Chloride
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chloride
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon High
@@ -161,6 +161,7 @@ files:
161
161
  - chloride.gemspec
162
162
  - lib/chloride.rb
163
163
  - lib/chloride/action.rb
164
+ - lib/chloride/action/detect_platform.rb
164
165
  - lib/chloride/action/execute.rb
165
166
  - lib/chloride/action/file_copy.rb
166
167
  - lib/chloride/action/mkdir.rb
@@ -169,7 +170,10 @@ files:
169
170
  - lib/chloride/errors.rb
170
171
  - lib/chloride/event.rb
171
172
  - lib/chloride/event/message.rb
173
+ - lib/chloride/executor.rb
172
174
  - lib/chloride/host.rb
175
+ - lib/chloride/step.rb
176
+ - lib/chloride/step/noop.rb
173
177
  - lib/chloride/version.rb
174
178
  homepage: https://github.com/puppetlabs/chloride
175
179
  licenses: