cloud66_agent 1.3.1 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 51ef1d2f57617cdc1d773ba203a52f105f47437e
4
- data.tar.gz: 76ef024511f59e0182a94eb39e4466cb38a0070e
2
+ SHA256:
3
+ metadata.gz: c38dc8b98765dbcd9303528cc6ff8c57013613c1908b259e73c0b17d5f1327c7
4
+ data.tar.gz: 930f568ce197cf07f061f026af19231b6050486769450f617049449451b44e50
5
5
  SHA512:
6
- metadata.gz: dc9c0e1e78b71b067235a022b776d68122e03f6d412e4c1b7b9c2d9c3e0a559c6044a7544b7281993921b7811ad94a3da70121247a8a4a597d77c7de351793f9
7
- data.tar.gz: cb8c05474defa7dc3901c8dcb6dbeed028d1f7ee6f8ea52f59149ef602064bf22eaa74006adaf45b097228e2d7c85233b0880013744e5aa0972c9a18f6ac32aa
6
+ metadata.gz: 00c8fa84e68deea570a160aa7aa9eca9286312c35dad0b44e7700a7cb793f753a03f99f1a311be63aa666b918c1c9a1c42f7fc2d174386f9a6482f399cdd47fa
7
+ data.tar.gz: affeb9cb1ef085b1db0f8ff18e366b4e7e7af408c6fed305eb637587a46b315a22a9d7b9353288ed6fd741fda2331b16bb2eb7db7f00fb783339772f606c5854
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.4.4
1
+ ruby-2.4.5
@@ -7,7 +7,7 @@ Gem::Specification.new do |gem|
7
7
  gem.name = "cloud66_agent"
8
8
  gem.version = Cloud66::Utils::Version.current
9
9
  gem.platform = Gem::Platform::RUBY
10
- gem.date = '2018-04-10'
10
+ gem.date = '2019-03-27'
11
11
  gem.authors = ["Cloud 66"]
12
12
  gem.email = ['hello@cloud66.com']
13
13
  gem.licenses = ['MIT']
@@ -3,48 +3,54 @@ require 'cloud66_agent/utils/version'
3
3
  require 'cloud66_agent/utils/server'
4
4
 
5
5
  module Cloud66
6
- module Commands
7
- class Configure
8
- def self.perform(server_uid, cloud)
9
- begin
10
- if cloud.nil? || cloud.empty?
11
- # try figure it out
12
- $config.is_aws = Utils::VitalSigns.is_aws?
6
+ module Commands
7
+ class Configure
8
+ def self.perform(server_uid, cloud)
9
+ begin
10
+ if cloud.nil? || cloud.empty?
11
+ # try figure it out
12
+ $config.is_aws = Utils::VitalSigns.is_aws?
13
13
 
14
- if $config.is_aws
15
- $config.is_gc = false
16
- else
17
- # try figure it out
18
- $config.is_gc = Utils::VitalSigns.is_gc?
19
- end
20
- else
21
- # use the passed in value
22
- $config.is_aws = (cloud == 'aws')
14
+ if $config.is_aws
15
+ $config.is_gc = false
16
+ else
17
+ # try figure it out
18
+ $config.is_gc = Utils::VitalSigns.is_gc?
19
+ end
20
+ else
21
+ # use the passed in value
22
+ $config.is_aws = (cloud == 'aws')
23
23
 
24
- # use the passed in value
25
- $config.is_gc = (cloud == 'googlecloud')
26
- end
27
- data = {
28
- :timezone => Time.new.zone,
29
- :server_uid => server_uid,
30
- :version => Utils::Version.current,
31
- :system => Utils::VitalSigns.system_info }
24
+ # use the passed in value
25
+ $config.is_gc = (cloud == 'googlecloud')
26
+ end
27
+ data = {
28
+ :timezone => Time.new.zone,
29
+ :server_uid => server_uid,
30
+ :version => Utils::Version.current,
31
+ :system => Utils::VitalSigns.system_info}
32
32
 
