miq_utilities 0.2.2 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +11 -0
- data/.rubocop.yml +29 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +3 -28
- data/README.md +11 -12
- data/lib/miq_utilities/chef.rb +112 -0
- data/lib/miq_utilities/general.rb +46 -0
- data/lib/miq_utilities/infoblox.rb +6 -6
- data/lib/miq_utilities/logging.rb +7 -4
- data/lib/miq_utilities/notification.rb +33 -41
- data/lib/miq_utilities/sql.rb +8 -7
- data/lib/miq_utilities/ssh.rb +33 -0
- data/lib/miq_utilities/version.rb +1 -1
- data/lib/miq_utilities/vmware.rb +15 -10
- data/lib/miq_utilities/winrm.rb +5 -5
- data/lib/miq_utilities.rb +4 -0
- data/miq_utilities.gemspec +1 -0
- metadata +20 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85f2ae04d311c596c5309f1f79bf31a8b407b02e754dc756dabb016c557b4572
|
4
|
+
data.tar.gz: 498e1d8d0c3ad8dfa112791d937d99aad1a259e2ce411ba15b00e5823522553c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a239b30ffc757799835233191fd57c9533838a9a637c0a0a8d9f6d0f2ca804e55132b53ce6496efecb250ec60d52cfaa1b9d5250a3dae8da52b88085dc03594
|
7
|
+
data.tar.gz: d95c06245eddba23773ac1164e701c0b5efd3a1975113a973a657ae71f1b222cf43bfc7440b37cfdc138c394186575a68bc2402dd2c64b153c48862780acd3fd
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
Exclude:
|
4
|
+
- vendor/**/*
|
5
|
+
- Guardfile
|
6
|
+
|
7
|
+
ClassLength:
|
8
|
+
Enabled: false
|
9
|
+
CyclomaticComplexity:
|
10
|
+
Enabled: false
|
11
|
+
GlobalVars:
|
12
|
+
AllowedVariables:
|
13
|
+
- $evm
|
14
|
+
LineLength:
|
15
|
+
Enabled: false
|
16
|
+
MethodLength:
|
17
|
+
Enabled: false
|
18
|
+
Metrics/AbcSize:
|
19
|
+
Enabled: false
|
20
|
+
Metrics/LineLength:
|
21
|
+
Enabled: false
|
22
|
+
Metrics/ModuleLength:
|
23
|
+
Enabled: false
|
24
|
+
Metrics/PerceivedComplexity:
|
25
|
+
Enabled: false
|
26
|
+
Metrics/ParameterLists:
|
27
|
+
Enabled: false
|
28
|
+
Style/RescueStandardError:
|
29
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -4,11 +4,11 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in miq_utilities.gemspec
|
6
6
|
gemspec
|
7
|
-
gem 'slack-
|
7
|
+
gem 'slack-notifier'
|
8
8
|
gem 'eventmachine'
|
9
9
|
gem 'faye-websocket'
|
10
10
|
gem 'rbvmomi'
|
11
11
|
gem 'tiny_tds'
|
12
12
|
gem 'winrm'
|
13
13
|
gem 'rest-client'
|
14
|
-
gem 'json'
|
14
|
+
gem 'json'
|
data/Gemfile.lock
CHANGED
@@ -1,41 +1,27 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
miq_utilities (0.2.
|
4
|
+
miq_utilities (0.2.3)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
activesupport (5.2.0)
|
10
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
|
-
i18n (>= 0.7, < 2)
|
12
|
-
minitest (~> 5.1)
|
13
|
-
tzinfo (~> 1.1)
|
14
9
|
builder (3.2.3)
|
15
|
-
concurrent-ruby (1.0.5)
|
16
10
|
domain_name (0.5.20180417)
|
17
11
|
unf (>= 0.0.5, < 1.0.0)
|
18
12
|
erubis (2.7.0)
|
19
13
|
eventmachine (1.2.6-x64-mingw32)
|
20
|
-
faraday (0.15.0)
|
21
|
-
multipart-post (>= 1.2, < 3)
|
22
|
-
faraday_middleware (0.12.2)
|
23
|
-
faraday (>= 0.7.4, < 1.0)
|
24
14
|
faye-websocket (0.10.7)
|
25
15
|
eventmachine (>= 0.12.0)
|
26
16
|
websocket-driver (>= 0.5.1)
|
27
17
|
ffi (1.9.23-x64-mingw32)
|
28
|
-
gli (2.17.1)
|
29
18
|
gssapi (1.2.0)
|
30
19
|
ffi (>= 1.0.1)
|
31
20
|
gyoku (1.3.1)
|
32
21
|
builder (>= 2.1.2)
|
33
|
-
hashie (3.5.7)
|
34
22
|
http-cookie (1.0.3)
|
35
23
|
domain_name (~> 0.5)
|
36
24
|
httpclient (2.8.3)
|
37
|
-
i18n (1.0.1)
|
38
|
-
concurrent-ruby (~> 1.0)
|
39
25
|
json (2.1.0)
|
40
26
|
little-plugger (1.1.4)
|
41
27
|
logging (2.2.2)
|
@@ -45,9 +31,7 @@ GEM
|
|
45
31
|
mime-types-data (~> 3.2015)
|
46
32
|
mime-types-data (3.2016.0521)
|
47
33
|
mini_portile2 (2.3.0)
|
48
|
-
minitest (5.11.3)
|
49
34
|
multi_json (1.13.1)
|
50
|
-
multipart-post (2.0.0)
|
51
35
|
netrc (0.11.0)
|
52
36
|
nokogiri (1.8.2-x64-mingw32)
|
53
37
|
mini_portile2 (~> 2.3.0)
|
@@ -64,18 +48,9 @@ GEM
|
|
64
48
|
mime-types (>= 1.16, < 4.0)
|
65
49
|
netrc (~> 0.8)
|
66
50
|
rubyntlm (0.6.2)
|
67
|
-
slack-
|
68
|
-
activesupport
|
69
|
-
faraday (>= 0.9)
|
70
|
-
faraday_middleware
|
71
|
-
gli
|
72
|
-
hashie
|
73
|
-
websocket-driver
|
74
|
-
thread_safe (0.3.6)
|
51
|
+
slack-notifier (2.3.2)
|
75
52
|
tiny_tds (2.1.1-x64-mingw32)
|
76
53
|
trollop (2.1.2)
|
77
|
-
tzinfo (1.2.5)
|
78
|
-
thread_safe (~> 0.1)
|
79
54
|
unf (0.1.4)
|
80
55
|
unf_ext
|
81
56
|
unf_ext (0.0.7.5-x64-mingw32)
|
@@ -104,7 +79,7 @@ DEPENDENCIES
|
|
104
79
|
rake (~> 10.0)
|
105
80
|
rbvmomi
|
106
81
|
rest-client
|
107
|
-
slack-
|
82
|
+
slack-notifier
|
108
83
|
tiny_tds
|
109
84
|
winrm
|
110
85
|
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
## Installation
|
4
4
|
|
5
|
-
$
|
5
|
+
$ bundle install
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
@@ -15,7 +15,7 @@
|
|
15
15
|
3. rbvmomi ~> 1.11.3
|
16
16
|
4. tiny_tds ~> 2.1.0
|
17
17
|
5. winrm ~> 2.2.3
|
18
|
-
6. slack-
|
18
|
+
6. slack-notifier ~> 2.3.2
|
19
19
|
7. rest-client ~> 1.8.0 x64-mingw32
|
20
20
|
8. json ~> 2.0.4
|
21
21
|
|
@@ -214,7 +214,7 @@ password ¦ String ¦ The users password
|
|
214
214
|
|
215
215
|
## Notification (NotificationClass)
|
216
216
|
|
217
|
-
This Class is used to notify users and log messages accordingly. This Class utilises the
|
217
|
+
This Class is used to notify users and log messages accordingly. This Class utilises the slack-notifier Ruby Gem (version => 2.3.2).
|
218
218
|
|
219
219
|
### Class Method Summary
|
220
220
|
|
@@ -229,8 +229,8 @@ event_level ¦ String ¦ info, warn, error
|
|
229
229
|
event_message ¦ String ¦ The message to be used
|
230
230
|
email_to ¦ String ¦ Who to send an email to
|
231
231
|
email_from ¦ String ¦ Sent from which email address
|
232
|
-
|
233
|
-
|
232
|
+
signature ¦ String ¦ Who the emails from
|
233
|
+
webhookURL ¦ String ¦ The webhook to be used
|
234
234
|
```
|
235
235
|
|
236
236
|
##### Method usage
|
@@ -240,7 +240,7 @@ slack_channel ¦ Boolean ¦ The slcak channel to send the message to
|
|
240
240
|
logger.log('error', 'An error occured!', false, true)
|
241
241
|
```
|
242
242
|
|
243
|
-
#### Levels
|
243
|
+
#### Levels (event_level)
|
244
244
|
```
|
245
245
|
Level | Action
|
246
246
|
----------------------------------------------------------------------------------------------
|
@@ -260,7 +260,7 @@ message ¦ String ¦ The message to be used
|
|
260
260
|
subject ¦ String ¦ The Subject to be used
|
261
261
|
to_email ¦ String ¦ Recipient email
|
262
262
|
from_email ¦ String ¦ Sender email
|
263
|
-
|
263
|
+
signature ¦ String ¦ Who the emails from
|
264
264
|
```
|
265
265
|
##### Method usage
|
266
266
|
|
@@ -275,11 +275,10 @@ from ¦ String ¦ Sent from
|
|
275
275
|
_Sends a Slcak message_
|
276
276
|
##### Parameters
|
277
277
|
```
|
278
|
-
Name
|
278
|
+
Name | Type | Description
|
279
279
|
--------------------------------------------------------------
|
280
|
-
message
|
281
|
-
|
282
|
-
token ¦ String ¦ The API token used to authenticate
|
280
|
+
message ¦ String ¦ The message to be used
|
281
|
+
webhookURL ¦ String ¦ The webhook to be used
|
283
282
|
```
|
284
283
|
|
285
284
|
##### Method usage
|
@@ -287,7 +286,7 @@ token ¦ String ¦ The API token used to authenticate
|
|
287
286
|
```$xslt
|
288
287
|
require 'miq_utilities'
|
289
288
|
notify = NotificationCLass.new
|
290
|
-
notify.send_slack_message('This a Slack post!', '
|
289
|
+
notify.send_slack_message('This a Slack post!', 'https://hooks.slack.com/services/token')
|
291
290
|
```
|
292
291
|
|
293
292
|
#### **on_screen_message**
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This Class is used wrap the chef methods used
|
5
|
+
#
|
6
|
+
|
7
|
+
require_relative 'logging.rb'
|
8
|
+
|
9
|
+
# Wrapper class to interact with chef
|
10
|
+
class ChefClass
|
11
|
+
# rubocop:disable Naming/AccessorMethodName
|
12
|
+
def initialize(name)
|
13
|
+
@logger = LoggingClass.new(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call_chef(cmd, timeout = 20, pre_cmd = nil)
|
17
|
+
# unset the variables for knife
|
18
|
+
pre_cmd ||= 'unset GEM_HOME GEM_PATH IRBRC MY_RUBY_HOME'
|
19
|
+
|
20
|
+
require 'linux_admin'
|
21
|
+
require 'timeout'
|
22
|
+
|
23
|
+
begin
|
24
|
+
Timeout.timeout(timeout) do
|
25
|
+
@logger.log(level: 'info', message: "Executing [#{cmd}] with timeout of #{timeout} seconds")
|
26
|
+
result = LinuxAdmin::Common.run("#{pre_cmd};#{cmd}")
|
27
|
+
@logger.log(level: 'info', message: "success?: #{result.success?}")
|
28
|
+
@logger.log(level: 'info', message: "exit_status: #{result.exit_status}") unless result.exit_status.blank?
|
29
|
+
@logger.log(level: 'info', message: "output: #{result.output}")
|
30
|
+
@logger.log(level: 'info', message: "error: #{result.error}") unless result.error.blank?
|
31
|
+
return result
|
32
|
+
end
|
33
|
+
rescue => timeout
|
34
|
+
@logger.log(level: 'error', message: "Error executing chef: #{timeout.class} #{timeout} #{timeout.backtrace.join("\n")}")
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_chef_environment_name(ws_values = {})
|
40
|
+
chef_environment = $evm.object['chef_environment']
|
41
|
+
chef_environment ||= $evm.root['dialog_chef_environment']
|
42
|
+
if @task
|
43
|
+
env = @task.get_tags[:environment]
|
44
|
+
region = @task.get_option(:cmdb)[:ProvisionCMDBDetails]['CountryCode'].downcase
|
45
|
+
chef_environment = @task.get_tags[:chef_environment] || ws_values[:chef_environment] || @task.get_option(:chef_environment)
|
46
|
+
chef_environment ||= case env
|
47
|
+
when 'production'
|
48
|
+
"#{region}_prod"
|
49
|
+
when 'quality_excellence'
|
50
|
+
"#{region}_qe"
|
51
|
+
when 'development'
|
52
|
+
"#{region}_dev"
|
53
|
+
else
|
54
|
+
'_default'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
chef_environment ||= '_default'
|
58
|
+
@logger.log(level: 'info', message: "chef_environment: #{chef_environment}")
|
59
|
+
chef_environment
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_chef_type
|
63
|
+
chef_type = $evm.object['chef_type']
|
64
|
+
chef_type ||= $evm.root['dialog_chef_type']
|
65
|
+
chef_type ||= 'role'
|
66
|
+
@logger.log(level: 'info', message: "chef_type: #{chef_type}")
|
67
|
+
chef_type
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_chef_node_name
|
71
|
+
chef_node_name = begin
|
72
|
+
@vm.hostnames.first
|
73
|
+
rescue
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
domain_suffix = get_domain_suffix
|
77
|
+
chef_node_name ||= @task.get_option(:vm_target_hostname) if @task
|
78
|
+
chef_node_name ||= @vm.name.to_s
|
79
|
+
chef_node_name = "#{chef_node_name}.#{domain_suffix}" unless domain_suffix.nil? || chef_node_name.include?(domain_suffix)
|
80
|
+
|
81
|
+
@logger.log(level: 'info', message: "chef_node_name: #{chef_node_name}")
|
82
|
+
chef_node_name.downcase
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_chef_role(ws_values = {})
|
86
|
+
chef_role = $evm.object['chef_role']
|
87
|
+
chef_role ||= $evm.root['dialog_chef_role']
|
88
|
+
if @task
|
89
|
+
chef_role = @task.get_tags[:chef_role] || ws_values[:chef_role] || @task.get_option(:chef_role)
|
90
|
+
end
|
91
|
+
|
92
|
+
chef_role ||= ''
|
93
|
+
@logger.log(level: 'info', message: "chef_role: #{chef_role}")
|
94
|
+
chef_role
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_domain_suffix
|
98
|
+
domain_suffix = nil
|
99
|
+
domain_suffix ||= $evm.object['domain_suffix']
|
100
|
+
domain_suffix ||= $evm.root['dialog_domain_suffix']
|
101
|
+
domain_suffix ||= @task.get_tags[:domain_suffix] if @task
|
102
|
+
@logger.log(level: 'info', message: "domain_suffix: #{domain_suffix}")
|
103
|
+
domain_suffix
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_chef_version(chef_version = nil)
|
107
|
+
chef_version ||= $evm.object['chef_version']
|
108
|
+
@logger.log(level: 'info', message: "chef_version: #{chef_version}")
|
109
|
+
chef_version
|
110
|
+
end
|
111
|
+
# rubocop:enable Naming/AccessorMethodName
|
112
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This Class is used to hold general methods used within this GEM
|
5
|
+
#
|
6
|
+
# Methods Summary:
|
7
|
+
# > Name > Description/Params
|
8
|
+
#
|
9
|
+
|
10
|
+
require_relative 'logging.rb'
|
11
|
+
|
12
|
+
# Wrapper class to interact with linux machines via ssh
|
13
|
+
class GeneralClass
|
14
|
+
def initialize(name)
|
15
|
+
@logger = LoggingClass.new(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
# basic retry logic
|
19
|
+
def retry_method(retry_time = 1.minute)
|
20
|
+
@logger.log(level: 'info', message: "Sleeping for #{retry_time} seconds")
|
21
|
+
$evm.root['ae_result'] = 'retry'
|
22
|
+
$evm.root['ae_retry_interval'] = retry_time
|
23
|
+
exit(MIQ_OK)
|
24
|
+
end
|
25
|
+
|
26
|
+
# process tags
|
27
|
+
def process_tags(category, category_description, single_value, tag, tag_description)
|
28
|
+
# Convert to lower case and replace all non-word characters with underscores
|
29
|
+
category_name = category.to_s.downcase.gsub(/\W/, '_')
|
30
|
+
tag_name = tag.to_s.downcase.gsub(/\W|:/, '_')
|
31
|
+
@logger.log(level: 'info', message: "Converted category name:<#{category_name}> Converted tag name: <#{tag_name}>")
|
32
|
+
# if the category exists else create it
|
33
|
+
unless $evm.execute('category_exists?', category_name)
|
34
|
+
@logger.log(level: 'info', message: "Category <#{category_name}> doesn't exist, creating category")
|
35
|
+
$evm.execute('category_create', name: category_name, single_value: single_value, description: category_description.to_s)
|
36
|
+
end
|
37
|
+
# if the tag exists else create it
|
38
|
+
@logger.log(level: 'info', message: "Adding new tag <#{tag_name}> description <#{tag_description}> in Category <#{category_name}>") unless $evm.execute('tag_exists?', category_name, tag_name)
|
39
|
+
$evm.execute('tag_create', category_name, name: tag_name, description: tag_description.to_s) unless $evm.execute('tag_exists?', category_name, tag_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_vm_custom_attributes(key, value)
|
43
|
+
@logger.log(level: 'debug', message: "#{key} #{value}")
|
44
|
+
@vm.custom_set(key, value)
|
45
|
+
end
|
46
|
+
end
|
@@ -40,7 +40,7 @@ require 'rest-client'
|
|
40
40
|
require 'json'
|
41
41
|
require_relative 'logging.rb'
|
42
42
|
|
43
|
-
#
|
43
|
+
# Wrapper class to interact with Infoblox
|
44
44
|
class InfobloxClass
|
45
45
|
private def process_args(inargs, inurl)
|
46
46
|
loops = 1
|
@@ -106,7 +106,7 @@ class InfobloxClass
|
|
106
106
|
url
|
107
107
|
end
|
108
108
|
|
109
|
-
@logger.log('info', "URL: \"#{url}\"")
|
109
|
+
@logger.log(level: 'info', message: "URL: \"#{url}\"")
|
110
110
|
|
111
111
|
params = {
|
112
112
|
method: action,
|
@@ -119,18 +119,18 @@ class InfobloxClass
|
|
119
119
|
|
120
120
|
if body_type == :json
|
121
121
|
params[:payload] = JSON.generate(body) if body
|
122
|
-
@logger.log('info', "Calling -> Infoblox:<#{url}> action:<#{action}> payload:<#{params[:payload]}>") if body
|
122
|
+
@logger.log(level: 'info', message: "Calling -> Infoblox:<#{url}> action:<#{action}> payload:<#{params[:payload]}>") if body
|
123
123
|
elsif body
|
124
124
|
params[:payload] = body
|
125
125
|
end
|
126
126
|
|
127
127
|
response = RestClient::Request.new(params).execute
|
128
128
|
if response.code == 200 || response.code == 201
|
129
|
-
@logger.log('info', "Success <- Infoblox Response:<#{response.code}>")
|
129
|
+
@logger.log(level: 'info', message: "Success <- Infoblox Response:<#{response.code}>")
|
130
130
|
else
|
131
131
|
err_msg = "Error calling infoblox. <#{response.inspect}>"
|
132
|
-
@logger.log('error', err_msg,
|
132
|
+
@logger.log(level: 'error', message: err_msg, notify: true)
|
133
133
|
end
|
134
134
|
response
|
135
135
|
end
|
136
|
-
end
|
136
|
+
end
|
@@ -16,7 +16,7 @@
|
|
16
16
|
#
|
17
17
|
require_relative 'notification.rb'
|
18
18
|
|
19
|
-
#
|
19
|
+
# Wrapper class for logging
|
20
20
|
class LoggingClass
|
21
21
|
# initialize class
|
22
22
|
def initialize(name)
|
@@ -24,18 +24,21 @@ class LoggingClass
|
|
24
24
|
@notification = NotificationClass.new
|
25
25
|
end
|
26
26
|
|
27
|
-
def log(level
|
28
|
-
levelvalid = %w[info warn error].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
27
|
+
def log(level:, message:, logtoscreenonly: false, notify: false, email_to: nil, email_from: nil, signature: nil, webhookurl: nil, subjecttype: nil, update_message: false)
|
28
|
+
levelvalid = %w[info warn error debug].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
29
29
|
|
30
30
|
if $evm.nil? || logtoscreenonly
|
31
31
|
puts "#{level}: #{@initializer} - #{message}"
|
32
32
|
elsif levelvalid
|
33
33
|
$evm.log(level, "#{@initializer} - #{message}")
|
34
|
+
@task.message = message if @task && (level.casecmp('ERROR').zero? || update_message)
|
34
35
|
else
|
35
36
|
$evm.log('info', "#{@initializer} - #{message}")
|
36
37
|
end
|
37
38
|
|
38
39
|
# Notify - Only if flag (notify) is set to TRUE
|
39
|
-
@notification.notify(level, message) if notify
|
40
|
+
@notification.notify(event_level: level, event_message: message, email_to: email_to, email_from: email_from, signature: signature, webhookurl: webhookurl, subjecttype: subjecttype) if notify
|
41
|
+
rescue => err
|
42
|
+
raise("Oopps! Something went wrong.\nError:<#{err}>")
|
40
43
|
end
|
41
44
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# .SYNOPSIS
|
4
|
-
# This Class utilises the slack-
|
4
|
+
# This Class utilises the slack-notifier Ruby Gem (version => 2.3.2).
|
5
5
|
#
|
6
6
|
# Methods Summary:
|
7
7
|
# > Name > Description/Params
|
@@ -10,48 +10,49 @@
|
|
10
10
|
# event_message - String : The message to be used
|
11
11
|
# email_to - String : Who to send an email to
|
12
12
|
# email_from - String : Sent from which email address
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# signature - String : Who the emails from
|
14
|
+
# webhookurl - String : The slcak channel to send the message to
|
15
15
|
#
|
16
16
|
# send_email - Sends an email to the specified user
|
17
17
|
# message - String : The message to be used
|
18
18
|
# subject - String : The Subject to be used
|
19
|
-
# to_email - String : Recipient email
|
20
19
|
# from_email - String : Sender email
|
21
|
-
#
|
20
|
+
# signature - String : Who the emails from
|
21
|
+
# to_email - String : Recipient email
|
22
22
|
#
|
23
23
|
# send_slack_message - Sends a Slcak message
|
24
|
-
# message
|
25
|
-
#
|
26
|
-
# token - String : The API token used to authenticate
|
24
|
+
# message - String : The message to be used
|
25
|
+
# webhookurl - String : The webhook to be used
|
27
26
|
#
|
28
27
|
# on_screen_message - Sends an on-screen notification
|
29
28
|
# level - String : info, warn, error
|
30
29
|
# message - String : The message to be used
|
31
30
|
# subject - String : The Subject to be used
|
32
31
|
# WIP
|
33
|
-
require 'slack-
|
32
|
+
require 'slack-notifier'
|
34
33
|
|
35
|
-
#
|
34
|
+
# Wrapper class to notify stakeholders
|
36
35
|
class NotificationClass
|
37
|
-
|
38
|
-
|
36
|
+
def notify(event_level:, event_message:, email_to: nil, email_from: nil, signature: nil, webhookurl: nil, subjecttype: nil)
|
37
|
+
signature ||= 'ManageIQ'
|
39
38
|
case event_level.upcase
|
40
39
|
when %w[WARN WARNING]
|
41
|
-
|
42
|
-
|
40
|
+
subject = 'ManageIQ Warning'
|
41
|
+
send_email(message: event_message, subject: subject, from_email: email_from, signature: signature, to_email: email_to)
|
42
|
+
send_slack_message(message: event_message, webhookurl: webhookurl)
|
43
43
|
when %w[ERR ERROR]
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
subject = 'ManageIQ Error'
|
45
|
+
send_email(message: event_message, subject: subject, from_email: email_from, signature: signature, to_email: email_to)
|
46
|
+
send_slack_message(message: event_message, webhookurl: webhookurl)
|
47
|
+
on_screen_message(level: event_level, message: event_message, type: subjecttype)
|
47
48
|
when 'NOTE'
|
48
|
-
on_screen_message(event_level, event_message)
|
49
|
+
on_screen_message(level: event_level, message: event_message, type: subjecttype)
|
49
50
|
end
|
50
51
|
rescue => err
|
51
52
|
raise("Oopps! Something went wrong trying to notify. Error:<#{err}>")
|
52
53
|
end
|
53
54
|
|
54
|
-
def send_email(message
|
55
|
+
def send_email(message:, subject:, from_email:, signature:, to_email: nil)
|
55
56
|
# Look in the current object for a VM
|
56
57
|
vm = $evm.object['vm']
|
57
58
|
if vm.nil?
|
@@ -95,47 +96,38 @@ class NotificationClass
|
|
95
96
|
body = 'Hello, '
|
96
97
|
body += message
|
97
98
|
body += 'Thank you,'
|
98
|
-
body +=
|
99
|
+
body += signature
|
99
100
|
|
100
101
|
$evm.execute(:send_email, to, from_email, subject, body)
|
101
102
|
rescue => err
|
102
103
|
raise("Oopps! Something went wrong trying to send an email to:<#{to}>. Error:<#{err}>")
|
103
104
|
end
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
config.token = ENV['SLACK_API_TOKEN']
|
111
|
-
raise 'Missing ENV[SLACK_API_TOKEN]!' unless config.token
|
112
|
-
end
|
113
|
-
else
|
114
|
-
config.token = token
|
115
|
-
end
|
116
|
-
|
117
|
-
begin
|
118
|
-
client = Slack::Web::Client.new
|
119
|
-
client.auth_test
|
120
|
-
client.chat_postMessage(channel: channel, text: message, as_user: true)
|
121
|
-
rescue => err
|
122
|
-
raise("Oopps! Something went wrong trying to send a Slack notification. Error:<#{err}>")
|
123
|
-
end
|
106
|
+
def send_slack_message(message:, webhookurl:)
|
107
|
+
notifier = Slack::Notifier.new webhookurl
|
108
|
+
notifier.ping message
|
109
|
+
rescue => err
|
110
|
+
raise("Oopps! Something went wrong trying to send a Slack notification. Error:<#{err}>")
|
124
111
|
end
|
125
112
|
|
126
|
-
def on_screen_message(level
|
113
|
+
def on_screen_message(level:, message:, subject: nil, type: nil)
|
127
114
|
if subject.nil?
|
128
115
|
vm = $evm.root['vm']
|
129
116
|
prov = $evm.root['miq_provision']
|
130
117
|
subject ||= vm unless vm.nil?
|
131
118
|
subject ||= prov.miq_request unless prov.miq_request.nil?
|
119
|
+
prov.message = message unless prov.nil?
|
132
120
|
end
|
133
121
|
|
134
122
|
levelvalid = %w[info warn error].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
135
123
|
level = 'info' unless levelvalid
|
136
124
|
|
137
125
|
begin
|
138
|
-
|
126
|
+
if type.nil?
|
127
|
+
$evm.create_notification(level: level, subject: subject, message: message)
|
128
|
+
else
|
129
|
+
$evm.create_notification(type: type, subject: subject)
|
130
|
+
end
|
139
131
|
rescue => err
|
140
132
|
raise("Oopps! Something went wrong trying to display on-screen notification. Error:<#{err}>")
|
141
133
|
end
|
data/lib/miq_utilities/sql.rb
CHANGED
@@ -9,9 +9,9 @@
|
|
9
9
|
# user - String : Username
|
10
10
|
# password - String : Password
|
11
11
|
# host - String : The host name to connect to
|
12
|
-
# port - String : The port to use, default (nil) 1433
|
13
12
|
# database - String : The database name to connect to
|
14
13
|
# azure - Boolean : Set to true when connecting to Azure
|
14
|
+
# port - String : The port to use, default (nil) 1433
|
15
15
|
#
|
16
16
|
# get_client - returns the client to utilise the tiny_tds functionality
|
17
17
|
#
|
@@ -21,17 +21,18 @@
|
|
21
21
|
# close_connection - closes the connection to the client
|
22
22
|
#
|
23
23
|
require 'tiny_tds'
|
24
|
+
require_relative 'logging.rb'
|
24
25
|
|
25
|
-
#
|
26
|
+
# Wrapper class to interact with sql server
|
26
27
|
class SqlClass
|
27
28
|
# Initialize Class
|
28
|
-
def initialize(user, password, host, port = nil
|
29
|
+
def initialize(user, password, host, database, azure, port = nil)
|
29
30
|
# Logging
|
30
31
|
@logger = LoggingClass.new('SQL')
|
31
32
|
|
32
33
|
# Default port
|
33
|
-
unless port.nil?
|
34
|
-
@logger.log('info', 'Using default port 1433')
|
34
|
+
unless port.nil?
|
35
|
+
@logger.log(level: 'info', message: 'Using default port 1433')
|
35
36
|
port = '1433'
|
36
37
|
end
|
37
38
|
|
@@ -53,7 +54,7 @@ class SqlClass
|
|
53
54
|
# Run Sql query
|
54
55
|
def run_sql_query(sql)
|
55
56
|
if @client.nil?
|
56
|
-
@logger.log('warn', 'SQL Server Connection Not Established! Query hasn\'t been run!')
|
57
|
+
@logger.log(level: 'warn', message: 'SQL Server Connection Not Established! Query hasn\'t been run!')
|
57
58
|
else
|
58
59
|
@client.execute(sql)
|
59
60
|
end
|
@@ -62,6 +63,6 @@ class SqlClass
|
|
62
63
|
# Close the connection to the sql client
|
63
64
|
def close_connection
|
64
65
|
@client.close unless @client.closed?
|
65
|
-
@logger.log('info', 'Connection to SQL Client Closed Successfully.') if @client.closed?
|
66
|
+
@logger.log(level: 'info', message: 'Connection to SQL Client Closed Successfully.') if @client.closed?
|
66
67
|
end
|
67
68
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This Class is used to handle the logging for ManageIQ and an IDE
|
5
|
+
#
|
6
|
+
# Methods Summary:
|
7
|
+
# > Name > Description/Params
|
8
|
+
# ssh_run - Run script via ssh
|
9
|
+
# script - String : The script to run
|
10
|
+
# ipaddress - String : The message
|
11
|
+
# linux_user - String : User to login as
|
12
|
+
# linux_password - String : password to use
|
13
|
+
#
|
14
|
+
|
15
|
+
require 'net/ssh'
|
16
|
+
require_relative 'logging.rb'
|
17
|
+
|
18
|
+
# This wrapper class is used to run ssh commands on linux machines
|
19
|
+
class SshClass
|
20
|
+
def ssh_run(ipaddr, script, linux_user = nil, linux_password = nil)
|
21
|
+
@logger = LoggingClass.new('ssh_run')
|
22
|
+
linux_password ||= $evm.object.decrypt('linux_password').to_s
|
23
|
+
linux_user ||= 'root'
|
24
|
+
|
25
|
+
Net::SSH.start(ipaddr, linux_user, password: linux_password, paranoid: Net::SSH::Verifiers::Null.new) do |ssh|
|
26
|
+
command = script
|
27
|
+
output = ssh.exec!(command)
|
28
|
+
@logger.log(level: 'info', message: "ssh command being run on #{ipaddr}")
|
29
|
+
@logger.log(level: 'info', message: "ssh script being run is #{script}")
|
30
|
+
@logger.log(level: 'info', message: "SSH output = #{output}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/miq_utilities/vmware.rb
CHANGED
@@ -12,13 +12,18 @@
|
|
12
12
|
# user - String : The user to connect with
|
13
13
|
# password - String : The users password
|
14
14
|
#
|
15
|
-
#
|
16
|
-
# vsphereconn - connection : The return of "get_vsphere_connection"
|
17
|
-
# dcname - String : The name of the datacenter
|
15
|
+
# retrieve_data_center - returns the datacenter based on the connection and datacenter
|
18
16
|
#
|
17
|
+
#
|
18
|
+
# find_vm - Get the VM details from vmware
|
19
|
+
# datacenter - String : retrieve_data_center return value
|
20
|
+
# vmname - String : The vmname
|
21
|
+
#
|
22
|
+
# upg_tools - Get the VM details from vmware
|
23
|
+
# vmobj - Object : find_vm return value
|
19
24
|
require 'rbvmomi'
|
20
25
|
|
21
|
-
#
|
26
|
+
# Wrapper class to interact with vmware
|
22
27
|
class VmwareClass
|
23
28
|
def initialize(host_name)
|
24
29
|
@host_name = host_name
|
@@ -34,10 +39,10 @@ class VmwareClass
|
|
34
39
|
raise("No connection established!\nUse the \"get_vsphere_connection\" method to connect.") if @connection.nil?
|
35
40
|
end
|
36
41
|
|
37
|
-
def find_vm(
|
42
|
+
def find_vm(datacenter, vmname)
|
38
43
|
vm = {}
|
39
|
-
|
40
|
-
vm[:instance] = datastore.vm.find { |x| x.name ==
|
44
|
+
datacenter.datastoreFolder.childEntity.collect do |datastore|
|
45
|
+
vm[:instance] = datastore.vm.find { |x| x.name == vmname }
|
41
46
|
if vm[:instance]
|
42
47
|
vm[:datastore] = datastore.name
|
43
48
|
break
|
@@ -46,10 +51,10 @@ class VmwareClass
|
|
46
51
|
vm
|
47
52
|
end
|
48
53
|
|
49
|
-
def upg_tools(
|
50
|
-
instopts = if
|
54
|
+
def upg_tools(vmobj)
|
55
|
+
instopts = if vmobj[:instance][:guest][:guestFamily] == 'windowsGuest'
|
51
56
|
'/s /v "/qn REBOOT=ReallySuppress"'
|
52
57
|
end
|
53
|
-
|
58
|
+
vmobj[:instance].UpgradeTools_Task(installerOptions: instopts).wait_for_completion
|
54
59
|
end
|
55
60
|
end
|
data/lib/miq_utilities/winrm.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
require 'winrm'
|
15
15
|
require 'logging.rb'
|
16
16
|
|
17
|
-
#
|
17
|
+
# Wrapper class to interact with winrm
|
18
18
|
class WinrmClass
|
19
19
|
def winrm_run(ps_script, host, user, password)
|
20
20
|
@logger = LoggingClass.new('WinRM')
|
@@ -31,9 +31,9 @@ class WinrmClass
|
|
31
31
|
|
32
32
|
conn = WinRM::Connection.new(opts)
|
33
33
|
|
34
|
-
@logger.log('info', "WinRM is connecting to #{opts[:endpoint]}")
|
34
|
+
@logger.log(level: 'info', message: "WinRM is connecting to #{opts[:endpoint]}")
|
35
35
|
msg = ps1.to_s.gsub(password.to_s, '****')
|
36
|
-
@logger.log('info', "Running PowerShell script: #{msg}")
|
36
|
+
@logger.log(level: 'info', message: "Running PowerShell script: #{msg}")
|
37
37
|
|
38
38
|
conn.shell(:powershell) do |shell|
|
39
39
|
err = ''
|
@@ -42,9 +42,9 @@ class WinrmClass
|
|
42
42
|
err = stderr
|
43
43
|
end
|
44
44
|
if output.exitcode.zero?
|
45
|
-
@logger.log('info', "PS script finished with exit code #{output.exitcode} - Output: <#{value.to_s.strip}>")
|
45
|
+
@logger.log(level: 'info', message: "PS script finished with exit code #{output.exitcode} - Output: <#{value.to_s.strip}>")
|
46
46
|
else
|
47
|
-
@logger.log('error', "PS script failed with exit code #{output.exitcode} and error message #{err}. STDOUT: #{value.to_s.strip}")
|
47
|
+
@logger.log(level: 'error', message: "PS script failed with exit code #{output.exitcode} and error message #{err}. STDOUT: #{value.to_s.strip}")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
value.to_s.strip
|
data/lib/miq_utilities.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
3
|
+
# Module to include resources
|
2
4
|
module MiqUtilities
|
3
5
|
require_relative 'miq_utilities/version'
|
4
6
|
require_relative 'miq_utilities/infoblox.rb'
|
@@ -7,4 +9,6 @@ module MiqUtilities
|
|
7
9
|
require_relative 'miq_utilities/sql.rb'
|
8
10
|
require_relative 'miq_utilities/winrm.rb'
|
9
11
|
require_relative 'miq_utilities/vmware.rb'
|
12
|
+
require_relative 'miq_utilities/ssh.rb'
|
13
|
+
require_relative 'miq_utilities/chef.rb'
|
10
14
|
end
|
data/miq_utilities.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miq_utilities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron McCatty
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '2.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: slack-notifier
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '2.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '2.3'
|
111
125
|
description: " This Gem was written to hold utilities commonly used within ManageIQ/Cloudforms. "
|
112
126
|
email:
|
113
127
|
- aaronmccatty@hotmail.co.uk
|
@@ -116,6 +130,7 @@ extensions: []
|
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
132
|
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
119
134
|
- Gemfile
|
120
135
|
- Gemfile.lock
|
121
136
|
- LICENSE.txt
|
@@ -124,10 +139,13 @@ files:
|
|
124
139
|
- bin/console
|
125
140
|
- bin/setup
|
126
141
|
- lib/miq_utilities.rb
|
142
|
+
- lib/miq_utilities/chef.rb
|
143
|
+
- lib/miq_utilities/general.rb
|
127
144
|
- lib/miq_utilities/infoblox.rb
|
128
145
|
- lib/miq_utilities/logging.rb
|
129
146
|
- lib/miq_utilities/notification.rb
|
130
147
|
- lib/miq_utilities/sql.rb
|
148
|
+
- lib/miq_utilities/ssh.rb
|
131
149
|
- lib/miq_utilities/version.rb
|
132
150
|
- lib/miq_utilities/vmware.rb
|
133
151
|
- lib/miq_utilities/winrm.rb
|