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/chef/instrumental_tools/templates/{instrumental.yml.erb → default/instrumental.yml.erb}
RENAMED
@@ -1,6 +1,6 @@
|
|
1
|
-
---
|
2
|
-
# Replace YOUR_API_KEY with the API key for your Instrumental project and
|
3
|
-
# remove the # from the beginning of the following line to have instrument_server
|
4
|
-
# start sending metrics to your account.
|
5
|
-
|
6
|
-
api_key: <%= @api_key %>
|
1
|
+
---
|
2
|
+
# Replace YOUR_API_KEY with the API key for your Instrumental project and
|
3
|
+
# remove the # from the beginning of the following line to have instrument_server
|
4
|
+
# start sending metrics to your account.
|
5
|
+
|
6
|
+
api_key: <%= @api_key %>
|
data/chef/omnibus.sh
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
if ! which chef-solo; then
|
3
|
+
if [ -e "/etc/gentoo-release" ]; then
|
4
|
+
mkdir -p /usr/portage
|
5
|
+
emerge --sync
|
6
|
+
emerge --oneshot portage
|
7
|
+
emerge -C perl-core/Module-Metadata
|
8
|
+
emerge -C perl-core/Parse-CPAN-Meta
|
9
|
+
emerge -C lang-dev/perl
|
10
|
+
emerge perl
|
11
|
+
emerge layman
|
12
|
+
echo "source /var/lib/layman/make.conf" >> /etc/portage/make.conf
|
13
|
+
echo "conf_type : make.conf" >> /etc/layman/layman.cfg
|
14
|
+
layman -o https://raw.github.com/lxmx/gentoo-overlay/master/overlay.xml -f -a lxmx
|
15
|
+
echo "app-admin/chef-omnibus ~amd64" >> /etc/portage/package.keywords
|
16
|
+
emerge app-admin/chef-omnibus
|
17
|
+
else
|
18
|
+
if which curl; then
|
19
|
+
curl -L https://www.chef.io/chef/install.sh | bash
|
20
|
+
elif which wget; then
|
21
|
+
wget -qO- https://www.chef.io/chef/install.sh | bash
|
22
|
+
else
|
23
|
+
echo "Couldn't find curl or wget"
|
24
|
+
exit 1
|
25
|
+
fi
|
26
|
+
fi
|
27
|
+
fi
|
data/conf/instrumental.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
---
|
2
|
-
# Replace YOUR_API_KEY with the API key for your Instrumental project and
|
3
|
-
# remove the # from the beginning of the following line to have instrument_server
|
4
|
-
# start sending metrics to your account.
|
5
|
-
|
6
|
-
#api_key: YOUR_API_KEY
|
1
|
+
---
|
2
|
+
# Replace YOUR_API_KEY with the API key for your Instrumental project and
|
3
|
+
# remove the # from the beginning of the following line to have instrument_server
|
4
|
+
# start sending metrics to your account.
|
5
|
+
|
6
|
+
#api_key: YOUR_API_KEY
|
data/examples/README.md
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Redis Metrics
|
2
|
+
|
3
|
+
The [`redis_info.sh`](redis_info.sh) script generates metrics from the `redis-cli info` command for a redis instance. The following metrics will be output for every collection in your system:
|
4
|
+
|
5
|
+
* `connected_clients` - Total currently connected clients
|
6
|
+
* `instantaneous_ops_per_sec` - Current operations per second
|
7
|
+
|
8
|
+
Additionally, the following database level metrics will be output:
|
9
|
+
|
10
|
+
* `dbDB_NUM_keys` - Count of keys in the DB_NUM database
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#! /bin/bash
|
2
|
+
|
3
|
+
REDIS_HOST=${REDIS_HOST:-"127.0.0.1"}
|
4
|
+
REDIS_PORT=${REDIS_PORT:-"6379"}
|
5
|
+
|
6
|
+
all_redis_info=`redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" info`
|
7
|
+
main_info=`echo "$all_redis_info" | grep -e "connected_clients" -e "instantaneous_ops_per_sec" | sed 's/:/ /g'`
|
8
|
+
db_key_info=`echo "$all_redis_info" | grep "keys=" | sed 's/:/_/g' | sed 's/=/ /g' | sed 's/,.*//g'`
|
9
|
+
|
10
|
+
printf "%s\r\n%s\r\n" "$main_info" "$db_key_info"
|
data/ext/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
task :default
|
data/ext/mkrf_conf.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/command.rb'
|
3
|
+
require 'rubygems/dependency_installer.rb'
|
4
|
+
|
5
|
+
begin
|
6
|
+
Gem::Command.build_args = ARGV
|
7
|
+
rescue NoMethodError
|
8
|
+
end
|
9
|
+
|
10
|
+
inst = Gem::DependencyInstaller.new
|
11
|
+
|
12
|
+
begin
|
13
|
+
if RUBY_PLATFORM =~ /(win32|windows|mingw)/i
|
14
|
+
inst.install "wmi-lite", "~> 1.0.0"
|
15
|
+
end
|
16
|
+
rescue
|
17
|
+
exit(1)
|
18
|
+
end
|
data/instrumental_tools.gemspec
CHANGED
@@ -33,11 +33,16 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.test_files = test_files
|
34
34
|
s.executables = bin_files
|
35
35
|
s.require_paths = ["lib"]
|
36
|
+
s.extensions = "ext/mkrf_conf.rb"
|
36
37
|
|
37
|
-
s.required_ruby_version =
|
38
|
+
s.required_ruby_version = ">= 1.9"
|
38
39
|
|
39
|
-
s.add_runtime_dependency(%q<instrumental_agent>, [">=0.
|
40
|
+
s.add_runtime_dependency(%q<instrumental_agent>, [">=0.13.2"])
|
40
41
|
s.add_runtime_dependency(%q<pidly>, [">=0.1.3"])
|
42
|
+
if ENV["INSTALL_WINDOWS"] || RUBY_PLATFORM =~ /(windows|win32|ming)/i
|
43
|
+
s.add_runtime_dependency(%q<wmi-lite>, [">=1.0.0"])
|
44
|
+
end
|
45
|
+
|
41
46
|
s.add_development_dependency(%q<rake>, [">=0"])
|
42
47
|
s.add_development_dependency(%q<fpm>, [">=1.3.3"])
|
43
48
|
s.add_development_dependency(%q<package_cloud>, [">=0"])
|
@@ -48,4 +53,5 @@ Gem::Specification.new do |s|
|
|
48
53
|
s.add_development_dependency(%q<librarian-puppet>, [">=0"])
|
49
54
|
s.add_development_dependency(%q<puppet>, [">=0"])
|
50
55
|
s.add_development_dependency(%q<serverspec>, [">=0"])
|
56
|
+
s.add_development_dependency(%q<winrm-transport>, ["~>1.0"])
|
51
57
|
end
|
@@ -11,7 +11,7 @@ class MetricScriptExecutor
|
|
11
11
|
|
12
12
|
def can_execute_file?(path)
|
13
13
|
stat = File::Stat.new(path)
|
14
|
-
stat.executable? && file_is_owner_only?(stat)
|
14
|
+
powershell_script?(path) || (stat.executable? && file_is_owner_only?(stat))
|
15
15
|
end
|
16
16
|
|
17
17
|
def can_execute_in_directory?(directory)
|
@@ -19,8 +19,39 @@ class MetricScriptExecutor
|
|
19
19
|
stat.directory? && file_is_owner_only?(stat)
|
20
20
|
end
|
21
21
|
|
22
|
+
def powershell_script?(path)
|
23
|
+
windows? && File.extname(path).to_s.downcase == ".ps1"
|
24
|
+
end
|
25
|
+
|
26
|
+
def windows?
|
27
|
+
RUBY_PLATFORM =~ /(win32|mswin|mingw)/
|
28
|
+
end
|
29
|
+
|
22
30
|
def file_is_owner_only?(file_stat)
|
23
|
-
file_stat.owned?
|
31
|
+
owned_by_executor = file_stat.owned?
|
32
|
+
unless windows?
|
33
|
+
owned_by_executor && ((file_stat.mode & 0xFFF) ^ 0O700) == 0
|
34
|
+
else
|
35
|
+
owned_by_executor
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def print_executable_warning(path)
|
40
|
+
if windows?
|
41
|
+
puts "[INFO] Cannot execute #{path}, must exist and be executable"
|
42
|
+
else
|
43
|
+
uid = Process.uid
|
44
|
+
user = Etc.getpwuid(uid).name
|
45
|
+
puts "[INFO] Cannot execute #{path}, must exist, be executable and only readable/writable by #{user}/#{uid}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def print_executable_in_directory_warning(directory)
|
50
|
+
if windows?
|
51
|
+
puts "Directory #{directory} has gone away, not scanning for metric scripts."
|
52
|
+
else
|
53
|
+
puts "Directory #{directory} has gone away or does not have the correct permissions (0700), not scanning for metric scripts."
|
54
|
+
end
|
24
55
|
end
|
25
56
|
|
26
57
|
def execute_custom_script(full_path)
|
@@ -35,6 +66,16 @@ class MetricScriptExecutor
|
|
35
66
|
|
36
67
|
|
37
68
|
cmd = [full_path, (previous_time || 0).to_i, (previous_status && previous_status.to_i)].compact.map(&:to_s)
|
69
|
+
if powershell_script?(full_path) && !File.executable?(full_path)
|
70
|
+
native_path = if File::ALT_SEPARATOR
|
71
|
+
full_path.split(File::SEPARATOR).join(File::ALT_SEPARATOR)
|
72
|
+
else
|
73
|
+
full_path
|
74
|
+
end
|
75
|
+
cmd[0] = native_path
|
76
|
+
cmd.unshift "-File"
|
77
|
+
cmd.unshift "powershell"
|
78
|
+
end
|
38
79
|
|
39
80
|
pid = Process.spawn(*cmd,
|
40
81
|
:chdir => File.dirname(full_path),
|
@@ -74,9 +115,7 @@ class MetricScriptExecutor
|
|
74
115
|
execute_custom_script(full_path)
|
75
116
|
else
|
76
117
|
if !File.directory?(full_path)
|
77
|
-
|
78
|
-
user = Etc.getpwuid(uid).name
|
79
|
-
puts "[INFO] Cannot execute #{full_path}, must be executable and only readable/writable by #{user}/#{uid}"
|
118
|
+
print_executable_warning(full_path)
|
80
119
|
end
|
81
120
|
[full_path, []]
|
82
121
|
end
|
@@ -84,7 +123,7 @@ class MetricScriptExecutor
|
|
84
123
|
process_to_output = Hash[current]
|
85
124
|
@previous = process_to_output
|
86
125
|
else
|
87
|
-
|
126
|
+
print_executable_in_directory_warning(directory)
|
88
127
|
end
|
89
128
|
process_to_output.flat_map do |path, (status, time, output)|
|
90
129
|
if status && status.success?
|
@@ -60,7 +60,8 @@ class ServerController < Pidly::Control
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def build_agent(key, address, enabled)
|
63
|
-
|
63
|
+
secure_protocol = address.split(':').last != '8000'
|
64
|
+
Instrumental::Agent.new(key, collector: address, enabled: enabled, secure: secure_protocol)
|
64
65
|
end
|
65
66
|
|
66
67
|
def set_new_agent(key, address)
|
@@ -148,6 +149,8 @@ class ServerController < Pidly::Control
|
|
148
149
|
count += 1
|
149
150
|
end
|
150
151
|
end
|
152
|
+
agent.flush
|
153
|
+
agent.stop
|
151
154
|
if debug?
|
152
155
|
puts "Sent #{count} metrics"
|
153
156
|
end
|
@@ -17,6 +17,9 @@ class SystemInspector
|
|
17
17
|
when /darwin/
|
18
18
|
require "instrumental_tools/system_inspector/osx"
|
19
19
|
SystemInspector::OSX
|
20
|
+
when /(windows|win32|mingw)/
|
21
|
+
require "instrumental_tools/system_inspector/win32"
|
22
|
+
SystemInspector::Win32
|
20
23
|
else
|
21
24
|
raise "unsupported OS"
|
22
25
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "wmi-lite"
|
2
|
+
|
3
|
+
class SystemInspector
|
4
|
+
module Win32
|
5
|
+
|
6
|
+
def self.wmi
|
7
|
+
@wmi ||= WmiLite::Wmi.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.sanitize(name)
|
11
|
+
name.gsub(/[^a-z0-9\-\_]/i, "_").gsub(/(\A_+|_+\Z)/, "")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load_cpu
|
15
|
+
cpus = wmi.query("SELECT PercentProcessorTime, PercentUserTime, PercentPrivilegedTime, PercentIdleTime, PercentInterruptTime FROM Win32_PerfFormattedData_PerfOS_Processor")
|
16
|
+
cpu_zero = cpus[0]
|
17
|
+
sysresult = wmi.query("SELECT ProcessorQueueLength FROM Win32_PerfFormattedData_PerfOS_System")
|
18
|
+
sys_stat = sysresult[0]
|
19
|
+
{
|
20
|
+
:gauges => {
|
21
|
+
"cpu.in_use" => cpu_zero["PercentProcessorTime"].to_f,
|
22
|
+
"cpu.user" => cpu_zero["PercentUserTime"].to_f,
|
23
|
+
"cpu.system" => cpu_zero["PercentPrivilegedTime"].to_f,
|
24
|
+
"cpu.idle" => cpu_zero["PercentIdleTime"].to_f,
|
25
|
+
"cpu.iowait" => cpu_zero["PercentInterruptTime"].to_f,
|
26
|
+
"load.processor_queue_length" => sys_stat["ProcessorQueueLength"].to_i
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.load_memory
|
32
|
+
memresults = wmi.query("SELECT AvailableMBytes,CacheBytes FROM Win32_PerfFormattedData_PerfOS_Memory")
|
33
|
+
physmemory = wmi.query("SELECT Capacity FROM Win32_PhysicalMemory WHERE PoweredOn != false").reduce(0) { |memo, h| memo + h["Capacity"].to_f }
|
34
|
+
swapmemory = wmi.query("SELECT Name, PercentUsage FROM Win32_PerfFormattedData_PerfOS_PagingFile")
|
35
|
+
physmemory_mb = physmemory / 1024.0 / 1024.0
|
36
|
+
mainmemory = memresults[0]
|
37
|
+
avail_mb = mainmemory["AvailableMBytes"].to_f
|
38
|
+
used_mb = physmemory_mb - avail_mb
|
39
|
+
cached_mb = mainmemory["CacheBytes"].to_f / 1024.0 / 1024.0
|
40
|
+
free_perc = avail_mb / physmemory_mb
|
41
|
+
if free_perc.nan? || free_perc.infinite?
|
42
|
+
free_perc = 0
|
43
|
+
end
|
44
|
+
free_perc *= 100.0
|
45
|
+
memory_stats = {
|
46
|
+
"memory.used_mb" => used_mb,
|
47
|
+
"memory.free_mb" => avail_mb,
|
48
|
+
"memory.cached_mb" => cached_mb,
|
49
|
+
"memory.free_percent" => free_perc
|
50
|
+
}
|
51
|
+
swapmemory.each do |result|
|
52
|
+
formatted_name = sanitize(result["Name"])
|
53
|
+
used = result["PercentUsage"].to_f
|
54
|
+
memory_stats["swap.#{formatted_name}.free_percent"] = 100 - used
|
55
|
+
memory_stats["swap.#{formatted_name}.used_percent"] = used
|
56
|
+
end
|
57
|
+
{ :gauges => memory_stats }
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.load_disks
|
61
|
+
logical_disks = wmi.query("SELECT Name,FreeSpace,Size FROM Win32_LogicalDisk")
|
62
|
+
disk_stats = logical_disks.reduce({}) do |memo, disk|
|
63
|
+
name = sanitize(disk["Name"])
|
64
|
+
free_mb = disk["FreeSpace"].to_f / 1024.0 / 1024.0
|
65
|
+
size_mb = disk["Size"].to_f / 1024.0 / 1024.0
|
66
|
+
avail_perc = free_mb / size_mb
|
67
|
+
if avail_perc.nan? || avail_perc.infinite?
|
68
|
+
avail_perc = 0
|
69
|
+
end
|
70
|
+
avail_perc *= 100.0
|
71
|
+
memo.merge({
|
72
|
+
"disk.#{name}.total_mb" => size_mb,
|
73
|
+
"disk.#{name}.used_mb" => size_mb - free_mb,
|
74
|
+
"disk.#{name}.available_mb" => free_mb,
|
75
|
+
"disk.#{name}.available_percent" => avail_perc
|
76
|
+
})
|
77
|
+
end
|
78
|
+
{ :gauges => disk_stats }
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.load_filesystem
|
82
|
+
{}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -1,29 +1,45 @@
|
|
1
1
|
require 'serverspec'
|
2
2
|
|
3
|
-
|
3
|
+
details = {}
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
if RUBY_PLATFORM =~ /(win|mswin|mingw)/i
|
6
|
+
set :backend, :cmd
|
7
|
+
set :os, :family => 'windows'
|
8
|
+
details = {
|
9
|
+
check_owner: false,
|
10
|
+
config: "c:\\Program Files (x86)\\Instrumental Tools\\etc\\instrumental.yml",
|
11
|
+
has_pid: false,
|
12
|
+
service_name: "Instrument Server"
|
13
|
+
}
|
14
|
+
else
|
15
|
+
set :backend, :exec
|
16
|
+
details = {
|
17
|
+
check_owner: true,
|
18
|
+
config: "/etc/instrumental.yml",
|
19
|
+
has_pid: true,
|
20
|
+
pid_path: "/opt/instrumental-tools/instrument_server.pid",
|
21
|
+
owner: "nobody",
|
22
|
+
service_name: "instrument_server"
|
23
|
+
}
|
8
24
|
end
|
9
25
|
|
10
|
-
describe service(
|
26
|
+
describe service(details[:service_name]) do
|
11
27
|
it { should be_enabled }
|
12
28
|
it { should be_running }
|
13
29
|
end
|
14
30
|
|
15
|
-
|
16
|
-
|
17
|
-
|
31
|
+
if details[:has_pid]
|
32
|
+
describe file(details[:pid_path]) do
|
33
|
+
it { should be_file }
|
34
|
+
if details[:check_owner]
|
35
|
+
it { should be_owned_by(details[:owner]) }
|
36
|
+
end
|
37
|
+
end
|
18
38
|
end
|
19
39
|
|
20
|
-
describe file(
|
40
|
+
describe file(details[:config]) do
|
21
41
|
it { should be_file }
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
describe process('ruby') do
|
26
|
-
it { should be_running }
|
27
|
-
its(:user) { should eq 'nobody' }
|
28
|
-
its(:args) { should match /instrument_server/ }
|
42
|
+
if details[:check_owner]
|
43
|
+
it { should be_owned_by(details[:owner]) }
|
44
|
+
end
|
29
45
|
end
|
data/win32/Makefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
prefix=.
|
2
|
+
MCS=mcs
|
3
|
+
MCSFLAGS=-reference:System.ServiceProcess.dll -reference:System.Configuration.dll -reference:System.Configuration.Install.dll
|
4
|
+
TARGET=build
|
5
|
+
SRC=src
|
6
|
+
|
7
|
+
all: InstrumentServer.exe
|
8
|
+
|
9
|
+
InstrumentServer.exe: $(SRC)/instrumental/*.cs
|
10
|
+
mkdir -p $(TARGET)
|
11
|
+
$(MCS) -out:$(TARGET)/$@ $(MCSFLAGS) $^
|
12
|
+
|
13
|
+
clean:
|
14
|
+
rm $(TARGET)/*
|
15
|
+
|
16
|
+
install: all
|
17
|
+
install -m 0755 $(TARGET)/InstrumentServer.exe $(prefix)/.
|
18
|
+
|
@@ -0,0 +1,242 @@
|
|
1
|
+
!include FileFunc.nsh
|
2
|
+
!include LogicLib.nsh
|
3
|
+
!include MUI.nsh
|
4
|
+
!include nsDialogs.nsh
|
5
|
+
!include x64.nsh
|
6
|
+
|
7
|
+
|
8
|
+
!define MUI_ICON "win32/logo.ico"
|
9
|
+
|
10
|
+
!insertmacro MUI_PAGE_DIRECTORY
|
11
|
+
|
12
|
+
Name "Instrumental Tools"
|
13
|
+
Icon "win32/logo.ico"
|
14
|
+
OutFile "<%= installer_file_name %>"
|
15
|
+
|
16
|
+
InstallDir "$PROGRAMFILES\Instrumental Tools"
|
17
|
+
|
18
|
+
Var Dialog
|
19
|
+
Var WelcomeLabel
|
20
|
+
Var KeyLabel
|
21
|
+
Var HostnameLabel
|
22
|
+
Var EnableScriptsLabel
|
23
|
+
Var ScriptDirectoryLabel
|
24
|
+
Var KeyText
|
25
|
+
Var HostnameText
|
26
|
+
Var EnableScriptsCheckbox
|
27
|
+
Var ScriptDirectoryRequest
|
28
|
+
Var ScriptDirectoryBrowser
|
29
|
+
Var ScriptDirectoryTemp
|
30
|
+
|
31
|
+
Var ApiKey
|
32
|
+
Var ScriptDirectoryDestination
|
33
|
+
Var EnableScripts
|
34
|
+
Var Hostname
|
35
|
+
Var ServiceCommand
|
36
|
+
|
37
|
+
Var DotNetVersion
|
38
|
+
Var InstallUtilPath
|
39
|
+
Var DotNetFriendlyVersion
|
40
|
+
Var DotNetInstall
|
41
|
+
|
42
|
+
|
43
|
+
Function .onInit
|
44
|
+
|
45
|
+
StrCpy $DotNetFriendlyVersion "4.0"
|
46
|
+
StrCpy $DotNetInstall "http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en"
|
47
|
+
StrCpy $DotNetVersion "v4.0.30319"
|
48
|
+
StrCpy $InstallUtilPath "$WINDIR\Microsoft.NET\Framework\$DotNetVersion\installUtil.exe"
|
49
|
+
|
50
|
+
Call AssertDotNet
|
51
|
+
|
52
|
+
${GetOptions} $CMDLINE "/K" $ApiKey
|
53
|
+
IfErrors 0 +2
|
54
|
+
StrCpy $ApiKey "Your API Key"
|
55
|
+
|
56
|
+
${GetOptions} $CMDLINE "/H" $Hostname
|
57
|
+
IfErrors 0 +2
|
58
|
+
Call GetComputerName
|
59
|
+
|
60
|
+
${GetOptions} $CMDLINE "/E" $0
|
61
|
+
IfErrors 0 +2
|
62
|
+
StrCpy $EnableScripts 1
|
63
|
+
StrCpy $EnableScripts 0
|
64
|
+
|
65
|
+
|
66
|
+
${GetOptions} $CMDLINE "/SD" $ScriptDirectoryDestination
|
67
|
+
IfErrors 0 +2
|
68
|
+
StrCpy $ScriptDirectoryDestination "$INSTDIR\Scripts"
|
69
|
+
|
70
|
+
FunctionEnd
|
71
|
+
|
72
|
+
Function un.onInit
|
73
|
+
StrCpy $DotNetFriendlyVersion "4.0"
|
74
|
+
StrCpy $DotNetInstall "http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en"
|
75
|
+
StrCpy $DotNetVersion "v4.0.30319"
|
76
|
+
StrCpy $InstallUtilPath "$WINDIR\Microsoft.NET\Framework\$DotNetVersion\installUtil.exe"
|
77
|
+
FunctionEnd
|
78
|
+
|
79
|
+
Function GetComputerName
|
80
|
+
ReadRegStr $0 HKLM "System\CurrentControlSet\Control\ComputerName\ActiveComputerName" "ComputerName"
|
81
|
+
StrCmp $0 "" win9x
|
82
|
+
StrCpy $1 $0 4 3
|
83
|
+
Goto done
|
84
|
+
win9x:
|
85
|
+
ReadRegStr $0 HKLM "System\CurrentControlSet\Control\ComputerName\ComputerName" "ComputerName"
|
86
|
+
StrCpy $1 $0 4 3
|
87
|
+
done:
|
88
|
+
StrCpy $Hostname $0
|
89
|
+
FunctionEnd
|
90
|
+
|
91
|
+
Function WriteConfigFile
|
92
|
+
FileOpen $4 "$INSTDIR\etc\instrumental.yml" "w"
|
93
|
+
FileWrite $4 "---$\r$\n"
|
94
|
+
FileWrite $4 "# Replace YOUR_API_KEY with the API key for your Instrumental project and$\r$\n"
|
95
|
+
FileWrite $4 "# remove the # from the beginning of the following line to have instrument_server$\r$\n"
|
96
|
+
FileWrite $4 "# start sending metrics to your account.$\r$\n"
|
97
|
+
FileWrite $4 "$\r$\n"
|
98
|
+
FileWrite $4 "api_key: $ApiKey$\r$\n"
|
99
|
+
FileWrite $4 "$\r$\n"
|
100
|
+
FileClose $4
|
101
|
+
FunctionEnd
|
102
|
+
|
103
|
+
Page custom nsDialogsPage nsDialogsPageLeave
|
104
|
+
Page instfiles
|
105
|
+
|
106
|
+
Function AssertDotNet
|
107
|
+
IfFileExists $InstallUtilPath NextStep
|
108
|
+
MessageBox MB_OK|MB_ICONEXCLAMATION "You must have the Microsoft .NET Framework $DotNetFriendlyVersion Installed to use this application. $\n$\n The installer will now open the Microsft .NET Framework $DotNetFriendlyVersion webpage"
|
109
|
+
ExecShell Open "$DotNetInstall" SW_SHOWNORMAL
|
110
|
+
Quit
|
111
|
+
NextStep:
|
112
|
+
FunctionEnd
|
113
|
+
|
114
|
+
Function BrowseDest
|
115
|
+
nsDialogs::SelectFolderDialog "Select Folder" $ScriptDirectoryDestination
|
116
|
+
Pop $0
|
117
|
+
${If} $0 != error
|
118
|
+
StrCpy $ScriptDirectoryDestination $0
|
119
|
+
${NSD_SetText} $ScriptDirectoryRequest $ScriptDirectoryDestination
|
120
|
+
${EndIf}
|
121
|
+
FunctionEnd
|
122
|
+
|
123
|
+
Function EnDisableButton
|
124
|
+
${NSD_GetState} $EnableScriptsCheckbox $0
|
125
|
+
${If} $0 == 1
|
126
|
+
StrCpy $EnableScripts 1 1
|
127
|
+
EnableWindow $ScriptDirectoryBrowser 1
|
128
|
+
EnableWindow $ScriptDirectoryRequest 1
|
129
|
+
${Else}
|
130
|
+
StrCpy $EnableScripts 0 1
|
131
|
+
EnableWindow $ScriptDirectoryBrowser 0
|
132
|
+
EnableWindow $ScriptDirectoryRequest 0
|
133
|
+
${EndIf}
|
134
|
+
FunctionEnd
|
135
|
+
|
136
|
+
|
137
|
+
Function nsDialogsPage
|
138
|
+
!insertmacro MUI_HEADER_TEXT "Monitoring Options" "Enter your configuration details below. API key information is available on your account on https://instrumentalapp.com/."
|
139
|
+
nsDialogs::Create 1018
|
140
|
+
Pop $Dialog
|
141
|
+
|
142
|
+
${If} $Dialog == error
|
143
|
+
Abort
|
144
|
+
${EndIf}
|
145
|
+
|
146
|
+
${NSD_CreateLabel} 0 0 100% 12u "Enter configuration details below"
|
147
|
+
Pop $WelcomeLabel
|
148
|
+
|
149
|
+
${NSD_CreateLabel} 0 13u 30% 12u "API Key"
|
150
|
+
Pop $KeyLabel
|
151
|
+
|
152
|
+
${NSD_CreateText} 35% 13u 60% 12u $ApiKey
|
153
|
+
Pop $KeyText
|
154
|
+
|
155
|
+
${NSD_CreateLabel} 0 26u 30% 12u "Hostname"
|
156
|
+
Pop $HostnameLabel
|
157
|
+
|
158
|
+
${NSD_CreateText} 35% 26u 60% 12u $Hostname
|
159
|
+
Pop $HostnameText
|
160
|
+
|
161
|
+
${NSD_CreateLabel} 0 39u 30% 12u "Enable Custom Scripts?"
|
162
|
+
Pop $EnableScriptsLabel
|
163
|
+
|
164
|
+
${NSD_CreateCheckbox} 35% 39u 60% 12u ""
|
165
|
+
Pop $EnableScriptsCheckbox
|
166
|
+
|
167
|
+
${NSD_CreateLabel} 0 52u 30% 12u "Script Directory"
|
168
|
+
Pop $ScriptDirectoryLabel
|
169
|
+
|
170
|
+
${NSD_CreateDirRequest} 35% 52u 40% 12u $ScriptDirectoryDestination
|
171
|
+
Pop $ScriptDirectoryRequest
|
172
|
+
|
173
|
+
${NSD_CreateBrowseButton} 77% 52u 10% 12u ".."
|
174
|
+
Pop $ScriptDirectoryBrowser
|
175
|
+
|
176
|
+
StrCmp $EnableScripts 1 0 nomatch
|
177
|
+
${NSD_Check} $EnableScriptsCheckbox
|
178
|
+
Call EnDisableButton
|
179
|
+
nomatch:
|
180
|
+
Call EnDisableButton
|
181
|
+
|
182
|
+
${NSD_OnClick} $EnableScriptsCheckbox EnDisableButton
|
183
|
+
${NSD_OnClick} $ScriptDirectoryRequest BrowseDest
|
184
|
+
${NSD_OnClick} $ScriptDirectoryBrowser BrowseDest
|
185
|
+
|
186
|
+
nsDialogs::Show
|
187
|
+
|
188
|
+
FunctionEnd
|
189
|
+
|
190
|
+
Function nsDialogsPageLeave
|
191
|
+
|
192
|
+
${NSD_GetText} $HostnameText $Hostname
|
193
|
+
${NSD_GetText} $KeyText $ApiKey
|
194
|
+
${NSD_GetState} $EnableScriptsCheckbox $EnableScripts
|
195
|
+
${NSD_GetText} $ScriptDirectoryRequest $ScriptDirectoryDestination
|
196
|
+
|
197
|
+
|
198
|
+
FunctionEnd
|
199
|
+
|
200
|
+
|
201
|
+
Section "Installing Files"
|
202
|
+
SetOutPath $INSTDIR
|
203
|
+
<% directories.each do |directory| %>
|
204
|
+
File /r <%= directory %>/*.*
|
205
|
+
<% end %>
|
206
|
+
<% files, _ = removable_artifacts %>
|
207
|
+
<% files.each do |file| %>
|
208
|
+
SetFileAttributes "$INSTDIR\\<%= file %>" NORMAL
|
209
|
+
<% if file.index("Gemfile.lock") %>
|
210
|
+
Exec 'icacls "$INSTDIR\\<%= file %>" /grant BUILTIN\Users:f'
|
211
|
+
<% end %>
|
212
|
+
<% end %>
|
213
|
+
WriteUninstaller $INSTDIR\<%= uninstaller_name %>
|
214
|
+
Call WriteConfigFile
|
215
|
+
|
216
|
+
|
217
|
+
${If} $EnableScripts == 1
|
218
|
+
CreateDirectory "$ScriptDirectoryDestination"
|
219
|
+
Exec '"$InstallUtilPath" /Hostname="$Hostname" /ScriptsDirectory="$ScriptDirectoryDestination" /ScriptsEnabled="True" /Path="$INSTDIR" /Config="$INSTDIR\etc\instrumental.yml" InstrumentServer.exe'
|
220
|
+
${Else}
|
221
|
+
Exec '"$InstallUtilPath" /Path="$INSTDIR" /Config="$INSTDIR\etc\instrumental.yml" /Hostname="$Hostname" InstrumentServer.exe'
|
222
|
+
${EndIf}
|
223
|
+
|
224
|
+
Exec '"sc" start "Instrument Server"'
|
225
|
+
SectionEnd
|
226
|
+
|
227
|
+
Section "Uninstall"
|
228
|
+
Exec '"sc" stop "Instrument Server"'
|
229
|
+
Exec '"$InstallUtilPath" /u "$INSTDIR\InstrumentServer.exe"'
|
230
|
+
<% files, directories = removable_artifacts %>
|
231
|
+
<% files.each do |file| %>
|
232
|
+
delete "$INSTDIR\\<%= file %>"
|
233
|
+
<% end %>
|
234
|
+
delete "$INSTDIR\\<%= uninstaller_name %>"
|
235
|
+
<% directories.each do |directory| %>
|
236
|
+
<% if directory.strip.empty? %>
|
237
|
+
rmdir "$INSTDIR"
|
238
|
+
<% else %>
|
239
|
+
rmdir /R "$INSTDIR\\<%= directory %>"
|
240
|
+
<% end %>
|
241
|
+
<% end %>
|
242
|
+
SectionEnd
|