33
- address_info = Utils::VitalSigns.address_info
34
- data = data.merge(address_info)
35
- rescue => exc
36
- data = { error: exc.message }
37
- end
38
- result = Utils::Server.send_configure data
39
- $config.agent_uid = result['agent_uid']
40
- $config.disabled = false
41
- $config.save
42
- exit 0
43
- rescue => exc
44
- $logger.error "Command \"configure\" failed: #{exc.message}"
45
- exit -1
46
- end
33
+ address_info = Utils::VitalSigns.address_info
34
+ data = data.merge(address_info)
35
+ rescue => exc
36
+ data = {error: exc.message}
37
+ end
38
+ result = Utils::Server.send_configure data
39
+ $config.agent_uid = result['agent_uid']
47
40
 
48
- end
49
- end
41
+ disk_warning_percent = result['disk_warning_percent']
42
+ $config.disk_warning_percent = disk_warning_percent.to_i unless disk_warning_percent.nil?
43
+ disk_critical_percent = result['disk_critical_percent']
44
+ $config.disk_critical_percent = disk_critical_percent.to_i unless disk_critical_percent.nil?
45
+
46
+ $config.disabled = false
47
+ $config.save
48
+ exit 0
49
+ rescue => exc
50
+ $logger.error "Command \"configure\" failed: #{exc.message}"
51
+ exit -1
52
+ end
53
+
54
+ end
55
+ end
50
56
  end
@@ -6,11 +6,11 @@ module Cloud66
6
6
  class Vitals
7
7
  def self.perform
8
8
  begin
9
- data = Utils::VitalSigns.vitals_info
9
+ data = Utils::VitalSigns.vitals_alerts
10
10
  rescue => exc
11
11
  data = { error: exc.message }
12
12
  end
13
- Utils::Server.send_vitals data
13
+ Utils::Server.send_vitals(data) if !data.nil? && !data.empty?
14
14
  exit 0
15
15
  rescue => exc
16
16
  $logger.error "Command \"vitals\" failed: #{exc.message}"
@@ -1,115 +1,125 @@
1
1
  require 'cloud66_agent/utils/vital_signs'
2
2
 
3
3
  module Cloud66
