noah 0.0.5-jruby → 0.1-jruby
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/.gemtest +0 -0
- data/.gitignore +10 -0
- data/LICENSE +201 -0
- data/README.md +68 -212
- data/Rakefile +65 -41
- data/TODO.md +65 -0
- data/bin/noah +2 -1
- data/bin/noah-watcher.rb +103 -0
- data/config.ru +6 -3
- data/config/warble.rb +18 -0
- data/examples/README.md +116 -0
- data/examples/cluster.ru +2 -0
- data/examples/custom-watcher.rb +10 -0
- data/examples/httpclient-server.rb +7 -0
- data/examples/httpclient.rb +12 -0
- data/examples/httpclient2.rb +28 -0
- data/examples/js/FABridge.js +1452 -0
- data/examples/js/WebSocketMain.swf +830 -0
- data/examples/js/swfobject.js +851 -0
- data/examples/js/web_socket.js +312 -0
- data/examples/logger.rb +11 -0
- data/examples/reconfiguring-sinatra-watcher.rb +11 -0
- data/examples/reconfiguring-sinatra.rb +33 -0
- data/examples/simple-post.rb +17 -0
- data/examples/websocket.html +24 -0
- data/examples/websocket.rb +41 -0
- data/lib/noah.rb +6 -8
- data/lib/noah/app.rb +20 -268
- data/lib/noah/application_routes.rb +70 -0
- data/lib/noah/ark.rb +0 -0
- data/lib/noah/configuration_routes.rb +81 -0
- data/lib/noah/custom_watcher.rb +79 -0
- data/lib/noah/ephemeral_routes.rb +47 -0
- data/lib/noah/helpers.rb +37 -14
- data/lib/noah/host_routes.rb +69 -0
- data/lib/noah/models.rb +86 -5
- data/lib/noah/models/applications.rb +41 -0
- data/lib/noah/models/configurations.rb +49 -0
- data/lib/noah/models/ephemerals.rb +54 -0
- data/lib/noah/models/hosts.rb +56 -0
- data/lib/noah/models/services.rb +54 -0
- data/lib/noah/models/watchers.rb +62 -0
- data/lib/noah/passthrough.rb +11 -0
- data/lib/noah/service_routes.rb +71 -0
- data/lib/noah/validations.rb +1 -0
- data/lib/noah/validations/watcher_validations.rb +48 -0
- data/lib/noah/version.rb +1 -1
- data/lib/noah/watcher_routes.rb +45 -0
- data/noah.gemspec +25 -17
- data/spec/application_spec.rb +30 -30
- data/spec/configuration_spec.rb +78 -14
- data/spec/ephemeral_spec.rb +59 -0
- data/spec/host_spec.rb +21 -21
- data/spec/noahapp_application_spec.rb +6 -6
- data/spec/noahapp_configuration_spec.rb +5 -5
- data/spec/noahapp_ephemeral_spec.rb +115 -0
- data/spec/noahapp_host_spec.rb +3 -3
- data/spec/noahapp_service_spec.rb +10 -10
- data/spec/noahapp_watcher_spec.rb +123 -0
- data/spec/service_spec.rb +27 -27
- data/spec/spec_helper.rb +13 -22
- data/spec/support/db/.keep +0 -0
- data/spec/support/test-redis.conf +8 -0
- data/spec/watcher_spec.rb +62 -0
- data/views/index.haml +21 -15
- metadata +189 -146
- data/Gemfile.lock +0 -83
- data/doc/coverage/index.html +0 -138
- data/doc/coverage/jquery-1.3.2.min.js +0 -19
- data/doc/coverage/jquery.tablesorter.min.js +0 -15
- data/doc/coverage/lib-helpers_rb.html +0 -393
- data/doc/coverage/lib-models_rb.html +0 -1449
- data/doc/coverage/noah_rb.html +0 -2019
- data/doc/coverage/print.css +0 -12
- data/doc/coverage/rcov.js +0 -42
- data/doc/coverage/screen.css +0 -270
- data/lib/noah/applications.rb +0 -46
- data/lib/noah/configurations.rb +0 -49
- data/lib/noah/hosts.rb +0 -54
- data/lib/noah/services.rb +0 -57
- data/lib/noah/watchers.rb +0 -18
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            require 'eventmachine'
         | 
