Commit efc9081d authored by Hordur Freyr Yngvason's avatar Hordur Freyr Yngvason Committed by Enrique Alcantara

Expose namespace_per_environment flag for Kubernetes clusters

Adds the ability to use a namespace per project, instead of namespace
per environment, for deployments using GitLab's Kubernetes integration.

See https://gitlab.com/gitlab-org/gitlab/-/issues/38054
parent 1f21a463
...@@ -13,6 +13,10 @@ export default { ...@@ -13,6 +13,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
namespacePerEnvironmentHelpPath: {
type: String,
required: true,
},
kubernetesIntegrationHelpPath: { kubernetesIntegrationHelpPath: {
type: String, type: String,
required: true, required: true,
...@@ -40,6 +44,7 @@ export default { ...@@ -40,6 +44,7 @@ export default {
<eks-cluster-configuration-form <eks-cluster-configuration-form
v-if="hasCredentials" v-if="hasCredentials"
:gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath" :gitlab-managed-cluster-help-path="gitlabManagedClusterHelpPath"
:namespace-per-environment-help-path="namespacePerEnvironmentHelpPath"
:kubernetes-integration-help-path="kubernetesIntegrationHelpPath" :kubernetes-integration-help-path="kubernetesIntegrationHelpPath"
:external-link-icon="externalLinkIcon" :external-link-icon="externalLinkIcon"
/> />
......
...@@ -37,6 +37,10 @@ export default { ...@@ -37,6 +37,10 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
namespacePerEnvironmentHelpPath: {
type: String,
required: true,
},
kubernetesIntegrationHelpPath: { kubernetesIntegrationHelpPath: {
type: String, type: String,
required: true, required: true,
...@@ -60,6 +64,7 @@ export default { ...@@ -60,6 +64,7 @@ export default {
'selectedInstanceType', 'selectedInstanceType',
'nodeCount', 'nodeCount',
'gitlabManagedCluster', 'gitlabManagedCluster',
'namespacePerEnvironment',
'isCreatingCluster', 'isCreatingCluster',
]), ]),
...mapGetters(['subnetValid']), ...mapGetters(['subnetValid']),
...@@ -270,6 +275,20 @@ export default { ...@@ -270,6 +275,20 @@ export default {
false, false,
); );
}, },
namespacePerEnvironmentHelpText() {
const escapedUrl = escape(this.namespacePerEnvironmentClusterHelpPath);
return sprintf(
s__(
'ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared. %{startLink}More information%{endLink}',
),
{
startLink: `<a href="${escapedUrl}" target="_blank" rel="noopener noreferrer">`,
endLink: '</a>',
},
false,
);
},
}, },
mounted() { mounted() {
this.fetchRegions(); this.fetchRegions();
...@@ -290,6 +309,7 @@ export default { ...@@ -290,6 +309,7 @@ export default {
'setInstanceType', 'setInstanceType',
'setNodeCount', 'setNodeCount',
'setGitlabManagedCluster', 'setGitlabManagedCluster',
'setNamespacePerEnvironment',
]), ]),
...mapRegionsActions({ fetchRegions: 'fetchItems' }), ...mapRegionsActions({ fetchRegions: 'fetchItems' }),
...mapVpcActions({ fetchVpcs: 'fetchItems' }), ...mapVpcActions({ fetchVpcs: 'fetchItems' }),
...@@ -519,6 +539,14 @@ export default { ...@@ -519,6 +539,14 @@ export default {
> >
<p class="form-text text-muted" v-html="gitlabManagedHelpText"></p> <p class="form-text text-muted" v-html="gitlabManagedHelpText"></p>
</div> </div>
<div class="form-group">
<gl-form-checkbox
:checked="namespacePerEnvironment"
@input="setNamespacePerEnvironment({ namespacePerEnvironment: $event })"
>{{ s__('ClusterIntegration|Namespace per environment') }}</gl-form-checkbox
>
<p class="form-text text-muted" v-html="namespacePerEnvironmentHelpText"></p>
</div>
<div class="form-group"> <div class="form-group">
<loading-button <loading-button
class="js-create-cluster btn-success" class="js-create-cluster btn-success"
......
...@@ -9,6 +9,7 @@ Vue.use(Vuex); ...@@ -9,6 +9,7 @@ Vue.use(Vuex);
export default el => { export default el => {
const { const {
gitlabManagedClusterHelpPath, gitlabManagedClusterHelpPath,
namespacePerEnvironmentHelpPath,
kubernetesIntegrationHelpPath, kubernetesIntegrationHelpPath,
accountAndExternalIdsHelpPath, accountAndExternalIdsHelpPath,
createRoleArnHelpPath, createRoleArnHelpPath,
...@@ -42,6 +43,7 @@ export default el => { ...@@ -42,6 +43,7 @@ export default el => {
return createElement('create-eks-cluster', { return createElement('create-eks-cluster', {
props: { props: {
gitlabManagedClusterHelpPath, gitlabManagedClusterHelpPath,
namespacePerEnvironmentHelpPath,
kubernetesIntegrationHelpPath, kubernetesIntegrationHelpPath,
accountAndExternalIdsHelpPath, accountAndExternalIdsHelpPath,
createRoleArnHelpPath, createRoleArnHelpPath,
......
...@@ -55,6 +55,7 @@ export const createCluster = ({ dispatch, state }) => { ...@@ -55,6 +55,7 @@ export const createCluster = ({ dispatch, state }) => {
name: state.clusterName, name: state.clusterName,
environment_scope: state.environmentScope, environment_scope: state.environmentScope,
managed: state.gitlabManagedCluster, managed: state.gitlabManagedCluster,
namespace_per_environment: state.namespacePerEnvironment,
provider_aws_attributes: { provider_aws_attributes: {
kubernetes_version: state.kubernetesVersion, kubernetes_version: state.kubernetesVersion,
region: state.selectedRegion, region: state.selectedRegion,
...@@ -114,6 +115,10 @@ export const setGitlabManagedCluster = ({ commit }, payload) => { ...@@ -114,6 +115,10 @@ export const setGitlabManagedCluster = ({ commit }, payload) => {
commit(types.SET_GITLAB_MANAGED_CLUSTER, payload); commit(types.SET_GITLAB_MANAGED_CLUSTER, payload);
}; };
export const setNamespacePerEnvironment = ({ commit }, payload) => {
commit(types.SET_NAMESPACE_PER_ENVIRONMENT, payload);
};
export const setInstanceType = ({ commit }, payload) => { export const setInstanceType = ({ commit }, payload) => {
commit(types.SET_INSTANCE_TYPE, payload); commit(types.SET_INSTANCE_TYPE, payload);
}; };
......
...@@ -10,6 +10,7 @@ export const SET_SECURITY_GROUP = 'SET_SECURITY_GROUP'; ...@@ -10,6 +10,7 @@ export const SET_SECURITY_GROUP = 'SET_SECURITY_GROUP';
export const SET_INSTANCE_TYPE = 'SET_INSTANCE_TYPE'; export const SET_INSTANCE_TYPE = 'SET_INSTANCE_TYPE';
export const SET_NODE_COUNT = 'SET_NODE_COUNT'; export const SET_NODE_COUNT = 'SET_NODE_COUNT';
export const SET_GITLAB_MANAGED_CLUSTER = 'SET_GITLAB_MANAGED_CLUSTER'; export const SET_GITLAB_MANAGED_CLUSTER = 'SET_GITLAB_MANAGED_CLUSTER';
export const SET_NAMESPACE_PER_ENVIRONMENT = 'SET_NAMESPACE_PER_ENVIRONMENT';
export const REQUEST_CREATE_ROLE = 'REQUEST_CREATE_ROLE'; export const REQUEST_CREATE_ROLE = 'REQUEST_CREATE_ROLE';
export const CREATE_ROLE_SUCCESS = 'CREATE_ROLE_SUCCESS'; export const CREATE_ROLE_SUCCESS = 'CREATE_ROLE_SUCCESS';
export const CREATE_ROLE_ERROR = 'CREATE_ROLE_ERROR'; export const CREATE_ROLE_ERROR = 'CREATE_ROLE_ERROR';
......
...@@ -37,6 +37,9 @@ export default { ...@@ -37,6 +37,9 @@ export default {
[types.SET_GITLAB_MANAGED_CLUSTER](state, { gitlabManagedCluster }) { [types.SET_GITLAB_MANAGED_CLUSTER](state, { gitlabManagedCluster }) {
state.gitlabManagedCluster = gitlabManagedCluster; state.gitlabManagedCluster = gitlabManagedCluster;
}, },
[types.SET_NAMESPACE_PER_ENVIRONMENT](state, { namespacePerEnvironment }) {
state.namespacePerEnvironment = namespacePerEnvironment;
},
[types.REQUEST_CREATE_ROLE](state) { [types.REQUEST_CREATE_ROLE](state) {
state.isCreatingRole = true; state.isCreatingRole = true;
state.createRoleError = null; state.createRoleError = null;
......
...@@ -30,4 +30,5 @@ export default () => ({ ...@@ -30,4 +30,5 @@ export default () => ({
createClusterError: false, createClusterError: false,
gitlabManagedCluster: true, gitlabManagedCluster: true,
namespacePerEnvironment: true,
}); });
...@@ -180,13 +180,20 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -180,13 +180,20 @@ class Clusters::ClustersController < Clusters::BaseController
params.permit(:cleanup) params.permit(:cleanup)
end end
def base_permitted_cluster_params
[
:enabled,
:environment_scope,
:managed,
:namespace_per_environment
]
end
def update_params def update_params
if cluster.provided_by_user? if cluster.provided_by_user?
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, *base_permitted_cluster_params,
:name, :name,
:environment_scope,
:managed,
:base_domain, :base_domain,
:management_project_id, :management_project_id,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
...@@ -198,9 +205,7 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -198,9 +205,7 @@ class Clusters::ClustersController < Clusters::BaseController
) )
else else
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, *base_permitted_cluster_params,
:environment_scope,
:managed,
:base_domain, :base_domain,
:management_project_id, :management_project_id,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
...@@ -212,10 +217,8 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -212,10 +217,8 @@ class Clusters::ClustersController < Clusters::BaseController
def create_gcp_cluster_params def create_gcp_cluster_params
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, *base_permitted_cluster_params,
:name, :name,
:environment_scope,
:managed,
provider_gcp_attributes: [ provider_gcp_attributes: [
:gcp_project_id, :gcp_project_id,
:zone, :zone,
...@@ -232,10 +235,8 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -232,10 +235,8 @@ class Clusters::ClustersController < Clusters::BaseController
def create_aws_cluster_params def create_aws_cluster_params
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, *base_permitted_cluster_params,
:name, :name,
:environment_scope,
:managed,
provider_aws_attributes: [ provider_aws_attributes: [
:kubernetes_version, :kubernetes_version,
:key_name, :key_name,
...@@ -255,10 +256,8 @@ class Clusters::ClustersController < Clusters::BaseController ...@@ -255,10 +256,8 @@ class Clusters::ClustersController < Clusters::BaseController
def create_user_cluster_params def create_user_cluster_params
params.require(:cluster).permit( params.require(:cluster).permit(
:enabled, *base_permitted_cluster_params,
:name, :name,
:environment_scope,
:managed,
platform_kubernetes_attributes: [ platform_kubernetes_attributes: [
:namespace, :namespace,
:api_url, :api_url,
......
...@@ -7,6 +7,7 @@ class ClusterEntity < Grape::Entity ...@@ -7,6 +7,7 @@ class ClusterEntity < Grape::Entity
expose :enabled expose :enabled
expose :environment_scope expose :environment_scope
expose :id expose :id
expose :namespace_per_environment
expose :name expose :name
expose :nodes expose :nodes
expose :provider_type expose :provider_type
......
...@@ -42,11 +42,17 @@ ...@@ -42,11 +42,17 @@
class: 'js-gl-managed', class: 'js-gl-managed',
label_class: 'label-bold' } label_class: 'label-bold' }
.form-text.text-muted .form-text.text-muted
= s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.') = s_('ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank' = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
.form-group
= field.check_box :namespace_per_environment, { label: s_('ClusterIntegration|Namespace per environment'), label_class: 'label-bold' }
.form-text.text-muted
= s_('ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'custom-namespace'), target: '_blank'
- if cluster.allow_user_defined_namespace? - if cluster.allow_user_defined_namespace?
= render('clusters/clusters/namespace', platform_field: platform_field) = render('clusters/clusters/namespace', platform_field: platform_field, field: field)
.form-group .form-group
= field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success' = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
= s_('Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_start: documentation_link_start, link_end: '<a/>'.html_safe } = s_('Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_start: documentation_link_start, link_end: '<a/>'.html_safe }
- else - else
.js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), .js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'),
'namespace-per-environment-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'custom-namespace'),
'create-role-path' => clusterable.authorize_aws_role_path, 'create-role-path' => clusterable.authorize_aws_role_path,
'create-cluster-path' => clusterable.create_aws_clusters_path, 'create-cluster-path' => clusterable.create_aws_clusters_path,
'account-id' => Gitlab::CurrentSettings.eks_account_id, 'account-id' => Gitlab::CurrentSettings.eks_account_id,
......
...@@ -75,9 +75,15 @@ ...@@ -75,9 +75,15 @@
= field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'), = field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
label_class: 'label-bold' } label_class: 'label-bold' }
.form-text.text-muted .form-text.text-muted
= s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.') = s_('ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank' = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
.form-group
= field.check_box :namespace_per_environment, { label: s_('ClusterIntegration|Namespace per environment'), label_class: 'label-bold' }
.form-text.text-muted
= s_('ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'custom-namespace'), target: '_blank'
.form-group.js-gke-cluster-creation-submit-container .form-group.js-gke-cluster-creation-submit-container
= field.submit s_('ClusterIntegration|Create Kubernetes cluster'), = field.submit s_('ClusterIntegration|Create Kubernetes cluster'),
class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
...@@ -46,9 +46,15 @@ ...@@ -46,9 +46,15 @@
class: 'js-gl-managed', class: 'js-gl-managed',
label_class: 'label-bold' } label_class: 'label-bold' }
.form-text.text-muted .form-text.text-muted
= s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.') = s_('ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank' = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'), target: '_blank'
.form-group
= field.check_box :namespace_per_environment, { label: s_('ClusterIntegration|Namespace per environment'), label_class: 'label-bold' }
.form-text.text-muted
= s_('ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared.')
= link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'custom-namespace'), target: '_blank'
= field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field| = field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
- if @user_cluster.allow_user_defined_namespace? - if @user_cluster.allow_user_defined_namespace?
= render('clusters/clusters/namespace', platform_field: platform_kubernetes_field) = render('clusters/clusters/namespace', platform_field: platform_kubernetes_field)
......
---
title: Expose the option to use namespace-per-project instead of namespace-per-environment
for Kubernetes clusters
merge_request: 42309
author:
type: changed
...@@ -270,20 +270,30 @@ If your cluster was created before GitLab 12.2, default `KUBE_NAMESPACE` will be ...@@ -270,20 +270,30 @@ If your cluster was created before GitLab 12.2, default `KUBE_NAMESPACE` will be
### Custom namespace ### Custom namespace
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 12.6. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27630) in GitLab 12.6.
> - An option to use project-wide namespaces [was added](https://gitlab.com/gitlab-org/gitlab/-/issues/38054) in GitLab 13.5.
The Kubernetes integration defaults to project-environment-specific namespaces The Kubernetes integration provides a `KUBECONFIG` with an auto-generated namespace
of the form `<project_name>-<project_id>-<environment>` (see [Deployment to deployment jobs. It defaults to using project-environment specific namespaces
of the form `<prefix>-<environment>`, where `<prefix>` is of the form `<project_name>-<project_id>` (see [Deployment
variables](#deployment-variables)). variables](#deployment-variables)).
For **non**-GitLab-managed clusters, the namespace can be customized using The deployment namespace can be customized in a few ways:
[`environment:kubernetes:namespace`](../../../ci/environments/index.md#configuring-kubernetes-deployments)
- You can choose between a **namespace per [environment](../../../ci/environments/index.md)** or a **namespace per project**. A namespace per environment is the default and recommended setting, as it prevents the mixing of resources between production and non-production environments.
- When using a project-level cluster, you can additionally customize the namespace prefix. When using namespace-per-environment, the deployment namespace is `<prefix>-<environment>`, but otherwise just `<prefix>`.
- For **non-managed** clusters, the auto-generated namespace is set in the `KUBECONFIG`, but the user is responsible for ensuring its existence. The value can be fully customized using [`environment:kubernetes:namespace`](../../../ci/environments/index.md#configuring-kubernetes-deployments)
in `.gitlab-ci.yml`. in `.gitlab-ci.yml`.
NOTE: **Note:** NOTE: **Note:**
When using a [GitLab-managed cluster](#gitlab-managed-clusters), the When you customize the namespace, existing environments remain linked to their current namespaces until you [clear the cluster cache](#clearing-the-cluster-cache).
namespaces are created automatically prior to deployment and [can not be
customized](https://gitlab.com/gitlab-org/gitlab/-/issues/38054). CAUTION: **Warning:**
By default, anyone who can create a deployment job can access any CI variable within an environment's deployment job. This includes `KUBECONFIG`, which gives access to any secret available to the associated service account in your cluster.
To keep your production credentials safe, consider using [Protected Environments](../../../ci/environments/protected_environments.md), combined with either
- a GitLab-managed cluster and namespace per environment,
- *or*, an environment-scoped cluster per protected environment (the same cluster can be added multiple times with multiple restricted service accounts).
### Integrations ### Integrations
......
...@@ -37,6 +37,7 @@ module API ...@@ -37,6 +37,7 @@ module API
requires :name, type: String, desc: 'Cluster name' requires :name, type: String, desc: 'Cluster name'
optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true' optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true'
optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster' optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true' optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true'
...@@ -70,6 +71,7 @@ module API ...@@ -70,6 +71,7 @@ module API
optional :name, type: String, desc: 'Cluster name' optional :name, type: String, desc: 'Cluster name'
optional :enabled, type: Boolean, desc: 'Enable or disable Gitlab\'s connection to your Kubernetes cluster' optional :enabled, type: Boolean, desc: 'Enable or disable Gitlab\'s connection to your Kubernetes cluster'
optional :environment_scope, type: String, desc: 'The associated environment to the cluster' optional :environment_scope, type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
......
...@@ -4,7 +4,7 @@ module API ...@@ -4,7 +4,7 @@ module API
module Entities module Entities
class Cluster < Grape::Entity class Cluster < Grape::Entity
expose :id, :name, :created_at, :domain expose :id, :name, :created_at, :domain
expose :provider_type, :platform_type, :environment_scope, :cluster_type expose :provider_type, :platform_type, :environment_scope, :cluster_type, :namespace_per_environment
expose :user, using: Entities::UserBasic expose :user, using: Entities::UserBasic
expose :platform_kubernetes, using: Entities::Platform::Kubernetes expose :platform_kubernetes, using: Entities::Platform::Kubernetes
expose :provider_gcp, using: Entities::Provider::Gcp expose :provider_gcp, using: Entities::Provider::Gcp
......
...@@ -41,6 +41,7 @@ module API ...@@ -41,6 +41,7 @@ module API
requires :name, type: String, desc: 'Cluster name' requires :name, type: String, desc: 'Cluster name'
optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true' optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true'
optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster' optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true' optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true'
...@@ -74,6 +75,7 @@ module API ...@@ -74,6 +75,7 @@ module API
optional :name, type: String, desc: 'Cluster name' optional :name, type: String, desc: 'Cluster name'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :environment_scope, type: String, desc: 'The associated environment to the cluster' optional :environment_scope, type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
optional :api_url, type: String, desc: 'URL to access the Kubernetes API' optional :api_url, type: String, desc: 'URL to access the Kubernetes API'
......
...@@ -45,6 +45,7 @@ module API ...@@ -45,6 +45,7 @@ module API
optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true' optional :enabled, type: Boolean, default: true, desc: 'Determines if cluster is active or not, defaults to true'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster' optional :environment_scope, default: '*', type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true' optional :managed, type: Boolean, default: true, desc: 'Determines if GitLab will manage namespaces and service accounts for this cluster, defaults to true'
requires :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do requires :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
...@@ -78,6 +79,7 @@ module API ...@@ -78,6 +79,7 @@ module API
optional :name, type: String, desc: 'Cluster name' optional :name, type: String, desc: 'Cluster name'
optional :domain, type: String, desc: 'Cluster base domain' optional :domain, type: String, desc: 'Cluster base domain'
optional :environment_scope, type: String, desc: 'The associated environment to the cluster' optional :environment_scope, type: String, desc: 'The associated environment to the cluster'
optional :namespace_per_environment, default: true, type: Boolean, desc: 'Deploy each environment to a separate Kubernetes namespace'
optional :management_project_id, type: Integer, desc: 'The ID of the management project' optional :management_project_id, type: Integer, desc: 'The ID of the management project'
optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do optional :platform_kubernetes_attributes, type: Hash, desc: %q(Platform Kubernetes data) do
optional :api_url, type: String, desc: 'URL to access the Kubernetes API' optional :api_url, type: String, desc: 'URL to access the Kubernetes API'
......
...@@ -5379,10 +5379,10 @@ msgstr "" ...@@ -5379,10 +5379,10 @@ msgstr ""
msgid "ClusterIntegration|All installed applications and related resources" msgid "ClusterIntegration|All installed applications and related resources"
msgstr "" msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster." msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "" msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}" msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr "" msgstr ""
msgid "ClusterIntegration|Alternatively, " msgid "ClusterIntegration|Alternatively, "
...@@ -5565,6 +5565,12 @@ msgstr "" ...@@ -5565,6 +5565,12 @@ msgstr ""
msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal" msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
msgstr "" msgstr ""
msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared. %{startLink}More information%{endLink}"
msgstr ""
msgid "ClusterIntegration|Did you know?" msgid "ClusterIntegration|Did you know?"
msgstr "" msgstr ""
...@@ -5826,6 +5832,9 @@ msgstr "" ...@@ -5826,6 +5832,9 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}" msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
msgstr "" msgstr ""
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
msgid "ClusterIntegration|No IAM Roles found" msgid "ClusterIntegration|No IAM Roles found"
msgstr "" msgstr ""
......
...@@ -416,6 +416,7 @@ RSpec.describe Admin::ClustersController do ...@@ -416,6 +416,7 @@ RSpec.describe Admin::ClustersController do
expect(cluster).to be_user expect(cluster).to be_user
expect(cluster).to be_kubernetes expect(cluster).to be_kubernetes
expect(cluster).to be_platform_kubernetes_rbac expect(cluster).to be_platform_kubernetes_rbac
expect(cluster).to be_namespace_per_environment
end end
end end
end end
...@@ -585,6 +586,7 @@ RSpec.describe Admin::ClustersController do ...@@ -585,6 +586,7 @@ RSpec.describe Admin::ClustersController do
enabled: false, enabled: false,
name: 'my-new-cluster-name', name: 'my-new-cluster-name',
managed: false, managed: false,
namespace_per_environment: false,
base_domain: domain base_domain: domain
} }
} }
...@@ -599,6 +601,7 @@ RSpec.describe Admin::ClustersController do ...@@ -599,6 +601,7 @@ RSpec.describe Admin::ClustersController do
expect(cluster.enabled).to be_falsey expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name') expect(cluster.name).to eq('my-new-cluster-name')
expect(cluster).not_to be_managed expect(cluster).not_to be_managed
expect(cluster).not_to be_namespace_per_environment
expect(cluster.domain).to eq('test-domain.com') expect(cluster.domain).to eq('test-domain.com')
end end
...@@ -624,6 +627,7 @@ RSpec.describe Admin::ClustersController do ...@@ -624,6 +627,7 @@ RSpec.describe Admin::ClustersController do
enabled: false, enabled: false,
name: 'my-new-cluster-name', name: 'my-new-cluster-name',
managed: false, managed: false,
namespace_per_environment: false,
domain: domain domain: domain
} }
} }
...@@ -637,6 +641,7 @@ RSpec.describe Admin::ClustersController do ...@@ -637,6 +641,7 @@ RSpec.describe Admin::ClustersController do
expect(cluster.enabled).to be_falsey expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name') expect(cluster.name).to eq('my-new-cluster-name')
expect(cluster).not_to be_managed expect(cluster).not_to be_managed
expect(cluster).not_to be_namespace_per_environment
end end
end end
......
...@@ -271,6 +271,7 @@ RSpec.describe Groups::ClustersController do ...@@ -271,6 +271,7 @@ RSpec.describe Groups::ClustersController do
expect(cluster).to be_kubernetes expect(cluster).to be_kubernetes
expect(cluster.provider_gcp).to be_legacy_abac expect(cluster.provider_gcp).to be_legacy_abac
expect(cluster).to be_managed expect(cluster).to be_managed
expect(cluster).to be_namespace_per_environment
end end
context 'when legacy_abac param is false' do context 'when legacy_abac param is false' do
...@@ -358,6 +359,7 @@ RSpec.describe Groups::ClustersController do ...@@ -358,6 +359,7 @@ RSpec.describe Groups::ClustersController do
expect(cluster).to be_user expect(cluster).to be_user
expect(cluster).to be_kubernetes expect(cluster).to be_kubernetes
expect(cluster).to be_managed expect(cluster).to be_managed
expect(cluster).to be_namespace_per_environment
end end
end end
...@@ -387,6 +389,7 @@ RSpec.describe Groups::ClustersController do ...@@ -387,6 +389,7 @@ RSpec.describe Groups::ClustersController do
expect(cluster).to be_user expect(cluster).to be_user
expect(cluster).to be_kubernetes expect(cluster).to be_kubernetes
expect(cluster).to be_platform_kubernetes_rbac expect(cluster).to be_platform_kubernetes_rbac
expect(cluster).to be_namespace_per_environment
end end
end end
...@@ -716,6 +719,7 @@ RSpec.describe Groups::ClustersController do ...@@ -716,6 +719,7 @@ RSpec.describe Groups::ClustersController do
enabled: false, enabled: false,
name: 'my-new-cluster-name', name: 'my-new-cluster-name',
managed: false, managed: false,
namespace_per_environment: false,
domain: domain domain: domain
} }
} }
...@@ -729,6 +733,7 @@ RSpec.describe Groups::ClustersController do ...@@ -729,6 +733,7 @@ RSpec.describe Groups::ClustersController do
expect(cluster.enabled).to be_falsey expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name') expect(cluster.name).to eq('my-new-cluster-name')
expect(cluster).not_to be_managed expect(cluster).not_to be_managed
expect(cluster).not_to be_namespace_per_environment
end end
end end
......
...@@ -251,6 +251,7 @@ RSpec.describe Projects::ClustersController do ...@@ -251,6 +251,7 @@ RSpec.describe Projects::ClustersController do
cluster: { cluster: {
name: 'new-cluster', name: 'new-cluster',
managed: '1', managed: '1',
namespace_per_environment: '0',
provider_gcp_attributes: { provider_gcp_attributes: {
gcp_project_id: 'gcp-project-12345', gcp_project_id: 'gcp-project-12345',
legacy_abac: legacy_abac_param legacy_abac: legacy_abac_param
...@@ -278,6 +279,7 @@ RSpec.describe Projects::ClustersController do ...@@ -278,6 +279,7 @@ RSpec.describe Projects::ClustersController do
expect(project.clusters.first).to be_kubernetes expect(project.clusters.first).to be_kubernetes
expect(project.clusters.first.provider_gcp).to be_legacy_abac expect(project.clusters.first.provider_gcp).to be_legacy_abac
expect(project.clusters.first.managed?).to be_truthy expect(project.clusters.first.managed?).to be_truthy
expect(project.clusters.first.namespace_per_environment?).to be_falsy
end end
context 'when legacy_abac param is false' do context 'when legacy_abac param is false' do
...@@ -369,6 +371,7 @@ RSpec.describe Projects::ClustersController do ...@@ -369,6 +371,7 @@ RSpec.describe Projects::ClustersController do
expect(project.clusters.first).to be_user expect(project.clusters.first).to be_user
expect(project.clusters.first).to be_kubernetes expect(project.clusters.first).to be_kubernetes
expect(project.clusters.first).to be_namespace_per_environment
end end
end end
...@@ -400,6 +403,7 @@ RSpec.describe Projects::ClustersController do ...@@ -400,6 +403,7 @@ RSpec.describe Projects::ClustersController do
expect(cluster).to be_user expect(cluster).to be_user
expect(cluster).to be_kubernetes expect(cluster).to be_kubernetes
expect(cluster).to be_platform_kubernetes_rbac expect(cluster).to be_platform_kubernetes_rbac
expect(cluster).to be_namespace_per_environment
end end
end end
...@@ -726,6 +730,7 @@ RSpec.describe Projects::ClustersController do ...@@ -726,6 +730,7 @@ RSpec.describe Projects::ClustersController do
enabled: false, enabled: false,
name: 'my-new-cluster-name', name: 'my-new-cluster-name',
managed: false, managed: false,
namespace_per_environment: false,
platform_kubernetes_attributes: { platform_kubernetes_attributes: {
namespace: 'my-namespace' namespace: 'my-namespace'
} }
...@@ -742,6 +747,7 @@ RSpec.describe Projects::ClustersController do ...@@ -742,6 +747,7 @@ RSpec.describe Projects::ClustersController do
expect(cluster.enabled).to be_falsey expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name') expect(cluster.name).to eq('my-new-cluster-name')
expect(cluster).not_to be_managed expect(cluster).not_to be_managed
expect(cluster).not_to be_namespace_per_environment
expect(cluster.platform_kubernetes.namespace).to eq('my-namespace') expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end end
......
...@@ -66,6 +66,10 @@ RSpec.describe 'User Cluster', :js do ...@@ -66,6 +66,10 @@ RSpec.describe 'User Cluster', :js do
expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked expect(page.find_field('cluster[platform_kubernetes_attributes][authorization_type]', disabled: true)).to be_checked
end end
end end
it 'user sees namespace per environment is enabled by default' do
expect(page).to have_checked_field('Namespace per environment')
end
end end
context 'when user filled form with invalid parameters' do context 'when user filled form with invalid parameters' do
......
...@@ -52,6 +52,10 @@ RSpec.describe 'User Cluster', :js do ...@@ -52,6 +52,10 @@ RSpec.describe 'User Cluster', :js do
it 'user sees RBAC is enabled by default' do it 'user sees RBAC is enabled by default' do
expect(page).to have_checked_field('RBAC-enabled cluster') expect(page).to have_checked_field('RBAC-enabled cluster')
end end
it 'user sees namespace per environment is enabled by default' do
expect(page).to have_checked_field('Namespace per environment')
end
end end
context 'when user filled form with invalid parameters' do context 'when user filled form with invalid parameters' do
......
...@@ -12,6 +12,7 @@ describe('CreateEksCluster', () => { ...@@ -12,6 +12,7 @@ describe('CreateEksCluster', () => {
let vm; let vm;
let state; let state;
const gitlabManagedClusterHelpPath = 'gitlab-managed-cluster-help-path'; const gitlabManagedClusterHelpPath = 'gitlab-managed-cluster-help-path';
const namespacePerEnvironmentHelpPath = 'namespace-per-environment-help-path';
const accountAndExternalIdsHelpPath = 'account-and-external-id-help-path'; const accountAndExternalIdsHelpPath = 'account-and-external-id-help-path';
const createRoleArnHelpPath = 'role-arn-help-path'; const createRoleArnHelpPath = 'role-arn-help-path';
const kubernetesIntegrationHelpPath = 'kubernetes-integration'; const kubernetesIntegrationHelpPath = 'kubernetes-integration';
...@@ -26,6 +27,7 @@ describe('CreateEksCluster', () => { ...@@ -26,6 +27,7 @@ describe('CreateEksCluster', () => {
vm = shallowMount(CreateEksCluster, { vm = shallowMount(CreateEksCluster, {
propsData: { propsData: {
gitlabManagedClusterHelpPath, gitlabManagedClusterHelpPath,
namespacePerEnvironmentHelpPath,
accountAndExternalIdsHelpPath, accountAndExternalIdsHelpPath,
createRoleArnHelpPath, createRoleArnHelpPath,
externalLinkIcon, externalLinkIcon,
...@@ -53,6 +55,12 @@ describe('CreateEksCluster', () => { ...@@ -53,6 +55,12 @@ describe('CreateEksCluster', () => {
); );
}); });
it('help url for namespace per environment cluster documentation', () => {
expect(vm.find(EksClusterConfigurationForm).props('namespacePerEnvironmentHelpPath')).toBe(
namespacePerEnvironmentHelpPath,
);
});
it('help url for gitlab managed cluster documentation', () => { it('help url for gitlab managed cluster documentation', () => {
expect(vm.find(EksClusterConfigurationForm).props('kubernetesIntegrationHelpPath')).toBe( expect(vm.find(EksClusterConfigurationForm).props('kubernetesIntegrationHelpPath')).toBe(
kubernetesIntegrationHelpPath, kubernetesIntegrationHelpPath,
......
...@@ -169,6 +169,7 @@ describe('EksClusterConfigurationForm', () => { ...@@ -169,6 +169,7 @@ describe('EksClusterConfigurationForm', () => {
store, store,
propsData: { propsData: {
gitlabManagedClusterHelpPath: '', gitlabManagedClusterHelpPath: '',
namespacePerEnvironmentHelpPath: '',
kubernetesIntegrationHelpPath: '', kubernetesIntegrationHelpPath: '',
externalLinkIcon: '', externalLinkIcon: '',
}, },
......
...@@ -14,6 +14,7 @@ import { ...@@ -14,6 +14,7 @@ import {
SET_ROLE, SET_ROLE,
SET_SECURITY_GROUP, SET_SECURITY_GROUP,
SET_GITLAB_MANAGED_CLUSTER, SET_GITLAB_MANAGED_CLUSTER,
SET_NAMESPACE_PER_ENVIRONMENT,
SET_INSTANCE_TYPE, SET_INSTANCE_TYPE,
SET_NODE_COUNT, SET_NODE_COUNT,
REQUEST_CREATE_ROLE, REQUEST_CREATE_ROLE,
...@@ -40,6 +41,7 @@ describe('EKS Cluster Store Actions', () => { ...@@ -40,6 +41,7 @@ describe('EKS Cluster Store Actions', () => {
let instanceType; let instanceType;
let nodeCount; let nodeCount;
let gitlabManagedCluster; let gitlabManagedCluster;
let namespacePerEnvironment;
let mock; let mock;
let state; let state;
let newClusterUrl; let newClusterUrl;
...@@ -57,6 +59,7 @@ describe('EKS Cluster Store Actions', () => { ...@@ -57,6 +59,7 @@ describe('EKS Cluster Store Actions', () => {
instanceType = 'small-1'; instanceType = 'small-1';
nodeCount = '5'; nodeCount = '5';
gitlabManagedCluster = true; gitlabManagedCluster = true;
namespacePerEnvironment = true;
newClusterUrl = '/clusters/1'; newClusterUrl = '/clusters/1';
...@@ -76,19 +79,20 @@ describe('EKS Cluster Store Actions', () => { ...@@ -76,19 +79,20 @@ describe('EKS Cluster Store Actions', () => {
}); });
it.each` it.each`
action | mutation | payload | payloadDescription action | mutation | payload | payloadDescription
${'setClusterName'} | ${SET_CLUSTER_NAME} | ${{ clusterName }} | ${'cluster name'} ${'setClusterName'} | ${SET_CLUSTER_NAME} | ${{ clusterName }} | ${'cluster name'}
${'setEnvironmentScope'} | ${SET_ENVIRONMENT_SCOPE} | ${{ environmentScope }} | ${'environment scope'} ${'setEnvironmentScope'} | ${SET_ENVIRONMENT_SCOPE} | ${{ environmentScope }} | ${'environment scope'}
${'setKubernetesVersion'} | ${SET_KUBERNETES_VERSION} | ${{ kubernetesVersion }} | ${'kubernetes version'} ${'setKubernetesVersion'} | ${SET_KUBERNETES_VERSION} | ${{ kubernetesVersion }} | ${'kubernetes version'}
${'setRole'} | ${SET_ROLE} | ${{ role }} | ${'role'} ${'setRole'} | ${SET_ROLE} | ${{ role }} | ${'role'}
${'setRegion'} | ${SET_REGION} | ${{ region }} | ${'region'} ${'setRegion'} | ${SET_REGION} | ${{ region }} | ${'region'}
${'setKeyPair'} | ${SET_KEY_PAIR} | ${{ keyPair }} | ${'key pair'} ${'setKeyPair'} | ${SET_KEY_PAIR} | ${{ keyPair }} | ${'key pair'}
${'setVpc'} | ${SET_VPC} | ${{ vpc }} | ${'vpc'} ${'setVpc'} | ${SET_VPC} | ${{ vpc }} | ${'vpc'}
${'setSubnet'} | ${SET_SUBNET} | ${{ subnet }} | ${'subnet'} ${'setSubnet'} | ${SET_SUBNET} | ${{ subnet }} | ${'subnet'}
${'setSecurityGroup'} | ${SET_SECURITY_GROUP} | ${{ securityGroup }} | ${'securityGroup'} ${'setSecurityGroup'} | ${SET_SECURITY_GROUP} | ${{ securityGroup }} | ${'securityGroup'}
${'setInstanceType'} | ${SET_INSTANCE_TYPE} | ${{ instanceType }} | ${'instance type'} ${'setInstanceType'} | ${SET_INSTANCE_TYPE} | ${{ instanceType }} | ${'instance type'}
${'setNodeCount'} | ${SET_NODE_COUNT} | ${{ nodeCount }} | ${'node count'} ${'setNodeCount'} | ${SET_NODE_COUNT} | ${{ nodeCount }} | ${'node count'}
${'setGitlabManagedCluster'} | ${SET_GITLAB_MANAGED_CLUSTER} | ${gitlabManagedCluster} | ${'gitlab managed cluster'} ${'setGitlabManagedCluster'} | ${SET_GITLAB_MANAGED_CLUSTER} | ${gitlabManagedCluster} | ${'gitlab managed cluster'}
${'setNamespacePerEnvironment'} | ${SET_NAMESPACE_PER_ENVIRONMENT} | ${namespacePerEnvironment} | ${'namespace per environment'}
`(`$action commits $mutation with $payloadDescription payload`, data => { `(`$action commits $mutation with $payloadDescription payload`, data => {
const { action, mutation, payload } = data; const { action, mutation, payload } = data;
...@@ -179,6 +183,7 @@ describe('EKS Cluster Store Actions', () => { ...@@ -179,6 +183,7 @@ describe('EKS Cluster Store Actions', () => {
name: clusterName, name: clusterName,
environment_scope: environmentScope, environment_scope: environmentScope,
managed: gitlabManagedCluster, managed: gitlabManagedCluster,
namespace_per_environment: namespacePerEnvironment,
provider_aws_attributes: { provider_aws_attributes: {
kubernetes_version: kubernetesVersion, kubernetes_version: kubernetesVersion,
region, region,
...@@ -204,6 +209,7 @@ describe('EKS Cluster Store Actions', () => { ...@@ -204,6 +209,7 @@ describe('EKS Cluster Store Actions', () => {
selectedInstanceType: instanceType, selectedInstanceType: instanceType,
nodeCount, nodeCount,
gitlabManagedCluster, gitlabManagedCluster,
namespacePerEnvironment,
}); });
}); });
......
...@@ -47,6 +47,7 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do ...@@ -47,6 +47,7 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to delegate_method(:external_hostname).to(:application_ingress).with_prefix } it { is_expected.to delegate_method(:external_hostname).to(:application_ingress).with_prefix }
it { is_expected.to respond_to :project } it { is_expected.to respond_to :project }
it { is_expected.to be_namespace_per_environment }
describe 'applications have inverse_of: :cluster option' do describe 'applications have inverse_of: :cluster option' do
let(:cluster) { create(:cluster) } let(:cluster) { create(:cluster) }
......
...@@ -162,6 +162,7 @@ RSpec.describe ::API::Admin::InstanceClusters do ...@@ -162,6 +162,7 @@ RSpec.describe ::API::Admin::InstanceClusters do
name: 'test-instance-cluster', name: 'test-instance-cluster',
domain: 'domain.example.com', domain: 'domain.example.com',
managed: false, managed: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes, platform_kubernetes_attributes: platform_kubernetes_attributes,
clusterable: clusterable clusterable: clusterable
} }
...@@ -206,6 +207,7 @@ RSpec.describe ::API::Admin::InstanceClusters do ...@@ -206,6 +207,7 @@ RSpec.describe ::API::Admin::InstanceClusters do
expect(cluster_result.enabled).to eq(true) expect(cluster_result.enabled).to eq(true)
expect(platform_kubernetes.authorization_type).to eq('rbac') expect(platform_kubernetes.authorization_type).to eq('rbac')
expect(cluster_result.managed).to be_falsy expect(cluster_result.managed).to be_falsy
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.api_url).to eq("https://example.com") expect(platform_kubernetes.api_url).to eq("https://example.com")
expect(platform_kubernetes.token).to eq('sample-token') expect(platform_kubernetes.token).to eq('sample-token')
end end
...@@ -235,6 +237,22 @@ RSpec.describe ::API::Admin::InstanceClusters do ...@@ -235,6 +237,22 @@ RSpec.describe ::API::Admin::InstanceClusters do
end end
end end
context 'when namespace_per_environment is not set' do
let(:cluster_params) do
{
name: 'test-cluster',
domain: 'domain.example.com',
platform_kubernetes_attributes: platform_kubernetes_attributes
}
end
it 'defaults to true' do
cluster_result = Clusters::Cluster.find(json_response['id'])
expect(cluster_result).to be_namespace_per_environment
end
end
context 'when an instance cluster already exists' do context 'when an instance cluster already exists' do
it 'allows user to add multiple clusters' do it 'allows user to add multiple clusters' do
post api('/admin/clusters/add', admin_user), params: multiple_cluster_params post api('/admin/clusters/add', admin_user), params: multiple_cluster_params
......
...@@ -172,6 +172,7 @@ RSpec.describe API::GroupClusters do ...@@ -172,6 +172,7 @@ RSpec.describe API::GroupClusters do
name: 'test-cluster', name: 'test-cluster',
domain: 'domain.example.com', domain: 'domain.example.com',
managed: false, managed: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes, platform_kubernetes_attributes: platform_kubernetes_attributes,
management_project_id: management_project_id management_project_id: management_project_id
} }
...@@ -206,6 +207,7 @@ RSpec.describe API::GroupClusters do ...@@ -206,6 +207,7 @@ RSpec.describe API::GroupClusters do
expect(cluster_result.domain).to eq('domain.example.com') expect(cluster_result.domain).to eq('domain.example.com')
expect(cluster_result.managed).to be_falsy expect(cluster_result.managed).to be_falsy
expect(cluster_result.management_project_id).to eq management_project_id expect(cluster_result.management_project_id).to eq management_project_id
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.rbac?).to be_truthy expect(platform_kubernetes.rbac?).to be_truthy
expect(platform_kubernetes.api_url).to eq(api_url) expect(platform_kubernetes.api_url).to eq(api_url)
expect(platform_kubernetes.token).to eq('sample-token') expect(platform_kubernetes.token).to eq('sample-token')
...@@ -237,6 +239,22 @@ RSpec.describe API::GroupClusters do ...@@ -237,6 +239,22 @@ RSpec.describe API::GroupClusters do
end end
end end
context 'when namespace_per_environment is not set' do
let(:cluster_params) do
{
name: 'test-cluster',
domain: 'domain.example.com',
platform_kubernetes_attributes: platform_kubernetes_attributes
}
end
it 'defaults to true' do
cluster_result = Clusters::Cluster.find(json_response['id'])
expect(cluster_result).to be_namespace_per_environment
end
end
context 'current user does not have access to management_project_id' do context 'current user does not have access to management_project_id' do
let(:management_project_id) { create(:project).id } let(:management_project_id) { create(:project).id }
......
...@@ -171,6 +171,7 @@ RSpec.describe API::ProjectClusters do ...@@ -171,6 +171,7 @@ RSpec.describe API::ProjectClusters do
name: 'test-cluster', name: 'test-cluster',
domain: 'domain.example.com', domain: 'domain.example.com',
managed: false, managed: false,
namespace_per_environment: false,
platform_kubernetes_attributes: platform_kubernetes_attributes, platform_kubernetes_attributes: platform_kubernetes_attributes,
management_project_id: management_project_id management_project_id: management_project_id
} }
...@@ -202,6 +203,7 @@ RSpec.describe API::ProjectClusters do ...@@ -202,6 +203,7 @@ RSpec.describe API::ProjectClusters do
expect(cluster_result.domain).to eq('domain.example.com') expect(cluster_result.domain).to eq('domain.example.com')
expect(cluster_result.managed).to be_falsy expect(cluster_result.managed).to be_falsy
expect(cluster_result.management_project_id).to eq management_project_id expect(cluster_result.management_project_id).to eq management_project_id
expect(cluster_result.namespace_per_environment).to eq(false)
expect(platform_kubernetes.rbac?).to be_truthy expect(platform_kubernetes.rbac?).to be_truthy
expect(platform_kubernetes.api_url).to eq(api_url) expect(platform_kubernetes.api_url).to eq(api_url)
expect(platform_kubernetes.namespace).to eq(namespace) expect(platform_kubernetes.namespace).to eq(namespace)
...@@ -235,6 +237,22 @@ RSpec.describe API::ProjectClusters do ...@@ -235,6 +237,22 @@ RSpec.describe API::ProjectClusters do
end end
end end
context 'when namespace_per_environment is not set' do
let(:cluster_params) do
{
name: 'test-cluster',
domain: 'domain.example.com',
platform_kubernetes_attributes: platform_kubernetes_attributes
}
end
it 'defaults to true' do
cluster_result = Clusters::Cluster.find(json_response['id'])
expect(cluster_result).to be_namespace_per_environment
end
end
context 'current user does not have access to management_project_id' do context 'current user does not have access to management_project_id' do
let(:management_project_id) { create(:project).id } let(:management_project_id) { create(:project).id }
......
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