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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/BUILD.md +15 -0
  3. data/CHANGELOG.md +17 -1
  4. data/CUSTOM_METRICS.md +4 -0
  5. data/INSTALL.md +12 -7
  6. data/README.md +2 -2
  7. data/Rakefile +202 -64
  8. data/TEST.md +18 -0
  9. data/bin/instrument_server +31 -15
  10. data/chef/.kitchen.yml +10 -1
  11. data/chef/instrumental_tools/attributes/default.rb +29 -2
  12. data/chef/instrumental_tools/recipes/default.rb +188 -17
  13. data/chef/instrumental_tools/templates/default/instrument_server.erb +46 -0
  14. data/chef/instrumental_tools/templates/{instrumental.yml.erb → default/instrumental.yml.erb} +6 -6
  15. data/chef/omnibus.sh +27 -0
  16. data/conf/instrumental.yml +6 -6
  17. data/examples/README.md +1 -0
  18. data/examples/redis/README.md +10 -0
  19. data/examples/redis/redis_info.sh +10 -0
  20. data/ext/Rakefile +1 -0
  21. data/ext/mkrf_conf.rb +18 -0
  22. data/instrumental_tools.gemspec +8 -2
  23. data/lib/instrumental_tools/metric_script_executor.rb +45 -6
  24. data/lib/instrumental_tools/server_controller.rb +4 -1
  25. data/lib/instrumental_tools/system_inspector.rb +3 -0
  26. data/lib/instrumental_tools/system_inspector/win32.rb +85 -0
  27. data/lib/instrumental_tools/version.rb +1 -1
  28. data/test/integration/default/serverspec/instrumental_tools_spec.rb +32 -16
  29. data/win32/Makefile +18 -0
  30. data/win32/installer.nsis.erb +242 -0
  31. data/win32/logo.ico +0 -0
  32. data/win32/src/instrumental/InstrumentServerProcess.cs +147 -0
  33. data/win32/src/instrumental/InstrumentServerProcessWorker.cs +89 -0
  34. data/win32/src/instrumental/InstrumentServerService.cs +146 -0
  35. data/win32/src/instrumental/InstrumentServerServiceInstaller.cs +60 -0
  36. 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
+ ```
@@ -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 => '8000',
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 = collector.split(':')
79
+ address, port = collector.split(':')
71
80
  options[:collector] = address
72
- options[:port] = port if 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
- 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|
100
- options[:user] = u
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 = File::Stat.new(File.expand_path(options[:script_location]))
175
-
176
- if !stat.owned? || ((stat.mode & 0xFFF) ^ 0O700) != 0
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
 
@@ -1,16 +1,25 @@
1
1
  ---
2
2
  driver:
3
3
  name: vagrant
4
- provider: vmware_fusion
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] = nil
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
- packagecloud_repo "expectedbehavior/instrumental" do
2
- case node["platform_family"]
3
- when "debian"
4
- type "deb"
5
- when "rhel"
6
- type "rpm"
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
- package "instrumental-tools" do
11
- action :upgrade
12
- end
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
- template "/etc/instrumental.yml" do
15
- source "instrumental.yml.erb"
16
- mode "0440"
17
- owner "nobody"
18
- variables(
19
- :api_key => node[:instrumental][:api_key]
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