Skip to content
This repository has been archived by the owner on Oct 12, 2018. It is now read-only.

Commit

Permalink
Merge pull request #6 from alphagov/add_router_to_single_registration
Browse files Browse the repository at this point in the history
Add router capability to single registration.
  • Loading branch information
dhwthompson committed Jul 11, 2012
2 parents f4176b5 + 98777b5 commit 38f681c
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 2 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ gem 'null_logger'
gem 'exception_notification'

gem 'gds-api-adapters'
gem 'router-client', "3.1.0"

gem 'aws-ses', require: 'aws/ses'

Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ GEM
json (~> 1.4)
rest-client (1.6.7)
mime-types (>= 1.16)
router-client (3.1.0)
activesupport
builder
null_logger
rubyzip (0.9.5)
rummageable (0.3.0)
json
Expand Down Expand Up @@ -302,6 +306,7 @@ DEPENDENCIES
rack (= 1.3.5)
rails (~> 3.1.1)
rake (= 0.9.2)
router-client (= 3.1.0)
rummageable (~> 0.3.0)
shoulda (~> 2.11.3)
simplecov (~> 0.6.4)
Expand Down
2 changes: 1 addition & 1 deletion app/models/enhancements/artefact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
class Artefact
# Add a non-field attribute so we can pass indexable content over to Rummager
# without persisting it
attr_accessor :indexable_content
attr_accessor :indexable_content, :paths, :prefixes
end
36 changes: 36 additions & 0 deletions app/models/routable_artefact.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'router'

class RoutableArtefact

def initialize(artefact)
@artefact = artefact
end

def logger
Rails.logger
end

def router
@router ||= Router.new
end

def ensure_application_exists
backend_url = Plek.current.find(@artefact.owning_app)
router.update_application(@artefact.owning_app, backend_url)
end

def submit
ensure_application_exists
paths = (@artefact.paths || [])
prefixes = (@artefact.prefixes || [])
unless prefixes.include?(@artefact.slug)
paths << @artefact.slug
end
paths.uniq.each do |path|
@router.create_route(path, "full", @artefact.owning_app)
end
prefixes.each do |prefix|
@router.create_route(prefix, "prefix", @artefact.owning_app)
end
end
end
7 changes: 7 additions & 0 deletions app/observers/update_router_observer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class UpdateRouterObserver < Mongoid::Observer
observe :artefact

def after_save(artefact)
RoutableArtefact.new(artefact).submit if artefact.live?
end
end
18 changes: 18 additions & 0 deletions config/initializers/router_callback.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# In development environments we don't want to depend on Router unless
# explicitly told to do so
unless Rails.env.development?
update_router = true
else
update_router = ENV['UPDATE_ROUTER'].present?
end

if update_router
Rails.logger.info "Registering router observer for artefacts"
# Use to_prepare so this gets reloaded with the app when in development
# In production, it will only be called once
ActionDispatch::Callbacks.to_prepare do
Panopticon::Application.config.mongoid.observers << :update_router_observer
end
else
Rails.logger.info "In development/test mode: not registering router observer"
end
1 change: 1 addition & 0 deletions features/editing.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Feature: Editing artefacts
Background:
Given I am an admin
And I have stubbed search
And I have stubbed the router

Scenario: Editing an artefact and changing the slug
Given two artefacts exist
Expand Down
3 changes: 3 additions & 0 deletions features/registering_resources.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ Feature: Registering resources
When I put a new smart answer's details into panopticon
Then a new artefact should be created
And rummager should be notified
And the router should be notified

Scenario: Updating a smart answer
When I put updated smart answer details into panopticon
Then the relevant artefact should be updated
And the API should reflect the change
And rummager should be notified
And the router should be notified

Scenario: Creating a draft item
When I put a draft smart answer's details into panopticon
Then a new artefact should be created
And rummager should not be notified
And the router should not be notified

Scenario: Putting an item whose slug is owned by another app
When I put a new item into panopticon whose slug is already taken
Expand Down
18 changes: 18 additions & 0 deletions features/step_definitions/registration_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
stub_search
end

Given /^I have stubbed the router$/ do
stub_router
end

When /^I put a new smart answer's details into panopticon$/ do
prepare_registration_environment

Expand Down Expand Up @@ -66,6 +70,20 @@
assert_requested @fake_search, times: 1 # The default, but let's be explicit
end

Then /^the router should be notified$/ do
assert ! @fake_routers.blank?, "No router requests registered to assert on"
@fake_routers.each do |fake_router|
assert_requested fake_router, times: 1
end
end

