Commit 0a8d441b authored by Martin Wortschack's avatar Martin Wortschack

Merge branch 'show-kubernetes-namespace-on-job-show-page' into 'master'

Show Kubernetes namespace on job show page

Closes #31756

See merge request gitlab-org/gitlab!20983
parents d3ee57b1 66dc32d2
...@@ -12,6 +12,11 @@ export default { ...@@ -12,6 +12,11 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
deploymentCluster: {
type: Object,
required: false,
default: null,
},
iconStatus: { iconStatus: {
type: Object, type: Object,
required: true, required: true,
...@@ -61,14 +66,14 @@ export default { ...@@ -61,14 +66,14 @@ export default {
: ''; : '';
}, },
hasCluster() { hasCluster() {
return this.hasLastDeployment && this.lastDeployment.cluster; return Boolean(this.deploymentCluster) && Boolean(this.deploymentCluster.name);
}, },
clusterNameOrLink() { clusterNameOrLink() {
if (!this.hasCluster) { if (!this.hasCluster) {
return ''; return '';
} }
const { name, path } = this.lastDeployment.cluster; const { name, path } = this.deploymentCluster;
const escapedName = _.escape(name); const escapedName = _.escape(name);
const escapedPath = _.escape(path); const escapedPath = _.escape(path);
...@@ -86,6 +91,9 @@ export default { ...@@ -86,6 +91,9 @@ export default {
false, false,
); );
}, },
kubernetesNamespace() {
return this.hasCluster ? this.deploymentCluster.kubernetes_namespace : null;
},
}, },
methods: { methods: {
deploymentLink(name) { deploymentLink(name) {
...@@ -109,75 +117,153 @@ export default { ...@@ -109,75 +117,153 @@ export default {
); );
}, },
lastEnvironmentMessage() { lastEnvironmentMessage() {
const { environmentLink, clusterNameOrLink, hasCluster } = this; const { environmentLink, clusterNameOrLink, hasCluster, kubernetesNamespace } = this;
if (hasCluster) {
const message = hasCluster if (kubernetesNamespace) {
? __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.') return sprintf(
: __('This job is deployed to %{environmentLink}.'); __(
'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
return sprintf(message, { environmentLink, clusterNameOrLink }, false); ),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
);
}
// we know the cluster but not the namespace
return sprintf(
__('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.'),
{ environmentLink, clusterNameOrLink },
false,
);
}
// not a cluster deployment
return sprintf(__('This job is deployed to %{environmentLink}.'), { environmentLink }, false);
}, },
outOfDateEnvironmentMessage() { outOfDateEnvironmentMessage() {
const { hasLastDeployment, hasCluster, environmentLink, clusterNameOrLink } = this; const {
hasLastDeployment,
hasCluster,
environmentLink,
clusterNameOrLink,
kubernetesNamespace,
} = this;
if (hasLastDeployment) { if (hasLastDeployment) {
const message = hasCluster const deploymentLink = this.deploymentLink(__('most recent deployment'));
? __( if (hasCluster) {
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.', if (kubernetesNamespace) {
) return sprintf(
: __( __(
'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.', 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink },
false,
); );
}
// we know the cluster but not the namespace
return sprintf(
__(
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, deploymentLink },
false,
);
}
// not a cluster deployment
return sprintf( return sprintf(
message, __(
{ 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.',
environmentLink, ),
clusterNameOrLink, { environmentLink, deploymentLink },
deploymentLink: this.deploymentLink(__('most recent deployment')),
},
false, false,
); );
} }
// no last deployment, i.e. this is the first deployment
const message = hasCluster if (hasCluster) {
? __( if (kubernetesNamespace) {
return sprintf(
__(
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
);
}
// we know the cluster but not the namespace
return sprintf(
__(
'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
) ),
: __('This job is an out-of-date deployment to %{environmentLink}.'); { environmentLink, clusterNameOrLink },
false,
);
}
// not a cluster deployment
return sprintf( return sprintf(
message, __('This job is an out-of-date deployment to %{environmentLink}.'),
{ { environmentLink },
environmentLink,
clusterNameOrLink,
},
false, false,
); );
}, },
creatingEnvironmentMessage() { creatingEnvironmentMessage() {
const { hasLastDeployment, hasCluster, environmentLink, clusterNameOrLink } = this; const {
hasLastDeployment,
hasCluster,
environmentLink,
clusterNameOrLink,
kubernetesNamespace,
} = this;
if (hasLastDeployment) { if (hasLastDeployment) {
const message = hasCluster const deploymentLink = this.deploymentLink(__('latest deployment'));
? __( if (hasCluster) {
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.', if (kubernetesNamespace) {
) return sprintf(
: __( __(
'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.', 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink },
false,
); );
}
// we know the cluster but not the namespace
return sprintf(
__(
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.',
),
{ environmentLink, clusterNameOrLink, deploymentLink },
false,
);
}
// not a cluster deployment
return sprintf( return sprintf(
message, __(
{ 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.',
environmentLink, ),
clusterNameOrLink, { environmentLink, deploymentLink },
deploymentLink: this.deploymentLink(__('latest deployment')),
},
false, false,
); );
} }
// no last deployment, i.e. this is the first deployment
if (hasCluster) {
if (kubernetesNamespace) {
return sprintf(
__(
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.',
),
{ environmentLink, clusterNameOrLink, kubernetesNamespace },
false,
);
}
// we know the cluster but not the namespace
return sprintf(
__(
'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.',
),
{ environmentLink, clusterNameOrLink },
false,
);
}
// not a cluster deployment
return sprintf( return sprintf(
__('This job is creating a deployment to %{environmentLink}.'), __('This job is creating a deployment to %{environmentLink}.'),
{ environmentLink }, { environmentLink },
......
...@@ -256,6 +256,7 @@ export default { ...@@ -256,6 +256,7 @@ export default {
v-if="hasEnvironment" v-if="hasEnvironment"
class="js-job-environment" class="js-job-environment"
:deployment-status="job.deployment_status" :deployment-status="job.deployment_status"
:deployment-cluster="job.deployment_cluster"
:icon-status="job.status" :icon-status="job.status"
/> />
......
...@@ -30,6 +30,7 @@ class Deployment < ApplicationRecord ...@@ -30,6 +30,7 @@ class Deployment < ApplicationRecord
validate :valid_ref, on: :create validate :valid_ref, on: :create
delegate :name, to: :environment, prefix: true delegate :name, to: :environment, prefix: true
delegate :kubernetes_namespace, to: :deployment_cluster, allow_nil: true
scope :for_environment, -> (environment) { where(environment_id: environment) } scope :for_environment, -> (environment) { where(environment_id: environment) }
scope :for_environment_name, -> (name) do scope :for_environment_name, -> (name) do
......
...@@ -22,6 +22,12 @@ class BuildDetailsEntity < JobEntity ...@@ -22,6 +22,12 @@ class BuildDetailsEntity < JobEntity
end end
end end
expose :deployment_cluster, if: -> (build) { build&.deployment&.cluster } do |build, options|
# Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster
# https://gitlab.com/gitlab-org/gitlab/issues/202628
DeploymentClusterEntity.represent(build.deployment, options)
end
expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
expose :download_path, if: -> (*) { build.artifacts? } do |build| expose :download_path, if: -> (*) { build.artifacts? } do |build|
download_project_job_artifacts_path(project, build) download_project_job_artifacts_path(project, build)
......
# frozen_string_literal: true
class ClusterBasicEntity < Grape::Entity
include RequestAwareEntity
expose :name
expose :path, if: -> (cluster) { can?(request.current_user, :read_cluster, cluster) } do |cluster|
cluster.present(current_user: request.current_user).show_path
end
end
# frozen_string_literal: true
class DeploymentClusterEntity < Grape::Entity
include RequestAwareEntity
# Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster
# https://gitlab.com/gitlab-org/gitlab/issues/202628
expose :name do |deployment|
deployment.cluster.name
end
expose :path, if: -> (deployment) { can?(request.current_user, :read_cluster, deployment.cluster) } do |deployment|
deployment.cluster.present(current_user: request.current_user).show_path
end
expose :kubernetes_namespace, if: -> (deployment) { can?(request.current_user, :read_cluster, deployment.cluster) } do |deployment|
deployment.kubernetes_namespace
end
end
...@@ -41,7 +41,11 @@ class DeploymentEntity < Grape::Entity ...@@ -41,7 +41,11 @@ class DeploymentEntity < Grape::Entity
JobEntity.represent(deployment.playable_build, options.merge(only: [:play_path, :retry_path])) JobEntity.represent(deployment.playable_build, options.merge(only: [:play_path, :retry_path]))
end end
expose :cluster, using: ClusterBasicEntity expose :cluster do |deployment, options|
# Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster
# https://gitlab.com/gitlab-org/gitlab/issues/202628
DeploymentClusterEntity.represent(deployment, options) unless deployment.cluster.nil?
end
private private
......
---
title: Show Kubernetes namespace on job show page
merge_request: 20983
author:
type: added
...@@ -19587,6 +19587,12 @@ msgstr "" ...@@ -19587,6 +19587,12 @@ msgstr ""
msgid "This job has not started yet" msgid "This job has not started yet"
msgstr "" msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}." msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
msgstr "" msgstr ""
...@@ -19602,6 +19608,15 @@ msgstr "" ...@@ -19602,6 +19608,15 @@ msgstr ""
msgid "This job is archived. Only the complete pipeline can be retried." msgid "This job is archived. Only the complete pipeline can be retried."
msgstr "" msgstr ""
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}." msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
msgstr "" msgstr ""
...@@ -19611,6 +19626,9 @@ msgstr "" ...@@ -19611,6 +19626,9 @@ msgstr ""
msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}." msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
msgstr "" msgstr ""
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
msgstr ""
msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}." msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
msgstr "" msgstr ""
......
# frozen_string_literal: true
FactoryBot.define do
factory :deployment_cluster, class: 'DeploymentCluster' do
cluster
deployment
kubernetes_namespace { 'the-namespace' }
end
end
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
"cluster": { "cluster": {
"oneOf": [ "oneOf": [
{ "type": "null" }, { "type": "null" },
{ "$ref": "cluster_basic.json" } { "$ref": "deployment_cluster.json" }
] ]
}, },
"manual_actions": { "manual_actions": {
......
...@@ -10,6 +10,12 @@ ...@@ -10,6 +10,12 @@
{ "type": "null" }, { "type": "null" },
{ "type": "string" } { "type": "string" }
] ]
},
"kubernetes_namespace": {
"oneOf": [
{ "type": "null" },
{ "type": "string" }
]
} }
}, },
"additionalProperties": false "additionalProperties": false
......
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
"terminal_path": { "type": "string" }, "terminal_path": { "type": "string" },
"trigger": { "$ref": "trigger.json" }, "trigger": { "$ref": "trigger.json" },
"deployment_status": { "$ref": "deployment_status.json" }, "deployment_status": { "$ref": "deployment_status.json" },
"deployment_cluster": {
"oneOf": [
{ "$ref": "../deployment_cluster.json" },
{ "type": "null" }
]
},
"runner": { "$ref": "runner.json" }, "runner": { "$ref": "runner.json" },
"runners": { "$ref": "runners.json" }, "runners": { "$ref": "runners.json" },
"has_trace": { "type": "boolean" }, "has_trace": { "type": "boolean" },
......
...@@ -4,6 +4,7 @@ import mountComponent from '../../helpers/vue_mount_component_helper'; ...@@ -4,6 +4,7 @@ import mountComponent from '../../helpers/vue_mount_component_helper';
const TEST_CLUSTER_NAME = 'test_cluster'; const TEST_CLUSTER_NAME = 'test_cluster';
const TEST_CLUSTER_PATH = 'path/to/test_cluster'; const TEST_CLUSTER_PATH = 'path/to/test_cluster';
const TEST_KUBERNETES_NAMESPACE = 'this-is-a-kubernetes-namespace';
describe('Environments block', () => { describe('Environments block', () => {
const Component = Vue.extend(component); const Component = Vue.extend(component);
...@@ -28,17 +29,18 @@ describe('Environments block', () => { ...@@ -28,17 +29,18 @@ describe('Environments block', () => {
last_deployment: { ...lastDeployment }, last_deployment: { ...lastDeployment },
}); });
const createEnvironmentWithCluster = () => ({ const createDeploymentWithCluster = () => ({ name: TEST_CLUSTER_NAME, path: TEST_CLUSTER_PATH });
...environment,
last_deployment: { const createDeploymentWithClusterAndKubernetesNamespace = () => ({
...lastDeployment, name: TEST_CLUSTER_NAME,
cluster: { name: TEST_CLUSTER_NAME, path: TEST_CLUSTER_PATH }, path: TEST_CLUSTER_PATH,
}, kubernetes_namespace: TEST_KUBERNETES_NAMESPACE,
}); });
const createComponent = (deploymentStatus = {}) => { const createComponent = (deploymentStatus = {}, deploymentCluster = {}) => {
vm = mountComponent(Component, { vm = mountComponent(Component, {
deploymentStatus, deploymentStatus,
deploymentCluster,
iconStatus: status, iconStatus: status,
}); });
}; };
...@@ -62,15 +64,36 @@ describe('Environments block', () => { ...@@ -62,15 +64,36 @@ describe('Environments block', () => {
expect(findText()).toEqual('This job is deployed to environment.'); expect(findText()).toEqual('This job is deployed to environment.');
}); });
it('renders info with cluster', () => { describe('when there is a cluster', () => {
createComponent({ it('renders info with cluster', () => {
status: 'last', createComponent(
environment: createEnvironmentWithCluster(), {
status: 'last',
environment: createEnvironmentWithLastDeployment(),
},
createDeploymentWithCluster(),
);
expect(findText()).toEqual(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
);
}); });
expect(findText()).toEqual( describe('when there is a kubernetes namespace', () => {
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`, it('renders info with cluster', () => {
); createComponent(
{
status: 'last',
environment: createEnvironmentWithLastDeployment(),
},
createDeploymentWithClusterAndKubernetesNamespace(),
);
expect(findText()).toEqual(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}.`,
);
});
});
}); });
}); });
...@@ -89,15 +112,36 @@ describe('Environments block', () => { ...@@ -89,15 +112,36 @@ describe('Environments block', () => {
expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar'); expect(findJobDeploymentLink().getAttribute('href')).toEqual('bar');
}); });
it('renders info with cluster', () => { describe('when there is a cluster', () => {
createComponent({ it('renders info with cluster', () => {
status: 'out_of_date', createComponent(
environment: createEnvironmentWithCluster(), {
status: 'out_of_date',
environment: createEnvironmentWithLastDeployment(),
},
createDeploymentWithCluster(),
);
expect(findText()).toEqual(
`This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`,
);
}); });
expect(findText()).toEqual( describe('when there is a kubernetes namespace', () => {
`This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME}. View the most recent deployment.`, it('renders info with cluster', () => {
); createComponent(
{
status: 'out_of_date',
environment: createEnvironmentWithLastDeployment(),
},
createDeploymentWithClusterAndKubernetesNamespace(),
);
expect(findText()).toEqual(
`This job is an out-of-date deployment to environment using cluster ${TEST_CLUSTER_NAME} and namespace ${TEST_KUBERNETES_NAMESPACE}. View the most recent deployment.`,
);
});
});
}); });
}); });
...@@ -143,7 +187,7 @@ describe('Environments block', () => { ...@@ -143,7 +187,7 @@ describe('Environments block', () => {
}); });
describe('without last deployment', () => { describe('without last deployment', () => {
it('renders info about failed deployment', () => { it('renders info about deployment being created', () => {
createComponent({ createComponent({
status: 'creating', status: 'creating',
environment, environment,
...@@ -151,6 +195,22 @@ describe('Environments block', () => { ...@@ -151,6 +195,22 @@ describe('Environments block', () => {
expect(findText()).toEqual('This job is creating a deployment to environment.'); expect(findText()).toEqual('This job is creating a deployment to environment.');
}); });
describe('when there is a cluster', () => {
it('inclues information about the cluster', () => {
createComponent(
{
status: 'creating',
environment,
},
createDeploymentWithCluster(),
);
expect(findText()).toEqual(
`This job is creating a deployment to environment using cluster ${TEST_CLUSTER_NAME}.`,
);
});
});
}); });
describe('without environment', () => { describe('without environment', () => {
...@@ -167,10 +227,13 @@ describe('Environments block', () => { ...@@ -167,10 +227,13 @@ describe('Environments block', () => {
describe('with a cluster', () => { describe('with a cluster', () => {
it('renders the cluster link', () => { it('renders the cluster link', () => {
createComponent({ createComponent(
status: 'last', {
environment: createEnvironmentWithCluster(), status: 'last',
}); environment: createEnvironmentWithLastDeployment(),
},
createDeploymentWithCluster(),
);
expect(findText()).toEqual( expect(findText()).toEqual(
`This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`, `This job is deployed to environment using cluster ${TEST_CLUSTER_NAME}.`,
...@@ -181,18 +244,13 @@ describe('Environments block', () => { ...@@ -181,18 +244,13 @@ describe('Environments block', () => {
describe('when the cluster is missing the path', () => { describe('when the cluster is missing the path', () => {
it('renders the name without a link', () => { it('renders the name without a link', () => {
const cluster = { createComponent(
name: 'the-cluster', {
}; status: 'last',
createComponent({ environment: createEnvironmentWithLastDeployment(),
status: 'last', },
environment: Object.assign({}, environment, { { name: 'the-cluster' },
last_deployment: { );
...lastDeployment,
cluster,
},
}),
});
expect(findText()).toContain('using cluster the-cluster.'); expect(findText()).toContain('using cluster the-cluster.');
......
...@@ -18,6 +18,7 @@ describe Deployment do ...@@ -18,6 +18,7 @@ describe Deployment do
it { is_expected.to delegate_method(:commit).to(:project) } it { is_expected.to delegate_method(:commit).to(:project) }
it { is_expected.to delegate_method(:commit_title).to(:commit).as(:try) } it { is_expected.to delegate_method(:commit_title).to(:commit).as(:try) }
it { is_expected.to delegate_method(:manual_actions).to(:deployable).as(:try) } it { is_expected.to delegate_method(:manual_actions).to(:deployable).as(:try) }
it { is_expected.to delegate_method(:kubernetes_namespace).to(:deployment_cluster).as(:kubernetes_namespace) }
it { is_expected.to validate_presence_of(:ref) } it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to validate_presence_of(:sha) } it { is_expected.to validate_presence_of(:sha) }
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
require 'spec_helper' require 'spec_helper'
describe ClusterBasicEntity do describe DeploymentClusterEntity do
describe '#as_json' do describe '#as_json' do
subject { described_class.new(cluster, request: request).as_json } subject { described_class.new(deployment, request: request).as_json }
let(:maintainer) { create(:user) } let(:maintainer) { create(:user) }
let(:developer) { create(:user) } let(:developer) { create(:user) }
...@@ -12,26 +12,30 @@ describe ClusterBasicEntity do ...@@ -12,26 +12,30 @@ describe ClusterBasicEntity do
let(:request) { double(:request, current_user: current_user) } let(:request) { double(:request, current_user: current_user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:cluster) { create(:cluster, name: 'the-cluster', projects: [project]) } let(:cluster) { create(:cluster, name: 'the-cluster', projects: [project]) }
let(:deployment) { create(:deployment, cluster: cluster) }
let!(:deployment_cluster) { create(:deployment_cluster, cluster: cluster, deployment: deployment) }
before do before do
project.add_maintainer(maintainer) project.add_maintainer(maintainer)
project.add_developer(developer) project.add_developer(developer)
end end
it 'matches cluster_basic entity schema' do it 'matches deployment_cluster entity schema' do
expect(subject.as_json).to match_schema('cluster_basic') expect(subject.as_json).to match_schema('deployment_cluster')
end end
it 'exposes the cluster details' do it 'exposes the cluster details' do
expect(subject[:name]).to eq('the-cluster') expect(subject[:name]).to eq('the-cluster')
expect(subject[:path]).to eq("/#{project.full_path}/-/clusters/#{cluster.id}") expect(subject[:path]).to eq("/#{project.full_path}/-/clusters/#{cluster.id}")
expect(subject[:kubernetes_namespace]).to eq(deployment_cluster.kubernetes_namespace)
end end
context 'when the user does not have permission to view the cluster' do context 'when the user does not have permission to view the cluster' do
let(:current_user) { developer } let(:current_user) { developer }
it 'does not include the path' do it 'does not include the path nor the namespace' do
expect(subject[:path]).to be_nil expect(subject[:path]).to be_nil
expect(subject[:kubernetes_namespace]).to be_nil
end end
end end
end end
......
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