-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy config affecting change events #1244
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
class ProxyConfigs::AffectingObjectChangedEvent < ServiceRelatedEvent | ||
def self.create(proxy, object) | ||
new( | ||
proxy_id: proxy.id, | ||
object_id: object.id, | ||
object_type: object.class.name, | ||
metadata: { | ||
service_id: proxy.service_id, | ||
provider_id: proxy.account.id | ||
} | ||
) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# frozen_string_literal: true | ||
|
||
module ProxyConfigAffectingChanges | ||
module ProxyRuleExtension | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
include ProxyConfigAffectingChanges | ||
|
||
after_commit :issue_proxy_affecting_change_events | ||
|
||
def issue_proxy_affecting_change_events | ||
case owner | ||
when Proxy | ||
issue_proxy_affecting_change_event(owner) | ||
when BackendApi | ||
owner.proxies.each(&method(:issue_proxy_affecting_change_event)) | ||
end | ||
end | ||
end | ||
end | ||
|
||
module ProxyExtension | ||
extend ActiveSupport::Concern | ||
|
||
PROXY_CONFIG_AFFECTING_ATTRIBUTES = %w[policies_config].freeze # TODO: add more attributes here | ||
|
||
included do | ||
include ProxyConfigAffectingChanges | ||
|
||
after_commit :issue_proxy_affecting_change_events, on: :update | ||
|
||
def issue_proxy_affecting_change_events | ||
changes_attributes = previous_changes.keys | ||
return if changes_attributes.include?('created_at') || (changes_attributes & PROXY_CONFIG_AFFECTING_ATTRIBUTES).empty? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So you can use |
||
issue_proxy_affecting_change_event(self) | ||
end | ||
end | ||
end | ||
|
||
def issue_proxy_affecting_change_event(proxy) | ||
ProxyConfigs::AffectingObjectChangedEvent.create_and_publish!(proxy, self) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ class Proxy < ApplicationRecord | |
include BackendApiLogic::ProxyExtension | ||
prepend BackendApiLogic::RoutingPolicy | ||
include GatewaySettings::ProxyExtension | ||
include ProxyConfigAffectingChanges::ProxyExtension | ||
|
||
DEFAULT_POLICY = { 'name' => 'apicast', 'humanName' => 'APIcast policy', 'description' => 'Main functionality of APIcast.', | ||
'configuration' => {}, 'version' => 'builtin', 'enabled' => true, 'removable' => false, 'id' => 'apicast-policy' }.freeze | ||
|
@@ -20,6 +21,9 @@ class Proxy < ApplicationRecord | |
|
||
validates :error_status_no_match, :error_status_auth_missing, :error_status_auth_failed, :error_status_limits_exceeded, presence: true | ||
|
||
has_one :proxy_config_affecting_change, dependent: :delete | ||
private :proxy_config_affecting_change | ||
|
||
uri_pattern = URI::DEFAULT_PARSER.pattern | ||
|
||
URI_OPTIONAL_PORT = /\Ahttps?:\/\/[a-zA-Z0-9._-]*(:\d+)?\Z/ | ||
|
@@ -515,6 +519,19 @@ def service_mesh_integration? | |
Service::DeploymentOption.service_mesh.include?(deployment_option) | ||
end | ||
|
||
def find_or_create_proxy_config_affecting_change | ||
proxy_config_affecting_change || create_proxy_config_affecting_change | ||
end | ||
alias affecting_change_history find_or_create_proxy_config_affecting_change | ||
private :find_or_create_proxy_config_affecting_change | ||
|
||
def pending_affecting_changes? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using this method (probably in the view) creates records right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, if we have a proxy config, then we can also have an affecting change history I think. It also saves us from having to migrate data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fair enough |
||
return unless apicast_configuration_driven? | ||
config = proxy_configs.sandbox.newest_first.first | ||
return false unless config | ||
config.created_at < affecting_change_history.updated_at | ||
end | ||
|
||
protected | ||
|
||
class PolicyConfig | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
class ProxyConfigAffectingChange < ApplicationRecord | ||
belongs_to :proxy | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
class ProxyConfigEventSubscriber | ||
def call(event) | ||
case event | ||
when ProxyConfigs::AffectingObjectChangedEvent then ProxyConfigAffectingChangeWorker.perform_later(event.event_id) | ||
else raise "Unknown event type #{event.class}" | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
class ProxyConfigAffectingChangeWorker < ActiveJob::Base # rubocop:disable Rails/ApplicationJob | ||
def perform(event_id) | ||
event = EventStore::Repository.find_event!(event_id) | ||
proxy = Proxy.find(event.proxy_id) | ||
proxy.affecting_change_history.touch | ||
rescue ActiveRecord::RecordNotFound | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateProxyConfigAffectingChanges < ActiveRecord::Migration | ||
disable_ddl_transaction! if System::Database.postgres? | ||
|
||
def change | ||
create_table :proxy_config_affecting_changes do |t| | ||
t.references :proxy, null: false | ||
t.timestamps null: false | ||
end | ||
|
||
index_options = System::Database.postgres? ? { algorithm: :concurrently } : {} | ||
add_index :proxy_config_affecting_changes, :proxy_id, index_options.merge(unique: true) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'test_helper' | ||
|
||
class ProxyConfigs::AffectingObjectChangedEventTest < ActiveSupport::TestCase | ||
test 'create' do | ||
proxy = FactoryBot.create(:proxy) | ||
proxy_rule = FactoryBot.build_stubbed(:proxy_rule, proxy: proxy) | ||
event = ProxyConfigs::AffectingObjectChangedEvent.create(proxy, proxy_rule) | ||
|
||
assert_equal proxy.id, event.proxy_id | ||
assert_equal proxy_rule.id, event.object_id | ||
assert_equal 'ProxyRule', event.object_type | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'test_helper' | ||
|
||
class ProxyConfigEventSubscriberTest < ActiveSupport::TestCase | ||
test 'create' do | ||
proxy = FactoryBot.create(:proxy) | ||
proxy_rule = FactoryBot.build_stubbed(:proxy_rule, proxy: proxy) | ||
event = ProxyConfigs::AffectingObjectChangedEvent.create(proxy, proxy_rule) | ||
|
||
ProxyConfigAffectingChangeWorker.expects(:perform_later).with(event.event_id) | ||
|
||
ProxyConfigEventSubscriber.new.call(event) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'test_helper' | ||
|
||
class ProxyConfigAffectingChangeWorkerTest < ActiveSupport::TestCase | ||
setup do | ||
@worker = ProxyConfigAffectingChangeWorker.new | ||
EventStore::Repository.stubs(raise_errors: true) | ||
end | ||
|
||
attr_reader :worker | ||
|
||
test '#perform' do | ||
proxy = FactoryBot.create(:proxy) | ||
event = ProxyConfigs::AffectingObjectChangedEvent.create_and_publish!(proxy, mock(id: 123)) | ||
|
||
affecting_change_history = mock | ||
Proxy.any_instance.expects(:create_proxy_config_affecting_change).returns(affecting_change_history) | ||
affecting_change_history.expects(:touch) | ||
|
||
worker.perform(event.event_id) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you can use
previously_changed?
https://github.com/3scale/porta/blob/d21f8d5e7a6dc740db6652e0604dcf0b639edb52/lib/previously_changed.rbWhich will be introduced in rails 5.0