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.
Files changed (51) hide show
  1. data/CHANGELOG +8 -0
  2. data/CONTRIBUTORS +2 -1
  3. data/README +86 -6
  4. data/Rakefile +4 -3
  5. data/TODO +1 -147
  6. data/bin/warningshot +11 -7
  7. data/lib/resolvers/core_lib_resolver.rb +2 -3
  8. data/lib/resolvers/directory_resolver.rb +1 -1
  9. data/lib/resolvers/file_resolver.rb +35 -17
  10. data/lib/resolvers/gem_resolver.rb +81 -60
  11. data/lib/resolvers/integrity_resolver.rb +10 -11
  12. data/lib/resolvers/manual_resolver.rb +15 -3
  13. data/lib/resolvers/permission_resolver.rb +6 -8
  14. data/lib/resolvers/symlink_resolver.rb +13 -8
  15. data/lib/resolvers/url_resolver.rb +28 -41
  16. data/lib/warningshot.rb +10 -7
  17. data/lib/warningshot/config.rb +254 -0
  18. data/lib/{warning_shot → warningshot}/dependency_resolver.rb +38 -17
  19. data/lib/{warning_shot → warningshot}/growl.rb +2 -0
  20. data/lib/{warning_shot → warningshot}/logger.rb +2 -0
  21. data/lib/{warning_shot → warningshot}/resolver.rb +177 -89
  22. data/lib/warningshot/suite.rb +4 -0
  23. data/lib/{warning_shot → warningshot}/template_generator.rb +4 -1
  24. data/lib/{warning_shot → warningshot}/version.rb +3 -1
  25. data/lib/warningshot/warning_shot.rb +187 -0
  26. data/tasks/gemspec.rb +3 -16
  27. data/tasks/yard.rb +1 -1
  28. data/templates/gems.yml +1 -0
  29. data/test/data/faux_test.yml +5 -0
  30. data/test/data/faux_test_resolver.rb +21 -0
  31. data/test/data/mock_resolver.rb +11 -5
  32. data/test/log/warningshot.log +3051 -532
  33. data/test/spec/unit/resolvers/core_lib_resolver_spec.rb +1 -1
  34. data/test/spec/unit/resolvers/directory_resolver_spec.rb +1 -1
  35. data/test/spec/unit/resolvers/file_resolver_spec.rb +9 -13
  36. data/test/spec/unit/resolvers/gem_resolver_spec.rb +108 -32
  37. data/test/spec/unit/resolvers/integrity_resolver_spec.rb +6 -6
  38. data/test/spec/unit/resolvers/permission_resolver_spec.rb +2 -2
  39. data/test/spec/unit/resolvers/symlink_resolver_spec.rb +8 -1
  40. data/test/spec/unit/resolvers/url_resolver_spec.rb +10 -10
  41. data/test/spec/unit/warningshot/config_spec.rb +57 -0
  42. data/test/spec/unit/{warning_shot → warningshot}/dependency_resolver_spec.rb +18 -9
  43. data/test/spec/unit/{warning_shot → warningshot}/resolver_spec.rb +54 -79
  44. data/test/spec/unit/{warning_shot → warningshot}/template_generator_spec.rb +1 -1
  45. data/test/spec/unit/{warning_shot → warningshot}/version_spec.rb +0 -0
  46. data/test/spec/unit/{warning_shot → warningshot}/warning_shot_spec.rb +0 -0
  47. metadata +24 -26
  48. data/lib/warning_shot/config.rb +0 -132
  49. data/lib/warning_shot/warning_shot.rb +0 -130
  50. data/test/spec/spec.opts.zoiks +0 -0
  51. data/test/spec/unit/warning_shot/config_spec.rb +0 -35
data/CHANGELOG CHANGED
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ = 0.9.5
4
+ 2009-01-22 Cory ODaniel <warningshot@coryodaniel.com>
5
+ * RubyGems 1.3 Support
6
+ * Various bug fixes / improvements in GemResolver
7
+ * Added RSpecs
8
+ * Fixed bug that crashed WS if YAML was malformed
@@ -1,2 +1,3 @@
1
1
  ==== Contributors