4
- module Utils
5
- class Config
6
-
7
- # default conf dir
8
- CONFIG_PATH = "/etc/cloud66/cloud66_agent.yml"
9
-
10
- attr_accessor :api_url,
11
- :api_key,
12
- :secret_key,
13
- :agent_uid,
14
- :disabled,
15
- :is_aws,
16
- :is_gc,
17
- :log,
18
- :log_level
19
-
20
- # load up the config at startup
21
- def initialize
22
- load if File.exists?(CONFIG_PATH)
23
-
24
- # set defaults
25
- @log = @log.nil? ? "/var/log/cloud66_agent.log" : @log == "STDOUT" ? STDOUT : @log
26
- @log_level ||= 2
27
- @api_url ||= 'https://api.cloud66.com'
28
- @disabled ||= false
29
- @is_aws ||= false
30
- @is_gc ||= false
31
- end
32
-
33
- def is_agent_configured?
34
- return !@agent_uid.nil? && !@agent_uid.empty?
35
- end
36
-
37
- def save
38
- Dir.mkdir(CONFIG_PATH) if !FileTest::directory?(File.dirname(CONFIG_PATH))
39
-
40
- File.open(CONFIG_PATH, 'w+') do |out|
41
- data = {
42
- 'api_url' => @api_url,
43
- 'api_key' => @api_key,
44
- 'secret_key' => @secret_key,
45
- 'agent_uid' => @agent_uid,
46
- 'disabled' => @disabled,
47
- 'is_aws' => @is_aws,
48
- 'is_gc' => @is_gc,
49
- 'log' => @log == STDOUT ? "STDOUT" : @log,
50
- 'log_level' => @log_level,
51
- }
52
- out.puts to_cust_yaml(data)
53
- end
54
- end
55
-
56
- def delete
57
- File.delete(CONFIG_PATH) if File.exists?(CONFIG_PATH)
58
- end
59
-
60
- private
61
-
62
- def load
63
- raise "config not found" unless File.exists?(CONFIG_PATH)
64
- config = from_cust_yaml(IO.read(CONFIG_PATH))
65
- @api_url = config['api_url']
66
- @api_key = config['api_key']
67
- @secret_key = config['secret_key']
68
- @agent_uid = config['agent_uid']
69
- @disabled = config['disabled']
70
- @is_aws = config['is_aws']
71
- @is_gc = config['is_gc']
72
- @log = config['log']
73
- @log_level = config['log_level']
74
- rescue
75
- # we can't load the file
76
- end
77
-
78
- # temporary measure to handle psych dependency errors
79
- def to_cust_yaml(hash)
80
- yaml_output = ''
81
- hash.each do |key, value|
82
- if !!value == value || value.is_a?(Integer)
83
- yaml_output += "#{key}: #{value.to_s}\n"
84
- else
85
- yaml_output += "#{key}: \"#{value.to_s}\"\n"
86
- end
87
- end
88
- return yaml_output
89
- end
90
-
91
- # temporary measure to handle psych dependency errors
92
- def from_cust_yaml(yaml)
93
- hash = {}
94
- yaml.lines.each do |line|
95
- next if line.nil? || !line.include?(':')
96
- key = line.split(':', 2)[0].strip
97
- value = line.split(':', 2)[1].strip
98
- next if value.empty?
99
-
100
- if value =~ /^(true|false)$/
101
- value = true if value == 'true'
102
- value = false if value == 'false'
103
- elsif value =~ /^[0-9]+$/
104
- value = value.to_i
105
- elsif value =~ /^".*"$/
106
- value = value.gsub(/^"/, '').gsub(/"$/,'')
107
- end
108
- hash[key] = value
109
- end
110
- return hash
111
- end
112
-
113
- end
114
- end
4
+ module Utils
5
+ class Config
6
+
7
+ # default conf dir
8
+ CONFIG_PATH = "/etc/cloud66/cloud66_agent.yml"
9
+
10
+ attr_accessor :api_url,
11
+ :api_key,
12
+ :secret_key,
13
+ :agent_uid,
14
+ :disabled,
15
+ :is_aws,
16
+ :is_gc,
17
+ :log,
18
+ :log_level,
19
+ :disk_warning_percent,
20
+ :disk_critical_percent
21
+
22
+ # load up the config at startup
23
+ def initialize
24
+ load if File.exists?(CONFIG_PATH)
25
+
26
+ # set defaults
27
+ @log = @log.nil? ? "/var/log/cloud66_agent.log" : @log == "STDOUT" ? STDOUT : @log
28
+ @log_level ||= 2
29
+ @api_url ||= 'https://api.cloud66.com'
30
+ @disabled ||= false
31
+ @is_aws ||= false
32
+ @is_gc ||= false
33
+
34
+ # defaults
35
+ @disk_warning_percent = 80
36
+ @disk_critical_percent = 90
37
+ end
38
+
39
+ def is_agent_configured?
40
+ return !@agent_uid.nil? && !@agent_uid.empty?
41
+ end
42
+
43
+ def save
44
+ Dir.mkdir(CONFIG_PATH) if !FileTest::directory?(File.dirname(CONFIG_PATH))
45
+
46
+ File.open(CONFIG_PATH, 'w+') do |out|
47
+ data = {
48
+ 'api_url' => @api_url,
49
+ 'api_key' => @api_key,
50
+ 'secret_key' => @secret_key,
51
+ 'agent_uid' => @agent_uid,
52
+ 'disabled' => @disabled,
53
+ 'is_aws' => @is_aws,
54
+ 'is_gc' => @is_gc,
55
+ 'log' => @log == STDOUT ? "STDOUT" : @log,
56
+ 'log_level' => @log_level,
57
+ 'disk_warning_percent' => @disk_warning_percent,
58
+ 'disk_critical_percent' => @disk_critical_percent,
59
+ }
60
+ out.puts to_cust_yaml(data)
61
+ end
62
+ end
63
+
64
+ def delete
65
+ File.delete(CONFIG_PATH) if File.exists?(CONFIG_PATH)
66
+ end
67
+
68
+ private
69
+
70
+ def load
71
+ raise "config not found" unless File.exists?(CONFIG_PATH)
72
+ config = from_cust_yaml(IO.read(CONFIG_PATH))
73
+ @api_url = config['api_url']
74
+ @api_key = config['api_key']
75
+ @secret_key = config['secret_key']
76
+ @agent_uid = config['agent_uid']
77
+ @disabled = config['disabled']
78
+ @is_aws = config['is_aws']
79
+ @is_gc = config['is_gc']
80
+ @log = config['log']
81
+ @log_level = config['log_level']
82
+ @disk_warning_percent = config['disk_warning_percent'].to_i if config['disk_warning_percent']
83
+ @disk_critical_percent = config['disk_critical_percent'].to_i if config['disk_critical_percent']
84
+ rescue
85
+ # we can't load the file
86
+ end
87
+
88
+ # temporary measure to handle psych dependency errors
89
+ def to_cust_yaml(hash)
90
+ yaml_output = ''
91
+ hash.each do |key, value|
92
+ if !!value == value || value.is_a?(Integer)
93
+ yaml_output += "#{key}: #{value.to_s}\n"
94
+ else
95
+ yaml_output += "#{key}: \"#{value.to_s}\"\n"
96
+ end
97
+ end
98
+ return yaml_output
99
+ end
100
+
101
+ # temporary measure to handle psych dependency errors
102
+ def from_cust_yaml(yaml)
103
+ hash = {}
104
+ yaml.lines.each do |line|
105
+ next if line.nil? || !line.include?(':')
106
+ key = line.split(':', 2)[0].strip
107
+ value = line.split(':', 2)[1].strip
108
+ next if value.empty?
109
+
110
+ if value =~ /^(true|false)$/
111
+ value = true if value == 'true'
112
+ value = false if value == 'false'
113
+ elsif value =~ /^[0-9]+$/
114
+ value = value.to_i
115
+ elsif value =~ /^".*"$/
116
+ value = value.gsub(/^"/, '').gsub(/"$/, '')
117
+ end
118
+ hash[key] = value
119
+ end
120
+ return hash
121
+ end
122
+
123
+ end
124
+ end
115
125
  end
