Commit df658c7b authored by Shinya Maeda's avatar Shinya Maeda

Disable STI of ActiveRecord. Refactoring specs.

parent 58d074e0
...@@ -12,6 +12,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati ...@@ -12,6 +12,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati
has_many :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::ClustersProject' has_many :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::ClustersProject'
has_many :clusters, through: :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Cluster' has_many :clusters, through: :cluster_projects, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Cluster'
has_many :services, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Service' has_many :services, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Service'
has_one :kubernetes_service, -> { where(category: 'deployment', type: 'KubernetesService') }, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Service', inverse_of: :project, foreign_key: :project_id
end end
class Cluster < ActiveRecord::Base class Cluster < ActiveRecord::Base
...@@ -55,8 +56,9 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati ...@@ -55,8 +56,9 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati
include EachBatch include EachBatch
self.table_name = 'services' self.table_name = 'services'
self.inheritance_column = :_type_disabled # Disable STI, otherwise KubernetesModel will be looked up
belongs_to :project, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Project' belongs_to :project, class_name: 'MigrateKubernetesServiceToNewClustersArchitectures::Project', foreign_key: :project_id
scope :unmanaged_kubernetes_service, -> do scope :unmanaged_kubernetes_service, -> do
joins('LEFT JOIN projects ON projects.id = services.project_id') joins('LEFT JOIN projects ON projects.id = services.project_id')
...@@ -72,6 +74,22 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati ...@@ -72,6 +74,22 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati
scope :kubernetes_service_without_template, -> do scope :kubernetes_service_without_template, -> do
where(category: 'deployment', type: 'KubernetesService', template: false) where(category: 'deployment', type: 'KubernetesService', template: false)
end end
def api_url
JSON.parse(self.properties)['api_url']
end
def ca_pem
JSON.parse(self.properties)['ca_pem']
end
def namespace
JSON.parse(self.properties)['namespace']
end
def token
JSON.parse(self.properties)['token']
end
end end
def find_dedicated_environement_scope(project) def find_dedicated_environement_scope(project)
...@@ -101,7 +119,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati ...@@ -101,7 +119,7 @@ class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migrati
name: DEFAULT_KUBERNETES_SERVICE_CLUSTER_NAME, name: DEFAULT_KUBERNETES_SERVICE_CLUSTER_NAME,
provider_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.provider_types[:user], provider_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.provider_types[:user],
platform_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.platform_types[:kubernetes], platform_type: MigrateKubernetesServiceToNewClustersArchitectures::Cluster.platform_types[:kubernetes],
projects: [kubernetes_service.project.becomes(MigrateKubernetesServiceToNewClustersArchitectures::Project)], projects: [kubernetes_service.project],
environment_scope: find_dedicated_environement_scope(kubernetes_service.project), environment_scope: find_dedicated_environement_scope(kubernetes_service.project),
platform_kubernetes_attributes: { platform_kubernetes_attributes: {
api_url: kubernetes_service.api_url, api_url: kubernetes_service.api_url,
......
...@@ -5,27 +5,32 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -5,27 +5,32 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
context 'when unique KubernetesService exists' do context 'when unique KubernetesService exists' do
shared_examples 'KubernetesService migration' do shared_examples 'KubernetesService migration' do
let(:sample_num) { 2 } let(:sample_num) { 2 }
let(:projects) { create_list(:project, sample_num) }
let(:projects) do
(1..sample_num).each_with_object([]) do |n, array|
array << MigrateKubernetesServiceToNewClustersArchitectures::Project.create!
end
end
let!(:kubernetes_services) do let!(:kubernetes_services) do
projects.map do |project| projects.map do |project|
create(:kubernetes_service, MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project, project: project,
active: active, active: active,
api_url: "https://kubernetes#{project.id}.com", category: 'deployment',
token: defined?(token) ? token : "token#{project.id}", type: 'KubernetesService',
ca_pem: "ca_pem#{project.id}") properties: "{\"namespace\":\"prod\",\"api_url\":\"https://kubernetes#{project.id}.com\",\"ca_pem\":\"ca_pem#{project.id}\",\"token\":\"token#{project.id}\"}")
end end
end end
it 'migrates the KubernetesService to Platform::Kubernetes' do it 'migrates the KubernetesService to Platform::Kubernetes' do
expect { migrate! }.to change { Clusters::Cluster.count }.by(sample_num) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(sample_num)
projects.each do |project| projects.each do |project|
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.enabled).to eq(active) expect(cluster.enabled).to eq(active)
expect(cluster.platform_kubernetes.api_url).to eq(project.kubernetes_service.api_url) expect(cluster.platform_kubernetes.api_url).to eq(project.kubernetes_service.api_url)
expect(cluster.platform_kubernetes.ca_pem).to eq(project.kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.ca_cert).to eq(project.kubernetes_service.ca_pem)
expect(cluster.platform_kubernetes.token).to eq(project.kubernetes_service.token) expect(cluster.platform_kubernetes.token).to eq(project.kubernetes_service.token)
expect(project.kubernetes_service).not_to be_active expect(project.kubernetes_service).not_to be_active
end end
...@@ -42,34 +47,38 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -42,34 +47,38 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
context 'when unique KubernetesService spawned from Service Template' do context 'when unique KubernetesService spawned from Service Template' do
let(:sample_num) { 2 } let(:sample_num) { 2 }
let(:projects) { create_list(:project, sample_num) }
let(:projects) do
(1..sample_num).each_with_object([]) do |n, array|
array << MigrateKubernetesServiceToNewClustersArchitectures::Project.create!
end
end
let!(:kubernetes_service_template) do let!(:kubernetes_service_template) do
create(:kubernetes_service, MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: nil, template: true,
template: true, category: 'deployment',
api_url: "https://sample.kubernetes.com", type: 'KubernetesService',
token: "token-sample", properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}")
ca_pem: "ca_pem-sample")
end end
let!(:kubernetes_services) do let!(:kubernetes_services) do
projects.map do |project| projects.map do |project|
create(:kubernetes_service, MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project, project: project,
api_url: kubernetes_service_template.api_url, category: 'deployment',
token: kubernetes_service_template.token, type: 'KubernetesService',
ca_pem: kubernetes_service_template.ca_pem) properties: "{\"namespace\":\"prod\",\"api_url\":\"#{kubernetes_service_template.api_url}\",\"ca_pem\":\"#{kubernetes_service_template.ca_pem}\",\"token\":\"#{kubernetes_service_template.token}\"}")
end end
end end
it 'migrates the KubernetesService to Platform::Kubernetes without template' do it 'migrates the KubernetesService to Platform::Kubernetes without template' do
expect { migrate! }.to change { Clusters::Cluster.count }.by(sample_num) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(sample_num)
projects.each do |project| projects.each do |project|
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.platform_kubernetes.api_url).to eq(project.kubernetes_service.api_url) expect(cluster.platform_kubernetes.api_url).to eq(project.kubernetes_service.api_url)
expect(cluster.platform_kubernetes.ca_pem).to eq(project.kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.ca_cert).to eq(project.kubernetes_service.ca_pem)
expect(cluster.platform_kubernetes.token).to eq(project.kubernetes_service.token) expect(cluster.platform_kubernetes.token).to eq(project.kubernetes_service.token)
expect(project.kubernetes_service).not_to be_active expect(project.kubernetes_service).not_to be_active
end end
...@@ -78,21 +87,32 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -78,21 +87,32 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when managed KubernetesService exists' do context 'when managed KubernetesService exists' do
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
let!(:platform_kubernetes) { cluster.platform_kubernetes } let(:cluster) do
MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create!(
projects: [project],
name: 'sample-cluster',
platform_type: :kubernetes,
provider_type: :user,
platform_kubernetes_attributes: {
api_url: 'https://sample.kubernetes.com',
ca_cert: 'ca_pem-sample',
token: 'token-sample'
} )
end
let!(:kubernetes_service) do let!(:kubernetes_service) do
create(:kubernetes_service, MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project, project: project,
active: cluster.enabled, active: cluster.enabled,
api_url: platform_kubernetes.api_url, category: 'deployment',
token: platform_kubernetes.token, type: 'KubernetesService',
ca_pem: platform_kubernetes.ca_cert) properties: "{\"api_url\":\"#{cluster.platform_kubernetes.api_url}\"}")
end end
it 'does not migrate the KubernetesService and disables the kubernetes_service' do # Because the corresponding Platform::Kubernetes already exists it 'does not migrate the KubernetesService and disables the kubernetes_service' do # Because the corresponding Platform::Kubernetes already exists
expect { migrate! }.not_to change { Clusters::Cluster.count } expect { migrate! }.not_to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }
kubernetes_service.reload kubernetes_service.reload
expect(kubernetes_service).not_to be_active expect(kubernetes_service).not_to be_active
...@@ -100,18 +120,39 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -100,18 +120,39 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when production cluster has already been existed' do # i.e. There are no environment_scope conflicts context 'when production cluster has already been existed' do # i.e. There are no environment_scope conflicts
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: 'production/*', projects: [project]) }
let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } let(:cluster) do
MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create!(
projects: [project],
name: 'sample-cluster',
platform_type: :kubernetes,
provider_type: :user,
environment_scope: 'production/*',
platform_kubernetes_attributes: {
api_url: 'https://sample.kubernetes.com',
ca_cert: 'ca_pem-sample',
token: 'token-sample'
} )
end
let!(:kubernetes_service) do
MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project,
active: true,
category: 'deployment',
type: 'KubernetesService',
properties: "{\"api_url\":\"https://debug.kube.com\"}")
end
it 'migrates the KubernetesService to Platform::Kubernetes' do it 'migrates the KubernetesService to Platform::Kubernetes' do
expect { migrate! }.to change { Clusters::Cluster.count }.by(1) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(1)
kubernetes_service.reload kubernetes_service.reload
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.environment_scope).to eq('*') expect(cluster.environment_scope).to eq('*')
expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url)
expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.ca_cert).to eq(kubernetes_service.ca_pem)
expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token)
expect(kubernetes_service).not_to be_active expect(kubernetes_service).not_to be_active
end end
...@@ -119,18 +160,39 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -119,18 +160,39 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when default cluster has already been existed' do context 'when default cluster has already been existed' do
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) }
let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } let!(:cluster) do
MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create!(
projects: [project],
name: 'sample-cluster',
platform_type: :kubernetes,
provider_type: :user,
environment_scope: '*',
platform_kubernetes_attributes: {
api_url: 'https://sample.kubernetes.com',
ca_cert: 'ca_pem-sample',
token: 'token-sample'
} )
end
let!(:kubernetes_service) do
MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project,
active: true,
category: 'deployment',
type: 'KubernetesService',
properties: "{\"api_url\":\"https://debug.kube.com\"}")
end
it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated
expect { migrate! }.to change { Clusters::Cluster.count }.by(1) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(1)
kubernetes_service.reload kubernetes_service.reload
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.environment_scope).to eq('migrated/*') expect(cluster.environment_scope).to eq('migrated/*')
expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url)
expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.ca_cert).to eq(kubernetes_service.ca_pem)
expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token)
expect(kubernetes_service).not_to be_active expect(kubernetes_service).not_to be_active
end end
...@@ -138,19 +200,53 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -138,19 +200,53 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when default cluster and migrated cluster has already been existed' do context 'when default cluster and migrated cluster has already been existed' do
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
let!(:cluster) { create(:cluster, :provided_by_gcp, environment_scope: '*', projects: [project]) }
let!(:migrated_cluster) { create(:cluster, :provided_by_gcp, environment_scope: 'migrated/*', projects: [project]) } let!(:cluster) do
let!(:kubernetes_service) { create(:kubernetes_service, api_url: 'https://debug.kube.com', active: true, project: project) } MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create!(
projects: [project],
name: 'sample-cluster',
platform_type: :kubernetes,
provider_type: :user,
environment_scope: '*',
platform_kubernetes_attributes: {
api_url: 'https://sample.kubernetes.com',
ca_cert: 'ca_pem-sample',
token: 'token-sample'
} )
end
let!(:migrated_cluster) do
MigrateKubernetesServiceToNewClustersArchitectures::Cluster.create!(
projects: [project],
name: 'sample-cluster',
platform_type: :kubernetes,
provider_type: :user,
environment_scope: 'migrated/*',
platform_kubernetes_attributes: {
api_url: 'https://sample.kubernetes.com',
ca_cert: 'ca_pem-sample',
token: 'token-sample'
} )
end
let!(:kubernetes_service) do
MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
project: project,
active: true,
category: 'deployment',
type: 'KubernetesService',
properties: "{\"api_url\":\"https://debug.kube.com\"}")
end
it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated it 'migrates the KubernetesService to Platform::Kubernetes with dedicated environment_scope' do # Because environment_scope is duplicated
expect { migrate! }.to change { Clusters::Cluster.count }.by(1) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(1)
kubernetes_service.reload kubernetes_service.reload
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.environment_scope).to eq('migrated0/*') expect(cluster.environment_scope).to eq('migrated0/*')
expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url) expect(cluster.platform_kubernetes.api_url).to eq(kubernetes_service.api_url)
expect(cluster.platform_kubernetes.ca_pem).to eq(kubernetes_service.ca_pem) expect(cluster.platform_kubernetes.ca_cert).to eq(kubernetes_service.ca_pem)
expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token) expect(cluster.platform_kubernetes.token).to eq(kubernetes_service.token)
expect(kubernetes_service).not_to be_active expect(kubernetes_service).not_to be_active
end end
...@@ -158,17 +254,19 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -158,17 +254,19 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when KubernetesService has nullified parameters' do context 'when KubernetesService has nullified parameters' do
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
before do before do
ActiveRecord::Base.connection.execute <<~SQL MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
INSERT INTO services (project_id, active, category, type, properties) project: project,
VALUES (#{project.id}, false, 'deployment', 'KubernetesService', '{}'); active: false,
SQL category: 'deployment',
type: 'KubernetesService',
properties: "{}")
end end
it 'does not migrate the KubernetesService and disables the kubernetes_service' do it 'does not migrate the KubernetesService and disables the kubernetes_service' do
expect { migrate! }.not_to change { Clusters::Cluster.count } expect { migrate! }.not_to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }
expect(project.kubernetes_service).not_to be_active expect(project.kubernetes_service).not_to be_active
end end
...@@ -179,23 +277,25 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -179,23 +277,25 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
# However, in this migration file, there are no validations because of the re-defined model class # However, in this migration file, there are no validations because of the re-defined model class
# therefore, we should safely add this raw to Platform::Kubernetes # therefore, we should safely add this raw to Platform::Kubernetes
context 'when KubernetesService has empty token' do context 'when KubernetesService has empty token' do
let(:project) { create(:project) } let(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
before do before do
ActiveRecord::Base.connection.execute <<~SQL MigrateKubernetesServiceToNewClustersArchitectures::Service.create!(
INSERT INTO services (project_id, active, category, type, properties) project: project,
VALUES (#{project.id}, false, 'deployment', 'KubernetesService', '{"namespace":"prod","api_url":"http://111.111.111.111","ca_pem":"a","token":""}'); active: false,
SQL category: 'deployment',
type: 'KubernetesService',
properties: "{\"namespace\":\"prod\",\"api_url\":\"http://111.111.111.111\",\"ca_pem\":\"a\",\"token\":\"\"}")
end end
it 'does not migrate the KubernetesService and disables the kubernetes_service' do it 'does not migrate the KubernetesService and disables the kubernetes_service' do
expect { migrate! }.to change { Clusters::Cluster.count }.by(1) expect { migrate! }.to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }.by(1)
project.clusters.last.tap do |cluster| project.clusters.last.tap do |cluster|
expect(cluster.environment_scope).to eq('*') expect(cluster.environment_scope).to eq('*')
expect(cluster.platform_kubernetes.namespace).to eq('prod') expect(cluster.platform_kubernetes.namespace).to eq('prod')
expect(cluster.platform_kubernetes.api_url).to eq('http://111.111.111.111') expect(cluster.platform_kubernetes.api_url).to eq('http://111.111.111.111')
expect(cluster.platform_kubernetes.ca_pem).to eq('a') expect(cluster.platform_kubernetes.ca_cert).to eq('a')
expect(cluster.platform_kubernetes.token).to be_empty expect(cluster.platform_kubernetes.token).to be_empty
expect(project.kubernetes_service).not_to be_active expect(project.kubernetes_service).not_to be_active
end end
...@@ -203,10 +303,10 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do ...@@ -203,10 +303,10 @@ describe MigrateKubernetesServiceToNewClustersArchitectures, :migration do
end end
context 'when KubernetesService does not exist' do context 'when KubernetesService does not exist' do
let!(:project) { create(:project) } let!(:project) { MigrateKubernetesServiceToNewClustersArchitectures::Project.create! }
it 'does not migrate the KubernetesService' do it 'does not migrate the KubernetesService' do
expect { migrate! }.not_to change { Clusters::Cluster.count } expect { migrate! }.not_to change { MigrateKubernetesServiceToNewClustersArchitectures::Cluster.count }
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment