warningshot 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|