@@ -2,92 +2,92 @@ require 'httparty'
2
2
  require 'json'
3
3
 
4
4
  module Cloud66
5
- module Utils
5
+ module Utils
6
6
 
7
- class Server
8
- include HTTParty
9
- # set the default request timeout to 45 seconds
10
- # this sets the open_timeout and the read_timeout
11
- default_timeout 45
7
+ class Server
8
+ include HTTParty
9
+ # set the default request timeout to 45 seconds
10
+ # this sets the open_timeout and the read_timeout
11
+ default_timeout 45
12
12
 
13
- def self.send_configure(data)
14
- process(do_request(:post, '/server/configure.json', build_content(data)))
15
- end
13
+ def self.send_configure(data)
14
+ process(do_request(:post, '/server/configure.json', build_content(data)))
15
+ end
16
16
 
17
- def self.send_pulse
18
- process(do_request(:get, "/server/#{$config.agent_uid}/pulse.json", build_content))
19
- end
17
+ def self.send_pulse
18
+ process(do_request(:get, "/server/#{$config.agent_uid}/pulse.json", build_content))
19
+ end
20
20
 
21
- def self.send_address(data)
22
- process(do_request(:post, "/server/#{$config.agent_uid}/address.json", build_content(data)))
23
- end
21
+ def self.send_address(data)
22
+ process(do_request(:post, "/server/#{$config.agent_uid}/address.json", build_content(data)))
23
+ end
24
24
 
25
- def self.send_vitals(data)
26
- process(do_request(:post, "/server/#{$config.agent_uid}/vitals.json", build_content(data)))
27
- end
25
+ def self.send_vitals(data)
26
+ process(do_request(:post, "/server/#{$config.agent_uid}/vitals_alerts.json", build_content(data)))
27
+ end
28
28
 
29
- def self.send_job_start(job_uid)
30
- process(do_request(:get, "/job/#{job_uid}/start.json", build_content))
31
- end
29
+ def self.send_job_start(job_uid)
30
+ process(do_request(:get, "/job/#{job_uid}/start.json", build_content))
31
+ end
32
32
 
33
- def self.send_job_end(job_uid, data)
34
- process(do_request(:post, "/job/#{job_uid}/end.json", build_content(data)))
35
- end
33
+ def self.send_job_end(job_uid, data)
34
+ process(do_request(:post, "/job/#{job_uid}/end.json", build_content(data)))
35
+ end
36
36
 
37
- def self.send_fail2ban(data)
38
- process(do_request(:post, "/server/#{$config.agent_uid}/fail2ban.json", build_content(data)))
39
- end
37
+ def self.send_fail2ban(data)
38
+ process(do_request(:post, "/server/#{$config.agent_uid}/fail2ban.json", build_content(data)))
39
+ end
40
40
 
