Commit 6be7774e authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'ee-fix-cluster-enviroment-missing' into 'master'

Ee fix cluster enviroment missing

Closes #4361

See merge request gitlab-org/gitlab-ee!3806
parents 1671614a f8cda25d
...@@ -39,6 +39,7 @@ class Projects::Clusters::GcpController < Projects::ApplicationController ...@@ -39,6 +39,7 @@ class Projects::Clusters::GcpController < Projects::ApplicationController
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, :enabled,
:name, :name,
:environment_scope,
provider_gcp_attributes: [ provider_gcp_attributes: [
:gcp_project_id, :gcp_project_id,
:zone, :zone,
......
...@@ -26,6 +26,7 @@ class Projects::Clusters::UserController < Projects::ApplicationController ...@@ -26,6 +26,7 @@ class Projects::Clusters::UserController < Projects::ApplicationController
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, :enabled,
:name, :name,
:environment_scope,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
:namespace, :namespace,
:api_url, :api_url,
......
...@@ -70,23 +70,11 @@ class Projects::ClustersController < Projects::ApplicationController ...@@ -70,23 +70,11 @@ class Projects::ClustersController < Projects::ApplicationController
.present(current_user: current_user) .present(current_user: current_user)
end end
def create_params
params.require(:cluster).permit(
:enabled,
:name,
:provider_type,
provider_gcp_attributes: [
:gcp_project_id,
:zone,
:num_nodes,
:machine_type
])
end
def update_params def update_params
if cluster.managed? if cluster.managed?
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, :enabled,
:environment_scope,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
:namespace :namespace
] ]
...@@ -95,6 +83,7 @@ class Projects::ClustersController < Projects::ApplicationController ...@@ -95,6 +83,7 @@ class Projects::ClustersController < Projects::ApplicationController
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, :enabled,
:name, :name,
:environment_scope,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
:api_url, :api_url,
:token, :token,
......
module ClustersHelper
def has_multiple_clusters?(project)
project.feature_available?(:multiple_clusters)
end
end
...@@ -27,7 +27,7 @@ module Clusters ...@@ -27,7 +27,7 @@ module Clusters
accepts_nested_attributes_for :platform_kubernetes, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true
validates :name, cluster_name: true validates :name, cluster_name: true
validate :unique_environment_scope, if: :has_project? validate :unique_environment_scope
validate :restrict_modification, on: :update validate :restrict_modification, on: :update
delegate :status, to: :provider, allow_nil: true delegate :status, to: :provider, allow_nil: true
...@@ -94,7 +94,7 @@ module Clusters ...@@ -94,7 +94,7 @@ module Clusters
private private
def unique_environment_scope def unique_environment_scope
if project.clusters.where(environment_scope: environment_scope).where.not(id: self.id).exists? if project && project.clusters.where(environment_scope: environment_scope).where.not(id: self.id).exists?
errors.add(:base, "cannot add duplicated environment scope") errors.add(:base, "cannot add duplicated environment scope")
return false return false
end end
...@@ -110,9 +110,5 @@ module Clusters ...@@ -110,9 +110,5 @@ module Clusters
true true
end end
def has_project?
projects.exists?
end
end end
end end
...@@ -8,6 +8,10 @@ ...@@ -8,6 +8,10 @@
= field.label :name, s_('ClusterIntegration|Cluster name') = field.label :name, s_('ClusterIntegration|Cluster name')
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name') = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
.form-group
= field.label :environment_scope, s_('ClusterIntegration|Environment scope')
= field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :provider_gcp, @cluster.provider_gcp do |provider_gcp_field| = field.fields_for :provider_gcp, @cluster.provider_gcp do |provider_gcp_field|
.form-group .form-group
= provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project ID') = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project ID')
......
...@@ -8,6 +8,11 @@ ...@@ -8,6 +8,11 @@
= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field| = form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
= form_errors(@cluster) = form_errors(@cluster)
.form-group
= field.label :environment_scope, s_('ClusterIntegration|Environment scope')
= field.text_field :environment_scope, class: 'form-control js-select-on-focus', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field| = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group .form-group
= platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL') = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
= field.label :name, s_('ClusterIntegration|Cluster name') = field.label :name, s_('ClusterIntegration|Cluster name')
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name') = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
.form-group
= field.label :environment_scope, s_('ClusterIntegration|Environment scope')
= field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field| = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group .form-group
= platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL') = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
= field.label :name, s_('ClusterIntegration|Cluster name') = field.label :name, s_('ClusterIntegration|Cluster name')
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name') = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Cluster name')
.form-group
= field.label :environment_scope, s_('ClusterIntegration|Environment scope')
= field.text_field :environment_scope, class: 'form-control js-select-on-focus', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field| = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group .form-group
= platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL') = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
......
require 'spec_helper' require 'spec_helper'
feature 'Clusters', :js do feature 'EE Clusters' do
include GoogleApi::CloudPlatformHelpers
let(:project) { create(:project) } let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
...@@ -11,27 +9,145 @@ feature 'Clusters', :js do ...@@ -11,27 +9,145 @@ feature 'Clusters', :js do
gitlab_sign_in(user) gitlab_sign_in(user)
end end
context 'when user has a cluster and visits cluster index page' do context 'when user has a cluster' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) } context 'when license has multiple clusters feature' do
let(:project) { cluster.project } before do
allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:multiple_clusters).and_return(true)
end
context 'when user adds an existing cluster' do
before do before do
create(:cluster, :provided_by_user, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project) visit project_clusters_path(project)
end end
context 'when license has multiple clusters feature' do it 'user sees a add cluster button ' do
expect(page).not_to have_selector('.js-add-cluster.readonly')
expect(page).to have_selector('.js-add-cluster')
end
context 'when user filled form with environment scope' do
before do
click_link 'Add cluster'
click_link 'Add an existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
click_button 'Add cluster'
end
it 'user sees a cluster details page' do
expect(page.find_field('cluster[name]').value).to eq('staging-cluster')
expect(page.find_field('cluster[environment_scope]').value).to eq('staging/*')
end
end
context 'when user updates environment scope' do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
click_button 'Save changes'
end
it 'user sees a cluster details page' do
expect(page.find_field('cluster[environment_scope]').value).to eq('production/*')
end
end
context 'when user updates duplicated environment scope' do
before do
click_link 'Add cluster'
click_link 'Add an existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
click_button 'Add cluster'
end
it 'users sees an environment scope validation error' do
expect(page).to have_content('cannot add duplicated environment scope')
end
end
end
context 'when user adds an GKE cluster' do
before do before do
allow_any_instance_of(EE::Project).to receive(:feature_available?).with(:multiple_clusters).and_return(true) allow_any_instance_of(Projects::Clusters::GcpController)
.to receive(:token_in_session).and_return('token')
allow_any_instance_of(Projects::Clusters::GcpController)
.to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
OpenStruct.new(
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
end
allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
create(:cluster, :provided_by_gcp, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project)
end end
it 'user sees a add cluster button ' do it 'user sees a add cluster button ' do
expect(page).not_to have_selector('.js-add-cluster.readonly')
expect(page).to have_selector('.js-add-cluster') expect(page).to have_selector('.js-add-cluster')
end end
context 'when user filled form with environment scope' do
before do
click_link 'Add cluster'
click_link 'Create on GKE'
fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
click_button 'Create cluster'
end
it 'user sees a cluster details page' do
expect(page).to have_content('Enable cluster integration')
expect(page.find_field('cluster[environment_scope]').value).to eq('staging/*')
end
end
context 'when user updates environment scope' do
before do
click_link 'default-cluster'
fill_in 'cluster_environment_scope', with: 'production/*'
click_button 'Save changes'
end
it 'user sees a cluster details page' do
expect(page.find_field('cluster[environment_scope]').value).to eq('production/*')
end
end
context 'when user updates duplicated environment scope' do
before do
click_link 'Add cluster'
click_link 'Create on GKE'
fill_in 'cluster_provider_gcp_attributes_gcp_project_id', with: 'gcp-project-123'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
click_button 'Create cluster'
end
it 'users sees an environment scope validation error' do
expect(page).to have_content('cannot add duplicated environment scope')
end
end
end
end end
context 'when license does not have multiple clusters feature' do context 'when license does not have multiple clusters feature' do
before do before do
allow_any_instance_of(EE::Project).to receive(:feature_available?).with(:multiple_clusters).and_return(false) allow(License).to receive(:feature_available?).and_call_original
allow(License).to receive(:feature_available?).with(:multiple_clusters).and_return(false)
create(:cluster, :provided_by_user, name: 'default-cluster', environment_scope: '*', projects: [project])
end
context 'when user visits cluster index page' do
before do
visit project_clusters_path(project)
end end
it 'user sees a disabled add cluster button ' do it 'user sees a disabled add cluster button ' do
...@@ -39,4 +155,5 @@ feature 'Clusters', :js do ...@@ -39,4 +155,5 @@ feature 'Clusters', :js do
end end
end end
end end
end
end end
...@@ -709,7 +709,7 @@ describe Project do ...@@ -709,7 +709,7 @@ describe Project do
context 'when environment is specified' do context 'when environment is specified' do
let(:environment) { create(:environment, project: project, name: 'review/name') } let(:environment) { create(:environment, project: project, name: 'review/name') }
let!(:default_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: '*') } let!(:default_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: '*') }
let!(:cluster) { create(:cluster, :provided_by_user, projects: [project]) } let!(:cluster) { create(:cluster, :provided_by_user, environment_scope: 'review/*', projects: [project]) }
subject { project.deployment_platform(environment: environment) } subject { project.deployment_platform(environment: environment) }
...@@ -782,8 +782,6 @@ describe Project do ...@@ -782,8 +782,6 @@ describe Project do
end end
context 'when environment scope has _' do context 'when environment scope has _' do
let!(:cluster) { create(:cluster, :provided_by_user, projects: [project]) }
before do before do
stub_licensed_features(multiple_clusters: true) stub_licensed_features(multiple_clusters: true)
end end
...@@ -807,8 +805,6 @@ describe Project do ...@@ -807,8 +805,6 @@ describe Project do
# it doesn't break in case some data sneaked in somehow as we're # it doesn't break in case some data sneaked in somehow as we're
# not checking this integrity in database level. # not checking this integrity in database level.
context 'when environment scope has %' do context 'when environment scope has %' do
let!(:cluster) { create(:cluster, :provided_by_user, projects: [project]) }
before do before do
stub_licensed_features(multiple_clusters: true) stub_licensed_features(multiple_clusters: true)
end end
...@@ -827,15 +823,14 @@ describe Project do ...@@ -827,15 +823,14 @@ describe Project do
end end
end end
context 'when variables with the same name have different environment scopes' do context 'when perfectly matched cluster exists' do
let!(:partially_matched_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'review/*') }
let!(:perfectly_matched_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'review/name') } let!(:perfectly_matched_cluster) { create(:cluster, :provided_by_user, projects: [project], environment_scope: 'review/name') }
before do before do
stub_licensed_features(multiple_clusters: true) stub_licensed_features(multiple_clusters: true)
end end
it 'puts variables matching environment scope more in the end' do it 'returns perfectly matched cluster as highest precedence' do
is_expected.to eq(perfectly_matched_cluster.platform_kubernetes) is_expected.to eq(perfectly_matched_cluster.platform_kubernetes)
end end
end end
......
...@@ -2,9 +2,10 @@ FactoryBot.define do ...@@ -2,9 +2,10 @@ FactoryBot.define do
factory :cluster, class: Clusters::Cluster do factory :cluster, class: Clusters::Cluster do
user user
name 'test-cluster' name 'test-cluster'
sequence(:environment_scope) { |n| "production#{n}/*" }
trait :project do trait :project do
after(:create) do |cluster, evaluator| before(:create) do |cluster, evaluator|
cluster.projects << create(:project) cluster.projects << create(:project)
end end
end end
......
...@@ -137,20 +137,20 @@ describe Clusters::Cluster do ...@@ -137,20 +137,20 @@ describe Clusters::Cluster do
end end
context 'when identical environment scope exists in project' do context 'when identical environment scope exists in project' do
let(:cluster) { create(:cluster, projects: [project], environment_scope: 'product/*') } let(:cluster) { build(:cluster, projects: [project], environment_scope: 'product/*') }
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
context 'when identical environment scope does not exist in project' do context 'when identical environment scope does not exist in project' do
let(:cluster) { create(:cluster, projects: [project], environment_scope: '*') } let(:cluster) { build(:cluster, projects: [project], environment_scope: '*') }
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
end end
context 'when identical environment scope exists in different project' do context 'when identical environment scope exists in different project' do
let(:project2) { create(:project) } let(:project2) { create(:project) }
let(:cluster) { create(:cluster, projects: [project2], environment_scope: 'product/*') } let(:cluster) { build(:cluster, projects: [project2], environment_scope: 'product/*') }
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
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