41054-Disallow creation of new Kubernetes integrations
This commit is contained in:
parent
0e7e9e32b3
commit
e028d795c4
18 changed files with 244 additions and 14 deletions
|
@ -268,3 +268,7 @@
|
|||
margin: 0 0 5px 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.deprecated-service {
|
||||
cursor: default;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <a href=\'#{Gitlab::Routing.url_helpers.project_clusters_path(project)}'/>Clusters</a> 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.flash-container.flash-container-page
|
||||
.flash-alert.deprecated-service
|
||||
%span= @service.deprecation_message
|
|
@ -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?
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -18,6 +18,7 @@ FactoryBot.define do
|
|||
|
||||
factory :kubernetes_service do
|
||||
project
|
||||
type 'KubernetesService'
|
||||
active true
|
||||
properties({
|
||||
api_url: 'https://kubernetes.example.com',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue