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 +5 -5
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/cloud66_agent.gemspec +1 -1
- data/lib/cloud66_agent/commands/configure.rb +46 -40
- data/lib/cloud66_agent/commands/vitals.rb +2 -2
- data/lib/cloud66_agent/utils/config.rb +121 -111
- data/lib/cloud66_agent/utils/server.rb +74 -74
- data/lib/cloud66_agent/utils/version.rb +1 -1
- data/lib/cloud66_agent/utils/vital_signs.rb +111 -85
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c38dc8b98765dbcd9303528cc6ff8c57013613c1908b259e73c0b17d5f1327c7
|
4
|
+
data.tar.gz: 930f568ce197cf07f061f026af19231b6050486769450f617049449451b44e50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00c8fa84e68deea570a160aa7aa9eca9286312c35dad0b44e7700a7cb793f753a03f99f1a311be63aa666b918c1c9a1c42f7fc2d174386f9a6482f399cdd47fa
|
7
|
+
data.tar.gz: affeb9cb1ef085b1db0f8ff18e366b4e7e7af408c6fed305eb637587a46b315a22a9d7b9353288ed6fd741fda2331b16bb2eb7db7f00fb783339772f606c5854
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.4.
|
1
|
+
ruby-2.4.5
|
data/cloud66_agent.gemspec
CHANGED
@@ -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 = '
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
49
|
-
|
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.
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
5
|
+
module Utils
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def self.send_configure(data)
|
14
|
+
process(do_request(:post, '/server/configure.json', build_content(data)))
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def self.send_pulse
|
18
|
+
process(do_request(:get, "/server/#{$config.agent_uid}/pulse.json", build_content))
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
46
|
+
private
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
92
|
-
|
91
|
+
end
|
92
|
+
end
|
93
93
|
end
|
@@ -1,97 +1,123 @@
|
|
1
1
|
module Cloud66
|
2
|
-
|
3
|
-
|
2
|
+
module Utils
|
3
|
+
class VitalSigns
|
4
4
|
|
5
|
-
|
6
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
# it is aws
|
66
|
+
return true
|
67
|
+
rescue => exc
|
68
|
+
return false
|
69
|
+
end
|
74
70
|
|
75
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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.
|
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:
|
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.
|
163
|
+
rubygems_version: 2.7.9
|
164
164
|
signing_key:
|
165
165
|
specification_version: 4
|
166
166
|
summary: Cloud 66 server component
|