41
- def self.send_message(data)
42
- #puts data
43
- process(do_request(:post, "/server/#{$config.agent_uid}/message.json", build_content(data)))
44
- end
41
+ def self.send_message(data)
42
+ #puts data
43
+ process(do_request(:post, "/server/#{$config.agent_uid}/message.json", build_content(data)))
44
+ end
45
45
 
46
- private
46
+ private
47
47
 
48
- def self.process(response)
49
- $logger.debug "Received response!"
50
- if response.code != 200
51
- $logger.debug "Response code: #{response.code}"
52
- $logger.debug "Response body: #{response.body}"
53
- raise response.body
54
- else
55
- parsed_response = response.parsed_response
56
- unless parsed_response['ok']
57
- if parsed_response['shut_down']
58
- $config.disabled = true
59
- $config.save
60
- exit 86
61
- elsif parsed_response.has_key?('error')
62
- raise parsed_response['error']
63
- else
64
- raise "unidentified error"
65
- end
66
- end
67
- $logger.debug "Parsed response: #{parsed_response}"
68
- parsed_response['data']
69
- end
70
- end
48
+ def self.process(response)
49
+ $logger.debug "Received response!"
50
+ if response.code != 200
51
+ $logger.debug "Response code: #{response.code}"
52
+ $logger.debug "Response body: #{response.body}"
53
+ raise response.body
54
+ else
55
+ parsed_response = response.parsed_response
56
+ unless parsed_response['ok']
57
+ if parsed_response['shut_down']
58
+ $config.disabled = true
59
+ $config.save
60
+ exit 86
61
+ elsif parsed_response.has_key?('error')
62
+ raise parsed_response['error']
63
+ else
64
+ raise "unidentified error"
65
+ end
66
+ end
67
+ $logger.debug "Parsed response: #{parsed_response}"
68
+ parsed_response['data']
69
+ end
70
+ end
71
71
 
72
- def self.do_request(verb, url, content)
73
- $logger.debug "Sending (#{verb}) request..."
74
- $logger.debug "Request url: #{url}"
75
- $logger.debug "Request content: #{content}"
76
- base_uri $config.api_url
77
- self.send verb, url, content
78
- end
72
+ def self.do_request(verb, url, content)
73
+ $logger.debug "Sending (#{verb}) request..."
74
+ $logger.debug "Request url: #{url}"
75
+ $logger.debug "Request content: #{content}"
76
+ base_uri $config.api_url
77
+ self.send verb, url, content
78
+ end
79
79
 
80
- def self.build_content(data = nil)
81
- time = Time.now.utc.to_i
82
- hash = Digest::SHA1.hexdigest("#{$config.api_key}#{$config.secret_key}#{time}").downcase
83
- if data.nil?
84
- content = { :headers => { 'api-key' => $config.api_key, 'hash' => hash, 'time' => time.to_s } }
85
- else
86
- content = { :headers => { 'api-key' => $config.api_key, 'hash' => hash, 'time' => time.to_s, 'Content-Type' => 'application/json' }, :body => { data: data }.to_json }
87
- end
88
- content
89
- end
80
+ def self.build_content(data = nil)
81
+ time = Time.now.utc.to_i
82
+ hash = Digest::SHA1.hexdigest("#{$config.api_key}#{$config.secret_key}#{time}").downcase
83
+ if data.nil?
84
+ content = {:headers => {'api-key' => $config.api_key, 'hash' => hash, 'time' => time.to_s}}
85
+ else
86
+ content = {:headers => {'api-key' => $config.api_key, 'hash' => hash, 'time' => time.to_s, 'Content-Type' => 'application/json'}, :body => {data: data}.to_json}
87
+ end
88
+ content
89
+ end
90
90
 
91
- end
92
- end
91
+ end
92
+ end
93
93
  end
@@ -13,7 +13,7 @@ module Cloud66
13
13
  # Defines the minor version
14
14
  # PATCH:
15
15
  # Defines the patch version
16
- MAJOR, MINOR, PATCH = 1, 3, 1
16
+ MAJOR, MINOR, PATCH = 1, 4, 0
17
17
 
18
18
  #ie. PRERELEASE_MODIFIER = 'beta1' or nil
19
19
  PRERELEASE_MODIFIER = nil
@@ -1,97 +1,123 @@
1
1
  module Cloud66