Then /^the router should not be notified$/ do
assert ! @fake_routers.blank?, "No router requests registered to assert on"
@fake_routers.each do |fake_router|
assert_not_requested fake_router
end
end

Then /^rummager should be told to do a partial update$/ do
amendments = {
title: @new_name,
Expand Down
24 changes: 23 additions & 1 deletion features/support/registration_info.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module RegistrationInfo

SEARCH_ROOT = "http://search.test.gov.uk"
ROUTER_ROOT = "http://router.cluster:8080"

def example_smart_answer
{
Expand All @@ -25,6 +26,7 @@ def example_smart_answer_json
def prepare_registration_environment
setup_user
stub_search
stub_router
end

def setup_user
Expand All @@ -36,14 +38,34 @@ def stub_search
@fake_search_amend = WebMock.stub_request(:post, %r{^#{Regexp.escape SEARCH_ROOT}/documents/.*$}).to_return(status: 200)
end

def stub_router
WebMock.stub_request(:put, %r{^#{ROUTER_ROOT}/applications/.*$}).
with(:body => { "backend_url" => %r{^.*.test.gov.uk:80$} }).
to_return(:status => 200, :body => "{}", :headers => {})

# catch-all
WebMock.stub_request(:put, %r{^#{ROUTER_ROOT}/routes/.*$}).
with(:body => {"application_id" => /.+/, "route_type" => "full"}).
to_return(:status => 200, :body => "{}", :headers => {})

# so that we can assert on them later
@fake_routers = [OpenStruct.new(example_smart_answer), @artefact, @related_artefact].reject(&:nil?).map do |artefact|
WebMock.stub_request(:put, "#{ROUTER_ROOT}/routes/#{artefact.slug}").
with(:body => { "application_id" => artefact.owning_app, "route_type" => "full"}).
to_return(:status => 200, :body => "{}", :headers => {})
end
end



def artefact_search_url(artefact)
# The search URL to which amendment requests should be POSTed
link = "/#{artefact.slug}"
"#{SEARCH_ROOT}/documents/#{CGI.escape link}"
end

def setup_existing_artefact
Artefact.observers.disable :update_search_observer do
Artefact.observers.disable :update_search_observer, :update_router_observer do
@artefact = Artefact.create!(example_smart_answer)
end
end
Expand Down
62 changes: 62 additions & 0 deletions test/unit/routable_artefact_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require 'test_helper'

class RoutableArtefactTest < ActiveSupport::TestCase
setup do
@artefact = FactoryGirl.create(:artefact, owning_app: "bee")
@routable = RoutableArtefact.new(@artefact)
end

should "ensure that the application exists in the router" do
Router.any_instance.expects(:update_application).with("bee", "http://bee.test.gov.uk")
Router.any_instance.stubs(:create_route)
@routable.submit
end

should "create a full route for the slug" do
Router.any_instance.stubs(:update_application)
Router.any_instance.expects(:create_route).with(@artefact.slug, "full", "bee")
@routable.submit
end

should "create full routes for paths" do
@artefact.paths = ["#{@artefact.slug}.json", "#{@artefact.slug}.ics"]
Router.any_instance.stubs(:update_application)
Router.any_instance.stubs(:create_route).with(@artefact.slug, "full", "bee")
Router.any_instance.expects(:create_route).with("#{@artefact.slug}.json", "full", "bee")
Router.any_instance.expects(:create_route).with("#{@artefact.slug}.ics", "full", "bee")
@routable.submit
end

context "the slug is repeated in one of the paths" do
setup do
@artefact.paths = [@artefact.slug]
end

should "not (attempt to) register duplicate full routes" do
Router.any_instance.stubs(:update_application)
Router.any_instance.expects(:create_route).with(@artefact.slug, "full", "bee")
@routable.submit
end
end

should "create prefix routes for prefixes" do
@artefact.prefixes = ["un", "re"]
Router.any_instance.stubs(:update_application)
Router.any_instance.stubs(:create_route).with(@artefact.slug, "full", "bee")
Router.any_instance.expects(:create_route).with("un", "prefix", "bee")
Router.any_instance.expects(:create_route).with("re", "prefix", "bee")
@routable.submit
end

context "the slug is also a prefix" do
setup do
@artefact.prefixes = [@artefact.slug]
end

should "send it as a prefix, and not send a full route" do
Router.any_instance.stubs(:update_application)
Router.any_instance.expects(:create_route).with(@artefact.slug, "prefix", "bee")
@routable.submit
end
end
end

0 comments on commit 38f681c

Please sign in to comment.