diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..d185457aeb386a61a6e6d172965de1ab0214d316 --- /dev/null +++ b/app/controllers/projects/google_cloud_controller.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Projects::GoogleCloudController < Projects::ApplicationController + before_action :authorize_can_manage_google_cloud_deployments! + + feature_category :release_orchestration + + def index + end + + private + + def authorize_can_manage_google_cloud_deployments! + access_denied! unless can?(current_user, :manage_project_google_cloud, project) + end +end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index c9f71e247ae5ca0b1e684a46fc158ac4f0d82500..59aa47beff9c4916d28c8bcd5507ecd4766dacee 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -438,6 +438,7 @@ class ProjectPolicy < BasePolicy enable :destroy_freeze_period enable :admin_feature_flags_client enable :update_runners_registration_token + enable :manage_project_google_cloud end rule { public_project & metrics_dashboard_allowed }.policy do diff --git a/app/views/projects/google_cloud/index.html.haml b/app/views/projects/google_cloud/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..4fc66e17810a0235c492ad499129f01aa6f5ad76 --- /dev/null +++ b/app/views/projects/google_cloud/index.html.haml @@ -0,0 +1,83 @@ +- breadcrumb_title _('Google Cloud') +- page_title _('Google Cloud') + +- @content_class = "limit-container-width" unless fluid_layout + +#js-google-cloud + + %h1.gl-font-size-h1 Google Cloud + + %section#js-section-google-cloud-service-accounts + + %h2.gl-font-size-h2 Service Accounts + + %p= _('Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project.') + + %table.table.b-table.gl-table + + %thead + %tr + %th Environment + %th GCP Project ID + %th Service Account Key + + %tbody + + %tr + %td * + %td serving-salutes-453 + %td ..... + + %tr + %td production + %td crimson-corey-234 + %td ..... + + %tr + %td review/* + %td roving-river-379 + %td ..... + + %a.gl-button.btn.btn-primary= _('Add new service account') + + %br + + %section#js-section-google-cloud-deployments + + .row.row-fluid + + .col-lg-4 + %h2.gl-font-size-h2 Deployments + %p= _('Google Cloud offers several deployment targets. Select the one most suitable for your project.') + %p + = _('Deployments to Google Kubernetes Engine can be ') + %a{ href: '#' }= _('managed') + = _('in Infrastructure :: Kubernetes clusters') + + .col-lg-8 + + %br + + .gl-card.gl-mb-6 + .gl-card-body + .gl-display-flex.gl-align-items-baseline + %strong.gl-font-lg App Engine + .gl-ml-auto.gl-text-gray-500 Disabled + %p= _('App Engine description and apps that are suitable for this deployment target') + %button.gl-button.btn.btn-default= _('Configure via Merge Request') + + .gl-card.gl-mb-6 + .gl-card-body + .gl-display-flex.gl-align-items-baseline + %strong.gl-font-lg Cloud Functions + .gl-ml-auto.gl-text-gray-500 Disabled + %p= _('Cloud Functions description and apps that are suitable for this deployment target') + %button.gl-button.btn.btn-default= _('Configure via Merge Request') + + .gl-card.gl-mb-6 + .gl-card-body + .gl-display-flex.gl-align-items-baseline + %strong.gl-font-lg Cloud Run + .gl-ml-auto.gl-text-gray-500 Disabled + %p= _('Cloud Run description and apps that are suitable for this deployment target') + %button.gl-button.btn.btn-default= _('Configure via Merge Request') diff --git a/config/feature_flags/development/incubation_5mp_google_cloud.yml b/config/feature_flags/development/incubation_5mp_google_cloud.yml new file mode 100644 index 0000000000000000000000000000000000000000..b687a656b40632e6fb9217fe6c3740a383e51e30 --- /dev/null +++ b/config/feature_flags/development/incubation_5mp_google_cloud.yml @@ -0,0 +1,8 @@ +--- +name: incubation_5mp_google_cloud +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70715 +rollout_issue_url: +milestone: '14.3' +type: development +group: group::incubation +default_enabled: false diff --git a/config/routes/project.rb b/config/routes/project.rb index bfb7802b3de0051d0a2745b08d6f8fffc56fee85..b1be9ad2ada9e4d51eb40953eadba0a843aa069d 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -313,6 +313,8 @@ resources :terraform, only: [:index] + resources :google_cloud, only: [:index] + resources :environments, except: [:destroy] do member do post :stop diff --git a/ee/spec/features/projects/navbar_spec.rb b/ee/spec/features/projects/navbar_spec.rb index 3b2119a7f40178fbe52b68fb550562b73352f2f3..ad37f8be60bf379e660d0f624e48b90e6dea0880 100644 --- a/ee/spec/features/projects/navbar_spec.rb +++ b/ee/spec/features/projects/navbar_spec.rb @@ -16,6 +16,7 @@ insert_package_nav(_('Infrastructure')) insert_infrastructure_registry_nav + insert_infrastructure_google_cloud_nav end context 'when issue analytics is available' do diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb index e26bb2237e6fa121e1942fb51ba51ecaed29c2d9..92e9cbb70406958d17da8f5c3a0c700e5ab10a40 100644 --- a/lib/sidebars/projects/menus/infrastructure_menu.rb +++ b/lib/sidebars/projects/menus/infrastructure_menu.rb @@ -11,6 +11,7 @@ def configure_menu_items add_item(kubernetes_menu_item) add_item(serverless_menu_item) add_item(terraform_menu_item) + add_item(google_cloud_menu_item) true end @@ -87,6 +88,22 @@ def terraform_menu_item item_id: :terraform ) end + + def google_cloud_menu_item + feature_is_enabled = Feature.enabled?(:incubation_5mp_google_cloud) + user_has_permissions = can?(context.current_user, :manage_project_google_cloud, context.project) + + unless feature_is_enabled && user_has_permissions + return ::Sidebars::NilMenuItem.new(item_id: :incubation_5mp_google_cloud) + end + + ::Sidebars::MenuItem.new( + title: _('Google Cloud'), + link: project_google_cloud_index_path(context.project), + active_routes: {}, + item_id: :google_cloud + ) + end end end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6d757abbad94daf75466a63f1a3232cb384ab6e3..61406b0c5c7600c46b53e086881b82cd2e0b2c41 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2045,6 +2045,9 @@ msgstr "" msgid "Add new directory" msgstr "" +msgid "Add new service account" +msgstr "" + msgid "Add or remove previously merged commits" msgstr "" @@ -3959,6 +3962,9 @@ msgstr "" msgid "Any namespace" msgstr "" +msgid "App Engine description and apps that are suitable for this deployment target" +msgstr "" + msgid "App ID" msgstr "" @@ -7174,6 +7180,12 @@ msgstr "" msgid "Closes this %{quick_action_target}." msgstr "" +msgid "Cloud Functions description and apps that are suitable for this deployment target" +msgstr "" + +msgid "Cloud Run description and apps that are suitable for this deployment target" +msgstr "" + msgid "Cloud licenses can not be removed." msgstr "" @@ -8613,6 +8625,9 @@ msgstr "" msgid "Configure the way a user creates a new account." msgstr "" +msgid "Configure via Merge Request" +msgstr "" + msgid "Configure which lists are shown for anyone who visits this board" msgstr "" @@ -11385,6 +11400,9 @@ msgstr "" msgid "Deployments" msgstr "" +msgid "Deployments to Google Kubernetes Engine can be " +msgstr "" + msgid "Deployments|%{deployments} environment impacted." msgid_plural "Deployments|%{deployments} environments impacted." msgstr[0] "" @@ -15832,6 +15850,12 @@ msgstr "" msgid "Goal of the changes and what reviewers should be aware of" msgstr "" +msgid "Google Cloud" +msgstr "" + +msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project." +msgstr "" + msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service." msgstr "" @@ -30832,6 +30856,9 @@ msgstr "" msgid "Service" msgstr "" +msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project." +msgstr "" + msgid "Service Desk" msgstr "" @@ -40159,6 +40186,9 @@ msgstr "" msgid "in" msgstr "" +msgid "in Infrastructure :: Kubernetes clusters" +msgstr "" + msgid "in all GitLab" msgstr "" @@ -40314,6 +40344,9 @@ msgstr "" msgid "log in" msgstr "" +msgid "managed" +msgstr "" + msgid "manual" msgstr "" diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb index 876bc82d16c7238db3240f718c6f850136682ee8..f61eaccf5b96bf0736ffa822a45ca26834263271 100644 --- a/spec/features/projects/navbar_spec.rb +++ b/spec/features/projects/navbar_spec.rb @@ -18,6 +18,7 @@ stub_config(registry: { enabled: false }) insert_package_nav(_('Infrastructure')) insert_infrastructure_registry_nav + insert_infrastructure_google_cloud_nav end it_behaves_like 'verified navigation bar' do diff --git a/spec/requests/projects/google_cloud_controller_spec.rb b/spec/requests/projects/google_cloud_controller_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..3b43f0d1dfbd3a395e1cd47145e10073f741d333 --- /dev/null +++ b/spec/requests/projects/google_cloud_controller_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::GoogleCloudController do + let_it_be(:project) { create(:project, :public) } + + describe 'GET index' do + let_it_be(:url) { "#{project_google_cloud_index_path(project)}" } + + let(:subject) { get url } + + context 'when user is authorized' do + let(:user) { project.creator } + + before do + sign_in(user) + subject + end + + it 'renders content' do + expect(response).to be_successful + end + end + + context 'when user is unauthorized' do + let(:user) { create(:user) } + + before do + project.add_guest(user) + sign_in(user) + subject + end + + it 'shows 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when no user is present' do + before do + subject + end + + it 'shows 404' do + expect(response).to have_gitlab_http_status(:not_found) + end + end + end +end diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb index 826108a63a5377bb99b1ea3e9c7120f7add3eb50..96e7942727887ab0038fbf1b1df8447dc639e6f3 100644 --- a/spec/support/helpers/navbar_structure_helper.rb +++ b/spec/support/helpers/navbar_structure_helper.rb @@ -52,4 +52,12 @@ def insert_infrastructure_registry_nav new_sub_nav_item_name: _('Infrastructure Registry') ) end + + def insert_infrastructure_google_cloud_nav + insert_after_sub_nav_item( + _('Terraform'), + within: _('Infrastructure'), + new_sub_nav_item_name: _('Google Cloud') + ) + end end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index adfe1cee6d6ad29d98830beb77ee4af2cbb41e04..20c5d9992be49f7233d2234f2c243c05440d8b1a 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -580,6 +580,23 @@ end end end + + describe 'Google Cloud' do + it 'has a link to the google cloud page' do + render + expect(rendered).to have_link('Google Cloud', href: project_google_cloud_index_path(project)) + end + + describe 'when the user does not have access' do + let(:user) { nil } + + it 'does not have a link to the google cloud page' do + render + + expect(rendered).not_to have_link('Google Cloud') + end + end + end end describe 'Packages and Registries' do