Revert back FetchKubernetesTokenService
This commit is contained in:
parent
ccf09824f6
commit
1427bdcadf
|
@ -29,7 +29,6 @@ class Projects::ClustersController < Projects::ApplicationController
|
||||||
def new
|
def new
|
||||||
@cluster = Clusters::Cluster.new.tap do |cluster|
|
@cluster = Clusters::Cluster.new.tap do |cluster|
|
||||||
cluster.build_provider_gcp
|
cluster.build_provider_gcp
|
||||||
cluster.build_platform_kubernetes
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@ module Clusters
|
||||||
accepts_nested_attributes_for :provider_gcp, update_only: true
|
accepts_nested_attributes_for :provider_gcp, update_only: true
|
||||||
accepts_nested_attributes_for :platform_kubernetes, 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
|
validates :name, cluster_name: true
|
||||||
validate :restrict_modification, on: :update
|
validate :restrict_modification, on: :update
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ module Clusters
|
||||||
}
|
}
|
||||||
|
|
||||||
# We expect to be `active?` only when enabled and cluster is created (the api_url is assigned)
|
# 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 :api_url, url: true, presence: true
|
||||||
validates :token, presence: true
|
validates :token, presence: true
|
||||||
end
|
end
|
||||||
|
@ -42,10 +42,6 @@ module Clusters
|
||||||
delegate :project, to: :cluster, allow_nil: true
|
delegate :project, to: :cluster, allow_nil: true
|
||||||
delegate :enabled?, to: :cluster, allow_nil: true
|
delegate :enabled?, to: :cluster, allow_nil: true
|
||||||
|
|
||||||
def active?
|
|
||||||
enabled? && api_url.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def namespace_for_project(project)
|
def namespace_for_project(project)
|
||||||
"#{project.path}-#{project.id}"
|
"#{project.path}-#{project.id}"
|
||||||
|
@ -87,7 +83,7 @@ module Clusters
|
||||||
return raise 'Kubernetes service already configured' unless manages_kubernetes_service?
|
return raise 'Kubernetes service already configured' unless manages_kubernetes_service?
|
||||||
|
|
||||||
ensure_kubernetes_service.update!(
|
ensure_kubernetes_service.update!(
|
||||||
active: active?,
|
active: enabled?,
|
||||||
api_url: api_url,
|
api_url: api_url,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
token: token,
|
token: token,
|
||||||
|
|
|
@ -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
|
|
@ -9,10 +9,7 @@ module Clusters
|
||||||
configure_provider
|
configure_provider
|
||||||
configure_kubernetes
|
configure_kubernetes
|
||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
provider.make_created!
|
||||||
kubernetes.save!
|
|
||||||
provider.make_created!
|
|
||||||
end
|
|
||||||
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||||
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
|
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
|
||||||
rescue KubeException => e
|
rescue KubeException => e
|
||||||
|
@ -28,23 +25,21 @@ module Clusters
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_kubernetes
|
def configure_kubernetes
|
||||||
kubernetes.api_url = 'https://' + gke_cluster.endpoint
|
cluster.platform_type = :kubernetes
|
||||||
kubernetes.ca_cert = Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate)
|
cluster.build_platform_kubernetes(
|
||||||
kubernetes.username = gke_cluster.master_auth.username
|
api_url: 'https://' + gke_cluster.endpoint,
|
||||||
kubernetes.password = gke_cluster.master_auth.password
|
ca_cert: Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
|
||||||
kubernetes.token = request_kuberenetes_token
|
username: gke_cluster.master_auth.username,
|
||||||
|
password: gke_cluster.master_auth.password,
|
||||||
|
token: request_kuberenetes_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_kuberenetes_token
|
def request_kuberenetes_token
|
||||||
kubernetes.read_secrets.each do |secret|
|
Ci::FetchKubernetesTokenService.new(
|
||||||
name = secret.dig('metadata', 'name')
|
'https://' + gke_cluster.endpoint,
|
||||||
if /default-token/ =~ name
|
Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
|
||||||
token_base64 = secret.dig('data', 'token')
|
gke_cluster.master_auth.username,
|
||||||
return Base64.decode64(token_base64) if token_base64
|
gke_cluster.master_auth.password)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def gke_cluster
|
def gke_cluster
|
||||||
|
@ -57,10 +52,6 @@ module Clusters
|
||||||
def cluster
|
def cluster
|
||||||
@cluster ||= provider.cluster
|
@cluster ||= provider.cluster
|
||||||
end
|
end
|
||||||
|
|
||||||
def kubernetes
|
|
||||||
@kubernetes ||= cluster.platform_kubernetes
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -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}
|
= 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|
|
= 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_errors(@cluster)
|
||||||
.form-group
|
.form-group
|
||||||
= field.label :name, s_('ClusterIntegration|Cluster name')
|
= 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')
|
= 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'
|
= 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
|
.form-group
|
||||||
= field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
|
= field.submit s_('ClusterIntegration|Create cluster'), class: 'btn btn-save'
|
||||||
|
|
|
@ -5,8 +5,8 @@ class CreateNewClustersArchitectures < ActiveRecord::Migration
|
||||||
create_table :clusters do |t|
|
create_table :clusters do |t|
|
||||||
t.references :user, null: false, index: true, foreign_key: { on_delete: :nullify }
|
t.references :user, null: false, index: true, foreign_key: { on_delete: :nullify }
|
||||||
|
|
||||||
t.integer :provider_type, null: false
|
t.integer :provider_type
|
||||||
t.integer :platform_type, null: false
|
t.integer :platform_type
|
||||||
|
|
||||||
t.datetime_with_timezone :created_at, null: false
|
t.datetime_with_timezone :created_at, null: false
|
||||||
t.datetime_with_timezone :updated_at, null: false
|
t.datetime_with_timezone :updated_at, null: false
|
||||||
|
|
|
@ -508,8 +508,8 @@ ActiveRecord::Schema.define(version: 20171017145932) do
|
||||||
|
|
||||||
create_table "clusters", force: :cascade do |t|
|
create_table "clusters", force: :cascade do |t|
|
||||||
t.integer "user_id", null: false
|
t.integer "user_id", null: false
|
||||||
t.integer "provider_type", null: false
|
t.integer "provider_type"
|
||||||
t.integer "platform_type", null: false
|
t.integer "platform_type"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.boolean "enabled", default: true
|
t.boolean "enabled", default: true
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue