This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
An example resolver
# As an example here is the FileResolver
class WarningShot::FileResolver
include WarningShot::Resolver
# What is the add_dependency garbage? Where is require?
# All core libraries and gems should be 'required' with add_dependency, this allows warningshot to 'pick' it dependencies.
# This makes warningshot minimalistic. For example, if 'net/scp' was required for FileResolver (which it will in the future)
# you could still use warningshot without it, it would simply disable the use of scp_protocol resolution. By default
# if a dependency is missing warningshot will disable the whole Resolver (ie, fileutils and uri below). This is because they are
# critical in how the FileResolver works. The additional dependencies are optional based on how warningshot is being used.
add_dependency :core, 'fileutils'
add_dependency :core, 'uri'
add_dependency :core, 'net/http', :disable => false, :unregister => :http_protocol_resolver
add_dependency :core, 'net/https', :disable => false, :unregister => :https_protocol_resolver
# The default sequential order for the resolver to run in, this can be modified
# by the end user by FileResolver.order(1) or by specifying the order in
# the priority loader.
# WarningShot::Config.new({:pload => [:file]})
order 500
# The branch of the dependency tree to use, in the near future multiple branches will be
# able to be specified
branch :file
# A description of what the resolver does
description 'Validates presence of files'
# A resource needs to be created to 'stuff' the YAML into. Why?
# Because additional methods are added to track the status of tests and
# and resolution, so the dependency needs to be a mutable object.
FileResource = Struct.new(:source,:target) do
def exists?;File.exists?(File.expand_path(target.path));end;
def remove;File.unlink(File.expand_path(target.path));end;
end
# Resolver.typecast is what puts the YAML into the resource (above).
# typecast takes a class (optional) and a block multiple typecasts only need
# to be declared if there are multiple datatypes per dependency in the yaml file.
# FileResource can handle a String or a Hash. The class is optional, so if there is only
# one type of data in your yaml, you can leave it off
typecast String do |file|
FileResource.new URI.parse(''), URI.parse(file)
end
# Handling a hash from yaml
typecast Hash do |file|
file[:source].sub!(/file:\/\//i,'') unless file[:source].nil?
FileResource.new URI.parse(file[:source] || ''), URI.parse(file[:target])
end
# Resolver#initialize can be defined. It will be passed one arg and a variable list argument.
# Make sure to call super in the constructor
#
# there is also an attr_reader :config that will be available to the object
# and an attr_accessor :dependencies which stores the set of dependencies to be checked
def initialize(config,*deps)
super
end
# Multiple tests can be registered. The first test to pass the :if or :unless block (if provided)
# will be executed, if none pass it, then a default test will be run (one without a conditional block).
# Examples of conditional blocks can be seen in register :resolution below
#
# The actual test block (after do) can take 0, 1, or 2 arguments. The Resolver will pass in the correct number
# attributes. If one is specified it will pass in the current dependency (at runtime). If two are specified it will
# pass in the current dependency and the running configuration.
#
# @example
# #A test taking a file dependency and a configuration
# register(:test) do |file,config|
# if file.target.path =~ /database.yml/ && config[:environment] == 'production'
# # ... do some specific test for production database config files
# end
# end
#
# #A test with an :if conditional that takes the configuration...
# register(:test,:if => lambda{|file,config| config[:environment] == 'development' }) do |file|
# # ... the :if statement only allows this to run in the 'development' environment
# # ... in this test I may only need file and not the config.
# end
#
register :test, {:name => :file_check} do |file|
if file_found = file.exists?
logger.debug " ~ [PASSED] file: #{file.target.path}"
else
logger.warn " ~ [FAILED] file: #{file.target.path}"
end
file_found
end
# Register a resolution. The :if condition checks to see that the protocol to resolve over
# is file://
register(:resolution, { :name => :file_protocol,
:desc => "Resolves files from target sources",
:if => lambda { |file|
!!(file.source.scheme =~ /file/i || file.source.scheme == nil && !file.source.path.empty?)
}
}) do |file|
begin
FileUtils.cp File.expand_path(file.source.path), File.expand_path(file.target.path)
rescue Exception => ex
logger.error " ~ Could not restore file (#{file.target.path}) from #{file.source.path}"
end
file.exists?
end
# Register a resolution. The :if condition checks to see that the protocol to resolve over
# is http:// or https://
register(:resolution, { :name => :http_protocol,
:desc => "Resolves files from HTTP sources",
:if => lambda { |file| !!(file.source.to_s =~ /http(s)?/i)}
}) do |file|
begin
http = Net::HTTP.new(file.source.host,file.source.port)
http.use_ssl = (file.source.scheme == 'https')
file.source.path = '/' if file.source.path.empty?
resp = http.get(file.source.path)
File.open(file.target.path,"w+"){ |fs| fs.puts resp.body } if resp.code == "200"
rescue Exception => ex
logger.error " ~ Could not restore file (#{file.target.path}) from #{file.source.path}"
end
file.exists?
end
end