| 2 | 
            +
            require 'uri'
         | 
| 3 | 
            +
            require 'logger'
         | 
| 4 | 
            +
            begin
         | 
| 5 | 
            +
              require 'em-hiredis'
         | 
| 6 | 
            +
            rescue LoadError
         | 
| 7 | 
            +
              puts "Please install: em-hiredis"
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            @log = Logger.new(STDOUT)
         | 
| 11 | 
            +
            @log.level = Logger::DEBUG
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require File.join(File.dirname(__FILE__), 'passthrough')
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            module Noah
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              class CustomWatcher
         | 
| 18 | 
            +
                extend Passthrough
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                passthrough :redis_host, :pattern, :destination, :run!, :run_watcher
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                attr_accessor :my_pattern, :my_destination, :my_redis
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def self.watch(&blk)
         | 
| 25 | 
            +
                  watcher = Noah::Watcher.new
         | 
| 26 | 
            +
                  watcher.instance_eval(&blk) if block_given?
         | 
| 27 | 
            +
                  watcher
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def initialize
         | 
| 31 | 
            +
                  @my_redis ||= ENV['REDIS_URL']
         | 
| 32 | 
            +
                  @my_pattern ||= '//noah'
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def self.redis_host(host)
         | 
| 36 | 
            +
                  @my_redis = host
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def self.pattern(pattern)
         | 
| 40 | 
            +
                  @my_pattern = pattern
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def self.destination(destination)
         | 
| 44 | 
            +
                  @my_destination = destination
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def self.run!
         | 
| 48 | 
            +
                  @my_destination.nil? ? (raise ArgumentError) : run_watcher(@my_destination)
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                private
         | 
| 52 | 
            +
                def self.run_watcher(dest)
         | 
| 53 | 
            +
                  log = Logger.new(STDOUT)
         | 
| 54 | 
            +
                  log.level = Logger::INFO
         | 
| 55 | 
            +
                  log.debug "#{dest.inspect}"
         | 
| 56 | 
            +
                  redis_url = URI.parse(@my_redis)
         | 
