instrumental_tools 1.0.0 → 1.1.3
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 +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
|