summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-09-17 08:43:48 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2018-09-17 08:43:48 +0000
commit5a8908bf587a0723b07e510dd6118a686d49af98 (patch)
treea19af868a1b0a7c676b56a43372811a662754b6f /spec
parentba40c7f1c32f62ad5370621f049500aa904149cd (diff)
parent528b060b89c2d6a6be611e88ceed28cfe86e167c (diff)
downloadgitlab-ce-5a8908bf587a0723b07e510dd6118a686d49af98.tar.gz
Merge branch '29398-support-rbac-for-gitlab-provisioned-clusters' into 'master'
Support Kubernetes RBAC for GitLab Managed Apps for creating new clusters Closes #29398 See merge request gitlab-org/gitlab-ce!21401
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb16
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb52
-rw-r--r--spec/features/projects/clusters/user_spec.rb55
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb2
-rw-r--r--spec/lib/gitlab/kubernetes/service_account_token_spec.rb35
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb47
-rw-r--r--spec/models/clusters/providers/gcp_spec.rb18
-rw-r--r--spec/services/ci/fetch_kubernetes_token_service_spec.rb64
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb123
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb96
-rw-r--r--spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb60
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb54
-rw-r--r--spec/support/services/clusters/create_service_shared.rb8
13 files changed, 454 insertions, 176 deletions
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 26a532ee01d..97ac11fd171 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -170,12 +170,14 @@ describe Projects::ClustersController do
end
describe 'POST create for new cluster' do
+ let(:legacy_abac_param) { 'true' }
let(:params) do
{
cluster: {
name: 'new-cluster',
provider_gcp_attributes: {
- gcp_project_id: 'gcp-project-12345'
+ gcp_project_id: 'gcp-project-12345',
+ legacy_abac: legacy_abac_param
}
}
}
@@ -201,6 +203,18 @@ describe Projects::ClustersController do
expect(response).to redirect_to(project_cluster_path(project, project.clusters.first))
expect(project.clusters.first).to be_gcp
expect(project.clusters.first).to be_kubernetes
+ expect(project.clusters.first.provider_gcp).to be_legacy_abac
+ end
+
+ context 'when legacy_abac param is false' do
+ let(:legacy_abac_param) { 'false' }
+
+ it 'creates a new cluster with legacy_abac_disabled' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+ expect(project.clusters.first.provider_gcp).not_to be_legacy_abac
+ end
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 31e3ebf675d..edc763ad0ad 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -33,6 +33,32 @@ describe 'Gcp Cluster', :js do
context 'when user filled form with valid parameters' do
subject { click_button 'Create Kubernetes cluster' }
+ shared_examples 'valid cluster gcp form' do
+ it 'users sees a form with the GCP token' do
+ expect(page).to have_selector(:css, 'form[data-token="token"]')
+ end
+
+ it 'user sees a cluster details page and creation status' do
+ subject
+
+ expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
+
+ Clusters::Cluster.last.provider.make_created!
+
+ expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine')
+ end
+
+ it 'user sees a error if something wrong during creation' do
+ subject
+
+ expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
+
+ Clusters::Cluster.last.provider.make_errored!('Something wrong!')
+
+ expect(page).to have_content('Something wrong!')
+ end
+ end
+
before do
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
@@ -56,28 +82,16 @@ describe 'Gcp Cluster', :js do
fill_in 'cluster[provider_gcp_attributes][machine_type]', with: 'n1-standard-2'
end
- it 'users sees a form with the GCP token' do
- expect(page).to have_selector(:css, 'form[data-token="token"]')
- end
-
- it 'user sees a cluster details page and creation status' do
- subject
-
- expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
-
- Clusters::Cluster.last.provider.make_created!
-
- expect(page).to have_content('Kubernetes cluster was successfully created on Google Kubernetes Engine')
- end
-
- it 'user sees a error if something wrong during creation' do
- subject
+ it_behaves_like 'valid cluster gcp form'
- expect(page).to have_content('Kubernetes cluster is being created on Google Kubernetes Engine...')
+ context 'rbac_clusters feature flag is enabled' do
+ before do
+ stub_feature_flags(rbac_clusters: true)
- Clusters::Cluster.last.provider.make_errored!('Something wrong!')
+ check 'cluster_provider_gcp_attributes_legacy_abac'
+ end
- expect(page).to have_content('Something wrong!')
+ it_behaves_like 'valid cluster gcp form'
end
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index ec968bfcf7d..00941efc8c8 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -21,42 +21,43 @@ describe 'User Cluster', :js do
end
context 'when user filled form with valid parameters' do
+ shared_examples 'valid cluster user form' do
+ it 'user sees a cluster details page' do
+ subject
+
+ expect(page).to have_content('Kubernetes cluster integration')
+ expect(page.find_field('cluster[name]').value).to eq('dev-cluster')
+ expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
+ .to have_content('http://example.com')
+ expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
+ .to have_content('my-token')
+ end
+ end
+
before do
fill_in 'cluster_name', with: 'dev-cluster'
fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'http://example.com'
fill_in 'cluster_platform_kubernetes_attributes_token', with: 'my-token'
- click_button 'Add Kubernetes cluster'
end
- it 'user sees a cluster details page' do
- expect(page).to have_content('Kubernetes cluster integration')
- expect(page.find_field('cluster[name]').value).to eq('dev-cluster')
- expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
- .to have_content('http://example.com')
- expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
- .to have_content('my-token')
- end
- end
+ subject { click_button 'Add Kubernetes cluster' }
- context 'rbac_clusters feature flag is enabled' do
- before do
- stub_feature_flags(rbac_clusters: true)
+ it_behaves_like 'valid cluster user form'
- fill_in 'cluster_name', with: 'dev-cluster'
- fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'http://example.com'
- fill_in 'cluster_platform_kubernetes_attributes_token', with: 'my-token'
- check 'cluster_platform_kubernetes_attributes_authorization_type'
- click_button 'Add Kubernetes cluster'
- end
+ context 'rbac_clusters feature flag is enabled' do
+ before do
+ stub_feature_flags(rbac_clusters: true)
+
+ check 'cluster_platform_kubernetes_attributes_authorization_type'
+ end
+
+ it_behaves_like 'valid cluster user form'
- it 'user sees a cluster details page' do
- expect(page).to have_content('Kubernetes cluster integration')
- expect(page.find_field('cluster[name]').value).to eq('dev-cluster')
- expect(page.find_field('cluster[platform_kubernetes_attributes][api_url]').value)
- .to have_content('http://example.com')
- expect(page.find_field('cluster[platform_kubernetes_attributes][token]').value)
- .to have_content('my-token')
- expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked
+ it 'user sees a cluster details page with RBAC enabled' do
+ subject
+
+ expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked
+ end
end
end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 9146729d139..53c5a4e7c94 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -116,12 +116,14 @@ describe Gitlab::Kubernetes::KubeClient do
:get_config_map,
:get_pod,
:get_namespace,
+ :get_secret,
:get_service,
:get_service_account,
:delete_pod,
:create_config_map,
:create_namespace,
:create_pod,
+ :create_secret,
:create_service_account,
:update_config_map,
:update_service_account
diff --git a/spec/lib/gitlab/kubernetes/service_account_token_spec.rb b/spec/lib/gitlab/kubernetes/service_account_token_spec.rb
new file mode 100644
index 00000000000..0773d3d9aec
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/service_account_token_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Kubernetes::ServiceAccountToken do
+ let(:name) { 'token-name' }
+ let(:service_account_name) { 'a_service_account' }
+ let(:namespace_name) { 'a_namespace' }
+ let(:service_account_token) { described_class.new(name, service_account_name, namespace_name) }
+
+ it { expect(service_account_token.name).to eq(name) }
+ it { expect(service_account_token.service_account_name).to eq(service_account_name) }
+ it { expect(service_account_token.namespace_name).to eq(namespace_name) }
+
+ describe '#generate' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: {
+ name: name,
+ namespace: namespace_name,
+ annotations: {
+ 'kubernetes.io/service-account.name': service_account_name
+ }
+ },
+ type: 'kubernetes.io/service-account-token'
+ )
+ end
+
+ subject { service_account_token.generate }
+
+ it 'should build a Kubeclient Resource' do
+ is_expected.to eq(resource)
+ end
+ end
+end
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index 27cb3198e5b..e2134dc279c 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -66,25 +66,30 @@ describe GoogleApi::CloudPlatform::Client do
describe '#projects_zones_clusters_create' do
subject do
client.projects_zones_clusters_create(
- spy, spy, cluster_name, cluster_size, machine_type: machine_type)
+ project_id, zone, cluster_name, cluster_size, machine_type: machine_type, legacy_abac: legacy_abac)
end
+ let(:project_id) { 'project-123' }
+ let(:zone) { 'us-central1-a' }
let(:cluster_name) { 'test-cluster' }
let(:cluster_size) { 1 }
let(:machine_type) { 'n1-standard-2' }
+ let(:legacy_abac) { true }
+ let(:create_cluster_request_body) { double('Google::Apis::ContainerV1::CreateClusterRequest') }
let(:operation) { double }
before do
allow_any_instance_of(Google::Apis::ContainerV1::ContainerService)
- .to receive(:create_cluster).with(any_args, options: user_agent_options)
+ .to receive(:create_cluster).with(any_args)
.and_return(operation)
end
- it { is_expected.to eq(operation) }
-
it 'sets corresponded parameters' do
- expect_any_instance_of(Google::Apis::ContainerV1::CreateClusterRequest)
- .to receive(:initialize).with(
+ expect_any_instance_of(Google::Apis::ContainerV1::ContainerService)
+ .to receive(:create_cluster).with(project_id, zone, create_cluster_request_body, options: user_agent_options)
+
+ expect(Google::Apis::ContainerV1::CreateClusterRequest)
+ .to receive(:new).with(
{
"cluster": {
"name": cluster_name,
@@ -96,9 +101,35 @@ describe GoogleApi::CloudPlatform::Client do
"enabled": true
}
}
- } )
+ } ).and_return(create_cluster_request_body)
+
+ expect(subject).to eq operation
+ end
+
+ context 'create without legacy_abac' do
+ let(:legacy_abac) { false }
+
+ it 'sets corresponded parameters' do
+ expect_any_instance_of(Google::Apis::ContainerV1::ContainerService)
+ .to receive(:create_cluster).with(project_id, zone, create_cluster_request_body, options: user_agent_options)
+
+ expect(Google::Apis::ContainerV1::CreateClusterRequest)
+ .to receive(:new).with(
+ {
+ "cluster": {
+ "name": cluster_name,
+ "initial_node_count": cluster_size,
+ "node_config": {
+ "machine_type": machine_type
+ },
+ "legacy_abac": {
+ "enabled": false
+ }
+ }
+ } ).and_return(create_cluster_request_body)
- subject
+ expect(subject).to eq operation
+ end
end
end
diff --git a/spec/models/clusters/providers/gcp_spec.rb b/spec/models/clusters/providers/gcp_spec.rb
index b38b5e6bcad..d134608b538 100644
--- a/spec/models/clusters/providers/gcp_spec.rb
+++ b/spec/models/clusters/providers/gcp_spec.rb
@@ -74,6 +74,24 @@ describe Clusters::Providers::Gcp do
end
end
+ describe '#legacy_abac?' do
+ let(:gcp) { build(:cluster_provider_gcp) }
+
+ subject { gcp }
+
+ it 'should default to true' do
+ is_expected.to be_legacy_abac
+ end
+
+ context 'legacy_abac is set to false' do
+ let(:gcp) { build(:cluster_provider_gcp, legacy_abac: false) }
+
+ it 'is false' do
+ is_expected.not_to be_legacy_abac
+ end
+ end
+ end
+
describe '#state_machine' do
context 'when any => [:created]' do
let(:gcp) { build(:cluster_provider_gcp, :creating) }
diff --git a/spec/services/ci/fetch_kubernetes_token_service_spec.rb b/spec/services/ci/fetch_kubernetes_token_service_spec.rb
deleted file mode 100644
index 1d05c9671a9..00000000000
--- a/spec/services/ci/fetch_kubernetes_token_service_spec.rb
+++ /dev/null
@@ -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
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 0cf91307589..0f484222228 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -12,9 +12,11 @@ describe Clusters::Gcp::FinalizeCreationService do
let(:zone) { provider.zone }
let(:cluster_name) { cluster.name }
+ subject { described_class.new.execute(provider) }
+
shared_examples 'success' do
it 'configures provider and kubernetes' do
- described_class.new.execute(provider)
+ subject
expect(provider).to be_created
end
@@ -22,7 +24,7 @@ describe Clusters::Gcp::FinalizeCreationService do
shared_examples 'error' do
it 'sets an error to provider object' do
- described_class.new.execute(provider)
+ subject
expect(provider.reload).to be_errored
end
@@ -33,6 +35,7 @@ describe Clusters::Gcp::FinalizeCreationService do
let(:api_url) { 'https://' + endpoint }
let(:username) { 'sample-username' }
let(:password) { 'sample-password' }
+ let(:secret_name) { 'gitlab-token' }
before do
stub_cloud_platform_get_zone_cluster(
@@ -43,60 +46,102 @@ describe Clusters::Gcp::FinalizeCreationService do
password: password
}
)
-
- stub_kubeclient_discover(api_url)
end
- context 'when suceeded to fetch kuberenetes token' do
- let(:token) { 'sample-token' }
-
+ context 'service account and token created' do
before do
- stub_kubeclient_get_secrets(
- api_url,
- {
- token: Base64.encode64(token)
- } )
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_create_service_account(api_url)
+ stub_kubeclient_create_secret(api_url)
end
- it_behaves_like 'success'
+ shared_context 'kubernetes token successfully fetched' do
+ let(:token) { 'sample-token' }
+
+ before do
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: secret_name,
+ token: Base64.encode64(token)
+ } )
+ end
+ end
+
+ context 'provider legacy_abac is enabled' do
+ include_context 'kubernetes token successfully fetched'
+
+ it_behaves_like 'success'
- it 'has corresponded data' do
- described_class.new.execute(provider)
- cluster.reload
- provider.reload
- platform.reload
+ it 'properly configures database models' do
+ subject
- 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)
+ cluster.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).to be_abac
+ expect(platform.authorization_type).to eq('abac')
+ expect(platform.token).to eq(token)
+ end
end
- end
- context 'when default-token is not found' do
- before do
- stub_kubeclient_get_secrets(api_url, metadata_name: 'aaaa')
+ context 'provider legacy_abac is disabled' do
+ before do
+ provider.legacy_abac = false
+ end
+
+ include_context 'kubernetes token successfully fetched'
+
+ context 'cluster role binding created' do
+ before do
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ end
+
+ it_behaves_like 'success'
+
+ it 'properly configures database models' do
+ subject
+
+ cluster.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).to be_rbac
+ expect(platform.token).to eq(token)
+ end
+ end
end
- it_behaves_like 'error'
- end
+ context 'when token is empty' do
+ before do
+ stub_kubeclient_get_secret(api_url, token: '', metadata_name: secret_name)
+ end
- context 'when token is empty' do
- before do
- stub_kubeclient_get_secrets(api_url, token: '')
+ it_behaves_like 'error'
end
- it_behaves_like 'error'
- end
+ context 'when failed to fetch kubernetes token' do
+ before do
+ stub_kubeclient_get_secret_error(api_url, secret_name)
+ end
- context 'when failed to fetch kuberenetes token' do
- before do
- stub_kubeclient_get_secrets_error(api_url)
+ it_behaves_like 'error'
end
- it_behaves_like 'error'
+ context 'when service account fails to create' do
+ before do
+ stub_kubeclient_create_service_account_error(api_url)
+ end
+
+ it_behaves_like 'error'
+ end
end
end
diff --git a/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
new file mode 100644
index 00000000000..065d021db5e
--- /dev/null
+++ b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Gcp::Kubernetes::CreateServiceAccountService do
+ include KubernetesHelpers
+
+ let(:service) { described_class.new(kubeclient, rbac: rbac) }
+
+ describe '#execute' do
+ let(:rbac) { false }
+ let(:api_url) { 'http://111.111.111.111' }
+ let(:username) { 'admin' }
+ let(:password) { 'xxx' }
+
+ let(:kubeclient) do
+ Gitlab::Kubernetes::KubeClient.new(
+ api_url,
+ ['api', 'apis/rbac.authorization.k8s.io'],
+ auth_options: { username: username, password: password }
+ )
+ end
+
+ subject { service.execute }
+
+ context 'when params are correct' do
+ before do
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_create_service_account(api_url)
+ stub_kubeclient_create_secret(api_url)
+ end
+
+ shared_examples 'creates service account and token' do
+ it 'creates a kubernetes service account' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/serviceaccounts').with(
+ body: hash_including(
+ kind: 'ServiceAccount',
+ metadata: { name: 'gitlab', namespace: 'default' }
+ )
+ )
+ end
+
+ it 'creates a kubernetes secret of type ServiceAccountToken' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/secrets').with(
+ body: hash_including(
+ kind: 'Secret',
+ metadata: {
+ name: 'gitlab-token',
+ namespace: 'default',
+ annotations: {
+ 'kubernetes.io/service-account.name': 'gitlab'
+ }
+ },
+ type: 'kubernetes.io/service-account-token'
+ )
+ )
+ end
+ end
+
+ context 'abac enabled cluster' do
+ it_behaves_like 'creates service account and token'
+ end
+
+ context 'rbac enabled cluster' do
+ let(:rbac) { true }
+
+ before do
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ end
+
+ it_behaves_like 'creates service account and token'
+
+ it 'creates a kubernetes cluster role binding' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings').with(
+ body: hash_including(
+ kind: 'ClusterRoleBinding',
+ metadata: { name: 'gitlab-admin' },
+ roleRef: {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: 'cluster-admin'
+ },
+ subjects: [{ kind: 'ServiceAccount', namespace: 'default', name: 'gitlab' }]
+ )
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
new file mode 100644
index 00000000000..c543de21d5b
--- /dev/null
+++ b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
+ describe '#execute' do
+ let(:api_url) { 'http://111.111.111.111' }
+ let(:username) { 'admin' }
+ let(:password) { 'xxx' }
+
+ let(:kubeclient) do
+ Gitlab::Kubernetes::KubeClient.new(
+ api_url,
+ ['api', 'apis/rbac.authorization.k8s.io'],
+ auth_options: { username: username, password: password }
+ )
+ end
+
+ subject { described_class.new(kubeclient).execute }
+
+ context 'when params correct' do
+ let(:decoded_token) { 'xxx.token.xxx' }
+ let(:token) { Base64.encode64(decoded_token) }
+
+ let(:secret_json) do
+ {
+ 'metadata': {
+ name: 'gitlab-token'
+ },
+ 'data': {
+ 'token': token
+ }
+ }
+ end
+
+ before do
+ allow_any_instance_of(Kubeclient::Client)
+ .to receive(:get_secret).and_return(secret_json)
+ end
+
+ context 'when gitlab-token exists' do
+ let(:metadata_name) { 'gitlab-token' }
+
+ it { is_expected.to eq(decoded_token) }
+ end
+
+ context 'when gitlab-token does not exist' do
+ let(:secret_json) { {} }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when token is nil' do
+ let(:token) { nil }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 994a2aaef90..c077ca9f15b 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -33,31 +33,49 @@ module KubernetesHelpers
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_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)))
+ def stub_kubeclient_get_secret(api_url, namespace: 'default', **options)
+ options[:metadata_name] ||= "default-token-1"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{options[:metadata_name]}")
+ .to_return(kube_response(kube_v1_secret_body(options)))
end
- def stub_kubeclient_get_secrets_error(api_url)
- WebMock.stub_request(:get, api_url + '/api/v1/secrets')
+ def stub_kubeclient_get_secret_error(api_url, name, namespace: 'default')
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{name}")
.to_return(status: [404, "Internal Server Error"])
end
- def kube_v1_secrets_body(**options)
+ def stub_kubeclient_create_service_account(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts")
+ .to_return(kube_response({}))
+ end
+
+ def stub_kubeclient_create_service_account_error(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts")
+ .to_return(status: [500, "Internal Server Error"])
+ end
+
+ def stub_kubeclient_create_secret(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces/#{namespace}/secrets")
+ .to_return(kube_response({}))
+ end
+
+ def stub_kubeclient_create_cluster_role_binding(api_url)
+ WebMock.stub_request(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings')
+ .to_return(kube_response({}))
+ end
+
+ def kube_v1_secret_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')
- }
- }
- ]
+ "metadata": {
+ "name": options[:metadata_name] || "default-token-1",
+ "namespace": "kube-system"
+ },
+ "data": {
+ "token": options[:token] || Base64.encode64('token-sample-123')
+ }
}
end
@@ -68,6 +86,7 @@ module KubernetesHelpers
{ "name" => "pods", "namespaced" => true, "kind" => "Pod" },
{ "name" => "deployments", "namespaced" => true, "kind" => "Deployment" },
{ "name" => "secrets", "namespaced" => true, "kind" => "Secret" },
+ { "name" => "serviceaccounts", "namespaced" => true, "kind" => "ServiceAccount" },
{ "name" => "services", "namespaced" => true, "kind" => "Service" }
]
}
@@ -80,6 +99,7 @@ module KubernetesHelpers
{ "name" => "pods", "namespaced" => true, "kind" => "Pod" },
{ "name" => "deployments", "namespaced" => true, "kind" => "Deployment" },
{ "name" => "secrets", "namespaced" => true, "kind" => "Secret" },
+ { "name" => "serviceaccounts", "namespaced" => true, "kind" => "ServiceAccount" },
{ "name" => "services", "namespaced" => true, "kind" => "Service" }
]
}
diff --git a/spec/support/services/clusters/create_service_shared.rb b/spec/support/services/clusters/create_service_shared.rb
index 43a2fd05498..22f712f3fcf 100644
--- a/spec/support/services/clusters/create_service_shared.rb
+++ b/spec/support/services/clusters/create_service_shared.rb
@@ -7,7 +7,8 @@ shared_context 'valid cluster create params' do
gcp_project_id: 'gcp-project',
zone: 'us-central1-a',
num_nodes: 1,
- machine_type: 'machine_type-a'
+ machine_type: 'machine_type-a',
+ legacy_abac: 'true'
}
}
end
@@ -29,6 +30,10 @@ shared_context 'invalid cluster create params' do
end
shared_examples 'create cluster service success' do
+ before do
+ stub_feature_flags(rbac_clusters: false)
+ end
+
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)
@@ -44,6 +49,7 @@ shared_examples 'create cluster service success' do
expect(subject.provider.num_nodes).to eq(1)
expect(subject.provider.machine_type).to eq('machine_type-a')
expect(subject.provider.access_token).to eq(access_token)
+ expect(subject.provider).to be_legacy_abac
expect(subject.platform).to be_nil
end
end