| 57 | 
            +
                  db = redis_url.path.gsub(/\//,'')
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  EventMachine.run do
         | 
| 60 | 
            +
                    trap("TERM") { log.info "Killed"; EventMachine.stop }
         | 
| 61 | 
            +
                    trap("INT")  { log.info "Interrupted"; EventMachine.stop }
         | 
| 62 | 
            +
                    channel = EventMachine::Channel.new
         | 
| 63 | 
            +
                    r = EventMachine::Hiredis::Client.connect(redis_url.host, redis_url.port)
         | 
| 64 | 
            +
                    # Pulling out dbnum for now. Need to rethink it
         | 
| 65 | 
            +
                    #log.info "Binding to pattern #{db}:#{@my_pattern}"
         | 
| 66 | 
            +
                    log.info "Binding to pattern #{@my_pattern}"
         | 
| 67 | 
            +
                    r.psubscribe("#{@my_pattern}*")
         | 
| 68 | 
            +
                    r.on(:pmessage) do |pattern, event, message|
         | 
| 69 | 
            +
                      log.debug "Got message"
         | 
| 70 | 
            +
                      channel.push "#{message}"
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                    r.errback { log.info "Something went tango-uniform" }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    sub = channel.subscribe {|msg| log.info "Calling message handler"; dest.call(msg)}
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            class Noah::App
         | 
| 2 | 
            +
              get '/e/?' do
         | 
| 3 | 
            +
                halt 404
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              get '/e/*' do
         | 
| 7 | 
            +
                params["splat"].size == 0 ? (halt 404) : (e=Noah::Ephemeral.find(:path => "/#{params["splat"][0]}").first)
         | 
| 8 | 
            +
                (halt 404) if e.nil?
         | 
| 9 | 
            +
                content_type "application/octet-stream"
         | 
| 10 | 
            +
                e.data.nil? ? "" : "#{e.data}"
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              put '/e/*/watch' do
         | 
| 14 | 
            +
                required_params = ["endpoint"]
         | 
| 15 | 
            +
                data = JSON.parse(request.body.read)
         | 
| 16 | 
            +
                (data.keys.sort == required_params.sort) ? (e = Noah::Watcher.find(:path => params[:splat][0]).first) : (raise "Missing Parameters")
         | 
| 17 | 
            +
                e.nil? ? (halt 404) : (w = e.watch!(:endpoint => data["endpoint"]))
         | 
| 18 | 
            +
                w.to_json
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              put '/e/*' do
         | 
| 22 | 
            +
                raise("Data too large") if request.body.size > 512
         | 
| 23 | 
            +
                d = request.body.read  || nil
         | 
| 24 | 
            +
                opts = {:path => "/#{params[:splat][0]}", :data => d}
         | 
| 25 | 
            +
                e = Noah::Ephemeral.find_or_create(opts)
         | 
| 26 | 
            +
                if e.valid?
         | 
| 27 | 
            +
                  action = e.is_new? ? "create" : "update"
         | 
| 28 | 
            +
                  r = {"action" => action, "result" => "success", "id" => e.id, "path" => e.path, "data" => e.data}
         | 
| 29 | 
            +
                  r.to_json
         | 
| 30 | 
            +
                else
         | 
| 31 | 
            +
                  raise "#{format_errors(e)}"
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              delete '/e/*' do
         | 
| 36 | 
            +
                p = params[:splat][0]
         | 
| 37 | 
            +
                e = Noah::Ephemeral.find(:path => "/"+p).first
         | 
| 38 | 
            +
                if e
         | 
| 39 | 
            +
                  e.delete
         | 
| 40 | 
            +
                  r = {"result" => "success", "id" => "#{e.id}", "action" => "delete", "path" => e.name}
         | 
| 41 | 
            +
                  r.to_json
         | 
| 42 | 
            +
                else
         | 
| 43 | 
            +
                  halt 404
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            end
         | 
    
        data/lib/noah/helpers.rb
    CHANGED
    
    | @@ -1,56 +1,79 @@ | |
| 1 | 
            -
            require File.join(File.dirname(__FILE__), 'models')
         | 
| 2 1 | 
             
            module Noah
         | 
| 3 2 | 
             
              module SinatraHelpers
         | 
| 4 | 
            -
             | 
| 3 | 
            +
                
         | 
| 4 | 
            +
                def format_errors(model)
         | 
| 5 | 
            +
                  error_messages = model.errors.present do |e|
         | 
| 6 | 
            +
                    # Missing attributes
         | 
| 7 | 
            +
                    e.on [:name, :not_present], "Name attribute missing"
         | 
| 8 | 
            +
                    e.on [:status, :not_present], "Status attribute missing"
         | 
| 9 | 
            +
                    e.on [:format, :not_present], "Format attribute missing"
         | 
| 10 | 
            +
                    e.on [:body, :not_present], "Body attribute missing"
         | 
| 11 | 
            +
                    e.on [:application_id, :not_present], "Application attribute missing"
         | 
| 12 | 
            +
                    e.on [:path, :not_present], "Path attribute missing"
         | 
| 13 | 
            +
                    e.on [:pattern, :not_present], "Pattern attribute missing"
         | 
| 14 | 
            +
                    e.on [:endpoint, :not_present], "Endpoint attribute missing"
         | 
| 15 | 
            +
                    # Invalid option
         | 
| 16 | 
            +
                    e.on [:status, :not_member], "Status must be up, down or pending"
         | 
| 17 | 
            +
                    # Duplicate keys
         | 
| 18 | 
            +
                    e.on [[:name, :application_id], :not_unique], "Record already exists"
         | 
| 19 | 
            +
                    e.on [[:name, :host_id], :not_unique], "Record already exists"
         | 
| 20 | 
            +
                    e.on [[:endpoint, :pattern], :not_unique], "Record already exists"
         | 
| 21 | 
            +
                    e.on [:path, :not_unique], "Record already exists"
         | 
| 22 | 
            +
                    # Custom exceptions
         | 
| 23 | 
            +
                    e.on [:pattern, :already_provided], "Pattern is already provided"
         | 
| 24 | 
            +
                    e.on [:pattern, :replaces_existing], "Pattern would overwrite existing"
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  error_messages.first
         | 
| 27 | 
            +
                end
         | 
| 5 28 |  | 
| 6 29 | 
             
                def host(opts = {})
         | 
| 7 | 
            -
             | 
| 30 | 
            +
                  Noah::Host.find(opts).first
         | 
| 8 31 | 
             
                end
         | 
| 9 32 |  | 
| 10 33 | 
             
                def hosts(opts = {})
         | 
| 11 | 
            -
                  Hosts.all(opts)
         | 
| 34 | 
            +
                  Noah::Hosts.all(opts)
         | 
| 12 35 | 
             
                end
         | 
| 13 36 |  | 
| 14 37 | 
             
                def service(opts = {})
         | 
| 15 | 
            -
                  Service.find(options)
         | 
| 38 | 
            +
                  Noah::Service.find(options)
         | 
| 16 39 | 
             
                end
         | 
| 17 40 |  | 
| 18 41 | 
             
                def services(opts = {})
         | 
| 19 | 
            -
                  Services.all(opts)
         | 
| 42 | 
            +
                  Noah::Services.all(opts)
         | 
| 20 43 | 
             
                end 
         | 
| 21 44 |  | 
| 22 45 | 
             
                def host_service(hostname, servicename)
         | 
| 23 | 
            -
                  h = Host.find(:name => hostname).first
         | 
| 46 | 
            +
                  h = Noah::Host.find(:name => hostname).first
         | 
| 24 47 | 
             
                  if h.nil?
         | 
| 25 48 | 
             
                    nil
         | 
| 26 49 | 
             
                  else  
         | 
| 27 | 
            -
                    Service.find(:host_id => h.id, :name => servicename).first
         | 
| 50 | 
            +
                    Noah::Service.find(:host_id => h.id, :name => servicename).first
         | 
| 28 51 | 
             
                  end  
         | 
| 29 52 | 
             
                end
         | 
| 30 53 |  | 
| 31 54 | 
             
                def host_services(hostname)
         | 
| 32 | 
            -
                  h = Host.find(:name => hostname).first
         | 
| 55 | 
            +
                  h = Noah::Host.find(:name => hostname).first
         | 
| 33 56 | 
             
                  if h.nil?
         | 
| 34 57 | 
             
                    nil
         | 
| 35 58 | 
             
                  else  
         | 
| 36 | 
            -
                    Services.all(:host_id => id)
         | 
| 59 | 
            +
                    Noah::Services.all(:host_id => id)
         | 
| 37 60 | 
             
                  end  
         | 
| 38 61 | 
             
                end 
         | 
| 39 62 |  | 
| 40 63 | 
             
                def application(opts = {})
         | 
| 41 | 
            -
                  Application.find(opts).first
         | 
| 64 | 
            +
                  Noah::Application.find(opts).first
         | 
| 42 65 | 
             
                end
         | 
| 43 66 |  | 
| 44 67 | 
             
                def applications(opts = {})
         | 
| 45 | 
            -
                  Applications.all(opts)
         | 
| 68 | 
            +
                  Noah::Applications.all(opts)
         | 
| 46 69 | 
             
                end
         | 
| 47 70 |  | 
| 48 71 | 
             
                def configuration(opts = {})
         | 
| 49 | 
            -
                  Configuration.find(opts).first
         | 
| 72 | 
            +
                  Noah::Configuration.find(opts).first
         | 
| 50 73 | 
             
                end
         | 
| 51 74 |  | 
| 52 75 | 
             
                def configurations(opts = {})
         | 
| 53 | 
            -
                  Configurations.all(opts)
         | 
| 76 | 
            +
                  Noah::Configurations.all(opts)
         | 
| 54 77 | 
             
                end
         | 
| 55 78 | 
             
              end
         | 
| 56 79 |  | 
| @@ -0,0 +1,69 @@ | |
| 1 | 
            +
            class Noah::App
         | 
| 2 | 
            +
            # Host URIs
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              # GET named {Service} for named {Host}
         | 
| 5 | 
            +
              get '/h/:hostname/:servicename/?' do |hostname, servicename|
         | 
| 6 | 
            +
                h = host_service(hostname, servicename)
         | 
| 7 | 
            +
                if h.nil?
         | 
| 8 | 
            +
                  halt 404
         | 
| 9 | 
            +
                else
         | 
| 10 | 
            +
                  h.to_json
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # GET named {Host}
         | 
| 15 | 
            +
              # @param :hostname name of {Host}
         | 
| 16 | 
            +
              # @return [JSON] representation of {Host}
         | 
| 17 | 
            +
              get '/h/:hostname/?' do |hostname|
         | 
| 18 | 
            +
                h = host(:name => hostname)
         | 
| 19 | 
            +
                if h.nil?
         | 
| 20 | 
            +
                  halt 404
         | 
| 21 | 
            +
                else
         | 
| 22 | 
            +
                  h.to_json
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              # GET all {Hosts}
         | 
| 27 | 
            +
              get '/h/?' do
         | 
| 28 | 
            +
                hosts.map {|h| h.to_hash}
         | 
| 29 | 
            +
                if hosts.size == 0
         | 
| 30 | 
            +
                  halt 404
         | 
| 31 | 
            +
                else
         | 
| 32 | 
            +
                  hosts.to_json
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              put '/h/:hostname/watch' do |hostname|
         | 
| 37 | 
            +
                required_params = ["endpoint"]
         | 
| 38 | 
            +
                data = JSON.parse(request.body.read)
         | 
| 39 | 
            +
                (data.keys.sort == required_params.sort) ? (h = Noah::Host.find(:name => hostname).first) : (raise "Missing Parameters")
         | 
| 40 | 
            +
                h.nil? ? (halt 404) : (w = h.watch!(:endpoint => data['endpoint']))
         | 
| 41 | 
            +
                w.to_json
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              put '/h/:hostname/?' do |hostname|
         | 
| 45 | 
            +
                required_params = ["name", "status"]
         | 
| 46 | 
            +
                data = JSON.parse(request.body.read)
         | 
| 47 | 
            +
                (data.keys.sort == required_params.sort && data['name'] == hostname) ? (host = Noah::Host.find_or_create(:name => data['name'], :status => data['status'])) : (raise "Missing Parameters")
         | 
| 48 | 
            +
                if host.valid?
         | 
| 49 | 
            +
                  r = {"result" => "success","id" => "#{host.id}","status" => "#{host.status}", "name" => "#{host.name}", "new_record" => host.is_new?}
         | 
| 50 | 
            +
                  r.to_json
         | 
| 51 | 
            +
                else
         | 
| 52 | 
            +
                  raise "#{format_errors(host)}"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              delete '/h/:hostname/?' do |hostname|
         | 
| 57 | 
            +
                host = Noah::Host.find(:name => hostname).first
         | 
| 58 | 
            +
                if host
         | 
| 59 | 
            +
                  services = []
         | 
| 60 | 
            +
                  Noah::Service.find(:host_id => host.id).sort.each {|x| services << x; x.delete} if host.services.size > 0
         | 
| 61 | 
            +
                  host.delete
         | 
| 62 | 
            +
                  r = {"result" => "success", "id" => "#{host.id}", "name" => "#{hostname}", "service_count" => "#{services.size}"}
         | 
| 63 | 
            +
                  r.to_json
         | 
| 64 | 
            +
                else
         | 
| 65 | 
            +
                  halt 404
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            end
         | 
    
        data/lib/noah/models.rb
    CHANGED
    
    | @@ -1,5 +1,86 @@ | |
| 1 | 
            -
            require  | 
| 2 | 
            -
            require  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 1 | 
            +
            require 'ohm'
         | 
| 2 | 
            +
            require 'ohm/contrib'
         | 
| 3 | 
            +
            module Noah
         | 
| 4 | 
            +
              class Model < Ohm::Model
         | 
| 5 | 
            +
                def self.inherited(model)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  model.send :include, Ohm::Timestamping
         | 
| 8 | 
            +
                  model.send :include, Ohm::Typecast
         | 
| 9 | 
            +
                  model.send :include, Ohm::Callbacks
         | 
| 10 | 
            +
                  model.send :include, Ohm::ExtraValidations
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  # removing this as it's simply redundant
         | 
| 13 | 
            +
                  # model.after :save, :notify_via_redis_save
         | 
| 14 | 
            +
                  model.after :create, :notify_via_redis_create
         | 
| 15 | 
            +
                  model.after :update, :notify_via_redis_update
         | 
| 16 | 
            +
                  model.before :delete, :stash_name
         | 
| 17 | 
            +
                  model.after :delete, :notify_via_redis_delete
         | 
| 18 | 
            +
                  model.send :include, ModelClassMethods
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              module ModelClassMethods
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def is_new?
         | 
| 25 | 
            +
                  self.created_at == self.updated_at
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
             | 
| 29 | 
            +
                def watch!(opts={:endpoint => nil, :pattern => nil})
         | 
| 30 | 
            +
                  base_pattern = "#{self.patternize_me}"
         | 
| 31 | 
            +
                  opts[:endpoint].nil? ? (raise ArgumentError, "Need an endpoint") : endpoint=opts[:endpoint]
         | 
| 32 | 
            +
                  opts[:pattern].nil? ? pattern=base_pattern : pattern=opts[:pattern]
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  begin
         | 
| 35 | 
            +
                    w = Watcher.new :pattern => pattern, :endpoint => endpoint
         | 
| 36 | 
            +
                    w.valid? ? w.save : (raise "#{w.errors}")
         | 
| 37 | 
            +
                    w.name
         | 
| 38 | 
            +
                  rescue Exception => e
         | 
| 39 | 
            +
                    e.message
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                  
         | 
| 43 | 
            +
                protected
         | 
| 44 | 
            +
                def patternize_me
         | 
| 45 | 
            +
                  "//noah/#{self.class_to_lower}/#{name}"
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def stash_name
         | 
| 49 | 
            +
                  @deleted_name = self.name
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def class_to_lower
         | 
| 53 | 
            +
                  self.class.to_s.gsub(/(.*)::(\w)/,'\2').downcase
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
                def dbnum
         | 
| 56 | 
            +
                  o = Ohm.options.first
         | 
| 57 | 
            +
                  return "0" if o.nil?
         | 
| 58 | 
            +
                  return "0" if (o[:db].nil? && o[:url].nil?)
         | 
| 59 | 
            +
                  o[:db].nil? ? "#{o[:url].split('/').last}" : "#{o[:db]}"
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                ["create", "update", "delete"].each do |meth|
         | 
| 63 | 
            +
                  class_eval do
         | 
| 64 | 
            +
                    define_method("notify_via_redis_#{meth}".to_sym) do
         | 
| 65 | 
            +
                      db = self.dbnum
         | 
| 66 | 
            +
                      self.name.nil? ? name=@deleted_name : name=self.name
         | 
| 67 | 
            +
                      # Pulling out dbnum for now. Need to rethink it
         | 
| 68 | 
            +
                      #pub_category = "#{db}:noah.#{self.class.to_s}[#{name}].#{meth}"
         | 
| 69 | 
            +
                      pub_category = "#{self.patternize_me}"
         | 
| 70 | 
            +
                      Ohm.redis.publish(pub_category, self.to_hash.merge({"action" => meth, "pubcategory" => pub_category}).to_json)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      # The following provides a post post-action hook. It allows a class to provide it's own handling after the fact
         | 
| 73 | 
            +
                      # good example is in [Noah::Ephemeral] where it's used to check for/clean up expired ephemeral nodes entries
         | 
| 74 | 
            +
                      self.send("#{meth}_hook".to_sym) unless self.protected_methods.member?("#{meth}_hook".to_sym) == false
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
            require File.join(File.dirname(__FILE__), 'models','hosts')
         | 
| 82 | 
            +
            require File.join(File.dirname(__FILE__), 'models','services')
         | 
| 83 | 
            +
            require File.join(File.dirname(__FILE__), 'models','applications')
         | 
| 84 | 
            +
            require File.join(File.dirname(__FILE__), 'models','configurations')
         | 
| 85 | 
            +
            require File.join(File.dirname(__FILE__), 'models','watchers')
         | 
| 86 | 
            +
            require File.join(File.dirname(__FILE__), 'models','ephemerals')
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'configurations')
         | 
