Commit 8463632f authored by anna_vovchenko's avatar anna_vovchenko Committed by Anna Vovchenko

Added a create cluster page for the FF

As we want to remove certificate-based cluster creation functionality,
we create a new page for cluster creation that leads to the docs.

Changelog: added
parent 4d048f64
<script>
import {
GlButton,
GlDropdown,
GlDropdownItem,
GlModalDirective,
......@@ -15,7 +14,6 @@ export default {
i18n: CLUSTERS_ACTIONS,
INSTALL_AGENT_MODAL_ID,
components: {
GlButton,
GlDropdown,
GlDropdownItem,
GlDropdownDivider,
......@@ -28,6 +26,7 @@ export default {
inject: [
'newClusterPath',
'addClusterPath',
'createClusterPath',
'canAddCluster',
'displayClusterAgents',
'certificateBasedClustersEnabled',
......@@ -47,6 +46,9 @@ export default {
shouldTriggerModal() {
return this.canAddCluster && this.displayClusterAgents;
},
hasSectionHeaders() {
return this.displayClusterAgents && this.certificateBasedClustersEnabled;
},
},
};
</script>
......@@ -54,7 +56,6 @@ export default {
<template>
<div class="nav-controls gl-ml-auto">
<gl-dropdown
v-if="certificateBasedClustersEnabled"
ref="dropdown"
v-gl-modal-directive="shouldTriggerModal && $options.INSTALL_AGENT_MODAL_ID"
v-gl-tooltip="tooltip"
......@@ -65,34 +66,36 @@ export default {
:split="displayClusterAgents"
right
>
<gl-dropdown-section-header v-if="hasSectionHeaders">{{
$options.i18n.agent
}}</gl-dropdown-section-header>
<template v-if="displayClusterAgents">
<gl-dropdown-section-header>{{ $options.i18n.agent }}</gl-dropdown-section-header>
<gl-dropdown-item
v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
data-testid="connect-new-agent-link"
>
{{ $options.i18n.connectWithAgent }}
</gl-dropdown-item>
<gl-dropdown-item :href="createClusterPath" data-testid="create-cluster-link" @click.stop>
{{ $options.i18n.createAndConnectCluster }}
</gl-dropdown-item>
</template>
<template v-if="hasSectionHeaders">
<gl-dropdown-divider />
<gl-dropdown-section-header>{{ $options.i18n.certificate }}</gl-dropdown-section-header>
</template>
<gl-dropdown-item :href="newClusterPath" data-testid="new-cluster-link" @click.stop>
{{ $options.i18n.createNewCluster }}
</gl-dropdown-item>
<gl-dropdown-item :href="addClusterPath" data-testid="connect-cluster-link" @click.stop>
{{ $options.i18n.connectExistingCluster }}
</gl-dropdown-item>
<template v-if="certificateBasedClustersEnabled">
<gl-dropdown-item :href="newClusterPath" data-testid="new-cluster-link" @click.stop>
{{ $options.i18n.createNewCluster }}
</gl-dropdown-item>
<gl-dropdown-item :href="addClusterPath" data-testid="connect-cluster-link" @click.stop>
{{ $options.i18n.connectExistingCluster }}
</gl-dropdown-item>
</template>
</gl-dropdown>
<gl-button
v-else
v-gl-modal-directive="$options.INSTALL_AGENT_MODAL_ID"
v-gl-tooltip="tooltip"
:disabled="!canAddCluster"
category="primary"
variant="confirm"
>
{{ $options.i18n.connectWithAgent }}
</gl-button>
</div>
</template>
......@@ -254,10 +254,11 @@ export const CLUSTERS_TABS = [ALL_TAB, AGENT_TAB, CERTIFICATE_TAB];
export const CLUSTERS_ACTIONS = {
actionsButton: s__('ClusterAgents|Actions'),
createNewCluster: s__('ClusterAgents|Create a new cluster'),
createAndConnectCluster: s__('ClusterAgents|Create and connect new cluster'),
connectWithAgent: s__('ClusterAgents|Connect with an agent'),
connectExistingCluster: s__('ClusterAgents|Connect with a certificate'),
agent: s__('ClusterAgents|Agent'),
certificate: s__('ClusterAgents|Certificate'),
certificate: s__('ClusterAgents|Certificate (deprecated)'),
dropdownDisabledHint: s__(
'ClusterAgents|Requires a Maintainer or greater role to perform these actions',
),
......
......@@ -25,6 +25,7 @@ export default () => {
kasAddress,
newClusterPath,
addClusterPath,
createClusterPath,
emptyStateHelpText,
clustersEmptyStateImage,
canAddCluster,
......@@ -43,6 +44,7 @@ export default () => {
kasAddress,
newClusterPath,
addClusterPath,
createClusterPath,
emptyStateHelpText,
clustersEmptyStateImage,
canAddCluster: parseBoolean(canAddCluster),
......
......@@ -19,6 +19,7 @@ module ClustersHelper
empty_state_help_text: clusterable.empty_state_help_text,
new_cluster_path: clusterable.new_path,
add_cluster_path: clusterable.connect_path,
create_cluster_path: clusterable.create_path,
can_add_cluster: clusterable.can_add_cluster?.to_s,
can_admin_cluster: clusterable.can_admin_cluster?.to_s,
display_cluster_agents: display_cluster_agents?(clusterable).to_s,
......
......@@ -36,6 +36,10 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated
polymorphic_path([clusterable, :clusters], action: :connect)
end
def create_path
polymorphic_path([clusterable, :clusters], action: :create_cluster)
end
def authorize_aws_role_path
polymorphic_path([clusterable, :clusters], action: :authorize_aws_role)
end
......
......@@ -31,7 +31,7 @@ class GroupClusterablePresenter < ClusterablePresenter
end
override :learn_more_link
def learn_more_link
def learn_more_link(docs_mode = false)
ApplicationController.helpers.link_to(s_('ClusterIntegration|Learn more about group Kubernetes clusters'), help_page_path('user/group/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
end
......
......@@ -43,6 +43,11 @@ class InstanceClusterablePresenter < ClusterablePresenter
connect_admin_clusters_path
end
override :create_path
def create_path
nil
end
override :create_user_clusters_path
def create_user_clusters_path
create_user_admin_clusters_path
......@@ -74,7 +79,7 @@ class InstanceClusterablePresenter < ClusterablePresenter
end
override :learn_more_link
def learn_more_link
def learn_more_link(docs_mode = false)
ApplicationController.helpers.link_to(s_('ClusterIntegration|Learn more about instance Kubernetes clusters'), help_page_path('user/instance/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
end
......
......@@ -26,8 +26,12 @@ class ProjectClusterablePresenter < ClusterablePresenter
end
override :learn_more_link
def learn_more_link
ApplicationController.helpers.link_to(s_('ClusterIntegration|Learn more about Kubernetes.'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
def learn_more_link(docs_mode = false)
if docs_mode
ApplicationController.helpers.link_to(s_('ClusterIntegration|Learn more about our integrations.'), help_page_path('user/infrastructure/iac/index', anchor: 'create-a-new-cluster-through-iac'))
else
ApplicationController.helpers.link_to(s_('ClusterIntegration|Learn more about Kubernetes.'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
end
end
def metrics_dashboard_path(cluster)
......
- docs_mode = local_assigns.fetch(:docs_mode, false)
%h3
= s_('ClusterIntegration|Connect a Kubernetes cluster')
%p
= clusterable.sidebar_text
%p
= clusterable.learn_more_link
= clusterable.learn_more_link(docs_mode)
= render 'clusters/clusters/multiple_clusters_message'
- if !docs_mode
= render 'clusters/clusters/multiple_clusters_message'
- provider = local_assigns.fetch(:provider)
- is_current_provider = provider == params[:provider]
- logo_path = local_assigns.fetch(:logo_path)
- help_path = local_assigns.fetch(:help_path)
- label = local_assigns.fetch(:label)
- last = local_assigns.fetch(:last, false)
- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-w-half js-create-#{provider}-cluster-button"]
- conditional_classes = [('gl-mr-5' unless last), ('active' if is_current_provider)]
- docs_mode = local_assigns.fetch(:docs_mode, false)
- classes = ["btn btn-confirm gl-button btn-confirm-secondary gl-flex-direction-column gl-w-half"]
- conditional_classes = [("gl-mr-5" unless last), ("active" if is_current_provider && !docs_mode), ("js-create-#{provider}-cluster-button" if !docs_mode)]
- link = docs_mode ? help_path : clusterable.new_path(provider: provider)
= link_to clusterable.new_path(provider: provider), class: classes + conditional_classes do
.svg-content.gl-p-3= image_tag logo_path, alt: label, class: 'gl-w-64 gl-h-64'
= link_to link, class: classes + conditional_classes do
.svg-content.gl-p-3= image_tag logo_path, alt: label, class: "gl-w-64 gl-h-64"
%span
= label
- gke_label = s_('ClusterIntegration|Google GKE')
- eks_label = s_('ClusterIntegration|Amazon EKS')
- create_cluster_label = s_('ClusterIntegration|Where do you want to create a cluster?')
- eks_help_path = help_page_path('user/infrastructure/clusters/connect/new_eks_cluster')
- gke_help_path = help_page_path('user/infrastructure/clusters/connect/new_gke_cluster')
- docs_mode = local_assigns.fetch(:docs_mode, false)
.gl-p-5
%h4.gl-mb-5
= create_cluster_label
.gl-display-flex
= render partial: 'clusters/clusters/cloud_providers/cloud_provider_button',
locals: { provider: 'aws', label: eks_label, logo_path: 'illustrations/logos/amazon_eks.svg' }
locals: { provider: 'aws', label: eks_label, logo_path: 'illustrations/logos/amazon_eks.svg', help_path: eks_help_path, docs_mode: docs_mode }
= render partial: 'clusters/clusters/cloud_providers/cloud_provider_button',
locals: { provider: 'gcp', label: gke_label, logo_path: 'illustrations/logos/google_gke.svg', last: true }
locals: { provider: 'gcp', label: gke_label, logo_path: 'illustrations/logos/google_gke.svg', help_path: gke_help_path, docs_mode: docs_mode, last: true }
- @content_class = 'limit-container-width' unless fluid_layout
- add_to_breadcrumbs _('Kubernetes Clusters'), clusterable.index_path
- breadcrumb_title _('Create a cluster')
- page_title _('Create a Kubernetes cluster')
- docs_mode = true
= render_gcp_signup_offer
.row.gl-mt-3
.col-md-3
= render 'sidebar', docs_mode: docs_mode
.col-md-9
= render 'clusters/clusters/cloud_providers/cloud_provider_selector', docs_mode: docs_mode
......@@ -237,6 +237,7 @@ Rails.application.routes.draw do
resources :clusters, only: [:index, :new, :show, :update, :destroy] do
collection do
get :connect
get :create_cluster
post :create_user
post :create_gcp
post :create_aws
......
......@@ -7873,6 +7873,9 @@ msgstr ""
msgid "ClusterAgents|Certificate"
msgstr ""
msgid "ClusterAgents|Certificate (deprecated)"
msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
......@@ -7912,6 +7915,9 @@ msgstr ""
msgid "ClusterAgents|Create agent: %{searchTerm}"
msgstr ""
msgid "ClusterAgents|Create and connect new cluster"
msgstr ""
msgid "ClusterAgents|Create token"
msgstr ""
......@@ -8451,6 +8457,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Learn more about our integrations."
msgstr ""
msgid "ClusterIntegration|Loading IAM Roles"
msgstr ""
......
import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import ClustersActions from '~/clusters_list/components/clusters_actions.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
......@@ -7,12 +7,14 @@ import { INSTALL_AGENT_MODAL_ID, CLUSTERS_ACTIONS } from '~/clusters_list/consta
describe('ClustersActionsComponent', () => {
let wrapper;
const newClusterPath = 'path/to/create/cluster';
const newClusterPath = 'path/to/add/cluster';
const addClusterPath = 'path/to/connect/existing/cluster';
const createClusterPath = 'path/to/create/new/cluster';
const defaultProvide = {
newClusterPath,
addClusterPath,
createClusterPath,
canAddCluster: true,
displayClusterAgents: true,
certificateBasedClustersEnabled: true,
......@@ -22,10 +24,11 @@ describe('ClustersActionsComponent', () => {
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findDropdownItemIds = () =>
findDropdownItems().wrappers.map((x) => x.attributes('data-testid'));
const findAllSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
const findSectionHeadersTexts = () => findAllSectionHeaders().wrappers.map((x) => x.text());
const findNewClusterLink = () => wrapper.findByTestId('new-cluster-link');
const findConnectClusterLink = () => wrapper.findByTestId('connect-cluster-link');
const findConnectNewAgentLink = () => wrapper.findByTestId('connect-new-agent-link');
const findConnectWithAgentButton = () => wrapper.findComponent(GlButton);
const createWrapper = (provideData = {}) => {
wrapper = shallowMountExtended(ClustersActions, {
......@@ -82,11 +85,19 @@ describe('ClustersActionsComponent', () => {
it('renders a dropdown with 3 actions items', () => {
expect(findDropdownItemIds()).toEqual([
'connect-new-agent-link',
'create-cluster-link',
'new-cluster-link',
'connect-cluster-link',
]);
});
it('renders proper section headers', () => {
expect(findSectionHeadersTexts()).toEqual([
CLUSTERS_ACTIONS.agent,
CLUSTERS_ACTIONS.certificate,
]);
});
it('renders correct modal id for the agent link', () => {
const binding = getBinding(findConnectNewAgentLink().element, 'gl-modal-directive');
......@@ -118,6 +129,10 @@ describe('ClustersActionsComponent', () => {
expect(findDropdownItemIds()).toEqual(['new-cluster-link', 'connect-cluster-link']);
});
it("doesn't render section headers", () => {
expect(findAllSectionHeaders()).toHaveLength(0);
});
it('shows tooltip', () => {
const tooltip = getBinding(findDropdown().element, 'gl-tooltip');
expect(tooltip.value).toBe(CLUSTERS_ACTIONS.connectExistingCluster);
......@@ -140,17 +155,12 @@ describe('ClustersActionsComponent', () => {
createWrapper({ certificateBasedClustersEnabled: false });
});
it('it does not show the the dropdown', () => {
expect(findDropdown().exists()).toBe(false);
it('renders a dropdown with 2 actions items', () => {
expect(findDropdownItemIds()).toEqual(['connect-new-agent-link', 'create-cluster-link']);
});
it('shows the connect with agent button', () => {
expect(findConnectWithAgentButton().props()).toMatchObject({
disabled: !defaultProvide.canAddCluster,
category: 'primary',
variant: 'confirm',
});
expect(findConnectWithAgentButton().text()).toBe(CLUSTERS_ACTIONS.connectWithAgent);
it("doesn't render section headers", () => {
expect(findAllSectionHeaders()).toHaveLength(0);
});
});
});
......@@ -74,6 +74,10 @@ RSpec.describe ClustersHelper do
expect(subject[:add_cluster_path]).to eq("#{project_path(project)}/-/clusters/connect")
end
it 'displays create cluster path' do
expect(subject[:create_cluster_path]).to eq("#{project_path(project)}/-/clusters/create_cluster")
end
it 'displays project default branch' do
expect(subject[:default_branch_name]).to eq(project.default_branch)
end
......
......@@ -49,6 +49,12 @@ RSpec.describe ProjectClusterablePresenter do
it { is_expected.to eq(connect_project_clusters_path(project)) }
end
describe '#create_path' do
subject { presenter.create_path }
it { is_expected.to eq(create_cluster_project_clusters_path(project)) }
end
describe '#authorize_aws_role_path' do
subject { presenter.authorize_aws_role_path }
......@@ -92,8 +98,18 @@ RSpec.describe ProjectClusterablePresenter do
end
describe '#learn_more_link' do
subject { presenter.learn_more_link }
subject { presenter.learn_more_link(docs_mode) }
context 'feature flag is enabled' do
let(:docs_mode) { true }
it { is_expected.to include('user/project/clusters/index') }
it { is_expected.to include('help/user/infrastructure/iac/index#create-a-new-cluster-through-iac') }
end
context 'feature flag is disabled' do
let(:docs_mode) { false }
it { is_expected.to include('user/project/clusters/index') }
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