warningshot 0.9.4 → 0.9.5
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.
- data/CHANGELOG +8 -0
- data/CONTRIBUTORS +2 -1
- data/README +86 -6
- data/Rakefile +4 -3
- data/TODO +1 -147
- data/bin/warningshot +11 -7
- data/lib/resolvers/core_lib_resolver.rb +2 -3
- data/lib/resolvers/directory_resolver.rb +1 -1
- data/lib/resolvers/file_resolver.rb +35 -17
- data/lib/resolvers/gem_resolver.rb +81 -60
- data/lib/resolvers/integrity_resolver.rb +10 -11
- data/lib/resolvers/manual_resolver.rb +15 -3
- data/lib/resolvers/permission_resolver.rb +6 -8
- data/lib/resolvers/symlink_resolver.rb +13 -8
- data/lib/resolvers/url_resolver.rb +28 -41
- data/lib/warningshot.rb +10 -7
- data/lib/warningshot/config.rb +254 -0
- data/lib/{warning_shot → warningshot}/dependency_resolver.rb +38 -17
- data/lib/{warning_shot → warningshot}/growl.rb +2 -0
- data/lib/{warning_shot → warningshot}/logger.rb +2 -0
- data/lib/{warning_shot → warningshot}/resolver.rb +177 -89
- data/lib/warningshot/suite.rb +4 -0
- data/lib/{warning_shot → warningshot}/template_generator.rb +4 -1
- data/lib/{warning_shot → warningshot}/version.rb +3 -1
- data/lib/warningshot/warning_shot.rb +187 -0
- data/tasks/gemspec.rb +3 -16
- data/tasks/yard.rb +1 -1
- data/templates/gems.yml +1 -0
- data/test/data/faux_test.yml +5 -0
- data/test/data/faux_test_resolver.rb +21 -0
- data/test/data/mock_resolver.rb +11 -5
- data/test/log/warningshot.log +3051 -532
- data/test/spec/unit/resolvers/core_lib_resolver_spec.rb +1 -1
- data/test/spec/unit/resolvers/directory_resolver_spec.rb +1 -1
- data/test/spec/unit/resolvers/file_resolver_spec.rb +9 -13
- data/test/spec/unit/resolvers/gem_resolver_spec.rb +108 -32
- data/test/spec/unit/resolvers/integrity_resolver_spec.rb +6 -6
- data/test/spec/unit/resolvers/permission_resolver_spec.rb +2 -2
- data/test/spec/unit/resolvers/symlink_resolver_spec.rb +8 -1
- data/test/spec/unit/resolvers/url_resolver_spec.rb +10 -10
- data/test/spec/unit/warningshot/config_spec.rb +57 -0
- data/test/spec/unit/{warning_shot → warningshot}/dependency_resolver_spec.rb +18 -9
- data/test/spec/unit/{warning_shot → warningshot}/resolver_spec.rb +54 -79
- data/test/spec/unit/{warning_shot → warningshot}/template_generator_spec.rb +1 -1
- data/test/spec/unit/{warning_shot → warningshot}/version_spec.rb +0 -0
- data/test/spec/unit/{warning_shot → warningshot}/warning_shot_spec.rb +0 -0
- metadata +24 -26
- data/lib/warning_shot/config.rb +0 -132
- data/lib/warning_shot/warning_shot.rb +0 -130
- data/test/spec/spec.opts.zoiks +0 -0
- data/test/spec/unit/warning_shot/config_spec.rb +0 -35
@@ -1,58 +1,77 @@
|
|
1
|
-
require 'rubygems/dependency_installer'
|
2
1
|
class WarningShot::GemResolver
|
3
2
|
include WarningShot::Resolver
|
3
|
+
add_dependency :core, 'rubygems'
|
4
|
+
add_dependency :core, 'rubygems/dependency_installer'
|
5
|
+
add_dependency :core, 'rubygems/uninstaller'
|
6
|
+
add_dependency :core, 'rubygems/dependency'
|
4
7
|
|
5
8
|
order 100
|
6
9
|
branch :gem
|
7
10
|
description 'Installs ruby gems and their dependencies'
|
8
|
-
|
9
|
-
# Matches >, <, >=, <=
|
10
|
-
CONDITIONAL_RGX = /[^\d]*/.freeze
|
11
|
-
|
12
|
-
# Matches digits in version
|
13
|
-
VERSION_RGX = /[\d\.]+/.freeze
|
14
|
-
|
11
|
+
|
15
12
|
# Default version to install
|
16
|
-
DEFAULT_VERSION = ">=0.0.0".freeze
|
17
|
-
|
18
|
-
cli(
|
19
|
-
:
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
DEFAULT_VERSION = ">= 0.0.0".freeze
|
14
|
+
|
15
|
+
cli("--gempath=PATH", String, "Alternate gem path ':' separated to check. First in path is where gems will be installed") do |gpath|
|
16
|
+
options[:gem_path] = gpath
|
17
|
+
end
|
18
|
+
|
19
|
+
cli("--update-sources","Update gem sources before installing") do |no_up_src|
|
20
|
+
options[:update_sources] = no_up_src
|
21
|
+
end
|
22
|
+
|
23
|
+
#cli("-m","--resolver-gems=GEMS", String,"Names of gems containing add'l resolvers (':' seperated)") do |resolver_gems|
|
24
|
+
# options[:resolver_gems] = resolver_gems.split(':')
|
25
|
+
#end
|
26
|
+
|
27
|
+
GemResource = Struct.new(:name,:version,:source) do
|
28
|
+
def installed?
|
29
|
+
return !!(Gem.source_index.find_name(self.name, self.version).first)
|
30
|
+
end
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
:description => "Not supported yet.",
|
28
|
-
:name => "minigems",
|
29
|
-
:default => false
|
30
|
-
)
|
31
|
-
|
32
|
-
GemResource = Struct.new(:name,:version) do
|
33
|
-
def installed?
|
34
|
-
self.version ||= DEFAULT_VERSION
|
35
|
-
installed_versions = Gem::cache.search self.name
|
36
|
-
installed = false
|
32
|
+
def install!
|
33
|
+
orig_gem_sources = Gem.sources.clone
|
37
34
|
|
38
|
-
|
35
|
+
installer = Gem::DependencyInstaller.new({
|
36
|
+
:user_install => false,
|
37
|
+
:install_dir => Gem.path.first
|
38
|
+
})
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
begin
|
41
|
+
Gem.sources.replace(self.source.kind_of?(Array) ? self.source : [self.source]) if self.source
|
42
|
+
installer.install(self.name,self.version)
|
43
|
+
rescue Gem::InstallError => ex
|
44
|
+
WarningShot::GemResolver.logger.error " ~ Could not install gem: #{self.name}:#{self.version}%s" % [self.source ? " from #{self.source}" : ""]
|
45
|
+
rescue Gem::GemNotFoundException => ex
|
46
|
+
WarningShot::GemResolver.logger.error " ~ Gem (#{self.name}:#{self.version}) was not found%s" % [self.source ? " from #{self.source}" : ""]
|
47
|
+
ensure
|
48
|
+
Gem.sources.replace orig_gem_sources # replace our gem sources
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
!installer.installed_gems.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def uninstall!
|
55
|
+
opts = {
|
56
|
+
:user_install => false,
|
57
|
+
:install_dir => Gem.path.first,
|
58
|
+
:version => self.version
|
59
|
+
}
|
60
|
+
WarningShot::GemResolver.update_source_index(opts[:install_dir])
|
61
|
+
Gem::Uninstaller.new(self.name, opts).uninstall rescue false
|
51
62
|
end
|
52
63
|
end #End GemResource
|
53
64
|
|
54
|
-
|
55
|
-
|
65
|
+
typecast(String){ |yaml|
|
66
|
+
_ver = Gem::Requirement.new [DEFAULT_VERSION]
|
67
|
+
GemResource.new yaml, _ver
|
68
|
+
}
|
69
|
+
|
70
|
+
typecast(Hash){ |yaml|
|
71
|
+
_ver = (yaml[:version].nil? || yaml[:version].empty?) ? DEFAULT_VERSION : yaml[:version]
|
72
|
+
_ver = Gem::Requirement.new [_ver]
|
73
|
+
GemResource.new yaml[:name], _ver, yaml[:source]
|
74
|
+
}
|
56
75
|
|
57
76
|
register :test do |dep|
|
58
77
|
if gem_found = dep.installed?
|
@@ -64,31 +83,33 @@ class WarningShot::GemResolver
|
|
64
83
|
end
|
65
84
|
|
66
85
|
register :resolution do |dep|
|
67
|
-
|
68
|
-
dep_inst = Gem::DependencyInstaller.new({:install_dir => Gem.path.first})
|
69
|
-
dep_inst.install(dep.name,Gem::Requirement.new(dep.version))
|
70
|
-
rescue Exception => ex
|
71
|
-
logger.error " ~ Could not install gem: #{dep.name}:#{dep.version}"
|
72
|
-
end
|
73
|
-
dep.installed?
|
86
|
+
dep.install!
|
74
87
|
end
|
75
88
|
|
76
89
|
class << self
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
Gem::cache.class.from_gems_in WarningShot::Config.configuration[:gem_path].split(":")
|
85
|
-
Gem::cache.refresh!
|
86
|
-
end
|
90
|
+
def update_source_index(*dirs)
|
91
|
+
spec_dirs = dirs.inject([]){|memo,dir|
|
92
|
+
memo << File.join(File.expand_path(dir), 'specifications')
|
93
|
+
}
|
94
|
+
|
95
|
+
Gem.send :class_variable_set, "@@source_index", Gem::SourceIndex.from_gems_in(*spec_dirs)
|
96
|
+
Gem::cache.refresh!
|
87
97
|
end
|
88
98
|
end
|
89
99
|
|
90
|
-
def initialize(
|
100
|
+
def initialize(config,*params)
|
91
101
|
super
|
92
|
-
|
102
|
+
|
103
|
+
Gem.configuration.update_sources = !!(self.config[:update_sources])
|
104
|
+
|
105
|
+
if self.config.key?(:gem_path) && !self.config[:gem_path].nil?
|
106
|
+
gem_dirs = self.config[:gem_path].split(':')
|
107
|
+
gem_dirs.reverse.each do |path|
|
108
|
+
Gem.path.unshift File.expand_path(path)
|
109
|
+
end
|
110
|
+
|
111
|
+
WarningShot::GemResolver.update_source_index *gem_dirs
|
112
|
+
end
|
93
113
|
end
|
114
|
+
|
94
115
|
end
|
@@ -1,10 +1,9 @@
|
|
1
|
-
require 'digest/md5'
|
2
|
-
require 'digest/sha1'
|
3
|
-
|
4
1
|
class WarningShot::IntegrityResolver
|
5
2
|
include WarningShot::Resolver
|
3
|
+
add_dependency :core, 'digest/md5', :disable => false, :unregister => [:md5_digest_test]
|
4
|
+
add_dependency :core, 'digest/sha1', :disable => false, :unregister => [:sha1_digest_test]
|
5
|
+
|
6
6
|
order 600
|
7
|
-
#disable!
|
8
7
|
|
9
8
|
# Uses the same config files as file resolver, just add md5 field to config YML
|
10
9
|
branch :file
|
@@ -12,14 +11,14 @@ class WarningShot::IntegrityResolver
|
|
12
11
|
|
13
12
|
# Define FileResource struct
|
14
13
|
FileResource = Struct.new(:source,:target,:digest,:digest_method) do
|
15
|
-
def exists?;File.exists?(target.path);end;
|
14
|
+
def exists?;File.exists?(File.expand_path(target.path));end;
|
16
15
|
end
|
17
16
|
|
18
|
-
|
17
|
+
typecast String do |file|
|
19
18
|
FileResource.new URI.parse(''), URI.parse(file), nil, nil
|
20
19
|
end
|
21
20
|
|
22
|
-
|
21
|
+
typecast Hash do |file|
|
23
22
|
file[:source].sub!(/file:\/\//i,'') unless file[:source].nil?
|
24
23
|
|
25
24
|
if file[:sha1] && file[:md5]
|
@@ -33,10 +32,10 @@ class WarningShot::IntegrityResolver
|
|
33
32
|
FileResource.new URI.parse(file[:source] || ''), URI.parse(file[:target]), digest, digest_method
|
34
33
|
end
|
35
34
|
|
36
|
-
register(:test,{:name=>:
|
35
|
+
register(:test,{:name=>:sha1_digest_test,
|
37
36
|
:if => lambda{|dep| dep.digest_method == :sha1}
|
38
37
|
})do |dep|
|
39
|
-
dep_ok = (dep.exists? ? Digest::SHA1.hexdigest(File.read(dep.target.path)) == dep.digest : false)
|
38
|
+
dep_ok = (dep.exists? ? Digest::SHA1.hexdigest(File.read(File.expand_path(dep.target.path))) == dep.digest : false)
|
40
39
|
|
41
40
|
if dep_ok
|
42
41
|
logger.debug " ~ [PASSED] checksum #{dep.target}"
|
@@ -47,10 +46,10 @@ class WarningShot::IntegrityResolver
|
|
47
46
|
dep_ok
|
48
47
|
end
|
49
48
|
|
50
|
-
register(:test,{:name=>:
|
49
|
+
register(:test,{:name=>:md5_digest_test,
|
51
50
|
:if => lambda{|dep| dep.digest_method == :md5}
|
52
51
|
})do |dep|
|
53
|
-
dep_ok = (dep.exists? ? Digest::MD5.hexdigest(File.read(dep.target.path)) == dep.digest : false)
|
52
|
+
dep_ok = (dep.exists? ? Digest::MD5.hexdigest(File.read(File.expand_path(dep.target.path))) == dep.digest : false)
|
54
53
|
|
55
54
|
if dep_ok
|
56
55
|
logger.debug " ~ [PASSED] checksum #{dep.target}"
|
@@ -1,15 +1,27 @@
|
|
1
1
|
class WarningShot::ManualResolver
|
2
2
|
include WarningShot::Resolver
|
3
3
|
order 10000
|
4
|
-
#disable!
|
5
|
-
|
6
4
|
branch :manual
|
5
|
+
|
7
6
|
description 'A glorified todo list of things that need to be resolved manually'
|
8
7
|
|
8
|
+
cli("--notes", "List all the notes in the manual branch") do |val|
|
9
|
+
WarningShot::Resolver.descendants.each{|d| d.disable!}
|
10
|
+
self.enable!
|
11
|
+
|
12
|
+
config = WarningShot::Config.parse_args
|
13
|
+
config[:verbose] = true
|
14
|
+
|
15
|
+
dr = WarningShot::DependencyResolver.new(config)
|
16
|
+
dr.dependency_tree[:manual].each { |note| puts "~ #{note}" }
|
17
|
+
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
|
9
21
|
#Encapsulated in a struct so Resolver doesn't freak out when we instance_eval #met & #resolved
|
10
22
|
NoteResource = Struct.new(:msg)
|
11
23
|
|
12
|
-
|
24
|
+
typecast do |note|
|
13
25
|
NoteResource.new(note)
|
14
26
|
end
|
15
27
|
|
@@ -39,14 +39,12 @@ class WarningShot::PermissionResolver
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
PermissionResource.new _path, _mode, _user, _group, _recursive
|
42
|
+
typecast Hash do |yaml|
|
43
|
+
PermissionResource.new yaml.delete(:path),
|
44
|
+
yaml.delete(:mode) || '0755',
|
45
|
+
yaml.delete(:user) || 'nobody',
|
46
|
+
yaml.delete(:group) || 'nobody',
|
47
|
+
yaml.delete(:recursive) || 'none'
|
50
48
|
end
|
51
49
|
|
52
50
|
register :test do |resource|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class WarningShot::SymlinkResolver
|
2
2
|
include WarningShot::Resolver
|
3
|
+
add_dependency :core, 'fileutils'
|
3
4
|
|
4
5
|
order 50
|
5
6
|
branch :symlink
|
@@ -11,25 +12,29 @@ class WarningShot::SymlinkResolver
|
|
11
12
|
def exists?
|
12
13
|
self.target ? File.symlink?(self.target) : false
|
13
14
|
end
|
15
|
+
|
16
|
+
# Determines if link points at correct file
|
17
|
+
def correct?
|
18
|
+
File.identical? self.source, self.target
|
19
|
+
end
|
20
|
+
|
14
21
|
end
|
15
22
|
|
16
|
-
|
17
|
-
SymlinkResource.new yaml, nil, false
|
18
|
-
end
|
19
|
-
|
20
|
-
cast Hash do |yaml|
|
23
|
+
typecast do |yaml|
|
21
24
|
use_force = yaml[:force].nil? ? true : yaml[:force]
|
22
|
-
|
25
|
+
_src = File.expand_path yaml[:source]
|
26
|
+
_trg = File.expand_path yaml[:target]
|
27
|
+
SymlinkResource.new _src, _trg, use_force
|
23
28
|
end
|
24
29
|
|
25
30
|
# If the target wasn't specified, it doesn't exist
|
26
31
|
register :test do |dep|
|
27
|
-
if
|
32
|
+
if symlink_correct = dep.exists? && dep.correct?
|
28
33
|
logger.debug " ~ [PASSED] symlink #{dep.target}"
|
29
34
|
else
|
30
35
|
logger.warn " ~ [FAILED] symlink #{dep.target}"
|
31
36
|
end
|
32
|
-
|
37
|
+
symlink_correct
|
33
38
|
end
|
34
39
|
|
35
40
|
register :resolution do |dep|
|
@@ -1,74 +1,61 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'net/http'
|
3
|
-
require 'net/https'
|
4
|
-
|
5
1
|
module WarningShot
|
6
2
|
class UrlResolver
|
7
3
|
include WarningShot::Resolver
|
4
|
+
add_dependency :core, 'uri'
|
5
|
+
add_dependency :core, 'net/http'
|
6
|
+
add_dependency :core, 'net/https'
|
7
|
+
|
8
8
|
order 900
|
9
|
-
#disable!
|
10
9
|
|
11
10
|
branch :url
|
12
11
|
description 'Validates that URLs are reachable.'
|
13
12
|
|
14
|
-
cli(
|
15
|
-
:
|
16
|
-
|
17
|
-
:name => "url_strict",
|
18
|
-
:default => false
|
19
|
-
)
|
20
|
-
|
21
|
-
cli(
|
22
|
-
:long => "--rootcert",
|
23
|
-
:description => "Path to root ca certificate",
|
24
|
-
:name => "root_ca",
|
25
|
-
:default => nil
|
26
|
-
)
|
13
|
+
cli("--strict", "Success is only for 200 instead of 2xx|3xx") do |val|
|
14
|
+
options[:url_strict] = val
|
15
|
+
end
|
27
16
|
|
28
|
-
cli(
|
29
|
-
:
|
30
|
-
|
31
|
-
:name => "ssl_verify_depth",
|
32
|
-
:default => 5
|
33
|
-
)
|
17
|
+
cli("--rootcert", "Path to root ca certificate") do |val|
|
18
|
+
options[:root_ca] = val
|
19
|
+
end
|
34
20
|
|
35
|
-
|
36
|
-
|
37
|
-
UrlResource.new URI.parse(dep)
|
21
|
+
cli("--vdepth", "SSL Verify Peer Depth") do |val|
|
22
|
+
options[:ssl_verify_depth] = val
|
38
23
|
end
|
24
|
+
|
25
|
+
typecast{ |dep| URI.parse(dep) }
|
39
26
|
|
40
|
-
register :test do |
|
27
|
+
register :test do |uri,config|
|
41
28
|
begin
|
42
|
-
http = Net::HTTP.new(
|
29
|
+
http = Net::HTTP.new(uri.host,uri.port)
|
43
30
|
|
44
|
-
if
|
31
|
+
if uri.scheme == 'https'
|
45
32
|
http.use_ssl = true
|
46
33
|
|
47
|
-
if
|
48
|
-
http.ca_file =
|
34
|
+
if config[:root_ca] && File.exist?(config[:root_ca])
|
35
|
+
http.ca_file = config[:root_ca]
|
49
36
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
50
|
-
http.verify_depth =
|
37
|
+
http.verify_depth = config[:ssl_verify_depth]
|
51
38
|
else
|
52
39
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
53
40
|
end
|
54
41
|
end
|
55
42
|
|
56
|
-
|
57
|
-
resp = http.head(
|
43
|
+
uri.path = '/' if uri.path.empty?
|
44
|
+
resp = http.head(uri.path)
|
58
45
|
|
59
|
-
valid_codes =
|
46
|
+
valid_codes = config[:url_strict] ? /200/ : /^[23][0-9][0-9]$/
|
60
47
|
|
61
48
|
page_found = (resp.code =~ valid_codes)
|
62
|
-
|
49
|
+
|
63
50
|
if page_found
|
64
|
-
logger.debug " ~ [PASSED] url #{
|
51
|
+
logger.debug " ~ [PASSED] url #{uri.to_s}"
|
65
52
|
else
|
66
|
-
logger.warn " ~ [FAILED] url #{
|
53
|
+
logger.warn " ~ [FAILED] url #{uri.to_s}"
|
67
54
|
end
|
68
55
|
|
69
56
|
page_found
|
70
|
-
rescue Exception
|
71
|
-
logger.error "Could not reach #{
|
57
|
+
rescue Exception => ex
|
58
|
+
logger.error "Could not reach #{uri.to_s}"
|
72
59
|
false
|
73
60
|
end
|
74
61
|
end
|
data/lib/warningshot.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'fileutils'
|
3
2
|
require 'yaml'
|
4
|
-
require 'optparse'
|
5
3
|
require 'logger'
|
6
4
|
require 'set'
|
7
5
|
require 'rbconfig'
|
6
|
+
require 'optparse'
|
8
7
|
|
9
8
|
# Load core extensions
|
10
|
-
Dir.glob(File.join(File.dirname(__FILE__),
|
9
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'core_ext', '**', '*.rb')).each {|f| require f}
|
11
10
|
|
12
11
|
# Load WarningShot
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
require File.dirname(__FILE__) / 'warningshot' / 'warning_shot'
|
13
|
+
require File.dirname(__FILE__) / 'warningshot' / 'version'
|
14
|
+
require File.dirname(__FILE__) / 'warningshot' / 'config'
|
15
|
+
require File.dirname(__FILE__) / 'warningshot' / 'logger'
|
16
|
+
require File.dirname(__FILE__) / 'warningshot' / 'resolver'
|
17
|
+
require File.dirname(__FILE__) / 'warningshot' / 'dependency_resolver'
|
18
|
+
require File.dirname(__FILE__) / 'warningshot' / 'growl'
|
19
|
+
require File.dirname(__FILE__) / 'warningshot' / 'template_generator'
|