| 2 | 
            +
            module Noah
         | 
| 3 | 
            +
              class Application < Model
         | 
| 4 | 
            +
                attribute :name
         | 
| 5 | 
            +
                collection :configurations, Configuration
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                index :name
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def validate
         | 
| 10 | 
            +
                  super
         | 
| 11 | 
            +
                  assert_present :name
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def to_hash
         | 
| 15 | 
            +
                  arr = []
         | 
| 16 | 
            +
                  configurations.sort.each {|c| arr << c.to_hash}
         | 
| 17 | 
            +
                  super.merge(:name => name, :created_at => created_at, :updated_at => updated_at, :configurations => arr)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                class << self
         | 
| 21 | 
            +
                def find_or_create(opts = {})
         | 
| 22 | 
            +
                  begin
         | 
| 23 | 
            +
                    find(opts).first.nil? ? (app = create(opts)) : (app = find(opts).first)
         | 
| 24 | 
            +
                    if app.valid?
         | 
| 25 | 
            +
                      app.save
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                    app
         | 
| 28 | 
            +
                  rescue Exception => e
         | 
| 29 | 
            +
                    e.message
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              class Applications
         | 
| 37 | 
            +
                def self.all(options = {})
         | 
| 38 | 
            +
                  options.empty? ? Application.all.sort : Application.find(options).sort
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            module Noah
         | 
