-
Notifications
You must be signed in to change notification settings - Fork 45
/
products_controller.rb
145 lines (115 loc) · 4.8 KB
/
products_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
class Api::Connect::V3::Systems::ProductsController < Api::Connect::BaseController
before_action :authenticate_system
before_action :require_product, only: %i[show activate upgrade destroy]
before_action :check_product_service_and_repositories, only: %i[show activate]
before_action :check_base_product_dependencies, only: %i[activate upgrade show]
def activate
create_product_activation
render_service
end
def show
if @system.products.include? @product
respond_with(
@product,
serializer: ::V3::ProductSerializer,
base_url: request.base_url
)
else
raise ActionController::TranslatedError.new(N_("The requested product '%s' is not activated on this system."), @product.friendly_name)
end
end
def migrations
require_params([:installed_products])
begin
upgrade_paths = MigrationEngine.new(@system, installed_products).online_migrations
render json: migration_paths_as_json(upgrade_paths)
rescue MigrationEngine::MigrationEngineError => e
raise ActionController::TranslatedError.new(e.message, *e.data)
end
end
def offline_migrations
require_params(%i[installed_products target_base_product])
begin
offline_upgrade_paths = MigrationEngine.new(@system, installed_products)
.offline_migrations(product_from_hash(params[:target_base_product]))
render json: migration_paths_as_json(offline_upgrade_paths)
rescue MigrationEngine::MigrationEngineError => e
raise ActionController::TranslatedError.new(e.message, *e.data)
end
end
def upgrade
obsoleted_product_ids = ([@product] + @product.predecessors + @product.successors).map(&:id)
obsoleted_service = @system.services.find_by(product_id: obsoleted_product_ids)
@obsolted_service_name = obsoleted_service.name if obsoleted_service
ActiveRecord::Base.transaction do
remove_previous_product_activation(obsoleted_product_ids)
create_product_activation
end
render_service
end
protected
def installed_products
params[:installed_products].map { |hash| product_from_hash(hash) rescue nil }.compact
end
def migration_paths_as_json(paths)
paths.reject(&:empty?).map do |item|
ActiveModelSerializers::SerializableResource.new(
item,
each_serializer: ::V3::UpgradePathItemSerializer
)
end.to_json
end
def require_product
require_params(%i[identifier version arch])
@product = Product.where(identifier: params[:identifier], version: params[:version], arch: params[:arch]).first
unless @product
raise ActionController::TranslatedError.new(N_('No product found'))
end
end
def check_product_service_and_repositories
unless @product.service && @product.repositories.present?
fail ActionController::TranslatedError.new(N_('No repositories found for product: %s'), @product.friendly_name)
end
mandatory_repos = @product.repositories.only_enabled
mirrored_repos = @product.repositories.only_enabled.only_mirrored
unless (mandatory_repos.size == mirrored_repos.size)
fail ActionController::TranslatedError.new(N_('Not all mandatory repositories are mirrored for product %s'), @product.friendly_name)
end
end
def create_product_activation
@system.activations.where(service_id: @product.service.id).first_or_create
end
def remove_previous_product_activation(product_ids)
@system.activations.includes(:product).where('products.id' => product_ids).destroy_all
end
# Check if extension base product is already activated
def check_base_product_dependencies
# TODO: For APIv5 and future. We skip this check for second level extensions. E.g. HA-GEO
# To fix bnc#951189 specifically the rollback part of it.
return if @product.bases.any?(&:extension?)
return if @product.base? || (@system.products & @product.bases).present?
logger.info("Tried to activate/upgrade to '#{@product.friendly_name}' with unmet base product dependency")
raise ActionController::TranslatedError.new(
N_('Unmet product dependencies, activate one of these products first: %s'),
@product.bases.map(&:friendly_name).join(', ')
)
end
def render_service
status = ((request.put? || request.post?) ? 201 : 200)
# manually setting request method, so respond_with actually renders content also for PUT
request.instance_variable_set(:@request_method, 'GET')
respond_with(
@product.service,
serializer: ::V3::ServiceSerializer,
base_url: request.base_url,
obsoleted_service_name: @obsoleted_service_name,
status: status
)
end
def product_search_params(product_hash)
product_hash.permit(:identifier, :version, :arch, :release_type).to_h.symbolize_keys
end
def product_from_hash(product_hash)
Product.find_by(product_search_params(product_hash))
end
end