2
- * Cory ODaniel (I'm lonely)
2
+ * Cory ODaniel (I'm lonely)
3
+ * Nate Murray
data/README CHANGED
@@ -1,16 +1,89 @@
1
1
  WarningShot Dependency Resolution Framework
2
2
  * Additional documentation @ http://github.com/coryodaniel/warningshot/wikis/
3
3
 
4
+
5
+ ==== Installing WarningShot
6
+ WarningShot installs a little differently than most gems. WarningShot itself has NO gem dependencies. Gems become
7
+ a dependency based on what Plugins/Resolvers you have installed. By default WarningShot will not install any additional gems.
8
+ When using WarningShot if a gem is missing that is needed for a feature you are using you will receive a warning that the gem
9
+ is missing. Optionally you can list and build all of warningshots dependencies from the command line.
10
+
11
+ sudo gem install warningshot
12
+ warningshot --list-deps (list all resolvers and their dependencies)
13
+ warningshot --build-deps (install all gems that resolvers are dependent on)
14
+
15
+ This method provides a minimalist WarningShot. WarningShot's dependencies essentially change depending on what you use
16
+ it for. Thats neat, not a lot of extra gems that you don't need installed being installed.
17
+
18
+
19
+ ==== Terminology
20
+ * Resolver
21
+ A class that includes WarningShot::Resolver. It should have the ability to test and resolve a type
22
+ of dependency
23
+
24
+ * Configuration
25
+ The current configuration the WarningShot instance is running under.
26
+ Configurations can be created with WarningShot::Config
27
+
28
+ * Dependency
29
+ A dependency is an entry in a machine recipe. A dependency should consist of some means of identifying the
30
+ dependency and optionally (but suggested) have some way of describing how it should be resolved.
31
+ Ex: File Dependencies specify where the file should be located, and where WarningShot can download it if it
32
+ does not exist
33
+
34
+ * Test
35
+ Tests are blocks that are registered in resolver. They are a means of determining if a dependency is met. Multiple tests
36
+ can be written, and may also have conditions as to whether they should run or not (a test could be environment
37
+ specific for instance). WarningShot will run the first test that it can based on any conditions provided.
38
+ Tests should always return a Boolean value
39
+
40
+ * Resolution
41
+ Resolutions are like tests in every way except instead of determine if a dependency has been met, they actually
42
+ repair or resolve the dependency. The gem resolver can install missing gems and the file resolver can download
43
+ missing files
44
+
45
+ * Machine Recipes / Application Recipes
46
+ A machine recipe is one or more dependency branches, the default file type is YAML, but that is configurable
47
+ within warningshot. A machine recipe can specify the complete configuration of a computer/application or just one
48
+ aspect of it. Example: warningshot --templates will create a separate machine recipe for each branch supported.
49
+ In the wiki (http://github.com/coryodaniel/warningshot/wikis/example-merbnginx-app-recipe-once-aptquality-dependencies-are-supported)
50
+ is an example of a machine recipe that specifies dependencies of files, gems, apt binaries, etc.
51
+
52
+ * DependencyTree
53
+ After WarningShot locates all of the Machine Recipes they are parsed into the dependency tree. The dependency
54
+ tree is a large hash of branch names to raw hashes parsed from the Machine Recipes (YAML).
55
+
56
+ * DependencyBranch
57
+ A specific type of dependency within the dependency tree. Examples include, :file, :gem, :directory
58
+
4
59
  ==== How it works
5
60
  * WarningShot - Factory class that creates and runs DependencyResolver
6
61
  * DependencyResolver - Locates Resolver classes, creates a dependency tree, and matches resolvers to resolution branches
7
62
  * Resolver - Class that can be included to create plugins. Composed of tests and resolutions that can determine if a dependency was met, and if not, how to fix it
8
63
 
9
-
64
+ ==== Command Line Examples
65
+ For a list of all flags do: warningshot --help
66
+
67
+ - Details on Resolvers
68
+ warningshot --version
69
+
70
+ - Loading specific resolvers
71
+ warningshot --oload=gem,file # => Only gem and file resolvers will be run
72
+ warningshot --pload=directory,file # => Only loads specified gems and loads in specified order
73
+ warningshot --resolvers=/path/to/my/resolvers/*.rb # => Glob to find additional resolvers
74
+
75
+ - Creating Recipe templates
76
+ warningshot --templates=./path/to/where/you/want/templates
77
+
78
+ - Warningshot's Dependencies
79
+ warningshot --list-deps # => Depedencies per Resolver
80
+ warningshot --build-deps # => Installs everything a full fledged warningshot needs
81
+
82
+
10
83
  ==== Ruby API
11
84
 
12
85
  - Configuring WarningShot
13
- WarningShot::Config.use do |c|
86
+ config = WarningShot::Config.create do |c|
14
87
  c[:environment] = 'development'
15
88
  c[:resolve] = false
16
89
  c[:config_paths] = ['.' / 'config' / 'warningshot']
@@ -24,7 +97,7 @@ WarningShot Dependency Resolution Framework
24
97
  end
25
98
 
26
99
  - Interfacing with a DependencyResolver
27
- dependency_resolver = WarningShot.fire!
100
+ dependency_resolver = WarningShot.fire!(config)
28
101
  dependency_resolver.stats # => Hash of statistics
29
102
 
30
103
  dependency_resolver.resolvers # => Array of all executed resolvers
@@ -67,7 +140,7 @@ WarningShot Dependency Resolution Framework
67
140
  * Config Files
68
141
 
69
142
 
70
- ==== Using Config Files
143
+ ==== Using Machine Recipes
71
144
  * Coming Soon
72
145
 
73
146
 
@@ -77,6 +150,7 @@ WarningShot Dependency Resolution Framework
77
150
 
78
151
  ==== Extending WarningShot
79
152
  * Writing a Resolver (Coming Soon)
153
+ * Kernel#require vs Resolver#add_dependency
80
154
  * Modifying Resolvers at run-time (Coming Soon)
81
155
 
82
156
 
@@ -87,13 +161,19 @@ WarningShot Dependency Resolution Framework
87
161
  * Bug reports / feature requests @:
88
162
  http://warningshot.lighthouseapp.com/projects/17241-warningshot/overview
89
163
 
90
- * Online Documentation available @: (eventually)
91
-
164
+ * Online Documentation available @:
165
+ http://github.com/coryodaniel/warningshot/wikis
166
+
92
167
  * RubyForge Project @:
93
168
  http://rubyforge.org/projects/warning-shot/
94
169
 
95
170
  * All modifications should also have applicable rpsecs
96
171
  http://rspec.info/
172
+
173
+ * A dummy gem has been created for testing the GemResolver
174
+ https://rubyforge.org/projects/ws-dummy/
175
+ http://github.com/coryodaniel/ws-dummy/tree/master
176
+ gem install ws-dummy
97
177
 
98
178
  * All code should be documented using YARD
99
179
  http://yard.rubyforge.org/
data/Rakefile CHANGED
@@ -16,13 +16,14 @@ require "fileutils"
16
16
  NAME = 'warningshot'
17
17
  ROOT = Pathname(__FILE__).dirname.expand_path
18
18
 
19
- require 'lib/warning_shot/version'
19
+ require 'lib/warningshot'
20
+ require 'lib/warningshot/version'
20
21
 
21
22
  CLEAN.include ["**/.*.sw?", "pkg", "lib/*.bundle", "*.gem", "doc/","doc/", "test/output/*", "coverage", "cache"]
22
23
  Dir['tasks/*.rb'].each {|r| require r}
23
24
 
24
25
 
25
26
  ##############################################################################
26
- # ADD YOUR CUSTOM TASKS IN /lib/tasks
27
- # NAME YOUR RAKE FILES file_name.rake
27
+ # ADD YOUR CUSTOM TASKS IN ./tasks
28
+ # NAME YOUR RAKE FILES file_name.rb
28
29
  ##############################################################################
data/TODO CHANGED
@@ -1,148 +1,2 @@
1
1
  Additional TODOS are at:
2
- http://warningshot.lighthouseapp.com
3
-
4
- ====
5
- WarningShot should have its own set of config files so it can test its self (for WS Developers)
6
-
7
- Gems
8
- * Minigems option, prepares gems as minigems
9
-
10
- Binary Resolver
11
- * Apt, Yum, Ports
12
- * Random binaries like awk, vi, etc... (previously used `which BINARY`)
13
-
14
- Git, Svn Resolver
15
-
16
- ServicesResolver
17
- * memcached, mysql, etc...
18
-
19
- IpTableResolver
20
- * Confirms, sets up, and saves Iptables
21
-
22
- Connections Resolver
23
- * test network connections
24
- # ifconfig -a => active interfaces
25
-
26
- Hardware Resolver
27
- * Determines if hardware requirements are met
28
-
29
- Script Resolver
30
- * A scripting interface... was in old WS that enabled people to do most of this stuff
31
- Should it just be left out since its so easy to extend?
32
-
33
- MountResolver / NFSMount Resolver
34
- * God knows.
35
-
36
- QA Resolvers
37
- * Rspec
38
- * YSlow
39
- * RCoverage
40
- * Watir, etc etc
41
-
42
- - :branch: quality
43
- :environments:
44
- :production:
45
- - {attrib: "rspec", grade: ">98"}
46
- - {attrib: "rcov", grade: ">90", rollback: "true"}
47
-
48
-
49
- - :branch: yslow
50
- :environments:
51
- :production:
52
- - {page: "http://example.com/login", grade: ">90"}
53
- - {page: "http://example.com/index", grade: ">=99", rollback: "true"}
54
-
55
- Interfaces for Cap, Vertebra, and Vlad
56
-
57
- ==== Old SHit.
58
- # This is old shit from a prototype i did of file/permissions resolver...
59
- # http://www.workingwithrails.com/railsplugin/6146-open4-9-3
60
- # http://codeforpeople.com/lib/ruby/open4/open4-0.9.3/README
61
-
62
- module WarningShot
63
- class FileSystemResource
64
-
65
- def initialize(path_data)
66
- @attributes = parse_params(path_data)
67
- end
68
-
69
- def [](key)
70
- return @attributes[key]
71
- end
72
-
73
- def []=(key,val)
74
- return @attributes[key] = val
75
- end
76
-
77
- def chown
78
- status = Open4::popen4("sh") do |p,i,o,e|
79
- command = ["chown"]
80
- command.push "-R" if ["chown","both"].member? self[:recursive]
81
- command.push "#{self[:user]}:#{self[:group]}"
82
- command.push self[:target]
83
-
84
- i.puts command.join(" ")
85
- i.close
86
- end
87
-
88
- if status.exitstatus == 0
89
- return true
90
- else
91
- raise Exception, "Could not chown:\n ~ #{@attributes.inspect}"
92
- end
93
- end
94
-
95
- def chmod
96
- status = Open4::popen4("sh") do |p,i,o,e|
97
- command = ["chmod"]
98
- command.push "-R" if ["chmod","both"].member? self[:recursive]
99
- command.push self[:mode]
100
- command.push self[:target]
101
-
102
- i.puts command.join(" ")
103
- i.close
104
- end
105
-
106
- if status.exitstatus == 0
107
- return true
108
- else
109
- raise Exception, "Could not chmod:\n ~ #{@attributes.inspect}"
110
- end
111
- end
112
-
113
- private
114
-
115
- def parse_params(path_data)
116
- attributes = defaults
117
-
118
- #Make path_data a hash if it was passed as a string
119
- path_data = {:target => path_data} if path_data.is_a? String
120
-
121
- attributes.merge! path_data.symbolize_keys!
122
- orig_group = attributes[:group]
123
-
124
- #Group defaults to user
125
- attributes[:group] = attributes[:user] if orig_group.nil? || orig_group.empty?
126
-
127
- #Expand source and dest paths
128
- #attributes[:source] = File.expand_path(attributes[:source]) unless attributes[:source].nil?
129
- #attributes[:target] = File.expand_path(attributes[:target])
130
-
131
- attributes[:recursive].downcase!
132
-
133
- return attributes
134
- end
135
-
136
- def defaults
137
- {
138
- :target => nil,
139
- :source => nil,
140
- :mode => "0755",
141
- :user => "nobody",
142
- :group => "nobody",
143
- :recursive => "none"
144
- }
145
- end
146
-
147
- end
148
- end
2
+ http://warningshot.lighthouseapp.com
@@ -1,19 +1,23 @@
1
1
  #! /usr/bin/env ruby
2
- require 'warningshot'
3
2
 
4
- # Parse ARGV
5
- WarningShot::Config.parse_args
3
+ #pre scan ARGV for pload oload
4
+ if ARGV.grep(/(o|p)load/i).empty?
5
+ require 'warningshot/suite'
6
+ else
7
+ require 'warningshot'
8
+ end
9
+
10
+ # Create a config hash
11
+ config = WarningShot::Config.parse_args
6
12
 
7
13
  # Initialize and run a new dependency resolver
8
- dep_resolver = WarningShot.fire!
14
+ dep_resolver = WarningShot.fire!(config)
9
15
 
10
16
  # Get the stats from the resolver
11
17
  stats = dep_resolver.stats
12
18
 
13
19
  # Growl the results if growl is on
14
- if WarningShot::Config[:growl]
15
- WarningShot::Growl.say stats.to_a.join('/')
16
- end
20
+ WarningShot::Growl.say stats.to_a.join('/') if config[:growl]
17
21
 
18
22
  #Return an exit status based on number of unresolved dependencies
19
23
  exit(stats[:unresolved])
@@ -6,15 +6,14 @@
6
6
 
7
7
  class WarningShot::CoreLibResolver
8
8
  include WarningShot::Resolver
9
-
10
9
  order 10
11
- #disable!
10
+
12
11
  description 'Checks that core ruby lib packages are available'
13
12
  branch :core_lib
14
13
  @@do_purge = false
15
14
 
16
15
  CoreLibResource = Struct.new(:lib)
17
- cast do |dep|
16
+ typecast do |dep|
18
17
  CoreLibResource.new(dep)
19
18
  end
20
19
 
@@ -6,7 +6,7 @@ class WarningShot::DirectoryResolver
6
6
  description 'Validates presence of directories'
7
7
 
8
8
  DirectoryResource = Struct.new(:path)
9
- cast do |path|
9
+ typecast do |path|
10
10
  DirectoryResource.new File.expand_path(path)
11
11
  end
12
12
 
@@ -1,8 +1,3 @@
1
- require 'fileutils'
2
- require 'uri'
3
- require 'net/http'
4
- require 'net/https'
5
-
6
1
  # Tests and Heals File Dependencies
7
2
  #
8
3
  # @notes
@@ -10,6 +5,12 @@ require 'net/https'
10
5
  # target is were the file should exist
11
6
  class WarningShot::FileResolver
12
7
  include WarningShot::Resolver
8
+
9
+ add_dependency :core, 'fileutils'
10
+ add_dependency :core, 'uri'
11
+ add_dependency :core, 'net/http', :disable => false, :unregister => [:http_protocol_resolver]
12
+ add_dependency :core, 'net/https', :disable => false, :unregister => [:https_protocol_resolver]
13
+
13
14
  order 500
14
15
 
15
16
  branch :file
@@ -17,20 +18,20 @@ class WarningShot::FileResolver
17
18
 
18
19
  # Define FileResource struct
19
20
  FileResource = Struct.new(:source,:target) do
20
- def exists?;File.exists?(target.path);end;
21
- def remove;File.unlink(target.path);end;
21
+ def exists?;File.exists?(File.expand_path(target.path));end;
22
+ def remove;File.unlink(File.expand_path(target.path));end;
22
23
  end
23
24
 
24
- cast String do |file|
25
+ typecast String do |file|
25
26
  FileResource.new URI.parse(''), URI.parse(file)
26
27
  end
27
28
 
28
- cast Hash do |file|
29
+ typecast Hash do |file|
29
30
  file[:source].sub!(/file:\/\//i,'') unless file[:source].nil?
30
31
  FileResource.new URI.parse(file[:source] || ''), URI.parse(file[:target])
31
32
  end
32
33
 
33
- register :test, {:name => :file_check} do |file|
34
+ register :test, {:name => :file_test} do |file|
34
35
  if file_found = file.exists?
35
36
  logger.debug " ~ [PASSED] file: #{file.target.path}"
36
37
  else
@@ -43,23 +44,39 @@ class WarningShot::FileResolver
43
44
  # Resolve files from target sources
44
45
  # @notes
45
46
  # :if matches FILE_PROTOCOL or uri.scheme == nil
46
- register(:resolution, { :name => :file_protocol,
47
- :desc => "Resolves files from target sources",
47
+ register(:resolution, { :name => :file_protocol_resolver,
48
+ :desc => "Resolves files via local filesystem",
48
49
  :if => lambda { |file|
49
- !!(file.source.scheme =~ /file/i || file.source.scheme == nil)
50
+ !!(file.source.scheme =~ /file/i || file.source.scheme == nil && !file.source.path.empty?)
50
51
  }
51
52
  }) do |file|
52
53
  begin
53
- FileUtils.cp file.source.path, file.target.path
54
+ FileUtils.cp File.expand_path(file.source.path), File.expand_path(file.target.path)
54
55
  rescue Exception => ex
55
56
  logger.error " ~ Could not restore file (#{file.target.path}) from #{file.source.path}"
56
57
  end
57
58
  file.exists?
58
59
  end
59
60
 
60
- register(:resolution, { :name => :http_protocol,
61
- :desc => "Resolves files from HTTP sources",
62
- :if => lambda { |file| !!(file.source.to_s =~ /http(s)?/i)}
61
+ register(:resolution, { :name => :http_protocol_resolver,
62
+ :desc => "Resolves files via HTTP",
63
+ :if => lambda { |file| !!(file.source.to_s =~ /http/i)}
64
+ }) do |file|
65
+ begin
66
+ http = Net::HTTP.new(file.source.host,file.source.port)
67
+ file.source.path = '/' if file.source.path.empty?
68
+ resp = http.get(file.source.path)
69
+
70
+ File.open(file.target.path,"w+"){ |fs| fs.puts resp.body } if resp.code == "200"
71
+ rescue Exception => ex
72
+ logger.error " ~ Could not restore file (#{file.target.path}) from #{file.source.path}"
73
+ end
74
+ file.exists?
75
+ end
76
+
77
+ register(:resolution, { :name => :https_protocol_resolver,
78
+ :desc => "Resolves files via HTTPS",
79
+ :if => lambda { |file| !!(file.source.to_s =~ /https/i)}
63
80
  }) do |file|
64
81
  begin
65
82
  http = Net::HTTP.new(file.source.host,file.source.port)
@@ -73,6 +90,7 @@ class WarningShot::FileResolver
73
90
  end
74
91
  file.exists?
75
92
  end
93
+
76
94
  =begin
77
95
  register(:resolution, {:name => :scp_protocol,
78
96
  :desc => "Resolves files over SSH",