2
- module Utils
3
- class VitalSigns
2
+ module Utils
3
+ class VitalSigns
4
4
 
5
- IP_BLOCK_REGEX = /\d{,2}|1\d{2}|2[0-4]\d|25[0-5]/
6
- IP_REGEX = /\A#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\z/
5
+ IP_BLOCK_REGEX = /\d{,2}|1\d{2}|2[0-4]\d|25[0-5]/
6
+ IP_REGEX = /\A#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\.#{IP_BLOCK_REGEX}\z/
7
7
 
8
- def self.system_info
9
- # system info
10
- return parse_data(`facter`)
11
- end
12
8
 
13
- def self.address_info
14
- result = {}
15
- # AWS special case
16
- if $config.is_aws
17
- reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
18
- result[:ext_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
19
- reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/local-ipv4`
20
- result[:int_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
21
- # GC special case
22
- elsif $config.is_gc
23
- external_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip`
24
- result[:ext_ipv4] = external_ip if external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
25
- internal_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/ip`
26
- result[:int_ipv4] = internal_ip if internal_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
27
- else
28
- interfaces_raw = `facter interfaces`.strip
29
- interfaces = interfaces_raw.split(',').select { |interface| interface !~ /^lo/ }
30
- # don't have any ip address info
31
- unless interfaces.empty?
32
- # return all interface information
33
- facter_command = "facter #{interfaces.map { |interface| "ipaddress_#{interface} ipaddress6_#{interface}" }.join(' ')}"
34
- raw_data = `#{facter_command}`.strip
35
- result = parse_data(raw_data) rescue {}
36
- end
37
- end
38
- normalised_hash = {}
39
- result.each do |key, value|
40
- if value =~ IP_REGEX && value != '127.0.0.1' && value != '127.0.1.1'
41
- normalised_hash[key] = value
42
- end
43
- end
44
- return normalised_hash
45
- end
9
+ def self.system_info
10
+ # system info
11
+ return parse_data(`facter`)
12
+ end
46
13
 
47
- def self.is_aws?
48
- # 6 seconds to find out if this is a AWS image or not!
49
- instance = `/usr/bin/curl --connect-timeout 6 -s http://169.254.169.254/latest/meta-data/instance-id` rescue nil
50
- return false if instance.nil? || instance.empty?
14
+ def self.vitals_alerts
15
+ vitals_alerts = {}
16
+ space_alerts = calculate_space_alerts($config.disk_warning_percent, $config.disk_critical_percent)
17
+ vitals_alerts[:disk] = space_alerts if space_alerts.present?
18
+ return vitals_alerts
19
+ end
51
20
 
52
- # now check the external ip to make sure we're not just being routed
53
- reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4` rescue nil
54
- return false if reported_ip.nil? || reported_ip.empty?
55
- return false unless reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
21
+ def self.address_info
22
+ result = {}
23
+ # AWS special case
24
+ if $config.is_aws
25
+ reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
26
+ result[:ext_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
27
+ reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/local-ipv4`
28
+ result[:int_ipv4] = reported_ip if reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
29
+ # GC special case
30
+ elsif $config.is_gc
31
+ external_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip`
32
+ result[:ext_ipv4] = external_ip if external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
33
+ internal_ip = `/usr/bin/curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/ip`
34
+ result[:int_ipv4] = internal_ip if internal_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
35
+ else
36
+ interfaces_raw = `facter interfaces`.strip
37
+ interfaces = interfaces_raw.split(',').select {|interface| interface !~ /^lo/}
38
+ # don't have any ip address info
39
+ unless interfaces.empty?
40
+ # return all interface information
41
+ facter_command = "facter #{interfaces.map {|interface| "ipaddress_#{interface} ipaddress6_#{interface}"}.join(' ')}"
42
+ raw_data = `#{facter_command}`.strip
43
+ result = parse_data(raw_data) rescue {}
44
+ end
45
+ end
46
+ normalised_hash = {}
47
+ result.each do |key, value|
48
+ if value =~ IP_REGEX && value != '127.0.0.1' && value != '127.0.1.1'
49
+ normalised_hash[key] = value
50
+ end
51
+ end
52
+ return normalised_hash
53
+ end
56
54
 
57
- # it is aws
58
- return true
59
- rescue => exc
60
- return false
61
- end
55
+ def self.is_aws?
56
+ # 6 seconds to find out if this is a AWS image or not!
57
+ instance = `/usr/bin/curl --connect-timeout 6 -s http://169.254.169.254/latest/meta-data/instance-id` rescue nil
58
+ return false if instance.nil? || instance.empty?
62
59
 
63
- def self.is_gc?
64
- # 6 seconds to find out if this is a AWS image or not!
65
- external_ip = `/usr/bin/curl --connect-timeout 6 -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip` rescue nil
66
- return false if external_ip.nil? || external_ip.empty?
67
- return false unless external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
60
+ # now check the external ip to make sure we're not just being routed
61
+ reported_ip = `/usr/bin/curl -s http://169.254.169.254/latest/meta-data/public-ipv4` rescue nil
62
+ return false if reported_ip.nil? || reported_ip.empty?
63
+ return false unless reported_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
68
64
 
69
- # it is google cloud
70
- return true
71
- rescue => exc
72
- return false
73
- end
65
+ # it is aws
66
+ return true
67
+ rescue => exc
68
+ return false
69
+ end
74
70
 
75
- private
71
+ def self.is_gc?
72
+ # 6 seconds to find out if this is a AWS image or not!
73
+ external_ip = `/usr/bin/curl --connect-timeout 6 -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip` rescue nil
74
+ return false if external_ip.nil? || external_ip.empty?
75
+ return false unless external_ip =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
76
76
 
77
- # parse the data, not using YAML due to YAML parsing issues and JSON output not always working
78
- def self.parse_data(data)
79
- hash = {}
80
- data.lines.each do |line|
81
- split = line.split('=>')
82
- if split.size == 2
83
- key = split[0].strip rescue ''
84
- value = split[1].strip rescue ''
85
- if !value.nil? && value != 'nil'
86
- # exclude empty or long results (like ssh keys)
87
- if !value.empty? && value.size < 100
88
- hash[key] = value
89
- end
90
- end
91
- end
92
- end
93
- return hash
94
- end
95
- end
96
- end
77
+ # it is google cloud
78
+ return true
79
+ rescue => exc
80
+ return false
81
+ end
82
+
83
+ def self.calculate_space_alerts(warning_threshold, critical_threshold)
84
+ space_alerts = []
85
+ return space_alerts if warning_threshold == 0 || critical_threshold == 0
86
+ # get the df output (linux only)
87
+ df_output = `sudo df -h | grep -v /var/lib/docker | grep -v /var/lib/kubelet | grep -v Use% | awk '{print $1"|"$6"|"$5}'`
88
+ df_output.lines.each do |df_line|
89
+ parts = df_line.split('|')
90
+ next unless parts.size == 3
91
+ filesystem = parts[0].strip
92
+ mounted = parts[1].strip
93
+ percentage = parts[2].strip.gsub(/%/, '').to_i
94
+ if percentage >= critical_threshold
95
+ space_alerts << {level: :critical, filesystem: filesystem, mounted: mounted, percentage: percentage}
96
+ elsif percentage > warning_threshold
97
+ space_alerts << {level: :warning, filesystem: filesystem, mounted: mounted, percentage: percentage}
98
+ end
99
+ end
100
+ return space_alerts
101
+ end
102
+
103
+ # parse the data, not using YAML due to YAML parsing issues and JSON output not always working
104
+ def self.parse_data(data)
105
+ hash = {}
106
+ data.lines.each do |line|
107
+ split = line.split('=>')
108
+ if split.size == 2
109
+ key = split[0].strip rescue ''
110
+ value = split[1].strip rescue ''
111
+ if !value.nil? && value != 'nil'
112
+ # exclude empty or long results (like ssh keys)
113
+ if !value.empty? && value.size < 100
114
+ hash[key] = value
115
+ end
116
+ end
117
+ end
118
+ end
119
+ return hash
120
+ end
121
+ end
122
+ end
97
123
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud66_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cloud 66
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-10 00:00:00.000000000 Z
11
+ date: 2019-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mime-types
@@ -160,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  version: '0'
161
161
  requirements: []
162
162
  rubyforge_project:
163
- rubygems_version: 2.6.14.1
163
+ rubygems_version: 2.7.9
164
164
  signing_key:
165
165
  specification_version: 4
166
166
  summary: Cloud 66 server component