Commit bbf639c4 authored by James Lopez's avatar James Lopez

Merge branch '39217-remove-kubernetes-service-integration' into 'master'

Remove KubernetesService integration

See merge request gitlab-org/gitlab-ce!31365
parents a5771230 e3696bf2
...@@ -39,7 +39,7 @@ module ServicesHelper ...@@ -39,7 +39,7 @@ module ServicesHelper
end end
def disable_fields_service?(service) def disable_fields_service?(service)
service.is_a?(KubernetesService) || (!current_controller?("admin/services") && service.deprecated?) !current_controller?("admin/services") && service.deprecated?
end end
extend self extend self
......
...@@ -162,7 +162,6 @@ class Project < ApplicationRecord ...@@ -162,7 +162,6 @@ class Project < ApplicationRecord
has_one :bugzilla_service has_one :bugzilla_service
has_one :gitlab_issue_tracker_service, inverse_of: :project has_one :gitlab_issue_tracker_service, inverse_of: :project
has_one :external_wiki_service has_one :external_wiki_service
has_one :kubernetes_service, inverse_of: :project
has_one :prometheus_service, inverse_of: :project has_one :prometheus_service, inverse_of: :project
has_one :mock_ci_service has_one :mock_ci_service
has_one :mock_deployment_service has_one :mock_deployment_service
......
# frozen_string_literal: true
class KubernetesService < Service
default_value_for :category, 'deployment'
# Namespace defaults to the project path, but can be overridden in case that
# is an invalid or inappropriate name
prop_accessor :namespace
# Access to kubernetes is directly through the API
prop_accessor :api_url
# Bearer authentication
# TODO: user/password auth, client certificates
prop_accessor :token
# Provide a custom CA bundle for self-signed deployments
prop_accessor :ca_pem
with_options presence: true, if: :activated? do
validates :api_url, public_url: true
validates :token
end
before_validation :enforce_namespace_to_lower_case
attr_accessor :skip_deprecation_validation
validate :deprecation_validation, unless: :skip_deprecation_validation
validates :namespace,
allow_blank: true,
length: 1..63,
if: :activated?,
format: {
with: Gitlab::Regex.kubernetes_namespace_regex,
message: Gitlab::Regex.kubernetes_namespace_regex_message
}
def self.supported_events
%w()
end
def can_test?
false
end
def initialize_properties
self.properties = {} if properties.nil?
end
def title
'Kubernetes'
end
def description
'Kubernetes / OpenShift integration'
end
def self.to_param
'kubernetes'
end
def fields
[
{ type: 'text',
name: 'api_url',
title: 'API URL',
placeholder: 'Kubernetes API URL, like https://kube.example.com/' },
{ type: 'textarea',
name: 'ca_pem',
title: 'CA Certificate',
placeholder: 'Certificate Authority bundle (PEM format)' },
{ type: 'text',
name: 'namespace',
title: 'Project namespace (optional/unique)',
placeholder: namespace_placeholder },
{ type: 'text',
name: 'token',
title: 'Token',
placeholder: 'Service token' }
]
end
def deprecated?
true
end
def editable?
false
end
def deprecation_message
content = if project
_("Kubernetes service integration has been disabled. Fields on this page are not used by GitLab, you can configure your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page") % {
url: Gitlab::Routing.url_helpers.project_clusters_path(project)
}
else
_("The instance-level Kubernetes service integration is disabled. Your data has been migrated to an <a href=\"%{url}\"/>instance-level cluster</a>.") % {
url: Gitlab::Routing.url_helpers.admin_clusters_path
}
end
content.html_safe
end
TEMPLATE_PLACEHOLDER = 'Kubernetes namespace'.freeze
private
def namespace_placeholder
default_namespace || TEMPLATE_PLACEHOLDER
end
def default_namespace
return unless project
slug = "#{project.path}-#{project.id}".downcase
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
end
def enforce_namespace_to_lower_case
self.namespace = self.namespace&.downcase
end
def deprecation_validation
return if active_changed?(from: true, to: false) || (new_record? && !active?)
if deprecated?
errors[:base] << deprecation_message
end
end
end
...@@ -260,7 +260,6 @@ class Service < ApplicationRecord ...@@ -260,7 +260,6 @@ class Service < ApplicationRecord
hipchat hipchat
irker irker
jira jira
kubernetes
mattermost_slash_commands mattermost_slash_commands
mattermost mattermost
packagist packagist
......
...@@ -6,6 +6,5 @@ ...@@ -6,6 +6,5 @@
= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form' } do |form| = form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form' } do |form|
= render 'shared/service_settings', form: form, subject: @service = render 'shared/service_settings', form: form, subject: @service
- unless @service.is_a?(KubernetesService) .footer-block.row-content-block
.footer-block.row-content-block = form.submit 'Save', class: 'btn btn-success'
= form.submit 'Save', class: 'btn btn-success'
---
title: Remove Kubernetes service integration page
merge_request: 31365
author:
type: removed
# frozen_string_literal: true
class DeleteKubernetesServices < ActiveRecord::Migration[5.2]
DOWNTIME = false
def up
Service.where(type: "KubernetesService").delete_all
end
def down
# no-op
end
end
...@@ -595,44 +595,6 @@ Remove all previously Jira settings from a project. ...@@ -595,44 +595,6 @@ Remove all previously Jira settings from a project.
DELETE /projects/:id/services/jira DELETE /projects/:id/services/jira
``` ```
## Kubernetes
Kubernetes / OpenShift integration
CAUTION: **Warning:**
Kubernetes service integration has been deprecated in GitLab 10.3. API service endpoints will continue to work as long as the Kubernetes service is active, however if the service is inactive API endpoints will automatically return a `400 Bad Request`. Read [GitLab 10.3 release post](https://about.gitlab.com/2017/12/22/gitlab-10-3-released/#kubernetes-integration-service) for more information.
### Create/Edit Kubernetes service
Set Kubernetes service for a project.
```
PUT /projects/:id/services/kubernetes
```
Parameters:
- `namespace` (**required**) - The Kubernetes namespace to use
- `api_url` (**required**) - The URL to the Kubernetes cluster API. For example, `https://kubernetes.example.com`
- `token` (**required**) - The service token to authenticate against the Kubernetes cluster with
- `ca_pem` (optional) - A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)
### Delete Kubernetes service
Delete Kubernetes service for a project.
```
DELETE /projects/:id/services/kubernetes
```
### Get Kubernetes service settings
Get Kubernetes service settings for a project.
```
GET /projects/:id/services/kubernetes
```
## Slack slash commands ## Slack slash commands
Ability to receive slash commands from a Slack chat instance. Ability to receive slash commands from a Slack chat instance.
......
...@@ -489,32 +489,6 @@ module API ...@@ -489,32 +489,6 @@ module API
desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`' desc: 'The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`'
} }
], ],
'kubernetes' => [
{
required: true,
name: :namespace,
type: String,
desc: 'The Kubernetes namespace to use'
},
{
required: true,
name: :api_url,
type: String,
desc: 'The URL to the Kubernetes cluster API, e.g., https://kubernetes.example.com'
},
{
required: true,
name: :token,
type: String,
desc: 'The service token to authenticate against the Kubernetes cluster with'
},
{
required: false,
name: :ca_pem,
type: String,
desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)'
}
],
'mattermost-slash-commands' => [ 'mattermost-slash-commands' => [
{ {
required: true, required: true,
...@@ -739,7 +713,6 @@ module API ...@@ -739,7 +713,6 @@ module API
::HipchatService, ::HipchatService,
::IrkerService, ::IrkerService,
::JiraService, ::JiraService,
::KubernetesService,
::MattermostSlashCommandsService, ::MattermostSlashCommandsService,
::SlackSlashCommandsService, ::SlackSlashCommandsService,
::PackagistService, ::PackagistService,
......
...@@ -6171,9 +6171,6 @@ msgstr "" ...@@ -6171,9 +6171,6 @@ msgstr ""
msgid "Kubernetes error: %{error_code}" msgid "Kubernetes error: %{error_code}"
msgstr "" msgstr ""
msgid "Kubernetes service integration has been disabled. Fields on this page are not used by GitLab, you can configure your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr ""
msgid "LDAP" msgid "LDAP"
msgstr "" msgstr ""
...@@ -10942,9 +10939,6 @@ msgstr "" ...@@ -10942,9 +10939,6 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination." msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "" msgstr ""
msgid "The instance-level Kubernetes service integration is disabled. Your data has been migrated to an <a href=\"%{url}\"/>instance-level cluster</a>."
msgstr ""
msgid "The invitation could not be accepted." msgid "The invitation could not be accepted."
msgstr "" msgstr ""
......
...@@ -325,10 +325,6 @@ FactoryBot.define do ...@@ -325,10 +325,6 @@ FactoryBot.define do
jira_service jira_service
end end
factory :kubernetes_project, parent: :project do
kubernetes_service
end
factory :mock_deployment_project, parent: :project do factory :mock_deployment_project, parent: :project do
mock_deployment_service mock_deployment_service
end end
......
...@@ -16,18 +16,6 @@ FactoryBot.define do ...@@ -16,18 +16,6 @@ FactoryBot.define do
) )
end end
factory :kubernetes_service do
project
type 'KubernetesService'
active true
properties({
api_url: 'https://kubernetes.example.com',
token: 'a' * 40
})
skip_deprecation_validation true
end
factory :mock_deployment_service do factory :mock_deployment_service do
project project
type 'MockDeploymentService' type 'MockDeploymentService'
......
...@@ -277,7 +277,6 @@ project: ...@@ -277,7 +277,6 @@ project:
- bugzilla_service - bugzilla_service
- gitlab_issue_tracker_service - gitlab_issue_tracker_service
- external_wiki_service - external_wiki_service
- kubernetes_service
- mock_ci_service - mock_ci_service
- mock_deployment_service - mock_deployment_service
- mock_monitoring_service - mock_monitoring_service
......
# frozen_string_literal: true
require 'spec_helper'
describe KubernetesService, :use_clean_rails_memory_store_caching do
include KubernetesHelpers
include ReactiveCachingHelpers
let(:project) { create(:kubernetes_project) }
let(:service) { create(:kubernetes_service, project: project) }
describe 'Associations' do
it { is_expected.to belong_to :project }
end
describe 'Validations' do
context 'when service is active' do
before do
subject.active = true
subject.skip_deprecation_validation = true
end
it { is_expected.not_to validate_presence_of(:namespace) }
it { is_expected.to validate_presence_of(:api_url) }
it { is_expected.to validate_presence_of(:token) }
context 'namespace format' do
before do
subject.project = project
subject.api_url = "http://example.com"
subject.token = "test"
end
{
'foo' => true,
'1foo' => true,
'foo1' => true,
'foo-bar' => true,
'-foo' => false,
'foo-' => false,
'a' * 63 => true,
'a' * 64 => false,
'a.b' => false,
'a*b' => false,
'FOO' => true
}.each do |namespace, validity|
it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do
subject.namespace = namespace
expect(subject.valid?).to eq(validity)
end
end
end
end
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.skip_deprecation_validation = false
kubernetes_service.properties['namespace'] = "foo"
end
it 'does not update attributes' do
expect(kubernetes_service.save).to be_falsy
end
it 'includes an error with a deprecation message' do
kubernetes_service.valid?
expect(kubernetes_service.errors[:base].first).to match(/Kubernetes service integration has been disabled/)
end
end
context 'with an active and deprecated service' do
let(:kubernetes_service) { create(:kubernetes_service) }
before do
kubernetes_service.skip_deprecation_validation = false
kubernetes_service.active = false
kubernetes_service.properties['namespace'] = 'foo'
kubernetes_service.save
end
it 'deactivates the service' do
expect(kubernetes_service.active?).to be_falsy
end
it 'does not include a deprecation message as error' do
expect(kubernetes_service.errors.messages.count).to eq(0)
end
it 'updates attributes' do
expect(kubernetes_service.properties['namespace']).to eq("foo")
end
end
end
describe '#initialize_properties' do
context 'without a project' do
it 'leaves the namespace unset' do
expect(described_class.new.namespace).to be_nil
end
end
end
describe '#fields' do
let(:kube_namespace) do
subject.fields.find { |h| h[:name] == 'namespace' }
end
context 'as template' do
before do
subject.template = true
end
it 'sets the namespace to the default' do
expect(kube_namespace).not_to be_nil
expect(kube_namespace[:placeholder]).to eq(subject.class::TEMPLATE_PLACEHOLDER)
end
end
context 'with associated project' do
before do
subject.project = project
end
it 'sets the namespace to the default' do
expect(kube_namespace).not_to be_nil
expect(kube_namespace[:placeholder]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
end
end
end
describe "#deprecated?" do
let(:kubernetes_service) { create(:kubernetes_service) }
it 'returns true' do
expect(kubernetes_service.deprecated?).to be_truthy
end
end
describe "#deprecation_message" do
let(:kubernetes_service) { create(:kubernetes_service) }
it 'indicates the service is deprecated' do
expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been disabled/)
end
context 'if the service is not active' do
it 'returns a message' do
kubernetes_service.update_attribute(:active, false)
expect(kubernetes_service.deprecation_message).to match(/Fields on this page are not used by GitLab/)
end
end
end
end
...@@ -10,10 +10,7 @@ describe API::Services do ...@@ -10,10 +10,7 @@ describe API::Services do
end end
Service.available_services_names.each do |service| Service.available_services_names.each do |service|
# TODO: Remove below `if: (service != "kubernetes")` in the next release describe "PUT /projects/:id/services/#{service.dasherize}" do
# KubernetesService was deprecated and it can't be updated. Right now it's
# only readable. It should be completely removed in the next iteration.
describe "PUT /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service include_context service
it "updates #{service} settings" do it "updates #{service} settings" do
...@@ -62,10 +59,7 @@ describe API::Services do ...@@ -62,10 +59,7 @@ describe API::Services do
end end
end end
# TODO: Remove below `if: (service != "kubernetes")` in the next release describe "DELETE /projects/:id/services/#{service.dasherize}" do
# KubernetesService was deprecated and it can't be updated. Right now it's
# only readable. It should be completely removed in the next iteration.
describe "DELETE /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service include_context service
before do before do
......
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