specs for services. Improved details.
This commit is contained in:
parent
478e59fe8d
commit
d6744d9838
|
@ -13,7 +13,7 @@ module Clusters
|
|||
has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes'
|
||||
|
||||
accepts_nested_attributes_for :provider_gcp
|
||||
accepts_nested_attributes_for :platform_kubernetes
|
||||
accepts_nested_attributes_for :platform_kubernetes, update_only: true
|
||||
|
||||
validates :name, cluster_name: true
|
||||
validate :restrict_modification, on: :update
|
||||
|
|
|
@ -111,9 +111,6 @@ module Clusters
|
|||
kubeclient = build_kubeclient!
|
||||
|
||||
kubeclient.get_secrets.as_json
|
||||
rescue KubeException => err
|
||||
raise err unless err.error_code == 404
|
||||
[]
|
||||
end
|
||||
|
||||
# Returns a hash of all pods in the namespace
|
||||
|
|
|
@ -14,9 +14,11 @@ module Clusters
|
|||
provider.make_created!
|
||||
end
|
||||
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
|
||||
cluster.make_errored!("Failed to request to CloudPlatform; #{e.message}")
|
||||
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
|
||||
rescue KubeException => e
|
||||
provider.make_errored!("Failed to request to Kubernetes; #{e.message}")
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
cluster.make_errored!("Failed to configure GKE Cluster: #{e.message}")
|
||||
provider.make_errored!("Failed to configure GKE Cluster: #{e.message}")
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -41,6 +43,8 @@ module Clusters
|
|||
return Base64.decode64(token_base64) if token_base64
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def gke_cluster
|
||||
|
|
|
@ -14,13 +14,19 @@ FactoryGirl.define do
|
|||
trait :provided_by_user do
|
||||
provider_type :user
|
||||
platform_type :kubernetes
|
||||
platform_kubernetes
|
||||
|
||||
platform_kubernetes do
|
||||
create(:platform_kubernetes, :configured)
|
||||
end
|
||||
end
|
||||
|
||||
trait :provided_by_gcp do
|
||||
provider_type :gcp
|
||||
platform_type :kubernetes
|
||||
platform_kubernetes
|
||||
|
||||
platform_kubernetes do
|
||||
create(:platform_kubernetes, :configured)
|
||||
end
|
||||
|
||||
provider_gcp do
|
||||
create(:provider_gcp, :created)
|
||||
|
@ -34,6 +40,10 @@ FactoryGirl.define do
|
|||
provider_gcp do
|
||||
create(:provider_gcp, :creating)
|
||||
end
|
||||
|
||||
after(:create) do |cluster, evaluator|
|
||||
create(:platform_kubernetes, cluster: cluster)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
FactoryGirl.define do
|
||||
factory :platform_kubernetes, class: Clusters::Platforms::Kubernetes do
|
||||
cluster
|
||||
api_url 'https://kubernetes.example.com'
|
||||
ca_cert nil
|
||||
token 'a' * 40
|
||||
username 'xxxxxx'
|
||||
password 'xxxxxx'
|
||||
namespace nil
|
||||
|
||||
trait :ca_cert do
|
||||
|
@ -14,5 +9,13 @@ FactoryGirl.define do
|
|||
platform_kubernetes.ca_cert = File.read(pem_file)
|
||||
end
|
||||
end
|
||||
|
||||
trait :configured do
|
||||
api_url 'https://kubernetes.example.com'
|
||||
ca_cert nil
|
||||
token 'a' * 40
|
||||
username 'xxxxxx'
|
||||
password 'xxxxxx'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,6 +3,10 @@ FactoryGirl.define do
|
|||
cluster
|
||||
gcp_project_id 'test-gcp-project'
|
||||
|
||||
trait :scheduled do
|
||||
access_token 'access_token_123'
|
||||
end
|
||||
|
||||
trait :creating do
|
||||
access_token 'access_token_123'
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::CreateClusterService do
|
||||
describe '#execute' do
|
||||
let(:access_token) { 'xxx' }
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
let(:result) { described_class.new(project, user, params).execute(access_token) }
|
||||
|
||||
context 'when correct params' do
|
||||
let(:params) do
|
||||
{
|
||||
gcp_project_id: 'gcp-project',
|
||||
gcp_cluster_name: 'test-cluster',
|
||||
gcp_cluster_zone: 'us-central1-a',
|
||||
gcp_cluster_size: 1
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a cluster object' do
|
||||
expect(ClusterProvisionWorker).to receive(:perform_async)
|
||||
expect { result }.to change { Gcp::Cluster.count }.by(1)
|
||||
expect(result.gcp_project_id).to eq('gcp-project')
|
||||
expect(result.gcp_cluster_name).to eq('test-cluster')
|
||||
expect(result.gcp_cluster_zone).to eq('us-central1-a')
|
||||
expect(result.gcp_cluster_size).to eq(1)
|
||||
expect(result.gcp_token).to eq(access_token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid params' do
|
||||
let(:params) do
|
||||
{
|
||||
gcp_project_id: 'gcp-project',
|
||||
gcp_cluster_name: 'test-cluster',
|
||||
gcp_cluster_zone: 'us-central1-a',
|
||||
gcp_cluster_size: 'ABC'
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns an error' do
|
||||
expect(ClusterProvisionWorker).not_to receive(:perform_async)
|
||||
expect { result }.to change { Gcp::Cluster.count }.by(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,36 +0,0 @@
|
|||
require 'spec_helper'
|
||||
require 'google/apis'
|
||||
|
||||
describe Ci::FetchGcpOperationService do
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:gcp_cluster) }
|
||||
let(:operation) { double }
|
||||
|
||||
context 'when suceeded' do
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_operations).and_return(operation)
|
||||
end
|
||||
|
||||
it 'fetch the gcp operaion' do
|
||||
expect { |b| described_class.new.execute(cluster, &b) }
|
||||
.to yield_with_args(operation)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when raises an error' do
|
||||
let(:error) { Google::Apis::ServerError.new('a') }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_operations).and_raise(error)
|
||||
end
|
||||
|
||||
it 'sets an error to cluster object' do
|
||||
expect { |b| described_class.new.execute(cluster, &b) }
|
||||
.not_to yield_with_args
|
||||
expect(cluster.reload).to be_errored
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,64 +0,0 @@
|
|||
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
|
|
@ -1,61 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::FinalizeClusterCreationService do
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:gcp_cluster) }
|
||||
let(:result) { described_class.new.execute(cluster) }
|
||||
|
||||
context 'when suceeded to get cluster from api' do
|
||||
let(:gke_cluster) { double }
|
||||
|
||||
before do
|
||||
allow(gke_cluster).to receive(:endpoint).and_return('111.111.111.111')
|
||||
allow(gke_cluster).to receive(:master_auth).and_return(spy)
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_clusters_get).and_return(gke_cluster)
|
||||
end
|
||||
|
||||
context 'when suceeded to get kubernetes token' do
|
||||
let(:kubernetes_token) { 'abc' }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(Ci::FetchKubernetesTokenService)
|
||||
.to receive(:execute).and_return(kubernetes_token)
|
||||
end
|
||||
|
||||
it 'executes integration cluster' do
|
||||
expect_any_instance_of(Ci::IntegrateClusterService).to receive(:execute)
|
||||
described_class.new.execute(cluster)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when failed to get kubernetes token' do
|
||||
before do
|
||||
allow_any_instance_of(Ci::FetchKubernetesTokenService)
|
||||
.to receive(:execute).and_return(nil)
|
||||
end
|
||||
|
||||
it 'sets an error to cluster object' do
|
||||
described_class.new.execute(cluster)
|
||||
|
||||
expect(cluster.reload).to be_errored
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when failed to get cluster from api' do
|
||||
let(:error) { Google::Apis::ServerError.new('a') }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_clusters_get).and_raise(error)
|
||||
end
|
||||
|
||||
it 'sets an error to cluster object' do
|
||||
described_class.new.execute(cluster)
|
||||
|
||||
expect(cluster.reload).to be_errored
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,42 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::IntegrateClusterService do
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:gcp_cluster, :custom_project_namespace) }
|
||||
let(:endpoint) { '123.123.123.123' }
|
||||
let(:ca_cert) { 'ca_cert_xxx' }
|
||||
let(:token) { 'token_xxx' }
|
||||
let(:username) { 'username_xxx' }
|
||||
let(:password) { 'password_xxx' }
|
||||
|
||||
before do
|
||||
described_class
|
||||
.new.execute(cluster, endpoint, ca_cert, token, username, password)
|
||||
|
||||
cluster.reload
|
||||
end
|
||||
|
||||
context 'when correct params' do
|
||||
it 'creates a cluster object' do
|
||||
expect(cluster.endpoint).to eq(endpoint)
|
||||
expect(cluster.ca_cert).to eq(ca_cert)
|
||||
expect(cluster.kubernetes_token).to eq(token)
|
||||
expect(cluster.username).to eq(username)
|
||||
expect(cluster.password).to eq(password)
|
||||
expect(cluster.service.active).to be_truthy
|
||||
expect(cluster.service.api_url).to eq(cluster.api_url)
|
||||
expect(cluster.service.ca_pem).to eq(ca_cert)
|
||||
expect(cluster.service.namespace).to eq(cluster.project_namespace)
|
||||
expect(cluster.service.token).to eq(token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid params' do
|
||||
let(:endpoint) { nil }
|
||||
|
||||
it 'sets an error to cluster object' do
|
||||
expect(cluster).to be_errored
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,85 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::ProvisionClusterService do
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:gcp_cluster) }
|
||||
let(:operation) { spy }
|
||||
|
||||
shared_examples 'error' do
|
||||
it 'sets an error to cluster object' do
|
||||
described_class.new.execute(cluster)
|
||||
|
||||
expect(cluster.reload).to be_errored
|
||||
end
|
||||
end
|
||||
|
||||
context 'when suceeded to request provision' do
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_clusters_create).and_return(operation)
|
||||
end
|
||||
|
||||
context 'when operation status is RUNNING' do
|
||||
before do
|
||||
allow(operation).to receive(:status).and_return('RUNNING')
|
||||
end
|
||||
|
||||
context 'when suceeded to parse gcp operation id' do
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:parse_operation_id).and_return('operation-123')
|
||||
end
|
||||
|
||||
context 'when cluster status is scheduled' do
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:parse_operation_id).and_return('operation-123')
|
||||
end
|
||||
|
||||
it 'schedules a worker for status minitoring' do
|
||||
expect(WaitForClusterCreationWorker).to receive(:perform_in)
|
||||
|
||||
described_class.new.execute(cluster)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when cluster status is creating' do
|
||||
before do
|
||||
cluster.make_creating!
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when failed to parse gcp operation id' do
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:parse_operation_id).and_return(nil)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when operation status is others' do
|
||||
before do
|
||||
allow(operation).to receive(:status).and_return('others')
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when failed to request provision' do
|
||||
let(:error) { Google::Apis::ServerError.new('a') }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
|
||||
.to receive(:projects_zones_clusters_create).and_raise(error)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,37 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Ci::UpdateClusterService do
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:gcp_cluster, :created_on_gke, :with_kubernetes_service) }
|
||||
|
||||
before do
|
||||
described_class.new(cluster.project, cluster.user, params).execute(cluster)
|
||||
|
||||
cluster.reload
|
||||
end
|
||||
|
||||
context 'when correct params' do
|
||||
context 'when enabled is true' do
|
||||
let(:params) { { 'enabled' => 'true' } }
|
||||
|
||||
it 'enables cluster and overwrite kubernetes service' do
|
||||
expect(cluster.enabled).to be_truthy
|
||||
expect(cluster.service.active).to be_truthy
|
||||
expect(cluster.service.api_url).to eq(cluster.api_url)
|
||||
expect(cluster.service.ca_pem).to eq(cluster.ca_cert)
|
||||
expect(cluster.service.namespace).to eq(cluster.project_namespace)
|
||||
expect(cluster.service.token).to eq(cluster.kubernetes_token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when enabled is false' do
|
||||
let(:params) { { 'enabled' => 'false' } }
|
||||
|
||||
it 'disables cluster and kubernetes service' do
|
||||
expect(cluster.enabled).to be_falsy
|
||||
expect(cluster.service.active).to be_falsy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,62 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::CreateService do
|
||||
let(:access_token) { 'xxx' }
|
||||
let(:project) { create(:project) }
|
||||
let(:user) { create(:user) }
|
||||
let(:result) { described_class.new(project, user, params).execute(access_token) }
|
||||
|
||||
context 'when correct params' do
|
||||
let(:params) do
|
||||
{
|
||||
name: 'test-cluster',
|
||||
platform_type: :kubernetes,
|
||||
provider_type: :gcp,
|
||||
platform_kubernetes_attributes: {
|
||||
namespace: 'custom-namespace'
|
||||
},
|
||||
provider_gcp_attributes: {
|
||||
gcp_project_id: 'gcp-project',
|
||||
zone: 'us-central1-a',
|
||||
num_nodes: 1,
|
||||
machine_type: 'machine_type-a'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a cluster object and performs a worker' do
|
||||
expect(ClusterProvisionWorker).to receive(:perform_async)
|
||||
expect { result }.to change { Clusters::Cluster.count }.by(1)
|
||||
expect(result.name).to eq('test-cluster')
|
||||
expect(result.user).to eq(user)
|
||||
expect(result.project).to eq(project)
|
||||
expect(result.provider.gcp_project_id).to eq('gcp-project')
|
||||
expect(result.provider.zone).to eq('us-central1-a')
|
||||
expect(result.provider.num_nodes).to eq(1)
|
||||
expect(result.provider.machine_type).to eq('machine_type-a')
|
||||
expect(result.provider.access_token).to eq(access_token)
|
||||
expect(result.platform.namespace).to eq('custom-namespace')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid params' do
|
||||
let(:params) do
|
||||
{
|
||||
name: 'test-cluster',
|
||||
platform_type: :kubernetes,
|
||||
provider_type: :user,
|
||||
provider_gcp_attributes: {
|
||||
gcp_project_id: 'gcp-project',
|
||||
zone: 'us-central1-a',
|
||||
num_nodes: 'ABC'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns an error' do
|
||||
expect(ClusterProvisionWorker).not_to receive(:perform_async)
|
||||
expect { result }.to change { Clusters::Cluster.count }.by(0)
|
||||
expect(result.errors[:"provider_gcp.num_nodes"]).to be_present
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::Gcp::FetchOperationService do
|
||||
include GoogleApi::CloudPlatformHelpers
|
||||
|
||||
describe '#execute' do
|
||||
let(:provider) { create(:provider_gcp, :creating) }
|
||||
let(:gcp_project_id) { provider.gcp_project_id }
|
||||
let(:zone) { provider.zone }
|
||||
let(:operation_id) { provider.operation_id }
|
||||
|
||||
shared_examples 'success' do
|
||||
it 'yields' do
|
||||
expect { |b| described_class.new.execute(provider, &b) }
|
||||
.to yield_with_args
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'error' do
|
||||
it 'sets an error to provider object' do
|
||||
expect { |b| described_class.new.execute(provider, &b) }
|
||||
.not_to yield_with_args
|
||||
expect(provider.reload).to be_errored
|
||||
end
|
||||
end
|
||||
|
||||
context 'when suceeded to fetch operation' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(gcp_project_id, zone, operation_id)
|
||||
end
|
||||
|
||||
it_behaves_like 'success'
|
||||
end
|
||||
|
||||
context 'when Internal Server Error happened' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation_error(gcp_project_id, zone, operation_id)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,110 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::Gcp::FinalizeCreationService do
|
||||
include GoogleApi::CloudPlatformHelpers
|
||||
include KubernetesHelpers
|
||||
|
||||
describe '#execute' do
|
||||
let(:cluster) { create(:cluster, :project, :providing_by_gcp) }
|
||||
let(:provider) { cluster.provider }
|
||||
let(:platform) { cluster.platform }
|
||||
let(:gcp_project_id) { provider.gcp_project_id }
|
||||
let(:zone) { provider.zone }
|
||||
let(:cluster_name) { cluster.name }
|
||||
|
||||
shared_examples 'success' do
|
||||
it 'configures provider and kubernetes' do
|
||||
described_class.new.execute(provider)
|
||||
|
||||
expect(provider).to be_created
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'error' do
|
||||
it 'sets an error to provider object' do
|
||||
described_class.new.execute(provider)
|
||||
|
||||
expect(provider.reload).to be_errored
|
||||
end
|
||||
end
|
||||
|
||||
context 'when suceeded to fetch gke cluster info' do
|
||||
let(:endpoint) { '111.111.111.111' }
|
||||
let(:api_url) { 'https://' + endpoint }
|
||||
let(:username) { 'sample-username' }
|
||||
let(:password) { 'sample-password' }
|
||||
|
||||
before do
|
||||
stub_cloud_platform_get_zone_cluster(
|
||||
gcp_project_id, zone, cluster_name,
|
||||
{
|
||||
endpoint: endpoint,
|
||||
username: username,
|
||||
password: password,
|
||||
}
|
||||
)
|
||||
|
||||
stub_kubeclient_discover(api_url)
|
||||
end
|
||||
|
||||
context 'when suceeded to fetch kuberenetes token' do
|
||||
let(:token) { 'sample-token' }
|
||||
|
||||
before do
|
||||
stub_kubeclient_get_secrets(
|
||||
api_url,
|
||||
{
|
||||
token: Base64.encode64(token)
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'success'
|
||||
|
||||
it 'has corresponded data' do
|
||||
described_class.new.execute(provider)
|
||||
provider.reload
|
||||
platform.reload
|
||||
|
||||
expect(provider.endpoint).to eq(endpoint)
|
||||
expect(platform.api_url).to eq(api_url)
|
||||
expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
|
||||
expect(platform.username).to eq(username)
|
||||
expect(platform.password).to eq(password)
|
||||
expect(platform.token).to eq(token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when default-token is not found' do
|
||||
before do
|
||||
stub_kubeclient_get_secrets(api_url, metadata_name: 'aaaa')
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
|
||||
context 'when token is empty' do
|
||||
before do
|
||||
stub_kubeclient_get_secrets(api_url, token: '')
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
|
||||
context 'when failed to fetch kuberenetes token' do
|
||||
before do
|
||||
stub_kubeclient_get_secrets_error(api_url)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when failed to fetch gke cluster info' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_cluster_error(gcp_project_id, zone, cluster_name)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,69 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::Gcp::ProvisionService do
|
||||
include GoogleApi::CloudPlatformHelpers
|
||||
|
||||
describe '#execute' do
|
||||
let(:provider) { create(:provider_gcp, :scheduled) }
|
||||
let(:gcp_project_id) { provider.gcp_project_id }
|
||||
let(:zone) { provider.zone }
|
||||
|
||||
shared_examples 'success' do
|
||||
it 'schedules a worker for status minitoring' do
|
||||
expect(WaitForClusterCreationWorker).to receive(:perform_in)
|
||||
|
||||
described_class.new.execute(provider)
|
||||
|
||||
expect(provider.reload).to be_creating
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'error' do
|
||||
it 'sets an error to provider object' do
|
||||
described_class.new.execute(provider)
|
||||
|
||||
expect(provider.reload).to be_errored
|
||||
end
|
||||
end
|
||||
|
||||
context 'when suceeded to request provision' do
|
||||
before do
|
||||
stub_cloud_platform_create_cluster(gcp_project_id, zone)
|
||||
end
|
||||
|
||||
it_behaves_like 'success'
|
||||
end
|
||||
|
||||
context 'when operation status is unexpected' do
|
||||
before do
|
||||
stub_cloud_platform_create_cluster(
|
||||
gcp_project_id, zone,
|
||||
{
|
||||
"status": 'unexpected'
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
|
||||
context 'when selfLink is unexpected' do
|
||||
before do
|
||||
stub_cloud_platform_create_cluster(
|
||||
gcp_project_id, zone,
|
||||
{
|
||||
"selfLink": 'unexpected'
|
||||
})
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
|
||||
context 'when Internal Server Error happened' do
|
||||
before do
|
||||
stub_cloud_platform_create_cluster_error(gcp_project_id, zone)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,107 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::Gcp::VerifyProvisionStatusService do
|
||||
include GoogleApi::CloudPlatformHelpers
|
||||
|
||||
describe '#execute' do
|
||||
let(:provider) { create(:provider_gcp, :creating) }
|
||||
let(:gcp_project_id) { provider.gcp_project_id }
|
||||
let(:zone) { provider.zone }
|
||||
let(:operation_id) { provider.operation_id }
|
||||
|
||||
shared_examples 'continue_creation' do
|
||||
it 'schedules a worker for status minitoring' do
|
||||
expect(WaitForClusterCreationWorker).to receive(:perform_in)
|
||||
|
||||
described_class.new.execute(provider)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'finalize_creation' do
|
||||
it 'schedules a worker for status minitoring' do
|
||||
expect_any_instance_of(Clusters::Gcp::FinalizeCreationService).to receive(:execute)
|
||||
|
||||
described_class.new.execute(provider)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'error' do
|
||||
it 'sets an error to provider object' do
|
||||
described_class.new.execute(provider)
|
||||
|
||||
expect(provider.reload).to be_errored
|
||||
end
|
||||
end
|
||||
|
||||
context 'when operation status is RUNNING' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(
|
||||
gcp_project_id, zone, operation_id,
|
||||
{
|
||||
"status": 'RUNNING',
|
||||
"startTime": 1.minute.ago.strftime("%FT%TZ")
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'continue_creation'
|
||||
|
||||
context 'when cluster creation time exceeds timeout' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(
|
||||
gcp_project_id, zone, operation_id,
|
||||
{
|
||||
"status": 'RUNNING',
|
||||
"startTime": 30.minutes.ago.strftime("%FT%TZ")
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when operation status is PENDING' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(
|
||||
gcp_project_id, zone, operation_id,
|
||||
{
|
||||
"status": 'PENDING',
|
||||
"startTime": 1.minute.ago.strftime("%FT%TZ")
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'continue_creation'
|
||||
end
|
||||
|
||||
context 'when operation status is DONE' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(
|
||||
gcp_project_id, zone, operation_id,
|
||||
{
|
||||
"status": 'DONE'
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'finalize_creation'
|
||||
end
|
||||
|
||||
context 'when operation status is unexpected' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation(
|
||||
gcp_project_id, zone, operation_id,
|
||||
{
|
||||
"status": 'unexpected'
|
||||
} )
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
|
||||
context 'when failed to get operation status' do
|
||||
before do
|
||||
stub_cloud_platform_get_zone_operation_error(gcp_project_id, zone, operation_id)
|
||||
end
|
||||
|
||||
it_behaves_like 'error'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,59 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Clusters::UpdateService do
|
||||
describe '#execute' do
|
||||
subject { described_class.new(cluster.project, cluster.user, params).execute(cluster) }
|
||||
|
||||
let(:cluster) { create(:cluster, :project, :provided_by_user) }
|
||||
|
||||
context 'when correct params' do
|
||||
context 'when enabled is true' do
|
||||
let(:params) { { enabled: true } }
|
||||
|
||||
it 'enables cluster' do
|
||||
is_expected.to eq(true)
|
||||
expect(cluster.enabled).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when enabled is false' do
|
||||
let(:params) { { enabled: false } }
|
||||
|
||||
it 'disables cluster' do
|
||||
is_expected.to eq(true)
|
||||
expect(cluster.enabled).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when namespace is specified' do
|
||||
let(:params) do
|
||||
{
|
||||
platform_kubernetes_attributes: {
|
||||
namespace: 'custom-namespace'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'updates namespace' do
|
||||
is_expected.to eq(true)
|
||||
expect(cluster.platform.namespace).to eq('custom-namespace')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid params' do
|
||||
let(:params) do
|
||||
{
|
||||
platform_kubernetes_attributes: {
|
||||
namespace: '!!!'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
is_expected.to eq(false)
|
||||
expect(cluster.errors[:"platform_kubernetes.namespace"]).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,140 @@
|
|||
module GoogleApi
|
||||
module CloudPlatformHelpers
|
||||
def stub_cloud_platform_get_zone_cluster(project_id, zone, cluster_id, **options)
|
||||
WebMock.stub_request(:get, cloud_platform_get_zone_cluster_url(project_id, zone, cluster_id))
|
||||
.to_return(cloud_platform_response(cloud_platform_cluster_body(options)))
|
||||
end
|
||||
|
||||
def stub_cloud_platform_get_zone_cluster_error(project_id, zone, cluster_id)
|
||||
WebMock.stub_request(:get, cloud_platform_get_zone_cluster_url(project_id, zone, cluster_id))
|
||||
.to_return(status: [500, "Internal Server Error"])
|
||||
end
|
||||
|
||||
def stub_cloud_platform_create_cluster(project_id, zone, **options)
|
||||
WebMock.stub_request(:post, cloud_platform_create_cluster_url(project_id, zone))
|
||||
.to_return(cloud_platform_response(cloud_platform_operation_body(options)))
|
||||
end
|
||||
|
||||
def stub_cloud_platform_create_cluster_error(project_id, zone)
|
||||
WebMock.stub_request(:post, cloud_platform_create_cluster_url(project_id, zone))
|
||||
.to_return(status: [500, "Internal Server Error"])
|
||||
end
|
||||
|
||||
def stub_cloud_platform_get_zone_operation(project_id, zone, operation_id, **options)
|
||||
WebMock.stub_request(:get, cloud_platform_get_zone_operation_url(project_id, zone, operation_id))
|
||||
.to_return(cloud_platform_response(cloud_platform_operation_body(options)))
|
||||
end
|
||||
|
||||
def stub_cloud_platform_get_zone_operation_error(project_id, zone, operation_id)
|
||||
WebMock.stub_request(:get, cloud_platform_get_zone_operation_url(project_id, zone, operation_id))
|
||||
.to_return(status: [500, "Internal Server Error"])
|
||||
end
|
||||
|
||||
def cloud_platform_get_zone_cluster_url(project_id, zone, cluster_id)
|
||||
"https://container.googleapis.com/v1/projects/#{project_id}/zones/#{zone}/clusters/#{cluster_id}"
|
||||
end
|
||||
|
||||
def cloud_platform_create_cluster_url(project_id, zone)
|
||||
"https://container.googleapis.com/v1/projects/#{project_id}/zones/#{zone}/clusters"
|
||||
end
|
||||
|
||||
def cloud_platform_get_zone_operation_url(project_id, zone, operation_id)
|
||||
"https://container.googleapis.com/v1/projects/#{project_id}/zones/#{zone}/operations/#{operation_id}"
|
||||
end
|
||||
|
||||
def cloud_platform_response(body)
|
||||
{ status: 200, headers: { 'Content-Type' => 'application/json' }, body: body.to_json }
|
||||
end
|
||||
|
||||
def load_sample_cert
|
||||
pem_file = File.expand_path(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
|
||||
Base64.encode64(File.read(pem_file))
|
||||
end
|
||||
|
||||
def cloud_platform_cluster_body(**options)
|
||||
{
|
||||
"name": options[:name] || 'string',
|
||||
"description": options[:description] || 'string',
|
||||
"initialNodeCount": options[:initialNodeCount] || 'number',
|
||||
# "nodeConfig": {,
|
||||
# object(NodeConfig),
|
||||
# },,
|
||||
"masterAuth": {
|
||||
"username": options[:username] || 'string',
|
||||
"password": options[:password] || 'string',
|
||||
# "clientCertificateConfig": {
|
||||
# object(ClientCertificateConfig)
|
||||
# },
|
||||
"clusterCaCertificate": options[:clusterCaCertificate] || load_sample_cert,
|
||||
"clientCertificate": options[:clientCertificate] || 'string',
|
||||
"clientKey": options[:clientKey] || 'string'
|
||||
},
|
||||
"loggingService": options[:loggingService] || 'string',
|
||||
"monitoringService": options[:monitoringService] || 'string',
|
||||
"network": options[:network] || 'string',
|
||||
"clusterIpv4Cidr": options[:clusterIpv4Cidr] || 'string',
|
||||
# "addonsConfig": {,
|
||||
# object(AddonsConfig),
|
||||
# },,
|
||||
"subnetwork": options[:subnetwork] || 'string',
|
||||
# "nodePools": [,
|
||||
# {,
|
||||
# object(NodePool),
|
||||
# },
|
||||
# ],,
|
||||
# "locations": [,
|
||||
# string,
|
||||
# ],,
|
||||
"enableKubernetesAlpha": options[:enableKubernetesAlpha] || 'boolean',
|
||||
# "resourceLabels": {,
|
||||
# string: string,,
|
||||
# ...,
|
||||
# },,
|
||||
"labelFingerprint": options[:labelFingerprint] || 'string',
|
||||
# "legacyAbac": {,
|
||||
# object(LegacyAbac),
|
||||
# },
|
||||
# "networkPolicy": {,
|
||||
# object(NetworkPolicy),
|
||||
# },
|
||||
# "ipAllocationPolicy": {,
|
||||
# object(IPAllocationPolicy),
|
||||
# },
|
||||
# "masterAuthorizedNetworksConfig": {,
|
||||
# object(MasterAuthorizedNetworksConfig),
|
||||
# },
|
||||
"selfLink": options[:selfLink] || 'string',
|
||||
"zone": options[:zone] || 'string',
|
||||
"endpoint": options[:endpoint] || 'string',
|
||||
"initialClusterVersion": options[:initialClusterVersion] || 'string',
|
||||
"currentMasterVersion": options[:currentMasterVersion] || 'string',
|
||||
"currentNodeVersion": options[:currentNodeVersion] || 'string',
|
||||
"createTime": options[:createTime] || 'string',
|
||||
"status": options[:status] || 'RUNNING',
|
||||
"statusMessage": options[:statusMessage] || 'string',
|
||||
"nodeIpv4CidrSize": options[:nodeIpv4CidrSize] || 'number',
|
||||
"servicesIpv4Cidr": options[:servicesIpv4Cidr] || 'string',
|
||||
# "instanceGroupUrls": [,
|
||||
# string,
|
||||
# ],,
|
||||
"currentNodeCount": options[:currentNodeCount] || 'number',
|
||||
"expireTime": options[:expireTime] || 'string'
|
||||
}
|
||||
end
|
||||
|
||||
def cloud_platform_operation_body(**options)
|
||||
{
|
||||
"name": options[:name] || 'operation-1234567891234-1234567',
|
||||
"zone": options[:zone] || 'us-central1-a',
|
||||
"operationType": options[:operationType] || 'CREATE_CLUSTER',
|
||||
"status": options[:status] || 'PENDING',
|
||||
"detail": options[:detail] || 'detail',
|
||||
"statusMessage": options[:statusMessage] || '',
|
||||
"selfLink": options[:selfLink] || 'https://container.googleapis.com/v1/projects/123456789101/zones/us-central1-a/operations/operation-1234567891234-1234567',
|
||||
"targetLink": options[:targetLink] || 'https://container.googleapis.com/v1/projects/123456789101/zones/us-central1-a/clusters/test-cluster',
|
||||
"startTime": options[:startTime] || '2017-09-13T16:49:13.055601589Z',
|
||||
"endTime": options[:endTime] || ''
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,8 +9,8 @@ module KubernetesHelpers
|
|||
kube_response(kube_pods_body)
|
||||
end
|
||||
|
||||
def stub_kubeclient_discover
|
||||
WebMock.stub_request(:get, service.api_url + '/api/v1').to_return(kube_response(kube_v1_discovery_body))
|
||||
def stub_kubeclient_discover(api_url)
|
||||
WebMock.stub_request(:get, api_url + '/api/v1').to_return(kube_response(kube_v1_discovery_body))
|
||||
end
|
||||
|
||||
def stub_kubeclient_pods(response = nil)
|
||||
|
@ -20,11 +20,40 @@ module KubernetesHelpers
|
|||
WebMock.stub_request(:get, pods_url).to_return(response || kube_pods_response)
|
||||
end
|
||||
|
||||
def stub_kubeclient_get_secrets(api_url, **options)
|
||||
WebMock.stub_request(:get, api_url + '/api/v1/secrets')
|
||||
.to_return(kube_response(kube_v1_secrets_body(options)))
|
||||
end
|
||||
|
||||
def stub_kubeclient_get_secrets_error(api_url)
|
||||
WebMock.stub_request(:get, api_url + '/api/v1/secrets')
|
||||
.to_return(status: [500, "Internal Server Error"])
|
||||
end
|
||||
|
||||
def kube_v1_secrets_body(**options)
|
||||
{
|
||||
"kind" => "SecretList",
|
||||
"apiVersion": "v1",
|
||||
"items" => [
|
||||
{
|
||||
"metadata": {
|
||||
"name": options[:metadata_name] || "default-token-1",
|
||||
"namespace": "kube-system"
|
||||
},
|
||||
"data": {
|
||||
"token": options[:token] || Base64.encode64('token-sample-123')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
def kube_v1_discovery_body
|
||||
{
|
||||
"kind" => "APIResourceList",
|
||||
"resources" => [
|
||||
{ "name" => "pods", "namespaced" => true, "kind" => "Pod" }
|
||||
{ "name" => "pods", "namespaced" => true, "kind" => "Pod" },
|
||||
{ "name" => "secrets", "namespaced" => true, "kind" => "Secret" }
|
||||
]
|
||||
}
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue