From e028d795c484dcd1030b4f6bba8f53d4e677f0b3 Mon Sep 17 00:00:00 2001 From: Mayra Cabrera Date: Thu, 4 Jan 2018 09:33:51 +0000 Subject: 41054-Disallow creation of new Kubernetes integrations --- app/assets/stylesheets/pages/settings.scss | 4 + app/helpers/services_helper.rb | 11 +++ app/models/project_services/kubernetes_service.rb | 28 ++++++ app/models/service.rb | 8 ++ .../services/_deprecated_message.html.haml | 3 + app/views/projects/services/_form.html.haml | 5 +- app/views/projects/services/edit.html.haml | 2 + app/views/shared/_field.html.haml | 11 ++- app/views/shared/_service_settings.html.haml | 2 +- ...ble-creation-of-new-kubernetes-integrations.yml | 6 ++ .../projects/services_controller_spec.rb | 36 ++++++++ spec/factories/services.rb | 1 + .../projects/clusters/interchangeability_spec.rb | 2 +- .../project_services/kubernetes_service_spec.rb | 101 +++++++++++++++++++++ spec/models/service_spec.rb | 18 ++++ spec/requests/api/services_spec.rb | 8 +- spec/requests/api/v3/services_spec.rb | 4 + spec/support/services_shared_context.rb | 8 ++ 18 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 app/views/projects/services/_deprecated_message.html.haml create mode 100644 changelogs/unreleased/41054-disable-creation-of-new-kubernetes-integrations.yml diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index 5d630c7d61e..6353482ede7 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -268,3 +268,7 @@ margin: 0 0 5px 17px; } } + +.deprecated-service { + cursor: default; +} diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb index 3707bb5ba36..240783bc7fd 100644 --- a/app/helpers/services_helper.rb +++ b/app/helpers/services_helper.rb @@ -27,5 +27,16 @@ module ServicesHelper "#{event}_events" end + def service_save_button(service) + button_tag(class: 'btn btn-save', type: 'submit', disabled: service.deprecated?) do + icon('spinner spin', class: 'hidden js-btn-spinner') + + content_tag(:span, 'Save changes', class: 'js-btn-label') + end + end + + def disable_fields_service?(service) + !current_controller?("admin/services") && service.deprecated? + end + extend self end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index b82567ce2b3..c72b01b64af 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -31,6 +31,7 @@ class KubernetesService < DeploymentService before_validation :enforce_namespace_to_lower_case + validate :deprecation_validation, unless: :template? validates :namespace, allow_blank: true, length: 1..63, @@ -145,6 +146,17 @@ class KubernetesService < DeploymentService @kubeclient ||= build_kubeclient! end + def deprecated? + !active + end + + def deprecation_message + content = <<-MESSAGE.strip_heredoc + Kubernetes service integration has been deprecated. #{deprecated_message_content} your clusters using the new Clusters page + MESSAGE + content.html_safe + end + TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze private @@ -226,4 +238,20 @@ class KubernetesService < DeploymentService def enforce_namespace_to_lower_case self.namespace = self.namespace&.downcase end + + def deprecation_validation + return if active_changed?(from: true, to: false) + + if deprecated? + errors[:base] << deprecation_message + end + end + + def deprecated_message_content + if active? + "Your cluster information on this page is still editable, but you are advised to disable and reconfigure" + else + "Fields on this page are now uneditable, you can configure" + end + end end diff --git a/app/models/service.rb b/app/models/service.rb index 3c4f1885dd0..176b472e724 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -263,6 +263,14 @@ class Service < ActiveRecord::Base service end + def deprecated? + false + end + + def deprecation_message + nil + end + private def cache_project_has_external_issue_tracker diff --git a/app/views/projects/services/_deprecated_message.html.haml b/app/views/projects/services/_deprecated_message.html.haml new file mode 100644 index 00000000000..fea9506a4bb --- /dev/null +++ b/app/views/projects/services/_deprecated_message.html.haml @@ -0,0 +1,3 @@ +.flash-container.flash-container-page + .flash-alert.deprecated-service + %span= @service.deprecation_message diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index c0b1c62e8ef..21acd857ce7 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -13,10 +13,7 @@ = render 'shared/service_settings', form: form, subject: @service - if @service.editable? .footer-block.row-content-block - %button.btn.btn-save{ type: 'submit' } - = icon('spinner spin', class: 'hidden js-btn-spinner') - %span.js-btn-label - Save changes + = service_save_button(@service)   - if @service.valid? && @service.activated? - unless @service.can_test? diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml index 25770df1c90..df1fd583670 100644 --- a/app/views/projects/services/edit.html.haml +++ b/app/views/projects/services/edit.html.haml @@ -2,4 +2,6 @@ - page_title @service.title, "Services" - add_to_breadcrumbs("Settings", edit_project_path(@project)) += render 'deprecated_message' if @service.deprecation_message + = render 'form' diff --git a/app/views/shared/_field.html.haml b/app/views/shared/_field.html.haml index 795447a9ca6..aea0a8fd8e0 100644 --- a/app/views/shared/_field.html.haml +++ b/app/views/shared/_field.html.haml @@ -7,6 +7,7 @@ - choices = field[:choices] - default_choice = field[:default_choice] - help = field[:help] +- disabled = disable_fields_service?(@service) .form-group - if type == "password" && value.present? @@ -15,14 +16,14 @@ = form.label name, title, class: "control-label" .col-sm-10 - if type == 'text' - = form.text_field name, class: "form-control", placeholder: placeholder, required: required + = form.text_field name, class: "form-control", placeholder: placeholder, required: required, disabled: disabled - elsif type == 'textarea' - = form.text_area name, rows: 5, class: "form-control", placeholder: placeholder, required: required + = form.text_area name, rows: 5, class: "form-control", placeholder: placeholder, required: required, disabled: disabled - elsif type == 'checkbox' - = form.check_box name + = form.check_box name, disabled: disabled - elsif type == 'select' - = form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } + = form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control", disabled: disabled} - elsif type == 'password' - = form.password_field name, autocomplete: "new-password", class: "form-control", required: value.blank? && :required + = form.password_field name, autocomplete: "new-password", class: "form-control", required: value.blank? && required, disabled: disabled - if help %span.help-block= help diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml index 7ca14ac93cc..61b39afb5d4 100644 --- a/app/views/shared/_service_settings.html.haml +++ b/app/views/shared/_service_settings.html.haml @@ -11,7 +11,7 @@ .form-group = form.label :active, "Active", class: "control-label" .col-sm-10 - = form.check_box :active + = form.check_box :active, disabled: disable_fields_service?(@service) - if @service.supported_events.present? .form-group diff --git a/changelogs/unreleased/41054-disable-creation-of-new-kubernetes-integrations.yml b/changelogs/unreleased/41054-disable-creation-of-new-kubernetes-integrations.yml new file mode 100644 index 00000000000..b960b14624c --- /dev/null +++ b/changelogs/unreleased/41054-disable-creation-of-new-kubernetes-integrations.yml @@ -0,0 +1,6 @@ +--- +title: Disable creation of new Kubernetes Integrations unless they're active or created + from template +merge_request: 41054 +author: +type: added diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index 2c6ad00515e..847ac6f2be0 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -114,5 +114,41 @@ describe Projects::ServicesController do expect(flash[:notice]).to eq 'HipChat settings saved, but not activated.' end end + + context 'with a deprecated service' do + let(:service) { create(:kubernetes_service, project: project) } + + before do + put :update, + namespace_id: project.namespace, project_id: project, id: service.to_param, service: { namespace: 'updated_namespace' } + end + + it 'should not update the service' do + service.reload + expect(service.namespace).not_to eq('updated_namespace') + end + end + end + + describe "GET #edit" do + before do + get :edit, namespace_id: project.namespace, project_id: project, id: service_id + end + + context 'with approved services' do + let(:service_id) { 'jira' } + + it 'should render edit page' do + expect(response).to be_success + end + end + + context 'with a deprecated service' do + let(:service_id) { 'kubernetes' } + + it 'should render edit page' do + expect(response).to be_success + end + end end end diff --git a/spec/factories/services.rb b/spec/factories/services.rb index 4b0377967c7..110ef33c6f7 100644 --- a/spec/factories/services.rb +++ b/spec/factories/services.rb @@ -18,6 +18,7 @@ FactoryBot.define do factory :kubernetes_service do project + type 'KubernetesService' active true properties({ api_url: 'https://kubernetes.example.com', diff --git a/spec/features/projects/clusters/interchangeability_spec.rb b/spec/features/projects/clusters/interchangeability_spec.rb index 01f9526608f..3ddb35c755c 100644 --- a/spec/features/projects/clusters/interchangeability_spec.rb +++ b/spec/features/projects/clusters/interchangeability_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' feature 'Interchangeability between KubernetesService and Platform::Kubernetes' do - EXCEPT_METHODS = %i[test title description help fields initialize_properties namespace namespace= api_url api_url=].freeze + EXCEPT_METHODS = %i[test title description help fields initialize_properties namespace namespace= api_url api_url= deprecated? deprecation_message].freeze EXCEPT_METHODS_GREP_V = %w[_touched? _changed? _was].freeze it 'Clusters::Platform::Kubernetes covers core interfaces in KubernetesService' do diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index f037ee77a94..6980ba335b8 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -52,12 +52,75 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do context 'when service is inactive' do before do + subject.project = project subject.active = false end it { is_expected.not_to validate_presence_of(:api_url) } it { is_expected.not_to validate_presence_of(:token) } end + + context 'with a deprecated service' do + let(:kubernetes_service) { create(:kubernetes_service) } + + before do + kubernetes_service.update_attribute(:active, false) + kubernetes_service.properties[:namespace] = "foo" + end + + it 'should not update attributes' do + expect(kubernetes_service.save).to be_falsy + end + + it 'should include an error with a deprecation message' do + kubernetes_service.valid? + expect(kubernetes_service.errors[:base].first).to match(/Kubernetes service integration has been deprecated/) + end + end + + context 'with a non-deprecated service' do + let(:kubernetes_service) { create(:kubernetes_service) } + + it 'should update attributes' do + kubernetes_service.properties[:namespace] = 'foo' + expect(kubernetes_service.save).to be_truthy + end + end + + context 'with an active and deprecated service' do + let(:kubernetes_service) { create(:kubernetes_service) } + + before do + kubernetes_service.active = false + kubernetes_service.properties[:namespace] = 'foo' + kubernetes_service.save + end + + it 'should deactive the service' do + expect(kubernetes_service.active?).to be_falsy + end + + it 'should not include a deprecation message as error' do + expect(kubernetes_service.errors.messages.count).to eq(0) + end + + it 'should update attributes' do + expect(kubernetes_service.properties[:namespace]).to eq("foo") + end + end + + context 'with a template service' do + let(:kubernetes_service) { create(:kubernetes_service, template: true, active: false) } + + before do + kubernetes_service.properties[:namespace] = 'foo' + end + + it 'should update attributes' do + expect(kubernetes_service.save).to be_truthy + expect(kubernetes_service.properties[:namespace]).to eq('foo') + end + end end describe '#initialize_properties' do @@ -318,4 +381,42 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do it { is_expected.to eq(pods: []) } end end + + describe "#deprecated?" do + let(:kubernetes_service) { create(:kubernetes_service) } + + context 'with an active kubernetes service' do + it 'should return false' do + expect(kubernetes_service.deprecated?).to be_falsy + end + end + + context 'with a inactive kubernetes service' do + it 'should return true' do + kubernetes_service.update_attribute(:active, false) + expect(kubernetes_service.deprecated?).to be_truthy + end + end + end + + describe "#deprecation_message" do + let(:kubernetes_service) { create(:kubernetes_service) } + + it 'should indicate the service is deprecated' do + expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been deprecated/) + end + + context 'if the services is active' do + it 'should return a message' do + expect(kubernetes_service.deprecation_message).to match(/Your cluster information on this page is still editable/) + end + end + + context 'if the service is not active' do + it 'should return a message' do + kubernetes_service.update_attribute(:active, false) + expect(kubernetes_service.deprecation_message).to match(/Fields on this page are now uneditable/) + end + end + end end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 0f2f906c667..540615de117 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -254,4 +254,22 @@ describe Service do end end end + + describe "#deprecated?" do + let(:project) { create(:project, :repository) } + + it 'should return false by default' do + service = create(:service, project: project) + expect(service.deprecated?).to be_falsy + end + end + + describe "#deprecation_message" do + let(:project) { create(:project, :repository) } + + it 'should be empty by default' do + service = create(:service, project: project) + expect(service.deprecation_message).to be_nil + end + end end diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index ceafa0e2058..26d56c04862 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -53,6 +53,10 @@ describe API::Services do describe "DELETE /projects/:id/services/#{service.dasherize}" do include_context service + before do + initialize_service(service) + end + it "deletes #{service}" do delete api("/projects/#{project.id}/services/#{dashed_service}", user) @@ -67,9 +71,7 @@ describe API::Services do # inject some properties into the service before do - service_object = project.find_or_initialize_service(service) - service_object.properties = service_attrs - service_object.save + initialize_service(service) end it 'returns authentication error when unauthenticated' do diff --git a/spec/requests/api/v3/services_spec.rb b/spec/requests/api/v3/services_spec.rb index 8f212ab6be6..c69a7d58ca6 100644 --- a/spec/requests/api/v3/services_spec.rb +++ b/spec/requests/api/v3/services_spec.rb @@ -10,6 +10,10 @@ describe API::V3::Services do describe "DELETE /projects/:id/services/#{service.dasherize}" do include_context service + before do + initialize_service(service) + end + it "deletes #{service}" do delete v3_api("/projects/#{project.id}/services/#{dashed_service}", user) diff --git a/spec/support/services_shared_context.rb b/spec/support/services_shared_context.rb index 7457484a932..3f1fd169b72 100644 --- a/spec/support/services_shared_context.rb +++ b/spec/support/services_shared_context.rb @@ -29,5 +29,13 @@ Service.available_services_names.each do |service| end end end + + def initialize_service(service) + service_item = project.find_or_initialize_service(service) + service_item.properties = service_attrs + service_item.active = true if service == "kubernetes" + service_item.save + service_item + end end end -- cgit v1.2.1