summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzcinski <ayufan@ayufan.eu>2017-11-01 13:56:27 +0100
committerKamil Trzcinski <ayufan@ayufan.eu>2017-11-01 13:58:08 +0100
commit1427bdcadf5f4026d141a5c4e93db8b1b00fe40a (patch)
tree2a7fe415bce79a87bccc154a68b30ea7d45add48
parentccf09824f6d3ef41db4be3b40aa99b6dfd0dc9ac (diff)
downloadgitlab-ce-1427bdcadf5f4026d141a5c4e93db8b1b00fe40a.tar.gz
Revert back FetchKubernetesTokenService
-rw-r--r--app/controllers/projects/clusters_controller.rb1
-rw-r--r--app/models/clusters/cluster.rb2
-rw-r--r--app/models/clusters/platforms/kubernetes.rb8
-rw-r--r--app/services/ci/fetch_kubernetes_token_service.rb72
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb35
-rw-r--r--app/views/projects/clusters/_form.html.haml8
-rw-r--r--db/migrate/20171013094327_create_new_clusters_architectures.rb4
-rw-r--r--db/schema.rb4
-rw-r--r--spec/services/ci/fetch_kubernetes_token_service_spec.rb64
9 files changed, 156 insertions, 42 deletions
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index 0f35b4f9c21..7570da3e0b1 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -29,7 +29,6 @@ class Projects::ClustersController < Projects::ApplicationController
def new
@cluster = Clusters::Cluster.new.tap do |cluster|
cluster.build_provider_gcp
- cluster.build_platform_kubernetes
end
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index a3f6d20ba43..ca09b939f34 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -18,8 +18,6 @@ module Clusters
accepts_nested_attributes_for :provider_gcp, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
- validates :provider_type, presence: true
- validates :platform_type, presence: true
validates :name, cluster_name: true
validate :restrict_modification, on: :update
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 4c3e270892e..3ad2ffe531d 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -28,7 +28,7 @@ module Clusters
}
# We expect to be `active?` only when enabled and cluster is created (the api_url is assigned)
- with_options presence: true, if: :active? do
+ with_options presence: true, if: :enabled? do
validates :api_url, url: true, presence: true
validates :token, presence: true
end
@@ -42,10 +42,6 @@ module Clusters
delegate :project, to: :cluster, allow_nil: true
delegate :enabled?, to: :cluster, allow_nil: true
- def active?
- enabled? && api_url.present?
- end
-
class << self
def namespace_for_project(project)
"#{project.path}-#{project.id}"
@@ -87,7 +83,7 @@ module Clusters
return raise 'Kubernetes service already configured' unless manages_kubernetes_service?
ensure_kubernetes_service.update!(
- active: active?,
+ active: enabled?,
api_url: api_url,
namespace: namespace,
token: token,
diff --git a/app/services/ci/fetch_kubernetes_token_service.rb b/app/services/ci/fetch_kubernetes_token_service.rb
new file mode 100644
index 00000000000..44da87cb00c
--- /dev/null
+++ b/app/services/ci/fetch_kubernetes_token_service.rb
@@ -0,0 +1,72 @@
+##
+# TODO:
+# Almost components in this class were copied from app/models/project_services/kubernetes_service.rb
+# We should dry up those classes not to repeat the same code.
+# Maybe we should have a special facility (e.g. lib/kubernetes_api) to maintain all Kubernetes API caller.
+module Ci
+ class FetchKubernetesTokenService
+ attr_reader :api_url, :ca_pem, :username, :password
+
+ def initialize(api_url, ca_pem, username, password)
+ @api_url = api_url
+ @ca_pem = ca_pem
+ @username = username
+ @password = password
+ end
+
+ def execute
+ read_secrets.each do |secret|
+ name = secret.dig('metadata', 'name')
+ if /default-token/ =~ name
+ token_base64 = secret.dig('data', 'token')
+ return Base64.decode64(token_base64) if token_base64
+ end
+ end
+
+ nil
+ end
+
+ private
+
+ def read_secrets
+ kubeclient = build_kubeclient!
+
+ kubeclient.get_secrets.as_json
+ rescue KubeException => err
+ raise err unless err.error_code == 404
+ []
+ end
+
+ def build_kubeclient!(api_path: 'api', api_version: 'v1')
+ raise "Incomplete settings" unless api_url && username && password
+
+ ::Kubeclient::Client.new(
+ join_api_url(api_path),
+ api_version,
+ auth_options: { username: username, password: password },
+ ssl_options: kubeclient_ssl_options,
+ http_proxy_uri: ENV['http_proxy']
+ )
+ end
+
+ def join_api_url(api_path)
+ url = URI.parse(api_url)
+ prefix = url.path.sub(%r{/+\z}, '')
+
+ url.path = [prefix, api_path].join("/")
+
+ url.to_s
+ end
+
+ def kubeclient_ssl_options
+ opts = { verify_ssl: OpenSSL::SSL::VERIFY_PEER }
+
+ if ca_pem.present?
+ opts[:cert_store] = OpenSSL::X509::Store.new
+ opts[:cert_store].add_cert(OpenSSL::X509::Certificate.new(ca_pem))
+ end
+
+ opts
+ end
+ end
+end
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index d379870924a..53b13518771 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -9,10 +9,7 @@ module Clusters
configure_provider
configure_kubernetes
- ActiveRecord::Base.transaction do
- kubernetes.save!
- provider.make_created!
- end
+ provider.make_created!
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
rescue KubeException => e
@@ -28,23 +25,21 @@ module Clusters
end
def configure_kubernetes
- kubernetes.api_url = 'https://' + gke_cluster.endpoint
- kubernetes.ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
- kubernetes.username = gke_cluster.master_auth.username
- kubernetes.password = gke_cluster.master_auth.password
- kubernetes.token = request_kuberenetes_token
+ cluster.platform_type = :kubernetes
+ cluster.build_platform_kubernetes(
+ api_url: 'https://' + gke_cluster.endpoint,
+ ca_cert: Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
+ username: gke_cluster.master_auth.username,
+ password: gke_cluster.master_auth.password,
+ token: request_kuberenetes_token)
end
def request_kuberenetes_token
- kubernetes.read_secrets.each do |secret|
- name = secret.dig('metadata', 'name')
- if /default-token/ =~ name
- token_base64 = secret.dig('data', 'token')
- return Base64.decode64(token_base64) if token_base64
- end
- end
-
- nil
+ Ci::FetchKubernetesTokenService.new(
+ 'https://' + gke_cluster.endpoint,
+ Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
+ gke_cluster.master_auth.username,
+ gke_cluster.master_auth.password)
end
def gke_cluster
@@ -57,10 +52,6 @@ module Clusters
def cluster
@cluster ||= provider.cluster
end
-
- def kubernetes
- @kubernetes ||= cluster.platform_kubernetes
- end
end
end
end
diff --git a/app/views/projects/clusters/_form.html.haml b/app/views/projects/clusters/_form.html.haml
index 6b9f63b7515..d8e5b55bb88 100644
--- a/app/views/projects/clusters/_form.html.haml
+++ b/app/views/projects/clusters/_form.html.haml
@@ -5,8 +5,7 @@
= s_('ClusterIntegration|Read our %{link_to_help_page} on cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
= form_for @cluster, url: namespace_project_clusters_path(@project.namespace, @project, @cluster), as: :cluster do |field|
- = field.hidden_field :platform_type, :value => 'kubernetes'
- = field.hidden_field :provider_type, :value => 'gcp'
+ = field.hidden_field :provider_type, value: :gcp
= form_errors(@cluster)
.form-group
= field.label :name, s_('ClusterIntegration|Cluster name')
@@ -32,10 +31,5 @@
= link_to(s_('ClusterIntegration|See machine types'), 'https://cloud.google.com/compute/docs/machine-types', target: '_blank', rel: 'noopener noreferrer')
= provider_gcp_field.text_field :machine_type, class: 'form-control', placeholder: 'n1-standard-4'
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: Clusters::Platforms::Kubernetes.namespace_for_project(@project)
-
.form-group
= field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
diff --git a/db/migrate/20171013094327_create_new_clusters_architectures.rb b/db/migrate/20171013094327_create_new_clusters_architectures.rb
index a212288f859..b196aa1949c 100644
--- a/db/migrate/20171013094327_create_new_clusters_architectures.rb
+++ b/db/migrate/20171013094327_create_new_clusters_architectures.rb
@@ -5,8 +5,8 @@ class CreateNewClustersArchitectures < ActiveRecord::Migration
create_table :clusters do |t|
t.references :user, null: false, index: true, foreign_key: { on_delete: :nullify }
- t.integer :provider_type, null: false
- t.integer :platform_type, null: false
+ t.integer :provider_type
+ t.integer :platform_type
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
diff --git a/db/schema.rb b/db/schema.rb
index 24f2d4b439c..d76977d45f2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -508,8 +508,8 @@ ActiveRecord::Schema.define(version: 20171017145932) do
create_table "clusters", force: :cascade do |t|
t.integer "user_id", null: false
- t.integer "provider_type", null: false
- t.integer "platform_type", null: false
+ t.integer "provider_type"
+ t.integer "platform_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "enabled", default: true
diff --git a/spec/services/ci/fetch_kubernetes_token_service_spec.rb b/spec/services/ci/fetch_kubernetes_token_service_spec.rb
new file mode 100644
index 00000000000..1d05c9671a9
--- /dev/null
+++ b/spec/services/ci/fetch_kubernetes_token_service_spec.rb
@@ -0,0 +1,64 @@
+require 'spec_helper'
+
+describe Ci::FetchKubernetesTokenService do
+ describe '#execute' do
+ subject { described_class.new(api_url, ca_pem, username, password).execute }
+
+ let(:api_url) { 'http://111.111.111.111' }
+ let(:ca_pem) { '' }
+ let(:username) { 'admin' }
+ let(:password) { 'xxx' }
+
+ context 'when params correct' do
+ let(:token) { 'xxx.token.xxx' }
+
+ let(:secrets_json) do
+ [
+ {
+ 'metadata': {
+ name: metadata_name
+ },
+ 'data': {
+ 'token': Base64.encode64(token)
+ }
+ }
+ ]
+ end
+
+ before do
+ allow_any_instance_of(Kubeclient::Client)
+ .to receive(:get_secrets).and_return(secrets_json)
+ end
+
+ context 'when default-token exists' do
+ let(:metadata_name) { 'default-token-123' }
+
+ it { is_expected.to eq(token) }
+ end
+
+ context 'when default-token does not exist' do
+ let(:metadata_name) { 'another-token-123' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'when api_url is nil' do
+ let(:api_url) { nil }
+
+ it { expect { subject }.to raise_error("Incomplete settings") }
+ end
+
+ context 'when username is nil' do
+ let(:username) { nil }
+
+ it { expect { subject }.to raise_error("Incomplete settings") }
+ end
+
+ context 'when password is nil' do
+ let(:password) { nil }
+
+ it { expect { subject }.to raise_error("Incomplete settings") }
+ end
+ end
+end