Skip to content
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

Use subscription of the product class #1283

Merged
merged 12 commits into from
Feb 27, 2025
39 changes: 32 additions & 7 deletions engines/instance_verification/lib/instance_verification/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,35 @@ def find_product
product
end

def find_subscription(base_product, logger, request)
# this method is needed because
# https://bugzilla.suse.com/show_bug.cgi?id=1236816
# https://bugzilla.suse.com/show_bug.cgi?id=1236836
product_hash = {
identifier: base_product.identifier,
version: base_product.version,
arch: base_product.arch,
release_type: base_product.release_type
}
add_on_product_class = InstanceVerification.provider.new(
logger,
request,
product_hash,
@system.instance_data
).add_on
# add_on_product_class, if present, is the real product class
# i.e. in the case of SUMA, it would be SUMA product class
# not the SUMA base product's product class (Micro)
product_class = add_on_product_class.presence || base_product.product_class
# it returns the first subscription that matches
# even if there are more subscriptions that match
Subscription.joins(:product_classes).find_by(
subscription_product_classes: {
product_class: product_class
}
)
end

def verify_product_activation
product = find_product

Expand Down Expand Up @@ -83,12 +112,7 @@ def verify_payg_extension_activation!(product)
return if product.free?

base_product = @system.products.find_by(product_type: :base)
subscription = Subscription.joins(:product_classes).find_by(
subscription_product_classes: {
product_class: base_product.product_class
}
)

subscription = find_subscription(base_product, logger, request)
# This error would occur only if there's a problem with subscription setup on SCC side
raise InstanceVerification::Exception, "Can't find a subscription for base product #{base_product.product_string}" unless subscription

Expand Down Expand Up @@ -122,7 +146,8 @@ def verify_base_product_upgrade

activated_bases = @system.products.where(product_type: 'base')
activated_bases.each do |base_product|
return true if (base_product.identifier == upgrade_product.identifier)
base_product_subscription = find_subscription(base_product, logger, request)
return true if base_product_subscription && base_product_subscription.products.include?(upgrade_product)
end

raise ActionController::TranslatedError.new('Migration target not allowed on this instance type')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,10 @@ def allowed_extension?
# to be activated on SCC or not, i.e. LTSS in Azure Basic VM
true
end

def add_on
# method to check if a system has an add on product
# based on the system metadata
# and if so, it returns its real product class
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@
allow(InstanceVerification::Providers::Example).to receive(:new).and_return(plugin_double)
allow(plugin_double).to receive(:parse_instance_data).and_return({ InstanceId: 'foo' })
allow(plugin_double).to receive(:allowed_extension?).and_return(true)
allow(plugin_double).to receive(:add_on).and_return(nil)

FactoryBot.create(:subscription, product_classes: product_classes)
stub_request(:post, scc_activate_url)
Expand Down Expand Up @@ -532,6 +533,7 @@
.and_return(plugin_double)
allow(plugin_double).to receive(:parse_instance_data).and_return({ InstanceId: 'foo' })
allow(plugin_double).to receive(:allowed_extension?).and_return(true)
allow(plugin_double).to receive(:add_on).and_return(nil)

FactoryBot.create(:subscription, product_classes: product_classes)
stub_request(:post, scc_activate_url)
Expand Down Expand Up @@ -598,18 +600,24 @@
'User-Agent' => 'Ruby'
}
end
let(:plugin_double) { instance_double('InstanceVerification::Providers::Example') }

context 'when SCC upgrade success' do
before do
stub_request(:put, scc_systems_products_url)
.with({ headers: scc_headers, body: payload.merge({ byos_mode: 'byos' }) })
.and_return(status: 201, body: '', headers: {})
request
end
let(:fake_subscription) { instance_double(Subscription, id: 1, products: [new_product]) }

context "when migration target base product doesn't have an activated successor/predecessor" do
let(:new_product) { FactoryBot.create(:product, :with_mirrored_repositories) }

before do
allow(InstanceVerification::Providers::Example).to receive(:new)
.and_return(plugin_double)
allow(plugin_double).to receive(:add_on).and_return('foo')
stub_request(:put, scc_systems_products_url)
.with({ headers: scc_headers, body: payload.merge({ byos_mode: 'byos' }) })
.and_return(status: 201, body: '', headers: {})
request
end

it 'HTTP response code is 422' do
expect(response).to have_http_status(422)
end
Expand All @@ -628,6 +636,17 @@
)
end

before do
allow(InstanceVerification::Providers::Example).to receive(:new)
.and_return(plugin_double)
allow(plugin_double).to receive(:add_on).and_return('foo')
allow_any_instance_of(described_class).to receive(:find_subscription).and_return(fake_subscription)
stub_request(:put, scc_systems_products_url)
.with({ headers: scc_headers, body: payload.merge({ byos_mode: 'byos' }) })
.and_return(status: 201, body: '', headers: {})
request
end

it 'HTTP response code is 201' do
expect(response).to have_http_status(201)
end
Expand All @@ -648,12 +667,13 @@
body: 'Migration target not allowed on this instance type',
headers: {}
)
request
end

context "when migration target base product doesn't have an activated successor/predecessor" do
let(:new_product) { FactoryBot.create(:product, :with_mirrored_repositories) }

before { request }

it 'HTTP response code is 422' do
expect(response).to have_http_status(422)
end
Expand All @@ -671,8 +691,15 @@
version: '999', predecessors: [ old_product ]
)
end
let(:fake_subscription) { instance_double(Subscription, id: 1, products: [new_product]) }

before do
allow_any_instance_of(described_class).to receive(:find_subscription).and_return(fake_subscription)
request
end

it 'HTTP response code is 422' do
# problem here
expect(response).to have_http_status(422)
end

Expand All @@ -695,11 +722,11 @@
}
end

before { request }

context "when migration target base product doesn't have an activated successor/predecessor" do
let(:new_product) { FactoryBot.create(:product, :with_mirrored_repositories) }

before { request }

it 'HTTP response code is 422' do
expect(response).to have_http_status(422)
end
Expand All @@ -718,6 +745,8 @@
)
end

before { request }

it 'HTTP response code is 422' do
expect(response).to have_http_status(422)
end
Expand All @@ -735,6 +764,13 @@
version: '999', predecessors: [ old_product ]
)
end
let(:fake_subscription) { instance_double(Subscription, id: 1, products: [new_product]) }

before do
allow_any_instance_of(described_class).to receive(:find_subscription).and_return(fake_subscription)

request
end

it 'HTTP response code is 201' do
expect(response).to have_http_status(201)
Expand Down