| 2 | 
            +
              class Configuration < Model
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                attribute :name
         | 
| 5 | 
            +
                attribute :format
         | 
| 6 | 
            +
                attribute :body
         | 
| 7 | 
            +
                attribute :new_record
         | 
| 8 | 
            +
                reference :application, Application
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                index :name
         | 
| 11 | 
            +
                index :format
         | 
| 12 | 
            +
                index :body
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def validate
         | 
| 15 | 
            +
                  super
         | 
| 16 | 
            +
                  assert_present :name
         | 
| 17 | 
            +
                  assert_present :format
         | 
| 18 | 
            +
                  assert_present :body
         | 
| 19 | 
            +
                  assert_present :application_id
         | 
| 20 | 
            +
                  assert_unique [:name, :application_id]
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def to_hash
         | 
| 24 | 
            +
                  Application[application_id].nil? ? app_name=nil : app_name=Application[application_id].name
         | 
| 25 | 
            +
                  super.merge(:name => name, :format => format, :body => body, :created_at => created_at, :updated_at => updated_at, :application => app_name)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                class << self
         | 
| 29 | 
            +
                def find_or_create(opts={})
         | 
| 30 | 
            +
                  begin
         | 
| 31 | 
            +
                    if find(opts).first.nil?
         | 
| 32 | 
            +
                      conf = create(opts)
         | 
| 33 | 
            +
                    else  
         | 
| 34 | 
            +
                      conf = find(opts).first
         | 
| 35 | 
            +
                    end  
         | 
| 36 | 
            +
                  rescue Exception => e
         | 
| 37 | 
            +
                    e.message
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              class Configurations
         | 
| 45 | 
            +
                def self.all(options = {})
         | 
| 46 | 
            +
                  options.empty? ? Configuration.all.sort : Configuration.find(options).sort
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end 
         | 
| 49 | 
            +
            end
         |