instrumental_tools 1.0.0 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/BUILD.md +15 -0
- data/CHANGELOG.md +17 -1
- data/CUSTOM_METRICS.md +4 -0
- data/INSTALL.md +12 -7
- data/README.md +2 -2
- data/Rakefile +202 -64
- data/TEST.md +18 -0
- data/bin/instrument_server +31 -15
- data/chef/.kitchen.yml +10 -1
- data/chef/instrumental_tools/attributes/default.rb +29 -2
- data/chef/instrumental_tools/recipes/default.rb +188 -17
- data/chef/instrumental_tools/templates/default/instrument_server.erb +46 -0
- data/chef/instrumental_tools/templates/{instrumental.yml.erb → default/instrumental.yml.erb} +6 -6
- data/chef/omnibus.sh +27 -0
- data/conf/instrumental.yml +6 -6
- data/examples/README.md +1 -0
- data/examples/redis/README.md +10 -0
- data/examples/redis/redis_info.sh +10 -0
- data/ext/Rakefile +1 -0
- data/ext/mkrf_conf.rb +18 -0
- data/instrumental_tools.gemspec +8 -2
- data/lib/instrumental_tools/metric_script_executor.rb +45 -6
- data/lib/instrumental_tools/server_controller.rb +4 -1
- data/lib/instrumental_tools/system_inspector.rb +3 -0
- data/lib/instrumental_tools/system_inspector/win32.rb +85 -0
- data/lib/instrumental_tools/version.rb +1 -1
- data/test/integration/default/serverspec/instrumental_tools_spec.rb +32 -16
- data/win32/Makefile +18 -0
- data/win32/installer.nsis.erb +242 -0
- data/win32/logo.ico +0 -0
- data/win32/src/instrumental/InstrumentServerProcess.cs +147 -0
- data/win32/src/instrumental/InstrumentServerProcessWorker.cs +89 -0
- data/win32/src/instrumental/InstrumentServerService.cs +146 -0
- data/win32/src/instrumental/InstrumentServerServiceInstaller.cs +60 -0
- metadata +36 -7
data/TEST.md
CHANGED
@@ -7,3 +7,21 @@ bundle exec kitchen verify
|
|
7
7
|
```
|
8
8
|
|
9
9
|
to test installation and setup procedures for the `instrumental_tools` command. You must have [Vagrant](https://www.vagrantup.com/) installed; currently the KitchenCI integration is setup to use [VMWare Fusion](http://www.vmware.com/products/fusion) and the [VMWare Fusion Vagrant provider](https://www.vagrantup.com/vmware); you can configure a separate provider for your specific setup by change the `provider` flag in the `.kitchen.yml` file for your particular setup.
|
10
|
+
|
11
|
+
## Windows
|
12
|
+
|
13
|
+
Ensure you have the `winrm` vagrant plugin installed.
|
14
|
+
|
15
|
+
```
|
16
|
+
vagrant plugin install vagrant-winrm
|
17
|
+
```
|
18
|
+
|
19
|
+
|
20
|
+
To ensure you have a Windows Vagrant image, perform the following steps in a separate directory to build a Windows evaluation image:
|
21
|
+
|
22
|
+
```
|
23
|
+
git clone https://github.com/boxcutter/windows.git
|
24
|
+
cd windows
|
25
|
+
make virtualbox/eval-win2012r2-standard
|
26
|
+
vagrant box add windows-2012r2 ./box/virtualbox/eval-win2012r2-standard-nocm-1.0.4.box
|
27
|
+
```
|
data/bin/instrument_server
CHANGED
@@ -27,19 +27,28 @@ def require_api_key(options, parser)
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def coerce_path(path)
|
31
|
+
if File::ALT_SEPARATOR
|
32
|
+
File.join(*path.split(File::ALT_SEPARATOR))
|
33
|
+
else
|
34
|
+
path
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
30
38
|
|
31
39
|
cur_directory = Dir.pwd
|
32
40
|
home_directory = Dir.home rescue nil
|
33
41
|
script_location = File.expand_path(File.dirname(__FILE__))
|
34
42
|
tmp_dir = Dir.tmpdir
|
35
43
|
script_data_directory = [cur_directory, home_directory, script_location, tmp_dir].compact.detect { |dir| File.writable?(dir) }
|
44
|
+
windows = RUBY_PLATFORM =~ /(mswin|win32|mingw)/i
|
36
45
|
|
37
46
|
default_script_directory = File.join(script_data_directory, '.instrumental_scripts')
|
38
47
|
default_command = :foreground
|
39
48
|
|
40
49
|
options = {
|
41
50
|
:collector => 'collector.instrumentalapp.com',
|
42
|
-
:port => '
|
51
|
+
:port => '8001',
|
43
52
|
:hostname => Socket.gethostname,
|
44
53
|
:pid_location => File.join(script_data_directory, 'instrument_server.pid'),
|
45
54
|
:log_location => File.join(script_data_directory, 'instrument_server.log'),
|
@@ -63,13 +72,13 @@ Default command: #{default_command.to_s}
|
|
63
72
|
end
|
64
73
|
|
65
74
|
opts.on('-f', '--config-file PATH', "Config file with location of your API key (default #{options[:config_file]})") do |path|
|
66
|
-
options[:config_file] = path
|
75
|
+
options[:config_file] = coerce_path(path)
|
67
76
|
end
|
68
77
|
|
69
78
|
opts.on('-c', '--collector COLLECTOR[:PORT]', "Collector (default #{options[:collector]}:#{options[:port]})") do |collector|
|
70
|
-
address, port
|
79
|
+
address, port = collector.split(':')
|
71
80
|
options[:collector] = address
|
72
|
-
options[:port]
|
81
|
+
options[:port] = port if port
|
73
82
|
end
|
74
83
|
|
75
84
|
opts.on('-H', '--hostname HOSTNAME', "Hostname to report as (default #{options[:hostname]})") do |hostname|
|
@@ -77,11 +86,11 @@ Default command: #{default_command.to_s}
|
|
77
86
|
end
|
78
87
|
|
79
88
|
opts.on('-p', '--pid LOCATION', "Where daemon PID file is located (default #{options[:pid_location]})") do |pid_location|
|
80
|
-
options[:pid_location] = pid_location
|
89
|
+
options[:pid_location] = coerce_path(pid_location)
|
81
90
|
end
|
82
91
|
|
83
92
|
opts.on('-l', '--log LOCATION', "Where to put the instrument_server log file (default #{options[:log_location]})") do |log_location|
|
84
|
-
options[:log_location] = log_location
|
93
|
+
options[:log_location] = coerce_path(log_location)
|
85
94
|
end
|
86
95
|
|
87
96
|
opts.on('-r', '--report-interval INTERVAL_IN_SECONDS', "How often to report metrics to Instrumental (default #{options[:report_interval]})") do |interval|
|
@@ -93,15 +102,17 @@ Default command: #{default_command.to_s}
|
|
93
102
|
end
|
94
103
|
|
95
104
|
opts.on('-s', '--script-location PATH_TO_DIRECTORY', "Directory where local scripts for custom metrics are located (default #{options[:script_location]})") do |path|
|
96
|
-
options[:script_location] = path
|
105
|
+
options[:script_location] = coerce_path(path)
|
97
106
|
end
|
98
107
|
|
99
|
-
|
100
|
-
|
108
|
+
if !windows
|
109
|
+
opts.on('-u', '--user USER_TO_RUN_AS', "User to run instrument_server as. You must have permissions to drop privileges to this user.") do |u|
|
110
|
+
options[:user] = u
|
111
|
+
end
|
101
112
|
end
|
102
113
|
|
103
114
|
opts.on('-t', '--temp-dir TEMP_DIRECTORY', "Where to store temporary files (default #{options[:tmp_location]})") do |t|
|
104
|
-
options[:tmp_location] = t
|
115
|
+
options[:tmp_location] = coerce_path(t)
|
105
116
|
end
|
106
117
|
|
107
118
|
opts.on('--debug', "Print all sent metrics to the log") do
|
@@ -112,11 +123,16 @@ Default command: #{default_command.to_s}
|
|
112
123
|
puts opts
|
113
124
|
exit
|
114
125
|
end
|
126
|
+
|
127
|
+
opts.on('-v', '--version', 'Display version') do
|
128
|
+
puts "instrument_server: #{Instrumental::Tools::VERSION}"
|
129
|
+
exit 0
|
130
|
+
end
|
115
131
|
end
|
116
132
|
|
117
133
|
option_parser.parse!
|
118
134
|
|
119
|
-
if options[:user]
|
135
|
+
if options[:user] && !windows
|
120
136
|
desired_uid = Etc.getpwnam(options[:user]).uid
|
121
137
|
Process::Sys.setuid(desired_uid)
|
122
138
|
if desired_uid && desired_uid != 0
|
@@ -171,11 +187,11 @@ if options[:enable_scripts]
|
|
171
187
|
raise "The directory #{options[:script_location]} does not exist."
|
172
188
|
end
|
173
189
|
|
174
|
-
stat
|
175
|
-
|
176
|
-
|
190
|
+
stat = File::Stat.new(File.expand_path(options[:script_location]))
|
191
|
+
correct_mode = windows || ((stat.mode & 0xFFF) ^ 0O700) === 0
|
192
|
+
unless stat.owned? && correct_mode
|
177
193
|
uid = Process.uid
|
178
|
-
username = Etc.getpwuid(uid).name
|
194
|
+
username = Etc.getpwuid(uid).try(:name)
|
179
195
|
raise "The directory #{options[:script_location]} is writable/readable by others. Please ensure it is only writable / readable by user/uid #{username}/#{uid}"
|
180
196
|
end
|
181
197
|
|
data/chef/.kitchen.yml
CHANGED
@@ -1,16 +1,25 @@
|
|
1
1
|
---
|
2
2
|
driver:
|
3
3
|
name: vagrant
|
4
|
-
|
4
|
+
synced_folders:
|
5
|
+
- ["../", "/tools-root"]
|
6
|
+
customize:
|
7
|
+
memory: 2048
|
5
8
|
|
6
9
|
provisioner:
|
7
10
|
name: chef_solo
|
11
|
+
chef_omnibus_url: "https://raw.githubusercontent.com/expectedbehavior/instrumental_tools/master/chef/omnibus.sh"
|
8
12
|
|
9
13
|
platforms:
|
10
14
|
- name: ubuntu-12.04
|
11
15
|
- name: centos-6.6
|
16
|
+
- name: "d11wtq/gentoo"
|
17
|
+
- name: "windows-2012r2"
|
12
18
|
|
13
19
|
suites:
|
14
20
|
- name: default
|
15
21
|
run_list: ["instrumental_tools"]
|
16
22
|
attributes:
|
23
|
+
instrumental:
|
24
|
+
use_local: true
|
25
|
+
local_path: "/tools-root/"
|
@@ -1,2 +1,29 @@
|
|
1
|
-
default[:instrumental]
|
2
|
-
default[:instrumental][:api_key]
|
1
|
+
default[:instrumental] = {}
|
2
|
+
default[:instrumental][:api_key] = nil
|
3
|
+
|
4
|
+
default[:instrumental][:version] = "1.1.2"
|
5
|
+
default[:instrumental][:repo] = "https://s3.amazonaws.com/instrumental-tools"
|
6
|
+
|
7
|
+
default[:instrumental][:curl_path] = "/usr/bin/curl"
|
8
|
+
default[:instrumental][:wget_path] = "/usr/bin/wget"
|
9
|
+
|
10
|
+
default[:instrumental][:dest_init_file] = "/etc/init.d/instrument_server"
|
11
|
+
|
12
|
+
default[:instrumental][:enable_scripts] = false
|
13
|
+
|
14
|
+
|
15
|
+
if node[:platform_family] == "windows"
|
16
|
+
default[:instrumental][:destination_dir] = "C:\\Program Files (x86)\\Instrumental Tools"
|
17
|
+
default[:instrumental][:config_file] = "C:\\Program Files (x86)\\Instrumental Tools\\etc\\instrumental.yml"
|
18
|
+
default[:instrumental][:script_dir] = "C:\\Program Files (x86)\\Instrumental Tools\\scripts"
|
19
|
+
else
|
20
|
+
default[:instrumental][:destination_dir] = "/opt/instrumental-tools/"
|
21
|
+
default[:instrumental][:config_file] = "/etc/instrumental.yml"
|
22
|
+
default[:instrumental][:script_dir] = "/opt/instrumental-tools/.scripts"
|
23
|
+
default[:instrumental][:pid_file] = "/opt/instrumental-tools/instrument_server.pid"
|
24
|
+
default[:instrumental][:log_file] = "/opt/instrumental-tools/instrument_server.log"
|
25
|
+
default[:instrumental][:user] = "nobody"
|
26
|
+
end
|
27
|
+
|
28
|
+
default[:instrumental][:use_local] = false
|
29
|
+
default[:instrumental][:local_path] = nil
|
@@ -1,21 +1,192 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
supported_platforms = %w{debian rhel fedora arch gentoo slackware suse}
|
2
|
+
version = node["instrumental"]["version"]
|
3
|
+
arch = case node["kernel"]["machine"]
|
4
|
+
when "i386"
|
5
|
+
"x86"
|
6
|
+
else
|
7
|
+
node["kernel"]["machine"]
|
8
|
+
end
|
9
|
+
pkg_arch = case node["kernel"]["machine"]
|
10
|
+
when "x86_64"
|
11
|
+
"amd64"
|
12
|
+
else
|
13
|
+
node["kernel"]["machine"]
|
14
|
+
end
|
15
|
+
file_name = case node["platform_family"]
|
16
|
+
when "osx"
|
17
|
+
"instrumental-tools_%s_osx.tar.gz" % version
|
18
|
+
when "debian"
|
19
|
+
"instrumental-tools_%s_%s.deb" % [version, pkg_arch]
|
20
|
+
when "rhel", "fedora"
|
21
|
+
"instrumental-tools_%s_%s.rpm" % [version, pkg_arch]
|
22
|
+
when "windows"
|
23
|
+
"instrumental-tools_%s_win32.exe" % version
|
24
|
+
else
|
25
|
+
"instrumental-tools_%s_linux-%s.tar.gz" % [version, arch]
|
26
|
+
end
|
27
|
+
|
28
|
+
local_path = ::File.join(node[:instrumental][:local_path], file_name)
|
29
|
+
dest_dir = node[:instrumental][:destination_dir]
|
30
|
+
conf_file = node[:instrumental][:config_file]
|
31
|
+
remote_name = "%s/%s/%s" % [node[:instrumental][:repo], version, file_name]
|
32
|
+
package_destination = ::File.join(dest_dir, file_name)
|
33
|
+
|
34
|
+
case node["platform_family"]
|
35
|
+
when "debian", "rhel", "fedora"
|
36
|
+
if node[:instrumental][:use_local]
|
37
|
+
package "instrumental-tools" do
|
38
|
+
action :install
|
39
|
+
source local_path
|
40
|
+
provider node["platform_family"] == "debian" ? Chef::Provider::Package::Dpkg : Chef::Provider::Package::Yum
|
41
|
+
end
|
42
|
+
else
|
43
|
+
packagecloud_repo "expectedbehavior/instrumental" do
|
44
|
+
case node["platform_family"]
|
45
|
+
when "debian"
|
46
|
+
type "deb"
|
47
|
+
when "rhel", "fedora"
|
48
|
+
type "rpm"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
package "instrumental-tools" do
|
53
|
+
action :upgrade
|
54
|
+
version node["instrumental"]["version"]
|
55
|
+
end
|
7
56
|
end
|
8
|
-
end
|
9
57
|
|
10
|
-
|
11
|
-
|
12
|
-
|
58
|
+
template conf_file do
|
59
|
+
source "instrumental.yml.erb"
|
60
|
+
mode "0440"
|
61
|
+
owner "nobody"
|
62
|
+
variables(
|
63
|
+
:api_key => node[:instrumental][:api_key]
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
template node["instrumental"]["dest_init_file"] do
|
68
|
+
source "instrument_server.erb"
|
69
|
+
mode "0755"
|
70
|
+
owner "nobody"
|
71
|
+
variables(
|
72
|
+
:dest_dir => dest_dir,
|
73
|
+
:config_file => conf_file,
|
74
|
+
:enable_scripts => !!node[:instrumental][:enable_scripts],
|
75
|
+
:script_dir => node[:instrumental][:script_dir],
|
76
|
+
:log_file => node[:instrumental][:log_file],
|
77
|
+
:pid_file => node[:instrumental][:pid_file],
|
78
|
+
:user => node[:instrumental][:user]
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
service "instrument_server" do
|
83
|
+
action :restart
|
84
|
+
end
|
85
|
+
|
86
|
+
when "arch", "gentoo", "slackware", "suse", "osx"
|
87
|
+
|
88
|
+
local_path = "%s/%s" % [dest_dir, file_name]
|
89
|
+
|
90
|
+
directory dest_dir do
|
91
|
+
owner "nobody"
|
92
|
+
action :create
|
93
|
+
recursive true
|
94
|
+
end
|
13
95
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
96
|
+
|
97
|
+
if node[:instrumental][:use_local]
|
98
|
+
execute "copy_instrumental_tools_package" do
|
99
|
+
command "cp %s %s" % [local_path, package_destination]
|
100
|
+
cwd dest_dir
|
101
|
+
user "nobody"
|
102
|
+
end
|
103
|
+
else
|
104
|
+
remote_file package_destination do
|
105
|
+
source remote_name
|
106
|
+
user "nobody"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
execute "untar_instrumental_tools_package" do
|
111
|
+
command "tar --strip-components=3 -zxvf %s" % file_name
|
112
|
+
user "nobody"
|
113
|
+
cwd dest_dir
|
114
|
+
only_if { ::File.exists?(local_path) }
|
115
|
+
end
|
116
|
+
|
117
|
+
template node["instrumental"]["dest_init_file"] do
|
118
|
+
source "instrument_server.erb"
|
119
|
+
mode "0755"
|
120
|
+
owner "nobody"
|
121
|
+
variables(
|
122
|
+
:dest_dir => dest_dir,
|
123
|
+
:config_file => conf_file,
|
124
|
+
:enable_scripts => !!node[:instrumental][:enable_scripts],
|
125
|
+
:script_dir => node[:instrumental][:script_dir],
|
126
|
+
:log_file => node[:instrumental][:log_file],
|
127
|
+
:pid_file => node[:instrumental][:pid_file],
|
128
|
+
:user => node[:instrumental][:user]
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
template conf_file do
|
133
|
+
source "instrumental.yml.erb"
|
134
|
+
mode "0440"
|
135
|
+
owner "nobody"
|
136
|
+
variables(
|
137
|
+
:api_key => node[:instrumental][:api_key]
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
service "instrument_server" do
|
142
|
+
action [:enable, :start]
|
143
|
+
status_command "pgrep instrument_server"
|
144
|
+
supports :restart => true, :reload => true, :status => false
|
145
|
+
end
|
146
|
+
when "windows"
|
147
|
+
|
148
|
+
directory dest_dir do
|
149
|
+
action :create
|
150
|
+
recursive true
|
151
|
+
end
|
152
|
+
|
153
|
+
if node[:instrumental][:enable_scripts]
|
154
|
+
directory node[:instrumental][:script_dir] do
|
155
|
+
action :create
|
156
|
+
recursive true
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
extra_args = if node[:instrumental][:enable_scripts]
|
161
|
+
'/SD "%s" /E' % node[:instrumental][:script_dir]
|
162
|
+
else
|
163
|
+
""
|
164
|
+
end
|
165
|
+
|
166
|
+
if node[:instrumental][:use_local]
|
167
|
+
execute "install-tools" do
|
168
|
+
command 'call "%s" %s /S /D=%s' % [local_path, extra_args, dest_dir]
|
169
|
+
end
|
170
|
+
else
|
171
|
+
remote_file package_destination do
|
172
|
+
source remote_name
|
173
|
+
action :create
|
174
|
+
end
|
175
|
+
execute "install-tools" do
|
176
|
+
command 'call "%s" %s /S /D=%s' % [package_destination, extra_args, dest_dir]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
template conf_file do
|
181
|
+
source "instrumental.yml.erb"
|
182
|
+
variables(
|
183
|
+
:api_key => node[:instrumental][:api_key]
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
service "Instrument Server" do
|
188
|
+
action [:enable, :start]
|
189
|
+
end
|
190
|
+
else
|
191
|
+
Chef::Log.warn("The platform %s is not supported, instrumental_tools will not be installed" % node["platform_family"])
|
21
192
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#! /bin/sh
|
2
|
+
### BEGIN INIT INFO
|
3
|
+
# Provides: instrument_server
|
4
|
+
# Required-Start: $all
|
5
|
+
# Required-Stop: $all
|
6
|
+
# Default-Start: 2 3 4 5
|
7
|
+
# Default-Stop: 0 1 6
|
8
|
+
# Short-Description: Start instrument_server at boot to provide system metrics
|
9
|
+
# Description: Report system level metrics to the Instrumental service (https://instrumentalapp.com/)
|
10
|
+
### END INIT INFO
|
11
|
+
|
12
|
+
set -e
|
13
|
+
|
14
|
+
DIRECTORY="<%= @dest_dir %>"
|
15
|
+
CONFIG_FILE="<%= @config_file %>"
|
16
|
+
TMPDIR=$DIRECTORY
|
17
|
+
PID="<%= @pid_file %>"
|
18
|
+
LOG="<%= @log_file %>"
|
19
|
+
SCRIPT_LOCATION="<%= @script_dir %>"
|
20
|
+
USER_TO_RUN_AS="<%= @user %>"
|
21
|
+
ARGS="-f ${CONFIG_FILE} -p ${PID} -l ${LOG} -s ${SCRIPT_LOCATION} -u ${USER_TO_RUN_AS} -t ${TMPDIR} <%= '-e' if @enable_scripts %>"
|
22
|
+
PROCESS="${DIRECTORY}instrument_server ${ARGS}"
|
23
|
+
|
24
|
+
case "$1" in
|
25
|
+
start)
|
26
|
+
$PROCESS start
|
27
|
+
;;
|
28
|
+
stop)
|
29
|
+
$PROCESS stop
|
30
|
+
;;
|
31
|
+
restart)
|
32
|
+
$PROCESS restart
|
33
|
+
;;
|
34
|
+
status)
|
35
|
+
$PROCESS status
|
36
|
+
;;
|
37
|
+
force-reload)
|
38
|
+
$PROCESS stop && $PROCESS clean && $PROCESS start
|
39
|
+
;;
|
40
|
+
*)
|
41
|
+
echo "Usage: /etc/init.d/instrumental-tools {start|stop|restart|status}"
|
42
|
+
exit 1
|
43
|
+
;;
|
44
|
+
esac
|
45
|
+
|
46
|
+
exit 0
|