warningshot 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
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",