From 2fbd205f31ff270e2021c56ffc393ae4a8fa7a31 Mon Sep 17 00:00:00 2001 From: Dzmitry Meshcharakou <12459192-dmeshcharakou@users.noreply.gitlab.com> Date: Mon, 8 Jan 2024 15:42:48 +0100 Subject: [PATCH] Move Cloud Seed files to cloud_seed namespace In order to give some room with a namespace for google cloud platform integration, specify more accurate namespace for cloud seed files as cloud_seed/google_cloud. Changelog: changed --- .rubocop_todo/layout/line_length.yml | 10 +- .rubocop_todo/lint/symbol_conversion.yml | 2 +- .../naming/heredoc_delimiter_naming.yml | 2 +- .rubocop_todo/performance/map_compact.yml | 2 +- .../rspec/before_all_role_assignment.yml | 2 +- .rubocop_todo/rspec/context_wording.yml | 2 +- .rubocop_todo/rspec/named_subject.yml | 4 +- .rubocop_todo/style/if_unless_modifier.yml | 2 +- .../style/inline_disable_annotation.yml | 2 +- .../google_cloud/configuration_controller.rb | 2 +- .../google_cloud/databases_controller.rb | 6 +- .../google_cloud/deployments_controller.rb | 6 +- .../google_cloud/gcp_regions_controller.rb | 2 +- .../service_accounts_controller.rb | 2 +- .../cloud_seed/google_cloud/base_service.rb | 67 ++++++++++ .../create_cloudsql_instance_service.rb | 80 ++++++++++++ .../create_service_accounts_service.rb | 42 ++++++ .../google_cloud/enable_cloud_run_service.rb | 23 ++++ .../google_cloud/enable_cloudsql_service.rb | 27 ++++ .../google_cloud/enable_vision_ai_service.rb | 21 +++ .../fetch_google_ip_list_service.rb | 93 ++++++++++++++ .../gcp_region_add_or_replace_service.rb | 25 ++++ .../google_cloud/generate_pipeline_service.rb | 100 +++++++++++++++ .../get_cloudsql_instances_service.rb | 20 +++ .../google_cloud/service_accounts_service.rb | 53 ++++++++ .../setup_cloudsql_instance_service.rb | 120 ++++++++++++++++++ app/services/google_cloud/base_service.rb | 65 ---------- .../create_cloudsql_instance_service.rb | 78 ------------ .../create_service_accounts_service.rb | 40 ------ .../google_cloud/enable_cloud_run_service.rb | 21 --- .../google_cloud/enable_cloudsql_service.rb | 25 ---- .../google_cloud/enable_vision_ai_service.rb | 19 --- .../fetch_google_ip_list_service.rb | 91 ------------- .../gcp_region_add_or_replace_service.rb | 23 ---- .../google_cloud/generate_pipeline_service.rb | 98 -------------- .../get_cloudsql_instances_service.rb | 18 --- .../google_cloud/service_accounts_service.rb | 51 -------- .../setup_cloudsql_instance_service.rb | 118 ----------------- .../create_cloudsql_instance_worker.rb | 2 +- .../fetch_google_ip_list_worker.rb | 2 +- .../google_cloud/databases_controller_spec.rb | 8 +- .../deployments_controller_spec.rb | 10 +- .../create_cloudsql_instance_service_spec.rb | 2 +- .../create_service_accounts_service_spec.rb | 2 +- .../enable_cloud_run_service_spec.rb | 2 +- .../enable_cloudsql_service_spec.rb | 2 +- .../enable_vision_ai_service_spec.rb | 2 +- .../fetch_google_ip_list_service_spec.rb | 2 +- .../gcp_region_add_or_replace_service_spec.rb | 2 +- .../generate_pipeline_service_spec.rb | 22 +++- .../get_cloudsql_instances_service_spec.rb | 2 +- .../service_accounts_service_spec.rb | 2 +- .../setup_cloudsql_instance_service_spec.rb | 2 +- .../object_storage/cdn/google_cdn_spec.rb | 2 +- .../create_cloudsql_instance_worker_spec.rb | 8 +- .../fetch_google_ip_list_worker_spec.rb | 2 +- 56 files changed, 738 insertions(+), 702 deletions(-) create mode 100644 app/services/cloud_seed/google_cloud/base_service.rb create mode 100644 app/services/cloud_seed/google_cloud/create_cloudsql_instance_service.rb create mode 100644 app/services/cloud_seed/google_cloud/create_service_accounts_service.rb create mode 100644 app/services/cloud_seed/google_cloud/enable_cloud_run_service.rb create mode 100644 app/services/cloud_seed/google_cloud/enable_cloudsql_service.rb create mode 100644 app/services/cloud_seed/google_cloud/enable_vision_ai_service.rb create mode 100644 app/services/cloud_seed/google_cloud/fetch_google_ip_list_service.rb create mode 100644 app/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service.rb create mode 100644 app/services/cloud_seed/google_cloud/generate_pipeline_service.rb create mode 100644 app/services/cloud_seed/google_cloud/get_cloudsql_instances_service.rb create mode 100644 app/services/cloud_seed/google_cloud/service_accounts_service.rb create mode 100644 app/services/cloud_seed/google_cloud/setup_cloudsql_instance_service.rb delete mode 100644 app/services/google_cloud/base_service.rb delete mode 100644 app/services/google_cloud/create_cloudsql_instance_service.rb delete mode 100644 app/services/google_cloud/create_service_accounts_service.rb delete mode 100644 app/services/google_cloud/enable_cloud_run_service.rb delete mode 100644 app/services/google_cloud/enable_cloudsql_service.rb delete mode 100644 app/services/google_cloud/enable_vision_ai_service.rb delete mode 100644 app/services/google_cloud/fetch_google_ip_list_service.rb delete mode 100644 app/services/google_cloud/gcp_region_add_or_replace_service.rb delete mode 100644 app/services/google_cloud/generate_pipeline_service.rb delete mode 100644 app/services/google_cloud/get_cloudsql_instances_service.rb delete mode 100644 app/services/google_cloud/service_accounts_service.rb delete mode 100644 app/services/google_cloud/setup_cloudsql_instance_service.rb rename spec/services/{ => cloud_seed}/google_cloud/create_cloudsql_instance_service_spec.rb (96%) rename spec/services/{ => cloud_seed}/google_cloud/create_service_accounts_service_spec.rb (95%) rename spec/services/{ => cloud_seed}/google_cloud/enable_cloud_run_service_spec.rb (93%) rename spec/services/{ => cloud_seed}/google_cloud/enable_cloudsql_service_spec.rb (97%) rename spec/services/{ => cloud_seed}/google_cloud/enable_vision_ai_service_spec.rb (92%) rename spec/services/{ => cloud_seed}/google_cloud/fetch_google_ip_list_service_spec.rb (95%) rename spec/services/{ => cloud_seed}/google_cloud/gcp_region_add_or_replace_service_spec.rb (88%) rename spec/services/{ => cloud_seed}/google_cloud/generate_pipeline_service_spec.rb (94%) rename spec/services/{ => cloud_seed}/google_cloud/get_cloudsql_instances_service_spec.rb (93%) rename spec/services/{ => cloud_seed}/google_cloud/service_accounts_service_spec.rb (97%) rename spec/services/{ => cloud_seed}/google_cloud/setup_cloudsql_instance_service_spec.rb (98%) diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index b8b267d6d860..4456f6d3985c 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -496,8 +496,8 @@ Layout/LineLength: - 'app/services/environments/schedule_to_delete_review_apps_service.rb' - 'app/services/feature_flags/update_service.rb' - 'app/services/git/process_ref_changes_service.rb' - - 'app/services/google_cloud/create_service_accounts_service.rb' - - 'app/services/google_cloud/generate_pipeline_service.rb' + - 'app/services/cloud_seed/google_cloud/create_service_accounts_service.rb' + - 'app/services/cloud_seed/google_cloud/generate_pipeline_service.rb' - 'app/services/groups/create_service.rb' - 'app/services/groups/destroy_service.rb' - 'app/services/groups/transfer_service.rb' @@ -4458,9 +4458,9 @@ Layout/LineLength: - 'spec/services/files/update_service_spec.rb' - 'spec/services/git/branch_hooks_service_spec.rb' - 'spec/services/git/branch_push_service_spec.rb' - - 'spec/services/google_cloud/enable_cloud_run_service_spec.rb' - - 'spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb' - - 'spec/services/google_cloud/service_accounts_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb' - 'spec/services/groups/autocomplete_service_spec.rb' - 'spec/services/groups/create_service_spec.rb' - 'spec/services/groups/transfer_service_spec.rb' diff --git a/.rubocop_todo/lint/symbol_conversion.yml b/.rubocop_todo/lint/symbol_conversion.yml index eae5c89eef7a..893e457ddff5 100644 --- a/.rubocop_todo/lint/symbol_conversion.yml +++ b/.rubocop_todo/lint/symbol_conversion.yml @@ -5,7 +5,7 @@ Lint/SymbolConversion: - 'app/helpers/breadcrumbs_helper.rb' - 'app/helpers/environments_helper.rb' - 'app/helpers/tooling/visual_review_helper.rb' - - 'app/services/google_cloud/create_cloudsql_instance_service.rb' + - 'app/services/cloud_seed/google_cloud/create_cloudsql_instance_service.rb' - 'config/puma.rb' - 'ee/app/components/billing/plan_component.rb' - 'ee/app/controllers/projects/security/scanned_resources_controller.rb' diff --git a/.rubocop_todo/naming/heredoc_delimiter_naming.yml b/.rubocop_todo/naming/heredoc_delimiter_naming.yml index 92f5994092b1..50f359fa4480 100644 --- a/.rubocop_todo/naming/heredoc_delimiter_naming.yml +++ b/.rubocop_todo/naming/heredoc_delimiter_naming.yml @@ -105,7 +105,7 @@ Naming/HeredocDelimiterNaming: - 'spec/services/ci/create_web_ide_terminal_service_spec.rb' - 'spec/services/ci/parse_dotenv_artifact_service_spec.rb' - 'spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb' - - 'spec/services/google_cloud/generate_pipeline_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb' - 'spec/services/task_list_toggle_service_spec.rb' - 'spec/support/helpers/repo_helpers.rb' - 'spec/support/helpers/seed_repo.rb' diff --git a/.rubocop_todo/performance/map_compact.yml b/.rubocop_todo/performance/map_compact.yml index 22cefbab067e..576a610006e3 100644 --- a/.rubocop_todo/performance/map_compact.yml +++ b/.rubocop_todo/performance/map_compact.yml @@ -31,7 +31,7 @@ Performance/MapCompact: - 'app/services/events/render_service.rb' - 'app/services/feature_flags/update_service.rb' - 'app/services/git/base_hooks_service.rb' - - 'app/services/google_cloud/fetch_google_ip_list_service.rb' + - 'app/services/cloud_seed/google_cloud/fetch_google_ip_list_service.rb' - 'app/services/jira_import/start_import_service.rb' - 'app/services/jira_import/users_mapper_service.rb' - 'app/services/labels/available_labels_service.rb' diff --git a/.rubocop_todo/rspec/before_all_role_assignment.yml b/.rubocop_todo/rspec/before_all_role_assignment.yml index a39743664aa6..ebf0eb9b3820 100644 --- a/.rubocop_todo/rspec/before_all_role_assignment.yml +++ b/.rubocop_todo/rspec/before_all_role_assignment.yml @@ -1405,7 +1405,7 @@ RSpec/BeforeAllRoleAssignment: - 'spec/services/environments/schedule_to_delete_review_apps_service_spec.rb' - 'spec/services/files/base_service_spec.rb' - 'spec/services/git/branch_push_service_spec.rb' - - 'spec/services/google_cloud/generate_pipeline_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb' - 'spec/services/groups/auto_devops_service_spec.rb' - 'spec/services/groups/autocomplete_service_spec.rb' - 'spec/services/groups/group_links/create_service_spec.rb' diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml index a141ac1e5089..9d2a497df51a 100644 --- a/.rubocop_todo/rspec/context_wording.yml +++ b/.rubocop_todo/rspec/context_wording.yml @@ -2560,7 +2560,7 @@ RSpec/ContextWording: - 'spec/services/git/tag_push_service_spec.rb' - 'spec/services/git/wiki_push_service/change_spec.rb' - 'spec/services/git/wiki_push_service_spec.rb' - - 'spec/services/google_cloud/generate_pipeline_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb' - 'spec/services/gpg_keys/create_service_spec.rb' - 'spec/services/groups/create_service_spec.rb' - 'spec/services/groups/deploy_tokens/revoke_service_spec.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index eda8e34b6f47..99ada0d6b3cd 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -3273,8 +3273,8 @@ RSpec/NamedSubject: - 'spec/services/git/process_ref_changes_service_spec.rb' - 'spec/services/git/tag_push_service_spec.rb' - 'spec/services/git/wiki_push_service_spec.rb' - - 'spec/services/google_cloud/fetch_google_ip_list_service_spec.rb' - - 'spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb' - 'spec/services/gpg_keys/create_service_spec.rb' - 'spec/services/gpg_keys/destroy_service_spec.rb' - 'spec/services/groups/autocomplete_service_spec.rb' diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml index db8f6d8d8512..c99e96f3e552 100644 --- a/.rubocop_todo/style/if_unless_modifier.yml +++ b/.rubocop_todo/style/if_unless_modifier.yml @@ -245,7 +245,7 @@ Style/IfUnlessModifier: - 'app/services/environments/canary_ingress/update_service.rb' - 'app/services/environments/reset_auto_stop_service.rb' - 'app/services/git/process_ref_changes_service.rb' - - 'app/services/google_cloud/generate_pipeline_service.rb' + - 'app/services/cloud_seed/google_cloud/generate_pipeline_service.rb' - 'app/services/groups/create_service.rb' - 'app/services/groups/transfer_service.rb' - 'app/services/groups/update_statistics_service.rb' diff --git a/.rubocop_todo/style/inline_disable_annotation.yml b/.rubocop_todo/style/inline_disable_annotation.yml index 98690775f3c9..20ff7ffc59b4 100644 --- a/.rubocop_todo/style/inline_disable_annotation.yml +++ b/.rubocop_todo/style/inline_disable_annotation.yml @@ -3127,7 +3127,7 @@ Style/InlineDisableAnnotation: - 'spec/services/ci/pipeline_schedules/calculate_next_run_service_spec.rb' - 'spec/services/draft_notes/destroy_service_spec.rb' - 'spec/services/event_create_service_spec.rb' - - 'spec/services/google_cloud/enable_cloudsql_service_spec.rb' + - 'spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb' - 'spec/services/import/gitlab_projects/file_acquisition_strategies/remote_file_spec.rb' - 'spec/services/merge_requests/create_service_spec.rb' - 'spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb' diff --git a/app/controllers/projects/google_cloud/configuration_controller.rb b/app/controllers/projects/google_cloud/configuration_controller.rb index d35b2d54c539..3baa1210ec26 100644 --- a/app/controllers/projects/google_cloud/configuration_controller.rb +++ b/app/controllers/projects/google_cloud/configuration_controller.rb @@ -8,7 +8,7 @@ def index configurationUrl: project_google_cloud_configuration_path(project), deploymentsUrl: project_google_cloud_deployments_path(project), databasesUrl: project_google_cloud_databases_path(project), - serviceAccounts: ::GoogleCloud::ServiceAccountsService.new(project).find_for_project, + serviceAccounts: ::CloudSeed::GoogleCloud::ServiceAccountsService.new(project).find_for_project, createServiceAccountUrl: project_google_cloud_service_accounts_path(project), emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/empty-state/empty-pipeline-md.svg'), diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb index ea79efd9f4f3..9023b8a5fa64 100644 --- a/app/controllers/projects/google_cloud/databases_controller.rb +++ b/app/controllers/projects/google_cloud/databases_controller.rb @@ -14,7 +14,7 @@ def index cloudsqlPostgresUrl: new_project_google_cloud_database_path(project, :postgres), cloudsqlMysqlUrl: new_project_google_cloud_database_path(project, :mysql), cloudsqlSqlserverUrl: new_project_google_cloud_database_path(project, :sqlserver), - cloudsqlInstances: ::GoogleCloud::GetCloudsqlInstancesService.new(project).execute, + cloudsqlInstances: ::CloudSeed::GoogleCloud::GetCloudsqlInstancesService.new(project).execute, emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/empty-state/empty-pipeline-md.svg') } @@ -46,7 +46,7 @@ def new end def create - enable_response = ::GoogleCloud::EnableCloudsqlService + enable_response = ::CloudSeed::GoogleCloud::EnableCloudsqlService .new(project, current_user, enable_service_params) .execute @@ -54,7 +54,7 @@ def create track_event(:error_enable_cloudsql_services) flash[:alert] = error_message(enable_response[:message]) else - create_response = ::GoogleCloud::CreateCloudsqlInstanceService + create_response = ::CloudSeed::GoogleCloud::CreateCloudsqlInstanceService .new(project, current_user, create_service_params) .execute diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb index 92c99ad42711..e4666f9335cb 100644 --- a/app/controllers/projects/google_cloud/deployments_controller.rb +++ b/app/controllers/projects/google_cloud/deployments_controller.rb @@ -17,7 +17,7 @@ def index def cloud_run params = { google_oauth2_token: token_in_session } - enable_cloud_run_response = GoogleCloud::EnableCloudRunService + enable_cloud_run_response = CloudSeed::GoogleCloud::EnableCloudRunService .new(project, current_user, params).execute if enable_cloud_run_response[:status] == :error @@ -25,8 +25,8 @@ def cloud_run flash[:alert] = enable_cloud_run_response[:message] redirect_to project_google_cloud_deployments_path(project) else - params = { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } - generate_pipeline_response = GoogleCloud::GeneratePipelineService + params = { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + generate_pipeline_response = CloudSeed::GoogleCloud::GeneratePipelineService .new(project, current_user, params).execute if generate_pipeline_response[:status] == :error diff --git a/app/controllers/projects/google_cloud/gcp_regions_controller.rb b/app/controllers/projects/google_cloud/gcp_regions_controller.rb index c51261721b26..593e27eeebf5 100644 --- a/app/controllers/projects/google_cloud/gcp_regions_controller.rb +++ b/app/controllers/projects/google_cloud/gcp_regions_controller.rb @@ -20,7 +20,7 @@ def index def create permitted_params = params.permit(:ref, :gcp_region) - GoogleCloud::GcpRegionAddOrReplaceService.new(project).execute(permitted_params[:ref], permitted_params[:gcp_region]) + CloudSeed::GoogleCloud::GcpRegionAddOrReplaceService.new(project).execute(permitted_params[:ref], permitted_params[:gcp_region]) track_event(:configure_region) redirect_to project_google_cloud_configuration_path(project), notice: _('GCP region configured') end diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb index 7b029e25ea2b..5a5f53943c07 100644 --- a/app/controllers/projects/google_cloud/service_accounts_controller.rb +++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb @@ -27,7 +27,7 @@ def index def create permitted_params = params.permit(:gcp_project, :ref) - response = GoogleCloud::CreateServiceAccountsService.new( + response = CloudSeed::GoogleCloud::CreateServiceAccountsService.new( project, current_user, google_oauth2_token: token_in_session, diff --git a/app/services/cloud_seed/google_cloud/base_service.rb b/app/services/cloud_seed/google_cloud/base_service.rb new file mode 100644 index 000000000000..e59031c5371c --- /dev/null +++ b/app/services/cloud_seed/google_cloud/base_service.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class BaseService < ::BaseService + protected + + def google_oauth2_token + @params[:google_oauth2_token] + end + + def gcp_project_id + @params[:gcp_project_id] + end + + def environment_name + @params[:environment_name] + end + + def google_api_client + @google_api_client_instance ||= GoogleApi::CloudPlatform::Client.new(google_oauth2_token, nil) + end + + def unique_gcp_project_ids + filter_params = { key: 'GCP_PROJECT_ID' } + @unique_gcp_project_ids ||= ::Ci::VariablesFinder.new(project, filter_params).execute.map(&:value).uniq + end + + def group_vars_by_environment(keys) + filtered_vars = project.variables.filter { |variable| keys.include? variable.key } + filtered_vars.each_with_object({}) do |variable, grouped| + grouped[variable.environment_scope] ||= {} + grouped[variable.environment_scope][variable.key] = variable.value + end + end + + def create_or_replace_project_vars(environment_scope, key, value, is_protected, is_masked = false) + change_params = { + variable_params: { + key: key, + value: value, + environment_scope: environment_scope, + protected: is_protected, + masked: is_masked + } + } + existing_variable = find_existing_variable(environment_scope, key) + + if existing_variable + change_params[:action] = :update + change_params[:variable] = existing_variable + else + change_params[:action] = :create + end + + ::Ci::ChangeVariableService.new(container: project, current_user: current_user, params: change_params).execute + end + + private + + def find_existing_variable(environment_scope, key) + filter_params = { key: key, filter: { environment_scope: environment_scope } } + ::Ci::VariablesFinder.new(project, filter_params).execute.first + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/create_cloudsql_instance_service.rb b/app/services/cloud_seed/google_cloud/create_cloudsql_instance_service.rb new file mode 100644 index 000000000000..8b967a2d551d --- /dev/null +++ b/app/services/cloud_seed/google_cloud/create_cloudsql_instance_service.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + DEFAULT_REGION = 'us-east1' + + class CreateCloudsqlInstanceService < ::CloudSeed::GoogleCloud::BaseService + WORKER_INTERVAL = 30.seconds + + def execute + create_cloud_instance + trigger_instance_setup_worker + success + rescue Google::Apis::Error => err + error(err.message) + end + + private + + def create_cloud_instance + google_api_client.create_cloudsql_instance( + gcp_project_id, + instance_name, + root_password, + database_version, + region, + tier + ) + end + + def trigger_instance_setup_worker + ::GoogleCloud::CreateCloudsqlInstanceWorker.perform_in( + WORKER_INTERVAL, + current_user.id, + project.id, + { + 'google_oauth2_token': google_oauth2_token, + 'gcp_project_id': gcp_project_id, + 'instance_name': instance_name, + 'database_version': database_version, + 'environment_name': environment_name, + 'is_protected': protected? + } + ) + end + + def protected? + project.protected_for?(environment_name) + end + + def instance_name + # Generates an `instance_name` for the to-be-created Cloud SQL instance + # Example: `gitlab-34647-postgres-14-staging` + environment_alias = environment_name == '*' ? 'ALL' : environment_name + name = "gitlab-#{project.id}-#{database_version}-#{environment_alias}" + name.tr("_", "-").downcase + end + + def root_password + SecureRandom.hex(16) + end + + def database_version + params[:database_version] + end + + def region + region = ::Ci::VariablesFinder + .new(project, { key: Projects::GoogleCloud::GcpRegionsController::GCP_REGION_CI_VAR_KEY, + environment_scope: environment_name }) + .execute.first + region&.value || DEFAULT_REGION + end + + def tier + params[:tier] + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/create_service_accounts_service.rb b/app/services/cloud_seed/google_cloud/create_service_accounts_service.rb new file mode 100644 index 000000000000..f15779cc14bb --- /dev/null +++ b/app/services/cloud_seed/google_cloud/create_service_accounts_service.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class CreateServiceAccountsService < ::CloudSeed::GoogleCloud::BaseService + def execute + service_account = google_api_client.create_service_account(gcp_project_id, service_account_name, service_account_desc) + service_account_key = google_api_client.create_service_account_key(gcp_project_id, service_account.unique_id) + google_api_client.grant_service_account_roles(gcp_project_id, service_account.email) + + service_accounts_service.add_for_project( + environment_name, + service_account.project_id, + Gitlab::Json.dump(service_account), + Gitlab::Json.dump(service_account_key), + ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name) + ) + + ServiceResponse.success(message: _('Service account generated successfully'), payload: { + service_account: service_account, + service_account_key: service_account_key + }) + end + + private + + def service_accounts_service + GoogleCloud::ServiceAccountsService.new(project) + end + + def service_account_name + "GitLab :: #{project.name} :: #{environment_name}" + end + + def service_account_desc + "GitLab generated service account for project '#{project.name}' and environment '#{environment_name}'" + end + end + end +end + +CloudSeed::GoogleCloud::CreateServiceAccountsService.prepend_mod diff --git a/app/services/cloud_seed/google_cloud/enable_cloud_run_service.rb b/app/services/cloud_seed/google_cloud/enable_cloud_run_service.rb new file mode 100644 index 000000000000..3ab5608c937f --- /dev/null +++ b/app/services/cloud_seed/google_cloud/enable_cloud_run_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class EnableCloudRunService < ::CloudSeed::GoogleCloud::BaseService + def execute + gcp_project_ids = unique_gcp_project_ids + + if gcp_project_ids.empty? + error("No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.") + else + gcp_project_ids.each do |gcp_project_id| + google_api_client.enable_cloud_run(gcp_project_id) + google_api_client.enable_artifacts_registry(gcp_project_id) + google_api_client.enable_cloud_build(gcp_project_id) + end + + success({ gcp_project_ids: gcp_project_ids }) + end + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/enable_cloudsql_service.rb b/app/services/cloud_seed/google_cloud/enable_cloudsql_service.rb new file mode 100644 index 000000000000..d36f3ffd7c25 --- /dev/null +++ b/app/services/cloud_seed/google_cloud/enable_cloudsql_service.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class EnableCloudsqlService < ::CloudSeed::GoogleCloud::BaseService + def execute + create_or_replace_project_vars(environment_name, 'GCP_PROJECT_ID', gcp_project_id, ci_var_protected?) + + unique_gcp_project_ids.each do |gcp_project_id| + google_api_client.enable_cloud_sql_admin(gcp_project_id) + google_api_client.enable_compute(gcp_project_id) + google_api_client.enable_service_networking(gcp_project_id) + end + + success({ gcp_project_ids: unique_gcp_project_ids }) + rescue Google::Apis::Error => err + error(err.message) + end + + private + + def ci_var_protected? + ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name) + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/enable_vision_ai_service.rb b/app/services/cloud_seed/google_cloud/enable_vision_ai_service.rb new file mode 100644 index 000000000000..865c11cba6a1 --- /dev/null +++ b/app/services/cloud_seed/google_cloud/enable_vision_ai_service.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class EnableVisionAiService < ::CloudSeed::GoogleCloud::BaseService + def execute + gcp_project_ids = unique_gcp_project_ids + + if gcp_project_ids.empty? + error("No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.") + else + gcp_project_ids.each do |gcp_project_id| + google_api_client.enable_vision_api(gcp_project_id) + end + + success({ gcp_project_ids: gcp_project_ids }) + end + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/fetch_google_ip_list_service.rb b/app/services/cloud_seed/google_cloud/fetch_google_ip_list_service.rb new file mode 100644 index 000000000000..c02b3a873521 --- /dev/null +++ b/app/services/cloud_seed/google_cloud/fetch_google_ip_list_service.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class FetchGoogleIpListService + include BaseServiceUtility + + GOOGLE_IP_RANGES_URL = 'https://www.gstatic.com/ipranges/cloud.json' + RESPONSE_BODY_LIMIT = 1.megabyte + EXPECTED_CONTENT_TYPE = 'application/json' + + IpListNotRetrievedError = Class.new(StandardError) + + def execute + # Prevent too many workers from hitting the same HTTP endpoint + if ::Gitlab::ApplicationRateLimiter.throttled?(:fetch_google_ip_list, scope: nil) + return error("#{self.class} was rate limited") + end + + subnets = fetch_and_update_cache! + + Gitlab::AppJsonLogger.info( + class: self.class.name, + message: 'Successfully retrieved Google IP list', + subnet_count: subnets.count + ) + + success({ subnets: subnets }) + rescue IpListNotRetrievedError => err + Gitlab::ErrorTracking.log_exception(err) + error('Google IP list not retrieved') + end + + private + + # Attempts to retrieve and parse the list of IPs from Google. Updates + # the internal cache so that the data is accessible. + # + # Returns an array of IPAddr objects consisting of subnets. + def fetch_and_update_cache! + parsed_response = fetch_google_ip_list + + parse_google_prefixes(parsed_response).tap do |subnets| + ::ObjectStorage::CDN::GoogleIpCache.update!(subnets) + end + end + + def fetch_google_ip_list + response = Gitlab::HTTP.get(GOOGLE_IP_RANGES_URL, follow_redirects: false, allow_local_requests: false) + + validate_response!(response) + + response.parsed_response + end + + def validate_response!(response) + raise IpListNotRetrievedError, "response was #{response.code}" unless response.code == 200 + raise IpListNotRetrievedError, "response was nil" unless response.body + + parsed_response = response.parsed_response + + unless response.content_type == EXPECTED_CONTENT_TYPE && parsed_response.is_a?(Hash) + raise IpListNotRetrievedError, "response was not JSON" + end + + if response.body&.bytesize.to_i > RESPONSE_BODY_LIMIT + raise IpListNotRetrievedError, "response was too large: #{response.body.bytesize}" + end + + prefixes = parsed_response['prefixes'] + + raise IpListNotRetrievedError, "JSON was type #{prefixes.class}, expected Array" unless prefixes.is_a?(Array) + raise IpListNotRetrievedError, "#{GOOGLE_IP_RANGES_URL} did not return any IP ranges" if prefixes.empty? + + response.parsed_response + end + + def parse_google_prefixes(parsed_response) + ranges = parsed_response['prefixes'].map do |prefix| + ip_range = prefix['ipv4Prefix'] || prefix['ipv6Prefix'] + + next unless ip_range + + IPAddr.new(ip_range) + end.compact + + raise IpListNotRetrievedError, "#{GOOGLE_IP_RANGES_URL} did not return any IP ranges" if ranges.empty? + + ranges + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service.rb b/app/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service.rb new file mode 100644 index 000000000000..11a644b3e9df --- /dev/null +++ b/app/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class GcpRegionAddOrReplaceService < ::CloudSeed::GoogleCloud::BaseService + def execute(environment, region) + gcp_region_key = Projects::GoogleCloud::GcpRegionsController::GCP_REGION_CI_VAR_KEY + + change_params = { variable_params: { key: gcp_region_key, value: region, environment_scope: environment } } + filter_params = { key: gcp_region_key, filter: { environment_scope: environment } } + + existing_variable = ::Ci::VariablesFinder.new(project, filter_params).execute.first + + if existing_variable + change_params[:action] = :update + change_params[:variable] = existing_variable + else + change_params[:action] = :create + end + + ::Ci::ChangeVariableService.new(container: project, current_user: current_user, params: change_params).execute + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/generate_pipeline_service.rb b/app/services/cloud_seed/google_cloud/generate_pipeline_service.rb new file mode 100644 index 000000000000..d8b45f301ecc --- /dev/null +++ b/app/services/cloud_seed/google_cloud/generate_pipeline_service.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class GeneratePipelineService < ::CloudSeed::GoogleCloud::BaseService + ACTION_DEPLOY_TO_CLOUD_RUN = 'DEPLOY_TO_CLOUD_RUN' + ACTION_DEPLOY_TO_CLOUD_STORAGE = 'DEPLOY_TO_CLOUD_STORAGE' + ACTION_VISION_AI_PIPELINE = 'VISION_AI_PIPELINE' + + def execute + commit_attributes = generate_commit_attributes + create_branch_response = ::Branches::CreateService.new(project, current_user) + .execute(commit_attributes[:branch_name], project.default_branch) + + if create_branch_response[:status] == :error + return create_branch_response + end + + branch = create_branch_response[:branch] + + service = default_branch_gitlab_ci_yml.present? ? ::Files::UpdateService : ::Files::CreateService + + commit_response = service.new(project, current_user, commit_attributes).execute + + if commit_response[:status] == :error + return commit_response + end + + success({ branch_name: branch.name, commit: commit_response }) + end + + private + + def action + @params[:action] + end + + def generate_commit_attributes + case action + when ACTION_DEPLOY_TO_CLOUD_RUN + branch_name = "deploy-to-cloud-run-#{SecureRandom.hex(8)}" + { + commit_message: 'Enable Cloud Run deployments', + file_path: '.gitlab-ci.yml', + file_content: pipeline_content('gcp/cloud-run.gitlab-ci.yml'), + branch_name: branch_name, + start_branch: branch_name + } + when ACTION_DEPLOY_TO_CLOUD_STORAGE + branch_name = "deploy-to-cloud-storage-#{SecureRandom.hex(8)}" + { + commit_message: 'Enable Cloud Storage deployments', + file_path: '.gitlab-ci.yml', + file_content: pipeline_content('gcp/cloud-storage.gitlab-ci.yml'), + branch_name: branch_name, + start_branch: branch_name + } + when ACTION_VISION_AI_PIPELINE + branch_name = "vision-ai-pipeline-#{SecureRandom.hex(8)}" + { + commit_message: 'Enable Vision AI Pipeline', + file_path: '.gitlab-ci.yml', + file_content: pipeline_content('gcp/vision-ai.gitlab-ci.yml'), + branch_name: branch_name, + start_branch: branch_name + } + end + end + + def default_branch_gitlab_ci_yml + @default_branch_gitlab_ci_yml ||= project.ci_config_for(project.default_branch) + end + + def pipeline_content(include_path) + gitlab_ci_yml = ::Gitlab::Ci::Config::Yaml::Loader.new(default_branch_gitlab_ci_yml || '{}').load + + append_remote_include( + gitlab_ci_yml.content, + "https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/#{include_path}" + ) + end + + def append_remote_include(gitlab_ci_yml, include_url) + stages = gitlab_ci_yml['stages'] || [] + gitlab_ci_yml['stages'] = if action == ACTION_VISION_AI_PIPELINE + (stages + %w[validate detect render]).uniq + else + (stages + %w[build test deploy]).uniq + end + + includes = gitlab_ci_yml['include'] || [] + includes = Array.wrap(includes) + includes << { 'remote' => include_url } + gitlab_ci_yml['include'] = includes.uniq + + gitlab_ci_yml.deep_stringify_keys.to_yaml + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/get_cloudsql_instances_service.rb b/app/services/cloud_seed/google_cloud/get_cloudsql_instances_service.rb new file mode 100644 index 000000000000..b037298c8cbf --- /dev/null +++ b/app/services/cloud_seed/google_cloud/get_cloudsql_instances_service.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class GetCloudsqlInstancesService < ::CloudSeed::GoogleCloud::BaseService + CLOUDSQL_KEYS = %w[GCP_PROJECT_ID GCP_CLOUDSQL_INSTANCE_NAME GCP_CLOUDSQL_VERSION].freeze + + def execute + group_vars_by_environment(CLOUDSQL_KEYS).map do |environment_scope, value| + { + ref: environment_scope, + gcp_project: value['GCP_PROJECT_ID'], + instance_name: value['GCP_CLOUDSQL_INSTANCE_NAME'], + version: value['GCP_CLOUDSQL_VERSION'] + } + end + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/service_accounts_service.rb b/app/services/cloud_seed/google_cloud/service_accounts_service.rb new file mode 100644 index 000000000000..4881c440c9c8 --- /dev/null +++ b/app/services/cloud_seed/google_cloud/service_accounts_service.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + ## + # GCP keys used to store Google Cloud Service Accounts + GCP_KEYS = %w[GCP_PROJECT_ID GCP_SERVICE_ACCOUNT GCP_SERVICE_ACCOUNT_KEY].freeze + + ## + # This service deals with GCP Service Accounts in GitLab + + class ServiceAccountsService < ::CloudSeed::GoogleCloud::BaseService + ## + # Find GCP Service Accounts in a GitLab project + # + # This method looks up GitLab project's CI vars + # and returns Google Cloud Service Accounts combinations + # aligning GitLab project and ref to GCP projects + + def find_for_project + group_vars_by_environment(GCP_KEYS).map do |environment_scope, value| + { + ref: environment_scope, + gcp_project: value['GCP_PROJECT_ID'], + service_account_exists: value['GCP_SERVICE_ACCOUNT'].present?, + service_account_key_exists: value['GCP_SERVICE_ACCOUNT_KEY'].present? + } + end + end + + def add_for_project(ref, gcp_project_id, service_account, service_account_key, is_protected) + create_or_replace_project_vars( + ref, + 'GCP_PROJECT_ID', + gcp_project_id, + is_protected + ) + create_or_replace_project_vars( + ref, + 'GCP_SERVICE_ACCOUNT', + service_account, + is_protected + ) + create_or_replace_project_vars( + ref, + 'GCP_SERVICE_ACCOUNT_KEY', + service_account_key, + is_protected + ) + end + end + end +end diff --git a/app/services/cloud_seed/google_cloud/setup_cloudsql_instance_service.rb b/app/services/cloud_seed/google_cloud/setup_cloudsql_instance_service.rb new file mode 100644 index 000000000000..b8c160f06838 --- /dev/null +++ b/app/services/cloud_seed/google_cloud/setup_cloudsql_instance_service.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +module CloudSeed + module GoogleCloud + class SetupCloudsqlInstanceService < ::CloudSeed::GoogleCloud::BaseService + INSTANCE_STATE_RUNNABLE = 'RUNNABLE' + OPERATION_STATE_DONE = 'DONE' + DEFAULT_DATABASE_NAME = 'main_db' + DEFAULT_DATABASE_USER = 'main_user' + + def execute + return error('Unauthorized user') unless Ability.allowed?(current_user, :admin_project_google_cloud, project) + + get_instance_response = google_api_client.get_cloudsql_instance(gcp_project_id, instance_name) + + if get_instance_response.state != INSTANCE_STATE_RUNNABLE + return error("CloudSQL instance not RUNNABLE: #{Gitlab::Json.dump(get_instance_response)}") + end + + save_instance_ci_vars(get_instance_response) + + list_database_response = google_api_client.list_cloudsql_databases(gcp_project_id, instance_name) + list_user_response = google_api_client.list_cloudsql_users(gcp_project_id, instance_name) + + existing_database = list_database_response.items.find { |database| database.name == database_name } + existing_user = list_user_response.items.find { |user| user.name == username } + + if existing_database && existing_user + save_database_ci_vars + save_user_ci_vars(existing_user) + return success + end + + database_response = execute_database_setup(existing_database) + return database_response if database_response[:status] == :error + + save_database_ci_vars + + user_response = execute_user_setup(existing_user) + return user_response if user_response[:status] == :error + + save_user_ci_vars(existing_user) + + success + rescue Google::Apis::Error => err + error(message: Gitlab::Json.dump(err)) + end + + private + + def instance_name + @params[:instance_name] + end + + def database_version + @params[:database_version] + end + + def database_name + @params.fetch(:database_name, DEFAULT_DATABASE_NAME) + end + + def username + @params.fetch(:username, DEFAULT_DATABASE_USER) + end + + def password + @password ||= SecureRandom.hex(16) + end + + def save_ci_var(key, value, is_masked = false) + create_or_replace_project_vars(environment_name, key, value, @params[:is_protected], is_masked) + end + + def save_instance_ci_vars(cloudsql_instance) + primary_ip_address = cloudsql_instance.ip_addresses.first.ip_address + connection_name = cloudsql_instance.connection_name + + save_ci_var('GCP_PROJECT_ID', gcp_project_id) + save_ci_var('GCP_CLOUDSQL_INSTANCE_NAME', instance_name) + save_ci_var('GCP_CLOUDSQL_CONNECTION_NAME', connection_name) + save_ci_var('GCP_CLOUDSQL_PRIMARY_IP_ADDRESS', primary_ip_address) + save_ci_var('GCP_CLOUDSQL_VERSION', database_version) + end + + def save_database_ci_vars + save_ci_var('GCP_CLOUDSQL_DATABASE_NAME', database_name) + end + + def save_user_ci_vars(user_exists) + save_ci_var('GCP_CLOUDSQL_DATABASE_USER', username) + save_ci_var('GCP_CLOUDSQL_DATABASE_PASS', user_exists ? user_exists.password : password, true) + end + + def execute_database_setup(database_exists) + return success if database_exists + + database_response = google_api_client.create_cloudsql_database(gcp_project_id, instance_name, database_name) + + if database_response.status != OPERATION_STATE_DONE + return error("Database creation failed: #{Gitlab::Json.dump(database_response)}") + end + + success + end + + def execute_user_setup(existing_user) + return success if existing_user + + user_response = google_api_client.create_cloudsql_user(gcp_project_id, instance_name, username, password) + + if user_response.status != OPERATION_STATE_DONE + return error("User creation failed: #{Gitlab::Json.dump(user_response)}") + end + + success + end + end + end +end diff --git a/app/services/google_cloud/base_service.rb b/app/services/google_cloud/base_service.rb deleted file mode 100644 index 01aee2231c94..000000000000 --- a/app/services/google_cloud/base_service.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class BaseService < ::BaseService - protected - - def google_oauth2_token - @params[:google_oauth2_token] - end - - def gcp_project_id - @params[:gcp_project_id] - end - - def environment_name - @params[:environment_name] - end - - def google_api_client - @google_api_client_instance ||= GoogleApi::CloudPlatform::Client.new(google_oauth2_token, nil) - end - - def unique_gcp_project_ids - filter_params = { key: 'GCP_PROJECT_ID' } - @unique_gcp_project_ids ||= ::Ci::VariablesFinder.new(project, filter_params).execute.map(&:value).uniq - end - - def group_vars_by_environment(keys) - filtered_vars = project.variables.filter { |variable| keys.include? variable.key } - filtered_vars.each_with_object({}) do |variable, grouped| - grouped[variable.environment_scope] ||= {} - grouped[variable.environment_scope][variable.key] = variable.value - end - end - - def create_or_replace_project_vars(environment_scope, key, value, is_protected, is_masked = false) - change_params = { - variable_params: { - key: key, - value: value, - environment_scope: environment_scope, - protected: is_protected, - masked: is_masked - } - } - existing_variable = find_existing_variable(environment_scope, key) - - if existing_variable - change_params[:action] = :update - change_params[:variable] = existing_variable - else - change_params[:action] = :create - end - - ::Ci::ChangeVariableService.new(container: project, current_user: current_user, params: change_params).execute - end - - private - - def find_existing_variable(environment_scope, key) - filter_params = { key: key, filter: { environment_scope: environment_scope } } - ::Ci::VariablesFinder.new(project, filter_params).execute.first - end - end -end diff --git a/app/services/google_cloud/create_cloudsql_instance_service.rb b/app/services/google_cloud/create_cloudsql_instance_service.rb deleted file mode 100644 index 9a1263f0796a..000000000000 --- a/app/services/google_cloud/create_cloudsql_instance_service.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - DEFAULT_REGION = 'us-east1' - - class CreateCloudsqlInstanceService < ::GoogleCloud::BaseService - WORKER_INTERVAL = 30.seconds - - def execute - create_cloud_instance - trigger_instance_setup_worker - success - rescue Google::Apis::Error => err - error(err.message) - end - - private - - def create_cloud_instance - google_api_client.create_cloudsql_instance( - gcp_project_id, - instance_name, - root_password, - database_version, - region, - tier - ) - end - - def trigger_instance_setup_worker - GoogleCloud::CreateCloudsqlInstanceWorker.perform_in( - WORKER_INTERVAL, - current_user.id, - project.id, - { - 'google_oauth2_token': google_oauth2_token, - 'gcp_project_id': gcp_project_id, - 'instance_name': instance_name, - 'database_version': database_version, - 'environment_name': environment_name, - 'is_protected': protected? - } - ) - end - - def protected? - project.protected_for?(environment_name) - end - - def instance_name - # Generates an `instance_name` for the to-be-created Cloud SQL instance - # Example: `gitlab-34647-postgres-14-staging` - environment_alias = environment_name == '*' ? 'ALL' : environment_name - name = "gitlab-#{project.id}-#{database_version}-#{environment_alias}" - name.tr("_", "-").downcase - end - - def root_password - SecureRandom.hex(16) - end - - def database_version - params[:database_version] - end - - def region - region = ::Ci::VariablesFinder - .new(project, { key: Projects::GoogleCloud::GcpRegionsController::GCP_REGION_CI_VAR_KEY, - environment_scope: environment_name }) - .execute.first - region&.value || DEFAULT_REGION - end - - def tier - params[:tier] - end - end -end diff --git a/app/services/google_cloud/create_service_accounts_service.rb b/app/services/google_cloud/create_service_accounts_service.rb deleted file mode 100644 index ca0aa7c91dfb..000000000000 --- a/app/services/google_cloud/create_service_accounts_service.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class CreateServiceAccountsService < ::GoogleCloud::BaseService - def execute - service_account = google_api_client.create_service_account(gcp_project_id, service_account_name, service_account_desc) - service_account_key = google_api_client.create_service_account_key(gcp_project_id, service_account.unique_id) - google_api_client.grant_service_account_roles(gcp_project_id, service_account.email) - - service_accounts_service.add_for_project( - environment_name, - service_account.project_id, - Gitlab::Json.dump(service_account), - Gitlab::Json.dump(service_account_key), - ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name) - ) - - ServiceResponse.success(message: _('Service account generated successfully'), payload: { - service_account: service_account, - service_account_key: service_account_key - }) - end - - private - - def service_accounts_service - GoogleCloud::ServiceAccountsService.new(project) - end - - def service_account_name - "GitLab :: #{project.name} :: #{environment_name}" - end - - def service_account_desc - "GitLab generated service account for project '#{project.name}' and environment '#{environment_name}'" - end - end -end - -GoogleCloud::CreateServiceAccountsService.prepend_mod diff --git a/app/services/google_cloud/enable_cloud_run_service.rb b/app/services/google_cloud/enable_cloud_run_service.rb deleted file mode 100644 index 4fd92f423c5c..000000000000 --- a/app/services/google_cloud/enable_cloud_run_service.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class EnableCloudRunService < ::GoogleCloud::BaseService - def execute - gcp_project_ids = unique_gcp_project_ids - - if gcp_project_ids.empty? - error("No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.") - else - gcp_project_ids.each do |gcp_project_id| - google_api_client.enable_cloud_run(gcp_project_id) - google_api_client.enable_artifacts_registry(gcp_project_id) - google_api_client.enable_cloud_build(gcp_project_id) - end - - success({ gcp_project_ids: gcp_project_ids }) - end - end - end -end diff --git a/app/services/google_cloud/enable_cloudsql_service.rb b/app/services/google_cloud/enable_cloudsql_service.rb deleted file mode 100644 index 911cccca5cab..000000000000 --- a/app/services/google_cloud/enable_cloudsql_service.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class EnableCloudsqlService < ::GoogleCloud::BaseService - def execute - create_or_replace_project_vars(environment_name, 'GCP_PROJECT_ID', gcp_project_id, ci_var_protected?) - - unique_gcp_project_ids.each do |gcp_project_id| - google_api_client.enable_cloud_sql_admin(gcp_project_id) - google_api_client.enable_compute(gcp_project_id) - google_api_client.enable_service_networking(gcp_project_id) - end - - success({ gcp_project_ids: unique_gcp_project_ids }) - rescue Google::Apis::Error => err - error(err.message) - end - - private - - def ci_var_protected? - ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name) - end - end -end diff --git a/app/services/google_cloud/enable_vision_ai_service.rb b/app/services/google_cloud/enable_vision_ai_service.rb deleted file mode 100644 index f7adea706ede..000000000000 --- a/app/services/google_cloud/enable_vision_ai_service.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class EnableVisionAiService < ::GoogleCloud::BaseService - def execute - gcp_project_ids = unique_gcp_project_ids - - if gcp_project_ids.empty? - error("No GCP projects found. Configure a service account or GCP_PROJECT_ID ci variable.") - else - gcp_project_ids.each do |gcp_project_id| - google_api_client.enable_vision_api(gcp_project_id) - end - - success({ gcp_project_ids: gcp_project_ids }) - end - end - end -end diff --git a/app/services/google_cloud/fetch_google_ip_list_service.rb b/app/services/google_cloud/fetch_google_ip_list_service.rb deleted file mode 100644 index 54af841d002d..000000000000 --- a/app/services/google_cloud/fetch_google_ip_list_service.rb +++ /dev/null @@ -1,91 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class FetchGoogleIpListService - include BaseServiceUtility - - GOOGLE_IP_RANGES_URL = 'https://www.gstatic.com/ipranges/cloud.json' - RESPONSE_BODY_LIMIT = 1.megabyte - EXPECTED_CONTENT_TYPE = 'application/json' - - IpListNotRetrievedError = Class.new(StandardError) - - def execute - # Prevent too many workers from hitting the same HTTP endpoint - if ::Gitlab::ApplicationRateLimiter.throttled?(:fetch_google_ip_list, scope: nil) - return error("#{self.class} was rate limited") - end - - subnets = fetch_and_update_cache! - - Gitlab::AppJsonLogger.info( - class: self.class.name, - message: 'Successfully retrieved Google IP list', - subnet_count: subnets.count - ) - - success({ subnets: subnets }) - rescue IpListNotRetrievedError => err - Gitlab::ErrorTracking.log_exception(err) - error('Google IP list not retrieved') - end - - private - - # Attempts to retrieve and parse the list of IPs from Google. Updates - # the internal cache so that the data is accessible. - # - # Returns an array of IPAddr objects consisting of subnets. - def fetch_and_update_cache! - parsed_response = fetch_google_ip_list - - parse_google_prefixes(parsed_response).tap do |subnets| - ::ObjectStorage::CDN::GoogleIpCache.update!(subnets) - end - end - - def fetch_google_ip_list - response = Gitlab::HTTP.get(GOOGLE_IP_RANGES_URL, follow_redirects: false, allow_local_requests: false) - - validate_response!(response) - - response.parsed_response - end - - def validate_response!(response) - raise IpListNotRetrievedError, "response was #{response.code}" unless response.code == 200 - raise IpListNotRetrievedError, "response was nil" unless response.body - - parsed_response = response.parsed_response - - unless response.content_type == EXPECTED_CONTENT_TYPE && parsed_response.is_a?(Hash) - raise IpListNotRetrievedError, "response was not JSON" - end - - if response.body&.bytesize.to_i > RESPONSE_BODY_LIMIT - raise IpListNotRetrievedError, "response was too large: #{response.body.bytesize}" - end - - prefixes = parsed_response['prefixes'] - - raise IpListNotRetrievedError, "JSON was type #{prefixes.class}, expected Array" unless prefixes.is_a?(Array) - raise IpListNotRetrievedError, "#{GOOGLE_IP_RANGES_URL} did not return any IP ranges" if prefixes.empty? - - response.parsed_response - end - - def parse_google_prefixes(parsed_response) - ranges = parsed_response['prefixes'].map do |prefix| - ip_range = prefix['ipv4Prefix'] || prefix['ipv6Prefix'] - - next unless ip_range - - IPAddr.new(ip_range) - end.compact - - raise IpListNotRetrievedError, "#{GOOGLE_IP_RANGES_URL} did not return any IP ranges" if ranges.empty? - - ranges - end - end -end diff --git a/app/services/google_cloud/gcp_region_add_or_replace_service.rb b/app/services/google_cloud/gcp_region_add_or_replace_service.rb deleted file mode 100644 index f79df707a088..000000000000 --- a/app/services/google_cloud/gcp_region_add_or_replace_service.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class GcpRegionAddOrReplaceService < ::GoogleCloud::BaseService - def execute(environment, region) - gcp_region_key = Projects::GoogleCloud::GcpRegionsController::GCP_REGION_CI_VAR_KEY - - change_params = { variable_params: { key: gcp_region_key, value: region, environment_scope: environment } } - filter_params = { key: gcp_region_key, filter: { environment_scope: environment } } - - existing_variable = ::Ci::VariablesFinder.new(project, filter_params).execute.first - - if existing_variable - change_params[:action] = :update - change_params[:variable] = existing_variable - else - change_params[:action] = :create - end - - ::Ci::ChangeVariableService.new(container: project, current_user: current_user, params: change_params).execute - end - end -end diff --git a/app/services/google_cloud/generate_pipeline_service.rb b/app/services/google_cloud/generate_pipeline_service.rb deleted file mode 100644 index 97d008db76b8..000000000000 --- a/app/services/google_cloud/generate_pipeline_service.rb +++ /dev/null @@ -1,98 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class GeneratePipelineService < ::GoogleCloud::BaseService - ACTION_DEPLOY_TO_CLOUD_RUN = 'DEPLOY_TO_CLOUD_RUN' - ACTION_DEPLOY_TO_CLOUD_STORAGE = 'DEPLOY_TO_CLOUD_STORAGE' - ACTION_VISION_AI_PIPELINE = 'VISION_AI_PIPELINE' - - def execute - commit_attributes = generate_commit_attributes - create_branch_response = ::Branches::CreateService.new(project, current_user) - .execute(commit_attributes[:branch_name], project.default_branch) - - if create_branch_response[:status] == :error - return create_branch_response - end - - branch = create_branch_response[:branch] - - service = default_branch_gitlab_ci_yml.present? ? ::Files::UpdateService : ::Files::CreateService - - commit_response = service.new(project, current_user, commit_attributes).execute - - if commit_response[:status] == :error - return commit_response - end - - success({ branch_name: branch.name, commit: commit_response }) - end - - private - - def action - @params[:action] - end - - def generate_commit_attributes - case action - when ACTION_DEPLOY_TO_CLOUD_RUN - branch_name = "deploy-to-cloud-run-#{SecureRandom.hex(8)}" - { - commit_message: 'Enable Cloud Run deployments', - file_path: '.gitlab-ci.yml', - file_content: pipeline_content('gcp/cloud-run.gitlab-ci.yml'), - branch_name: branch_name, - start_branch: branch_name - } - when ACTION_DEPLOY_TO_CLOUD_STORAGE - branch_name = "deploy-to-cloud-storage-#{SecureRandom.hex(8)}" - { - commit_message: 'Enable Cloud Storage deployments', - file_path: '.gitlab-ci.yml', - file_content: pipeline_content('gcp/cloud-storage.gitlab-ci.yml'), - branch_name: branch_name, - start_branch: branch_name - } - when ACTION_VISION_AI_PIPELINE - branch_name = "vision-ai-pipeline-#{SecureRandom.hex(8)}" - { - commit_message: 'Enable Vision AI Pipeline', - file_path: '.gitlab-ci.yml', - file_content: pipeline_content('gcp/vision-ai.gitlab-ci.yml'), - branch_name: branch_name, - start_branch: branch_name - } - end - end - - def default_branch_gitlab_ci_yml - @default_branch_gitlab_ci_yml ||= project.ci_config_for(project.default_branch) - end - - def pipeline_content(include_path) - gitlab_ci_yml = ::Gitlab::Ci::Config::Yaml::Loader.new(default_branch_gitlab_ci_yml || '{}').load - - append_remote_include( - gitlab_ci_yml.content, - "https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library/-/raw/main/#{include_path}" - ) - end - - def append_remote_include(gitlab_ci_yml, include_url) - stages = gitlab_ci_yml['stages'] || [] - gitlab_ci_yml['stages'] = if action == ACTION_VISION_AI_PIPELINE - (stages + %w[validate detect render]).uniq - else - (stages + %w[build test deploy]).uniq - end - - includes = gitlab_ci_yml['include'] || [] - includes = Array.wrap(includes) - includes << { 'remote' => include_url } - gitlab_ci_yml['include'] = includes.uniq - - gitlab_ci_yml.deep_stringify_keys.to_yaml - end - end -end diff --git a/app/services/google_cloud/get_cloudsql_instances_service.rb b/app/services/google_cloud/get_cloudsql_instances_service.rb deleted file mode 100644 index 701e83d556de..000000000000 --- a/app/services/google_cloud/get_cloudsql_instances_service.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class GetCloudsqlInstancesService < ::GoogleCloud::BaseService - CLOUDSQL_KEYS = %w[GCP_PROJECT_ID GCP_CLOUDSQL_INSTANCE_NAME GCP_CLOUDSQL_VERSION].freeze - - def execute - group_vars_by_environment(CLOUDSQL_KEYS).map do |environment_scope, value| - { - ref: environment_scope, - gcp_project: value['GCP_PROJECT_ID'], - instance_name: value['GCP_CLOUDSQL_INSTANCE_NAME'], - version: value['GCP_CLOUDSQL_VERSION'] - } - end - end - end -end diff --git a/app/services/google_cloud/service_accounts_service.rb b/app/services/google_cloud/service_accounts_service.rb deleted file mode 100644 index e90fd112e2e7..000000000000 --- a/app/services/google_cloud/service_accounts_service.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - ## - # GCP keys used to store Google Cloud Service Accounts - GCP_KEYS = %w[GCP_PROJECT_ID GCP_SERVICE_ACCOUNT GCP_SERVICE_ACCOUNT_KEY].freeze - - ## - # This service deals with GCP Service Accounts in GitLab - - class ServiceAccountsService < ::GoogleCloud::BaseService - ## - # Find GCP Service Accounts in a GitLab project - # - # This method looks up GitLab project's CI vars - # and returns Google Cloud Service Accounts combinations - # aligning GitLab project and ref to GCP projects - - def find_for_project - group_vars_by_environment(GCP_KEYS).map do |environment_scope, value| - { - ref: environment_scope, - gcp_project: value['GCP_PROJECT_ID'], - service_account_exists: value['GCP_SERVICE_ACCOUNT'].present?, - service_account_key_exists: value['GCP_SERVICE_ACCOUNT_KEY'].present? - } - end - end - - def add_for_project(ref, gcp_project_id, service_account, service_account_key, is_protected) - create_or_replace_project_vars( - ref, - 'GCP_PROJECT_ID', - gcp_project_id, - is_protected - ) - create_or_replace_project_vars( - ref, - 'GCP_SERVICE_ACCOUNT', - service_account, - is_protected - ) - create_or_replace_project_vars( - ref, - 'GCP_SERVICE_ACCOUNT_KEY', - service_account_key, - is_protected - ) - end - end -end diff --git a/app/services/google_cloud/setup_cloudsql_instance_service.rb b/app/services/google_cloud/setup_cloudsql_instance_service.rb deleted file mode 100644 index 40184b927ad5..000000000000 --- a/app/services/google_cloud/setup_cloudsql_instance_service.rb +++ /dev/null @@ -1,118 +0,0 @@ -# frozen_string_literal: true - -module GoogleCloud - class SetupCloudsqlInstanceService < ::GoogleCloud::BaseService - INSTANCE_STATE_RUNNABLE = 'RUNNABLE' - OPERATION_STATE_DONE = 'DONE' - DEFAULT_DATABASE_NAME = 'main_db' - DEFAULT_DATABASE_USER = 'main_user' - - def execute - return error('Unauthorized user') unless Ability.allowed?(current_user, :admin_project_google_cloud, project) - - get_instance_response = google_api_client.get_cloudsql_instance(gcp_project_id, instance_name) - - if get_instance_response.state != INSTANCE_STATE_RUNNABLE - return error("CloudSQL instance not RUNNABLE: #{Gitlab::Json.dump(get_instance_response)}") - end - - save_instance_ci_vars(get_instance_response) - - list_database_response = google_api_client.list_cloudsql_databases(gcp_project_id, instance_name) - list_user_response = google_api_client.list_cloudsql_users(gcp_project_id, instance_name) - - existing_database = list_database_response.items.find { |database| database.name == database_name } - existing_user = list_user_response.items.find { |user| user.name == username } - - if existing_database && existing_user - save_database_ci_vars - save_user_ci_vars(existing_user) - return success - end - - database_response = execute_database_setup(existing_database) - return database_response if database_response[:status] == :error - - save_database_ci_vars - - user_response = execute_user_setup(existing_user) - return user_response if user_response[:status] == :error - - save_user_ci_vars(existing_user) - - success - rescue Google::Apis::Error => err - error(message: Gitlab::Json.dump(err)) - end - - private - - def instance_name - @params[:instance_name] - end - - def database_version - @params[:database_version] - end - - def database_name - @params.fetch(:database_name, DEFAULT_DATABASE_NAME) - end - - def username - @params.fetch(:username, DEFAULT_DATABASE_USER) - end - - def password - @password ||= SecureRandom.hex(16) - end - - def save_ci_var(key, value, is_masked = false) - create_or_replace_project_vars(environment_name, key, value, @params[:is_protected], is_masked) - end - - def save_instance_ci_vars(cloudsql_instance) - primary_ip_address = cloudsql_instance.ip_addresses.first.ip_address - connection_name = cloudsql_instance.connection_name - - save_ci_var('GCP_PROJECT_ID', gcp_project_id) - save_ci_var('GCP_CLOUDSQL_INSTANCE_NAME', instance_name) - save_ci_var('GCP_CLOUDSQL_CONNECTION_NAME', connection_name) - save_ci_var('GCP_CLOUDSQL_PRIMARY_IP_ADDRESS', primary_ip_address) - save_ci_var('GCP_CLOUDSQL_VERSION', database_version) - end - - def save_database_ci_vars - save_ci_var('GCP_CLOUDSQL_DATABASE_NAME', database_name) - end - - def save_user_ci_vars(user_exists) - save_ci_var('GCP_CLOUDSQL_DATABASE_USER', username) - save_ci_var('GCP_CLOUDSQL_DATABASE_PASS', user_exists ? user_exists.password : password, true) - end - - def execute_database_setup(database_exists) - return success if database_exists - - database_response = google_api_client.create_cloudsql_database(gcp_project_id, instance_name, database_name) - - if database_response.status != OPERATION_STATE_DONE - return error("Database creation failed: #{Gitlab::Json.dump(database_response)}") - end - - success - end - - def execute_user_setup(existing_user) - return success if existing_user - - user_response = google_api_client.create_cloudsql_user(gcp_project_id, instance_name, username, password) - - if user_response.status != OPERATION_STATE_DONE - return error("User creation failed: #{Gitlab::Json.dump(user_response)}") - end - - success - end - end -end diff --git a/app/workers/google_cloud/create_cloudsql_instance_worker.rb b/app/workers/google_cloud/create_cloudsql_instance_worker.rb index 8c4f4c83339a..e0d0747e2274 100644 --- a/app/workers/google_cloud/create_cloudsql_instance_worker.rb +++ b/app/workers/google_cloud/create_cloudsql_instance_worker.rb @@ -13,7 +13,7 @@ def perform(user_id, project_id, params = {}) project = Project.find(project_id) params = params.with_indifferent_access - response = ::GoogleCloud::SetupCloudsqlInstanceService.new(project, user, params).execute + response = ::CloudSeed::GoogleCloud::SetupCloudsqlInstanceService.new(project, user, params).execute if response[:status] == :error raise "Error SetupCloudsqlInstanceService: #{response.to_json}" diff --git a/app/workers/google_cloud/fetch_google_ip_list_worker.rb b/app/workers/google_cloud/fetch_google_ip_list_worker.rb index b14b4e735dc3..de725709bea8 100644 --- a/app/workers/google_cloud/fetch_google_ip_list_worker.rb +++ b/app/workers/google_cloud/fetch_google_ip_list_worker.rb @@ -11,7 +11,7 @@ class FetchGoogleIpListWorker idempotent! def perform - GoogleCloud::FetchGoogleIpListService.new.execute + CloudSeed::GoogleCloud::FetchGoogleIpListService.new.execute end end end diff --git a/spec/requests/projects/google_cloud/databases_controller_spec.rb b/spec/requests/projects/google_cloud/databases_controller_spec.rb index fa978a3921f6..46f6d27644c1 100644 --- a/spec/requests/projects/google_cloud/databases_controller_spec.rb +++ b/spec/requests/projects/google_cloud/databases_controller_spec.rb @@ -96,7 +96,7 @@ context 'when EnableCloudsqlService fails' do before do - allow_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::EnableCloudsqlService) do |service| allow(service).to receive(:execute) .and_return({ status: :error, message: 'error' }) end @@ -125,7 +125,7 @@ context 'when EnableCloudsqlService is successful' do before do - allow_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::EnableCloudsqlService) do |service| allow(service).to receive(:execute) .and_return({ status: :success, message: 'success' }) end @@ -133,7 +133,7 @@ context 'when CreateCloudsqlInstanceService fails' do before do - allow_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::CreateCloudsqlInstanceService) do |service| allow(service).to receive(:execute) .and_return({ status: :error, message: 'error' }) end @@ -162,7 +162,7 @@ context 'when CreateCloudsqlInstanceService is successful' do before do - allow_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::CreateCloudsqlInstanceService) do |service| allow(service).to receive(:execute) .and_return({ status: :success, message: 'success' }) end diff --git a/spec/requests/projects/google_cloud/deployments_controller_spec.rb b/spec/requests/projects/google_cloud/deployments_controller_spec.rb index e9eac1e7ecdc..1a6482477ef6 100644 --- a/spec/requests/projects/google_cloud/deployments_controller_spec.rb +++ b/spec/requests/projects/google_cloud/deployments_controller_spec.rb @@ -110,7 +110,7 @@ context 'when enable service fails' do before do - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |service| allow(service) .to receive(:execute) .and_return( @@ -146,7 +146,7 @@ before do mock_gcp_error = Google::Apis::ClientError.new('some_error') - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |service| allow(service).to receive(:execute).and_raise(mock_gcp_error) end end @@ -173,14 +173,14 @@ context 'GCP_PROJECT_IDs are defined' do before do - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |enable_cloud_run_service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |enable_cloud_run_service| allow(enable_cloud_run_service).to receive(:execute).and_return({ status: :success }) end end context 'when generate pipeline service fails' do before do - allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |generate_pipeline_service| + allow_next_instance_of(CloudSeed::GoogleCloud::GeneratePipelineService) do |generate_pipeline_service| allow(generate_pipeline_service).to receive(:execute).and_return({ status: :error }) end end @@ -206,7 +206,7 @@ end it 'redirects to create merge request form' do - allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::GeneratePipelineService) do |service| allow(service).to receive(:execute).and_return({ status: :success }) end diff --git a/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb b/spec/services/cloud_seed/google_cloud/create_cloudsql_instance_service_spec.rb similarity index 96% rename from spec/services/google_cloud/create_cloudsql_instance_service_spec.rb rename to spec/services/cloud_seed/google_cloud/create_cloudsql_instance_service_spec.rb index c31e76170d54..f6f1206e753f 100644 --- a/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/create_cloudsql_instance_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::CreateCloudsqlInstanceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::CreateCloudsqlInstanceService, feature_category: :deployment_management do let(:project) { create(:project) } let(:user) { create(:user) } let(:gcp_project_id) { 'gcp_project_120' } diff --git a/spec/services/google_cloud/create_service_accounts_service_spec.rb b/spec/services/cloud_seed/google_cloud/create_service_accounts_service_spec.rb similarity index 95% rename from spec/services/google_cloud/create_service_accounts_service_spec.rb rename to spec/services/cloud_seed/google_cloud/create_service_accounts_service_spec.rb index 3b57f2a9e5fc..da30037963b1 100644 --- a/spec/services/google_cloud/create_service_accounts_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/create_service_accounts_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::CreateServiceAccountsService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::CreateServiceAccountsService, feature_category: :deployment_management do describe '#execute' do before do mock_google_oauth2_creds = Struct.new(:app_id, :app_secret) diff --git a/spec/services/google_cloud/enable_cloud_run_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb similarity index 93% rename from spec/services/google_cloud/enable_cloud_run_service_spec.rb rename to spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb index 3de9e7fcd5c6..09f1b3460cc2 100644 --- a/spec/services/google_cloud/enable_cloud_run_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableCloudRunService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableCloudRunService, feature_category: :deployment_management do describe 'when a project does not have any gcp projects' do let_it_be(:project) { create(:project) } diff --git a/spec/services/google_cloud/enable_cloudsql_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb similarity index 97% rename from spec/services/google_cloud/enable_cloudsql_service_spec.rb rename to spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb index b14b827e8b88..137393e4544c 100644 --- a/spec/services/google_cloud/enable_cloudsql_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableCloudsqlService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableCloudsqlService, feature_category: :deployment_management do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } let_it_be(:params) do diff --git a/spec/services/google_cloud/enable_vision_ai_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_vision_ai_service_spec.rb similarity index 92% rename from spec/services/google_cloud/enable_vision_ai_service_spec.rb rename to spec/services/cloud_seed/google_cloud/enable_vision_ai_service_spec.rb index 5adafcffe699..c37b5681a4b7 100644 --- a/spec/services/google_cloud/enable_vision_ai_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_vision_ai_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableVisionAiService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableVisionAiService, feature_category: :deployment_management do describe 'when a project does not have any gcp projects' do let_it_be(:project) { create(:project) } diff --git a/spec/services/google_cloud/fetch_google_ip_list_service_spec.rb b/spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb similarity index 95% rename from spec/services/google_cloud/fetch_google_ip_list_service_spec.rb rename to spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb index f8d5ba99bf61..c4a0be782132 100644 --- a/spec/services/google_cloud/fetch_google_ip_list_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::FetchGoogleIpListService, :use_clean_rails_memory_store_caching, +RSpec.describe CloudSeed::GoogleCloud::FetchGoogleIpListService, :use_clean_rails_memory_store_caching, :clean_gitlab_redis_rate_limiting, feature_category: :build_artifacts do include StubRequests diff --git a/spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb b/spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb similarity index 88% rename from spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb rename to spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb index a748fed7134a..2af032914841 100644 --- a/spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GcpRegionAddOrReplaceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GcpRegionAddOrReplaceService, feature_category: :deployment_management do it 'adds and replaces GCP region vars' do project = create(:project, :public) service = described_class.new(project) diff --git a/spec/services/google_cloud/generate_pipeline_service_spec.rb b/spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb similarity index 94% rename from spec/services/google_cloud/generate_pipeline_service_spec.rb rename to spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb index 8f49e1af901d..14c1e6bae7fd 100644 --- a/spec/services/google_cloud/generate_pipeline_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GeneratePipelineService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GeneratePipelineService, feature_category: :deployment_management do describe 'for cloud-run' do describe 'when there is no existing pipeline' do let_it_be(:project) { create(:project, :repository) } @@ -64,7 +64,10 @@ describe 'when there is an existing pipeline without `deploy` stage' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before_all do @@ -119,7 +122,10 @@ describe 'when there is an existing pipeline with `deploy` stage' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do @@ -166,7 +172,10 @@ describe 'when there is an existing pipeline with `includes`' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do @@ -210,7 +219,10 @@ describe 'when there is no existing pipeline' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_STORAGE } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_STORAGE } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do diff --git a/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb b/spec/services/cloud_seed/google_cloud/get_cloudsql_instances_service_spec.rb similarity index 93% rename from spec/services/google_cloud/get_cloudsql_instances_service_spec.rb rename to spec/services/cloud_seed/google_cloud/get_cloudsql_instances_service_spec.rb index cd2ad00ac3fb..fb17d578af77 100644 --- a/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/get_cloudsql_instances_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GetCloudsqlInstancesService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GetCloudsqlInstancesService, feature_category: :deployment_management do let(:service) { described_class.new(project) } let(:project) { create(:project) } diff --git a/spec/services/google_cloud/service_accounts_service_spec.rb b/spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb similarity index 97% rename from spec/services/google_cloud/service_accounts_service_spec.rb rename to spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb index c900bf7d3005..62d58b3198a0 100644 --- a/spec/services/google_cloud/service_accounts_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::ServiceAccountsService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::ServiceAccountsService, feature_category: :deployment_management do let(:service) { described_class.new(project) } describe 'find_for_project' do diff --git a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb b/spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb similarity index 98% rename from spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb rename to spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb index 5095277f61a9..ce02672e3fab 100644 --- a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::SetupCloudsqlInstanceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::SetupCloudsqlInstanceService, feature_category: :deployment_management do let(:random_user) { create(:user) } let(:project) { create(:project) } let(:list_databases_empty) { Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: []) } diff --git a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb index 96413f622e80..04c6cf4bde9f 100644 --- a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb +++ b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb @@ -19,7 +19,7 @@ subject { described_class.new(options) } before do - WebMock.stub_request(:get, GoogleCloud::FetchGoogleIpListService::GOOGLE_IP_RANGES_URL) + WebMock.stub_request(:get, CloudSeed::GoogleCloud::FetchGoogleIpListService::GOOGLE_IP_RANGES_URL) .to_return(status: 200, body: google_cloud_ips, headers: headers) end diff --git a/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb b/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb index 7aea40807e88..e86d67713867 100644 --- a/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb +++ b/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb @@ -23,15 +23,15 @@ described_class.new.perform(user_id, project_id, worker_options) end - it 'calls GoogleCloud::SetupCloudsqlInstanceService' do - allow_next_instance_of(GoogleCloud::SetupCloudsqlInstanceService) do |service| + it 'calls CloudSeed::GoogleCloud::SetupCloudsqlInstanceService' do + allow_next_instance_of(CloudSeed::GoogleCloud::SetupCloudsqlInstanceService) do |service| expect(service).to receive(:execute).and_return({ status: :success }) end subject end - context 'when GoogleCloud::SetupCloudsqlInstanceService fails' do + context 'when CloudSeed::GoogleCloud::SetupCloudsqlInstanceService fails' do subject do user_id = random_user.id project_id = project.id @@ -39,7 +39,7 @@ end it 'raises error' do - allow_next_instance_of(GoogleCloud::SetupCloudsqlInstanceService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::SetupCloudsqlInstanceService) do |service| expect(service).to receive(:execute).and_return({ status: :error }) end diff --git a/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb b/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb index bdafc0764659..2a7d52d987f0 100644 --- a/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb +++ b/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb @@ -5,7 +5,7 @@ RSpec.describe GoogleCloud::FetchGoogleIpListWorker, feature_category: :build_artifacts do describe '#perform' do it 'returns success' do - allow_next_instance_of(GoogleCloud::FetchGoogleIpListService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::FetchGoogleIpListService) do |service| expect(service).to receive(:execute).and_return({ status: :success }) end -- GitLab