diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json index c721e9e3a77b4e3809aa8c9a6b66c5c5cbd5ca83..63ea8830caed19847f028acc7e310c80320e9a7d 100644 --- a/app/assets/javascripts/graphql_shared/possible_types.json +++ b/app/assets/javascripts/graphql_shared/possible_types.json @@ -11,8 +11,8 @@ "AuditEventStreamingHeader", "AuditEventsStreamingInstanceHeader" ], - "CiRunnerCloudProvisioningOptions": [ - "CiRunnerGoogleCloudProvisioningOptions" + "CiRunnerCloudProvisioning": [ + "CiRunnerGoogleCloudProvisioning" ], "CiVariable": [ "CiGroupVariable", diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 5fb982ee21ecc2e932081bfa104504e26fb1a1b7..506f4a7c32780752cbc1806a82bf9fa993abc794 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -42,6 +42,8 @@ class Runner < Ci::ApplicationRecord # Prefix assigned to runners created from the UI, instead of registered via the command line CREATED_RUNNER_TOKEN_PREFIX = 'glrt-' + RUNNER_SHORT_SHA_LENGTH = 8 + # This `ONLINE_CONTACT_TIMEOUT` needs to be larger than # `RUNNER_QUEUE_EXPIRY_TIME+UPDATE_CONTACT_COLUMN_EVERY` # @@ -394,7 +396,7 @@ def short_sha return unless token start_index = authenticated_user_registration_type? ? CREATED_RUNNER_TOKEN_PREFIX.length : 0 - token[start_index..start_index + 8] + token[start_index..start_index + RUNNER_SHORT_SHA_LENGTH] end def tag_list diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index df2e53bda31b0b9d30e0005c72bfe8e0d6c450ac..9910bf904f9a4e8795292ec00d63cb0ae27633e8 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -6787,37 +6787,6 @@ Input type: `PromoteToEpicInput` | <a id="mutationpromotetoepicerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationpromotetoepicissue"></a>`issue` | [`Issue`](#issue) | Issue after mutation. | -### `Mutation.provisionGoogleCloudRunner` - -Provisions a runner in Google Cloud. - -DETAILS: -**Introduced** in GitLab 16.10. -**Status**: Experiment. - -Input type: `ProvisionGoogleCloudRunnerInput` - -#### Arguments - -| Name | Type | Description | -| ---- | ---- | ----------- | -| <a id="mutationprovisiongooglecloudrunnerclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | -| <a id="mutationprovisiongooglecloudrunnerdryrun"></a>`dryRun` | [`Boolean`](#boolean) | If true, returns the Terraform script without executing it. Defaults to false. True is currently not supported. | -| <a id="mutationprovisiongooglecloudrunnerephemeralmachinetype"></a>`ephemeralMachineType` | [`GoogleCloudMachineType!`](#googlecloudmachinetype) | Name of the machine type to use for running jobs. | -| <a id="mutationprovisiongooglecloudrunnerprojectpath"></a>`projectPath` | [`ID!`](#id) | Project to create the runner in. | -| <a id="mutationprovisiongooglecloudrunnerprovisioningprojectid"></a>`provisioningProjectId` | [`GoogleCloudProject!`](#googlecloudproject) | Identifier of the project where the runner is provisioned. | -| <a id="mutationprovisiongooglecloudrunnerprovisioningregion"></a>`provisioningRegion` | [`GoogleCloudRegion!`](#googlecloudregion) | Name of the region to provision the runner in. | -| <a id="mutationprovisiongooglecloudrunnerprovisioningzone"></a>`provisioningZone` | [`GoogleCloudZone!`](#googlecloudzone) | Name of the zone to provision the runner in. | -| <a id="mutationprovisiongooglecloudrunnerrunnertoken"></a>`runnerToken` | [`String`](#string) | Authentication token of the runner. | - -#### Fields - -| Name | Type | Description | -| ---- | ---- | ----------- | -| <a id="mutationprovisiongooglecloudrunnerclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | -| <a id="mutationprovisiongooglecloudrunnererrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | -| <a id="mutationprovisiongooglecloudrunnerprovisioningsteps"></a>`provisioningSteps` | [`[CiRunnerCloudProvisioningStep!]`](#cirunnercloudprovisioningstep) | Steps used to provision the runner. | - ### `Mutation.refreshStandardsAdherenceChecks` Input type: `RefreshStandardsAdherenceChecksInput` @@ -16630,8 +16599,8 @@ Machine type used for runner cloud provisioning. | Name | Type | Description | | ---- | ---- | ----------- | | <a id="cirunnercloudprovisioningmachinetypedescription"></a>`description` | [`String`](#string) | Description of the machine type. | -| <a id="cirunnercloudprovisioningmachinetypename"></a>`name` | [`String`](#string) | Name of the machine type. | -| <a id="cirunnercloudprovisioningmachinetypezone"></a>`zone` | [`String`](#string) | Zone of the machine type. | +| <a id="cirunnercloudprovisioningmachinetypename"></a>`name` | [`GoogleCloudMachineType`](#googlecloudmachinetype) | Name of the machine type. | +| <a id="cirunnercloudprovisioningmachinetypezone"></a>`zone` | [`GoogleCloudZone`](#googlecloudzone) | Zone of the machine type. | ### `CiRunnerCloudProvisioningRegion` @@ -16642,7 +16611,7 @@ Region used for runner cloud provisioning. | Name | Type | Description | | ---- | ---- | ----------- | | <a id="cirunnercloudprovisioningregiondescription"></a>`description` | [`String`](#string) | Description of the region. | -| <a id="cirunnercloudprovisioningregionname"></a>`name` | [`String`](#string) | Name of the region. | +| <a id="cirunnercloudprovisioningregionname"></a>`name` | [`GoogleCloudRegion`](#googlecloudregion) | Name of the region. | ### `CiRunnerCloudProvisioningStep` @@ -16665,22 +16634,22 @@ Zone used for runner cloud provisioning. | Name | Type | Description | | ---- | ---- | ----------- | | <a id="cirunnercloudprovisioningzonedescription"></a>`description` | [`String`](#string) | Description of the zone. | -| <a id="cirunnercloudprovisioningzonename"></a>`name` | [`String`](#string) | Name of the zone. | +| <a id="cirunnercloudprovisioningzonename"></a>`name` | [`GoogleCloudZone`](#googlecloudzone) | Name of the zone. | -### `CiRunnerGoogleCloudProvisioningOptions` +### `CiRunnerGoogleCloudProvisioning` -Options for runner Google Cloud provisioning. +Information used for runner Google Cloud provisioning. #### Fields | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="cirunnergooglecloudprovisioningoptionsprojectsetupshellscript"></a>`projectSetupShellScript` | [`String`](#string) | Instructions for setting up a Google Cloud project. | -| <a id="cirunnergooglecloudprovisioningoptionsregions"></a>`regions` | [`CiRunnerCloudProvisioningRegionConnection`](#cirunnercloudprovisioningregionconnection) | Regions available for provisioning a runner. (see [Connections](#connections)) | +| <a id="cirunnergooglecloudprovisioningprojectsetupshellscript"></a>`projectSetupShellScript` | [`String`](#string) | Instructions for setting up a Google Cloud project. | +| <a id="cirunnergooglecloudprovisioningregions"></a>`regions` | [`CiRunnerCloudProvisioningRegionConnection`](#cirunnercloudprovisioningregionconnection) | Regions available for provisioning a runner. (see [Connections](#connections)) | #### Fields with arguments -##### `CiRunnerGoogleCloudProvisioningOptions.machineTypes` +##### `CiRunnerGoogleCloudProvisioning.machineTypes` Machine types available for provisioning a runner. @@ -16694,9 +16663,24 @@ four standard [pagination arguments](#pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="cirunnergooglecloudprovisioningoptionsmachinetypeszone"></a>`zone` | [`String!`](#string) | Zone to retrieve machine types for. | +| <a id="cirunnergooglecloudprovisioningmachinetypeszone"></a>`zone` | [`GoogleCloudZone!`](#googlecloudzone) | Zone to retrieve machine types for. | + +##### `CiRunnerGoogleCloudProvisioning.provisioningSteps` + +Steps used to provision a runner in the cloud. + +Returns [`[CiRunnerCloudProvisioningStep!]`](#cirunnercloudprovisioningstep). + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="cirunnergooglecloudprovisioningprovisioningstepsephemeralmachinetype"></a>`ephemeralMachineType` | [`GoogleCloudMachineType!`](#googlecloudmachinetype) | Name of the machine type to use for running jobs. | +| <a id="cirunnergooglecloudprovisioningprovisioningstepsregion"></a>`region` | [`GoogleCloudRegion!`](#googlecloudregion) | Name of the region to provision the runner in. | +| <a id="cirunnergooglecloudprovisioningprovisioningstepsrunnertoken"></a>`runnerToken` | [`String`](#string) | Authentication token of the runner. | +| <a id="cirunnergooglecloudprovisioningprovisioningstepszone"></a>`zone` | [`GoogleCloudZone!`](#googlecloudzone) | Name of the zone to provision the runner in. | -##### `CiRunnerGoogleCloudProvisioningOptions.zones` +##### `CiRunnerGoogleCloudProvisioning.zones` Zones available for provisioning a runner. @@ -16710,7 +16694,7 @@ four standard [pagination arguments](#pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="cirunnergooglecloudprovisioningoptionszonesregion"></a>`region` | [`String`](#string) | Region to retrieve zones for. Returns all zones if not specified. | +| <a id="cirunnergooglecloudprovisioningzonesregion"></a>`region` | [`GoogleCloudRegion`](#googlecloudregion) | Region to retrieve zones for. Returns all zones if not specified. | ### `CiRunnerManager` @@ -26563,22 +26547,22 @@ four standard [pagination arguments](#pagination-arguments): | <a id="projectrequirementsworkitemiid"></a>`workItemIid` | [`ID`](#id) | IID of the requirement work item, for example, "1". | | <a id="projectrequirementsworkitemiids"></a>`workItemIids` | [`[ID!]`](#id) | List of IIDs of requirement work items, for example, `[1, 2]`. | -##### `Project.runnerCloudProvisioningOptions` +##### `Project.runnerCloudProvisioning` -Options for provisioning the runner on a cloud provider. Returns `null` if `:google_cloud_runner_provisioning` feature flag is disabled, or the GitLab instance is not a SaaS instance. +Information used for provisioning the runner on a cloud provider. Returns `null` if `:google_cloud_runner_provisioning` feature flag is disabled, or the GitLab instance is not a SaaS instance. DETAILS: **Introduced** in GitLab 16.9. **Status**: Experiment. -Returns [`CiRunnerCloudProvisioningOptions`](#cirunnercloudprovisioningoptions). +Returns [`CiRunnerCloudProvisioning`](#cirunnercloudprovisioning). ###### Arguments | Name | Type | Description | | ---- | ---- | ----------- | -| <a id="projectrunnercloudprovisioningoptionscloudprojectid"></a>`cloudProjectId` | [`GoogleCloudProject!`](#googlecloudproject) | Identifier of the cloud project. | -| <a id="projectrunnercloudprovisioningoptionsprovider"></a>`provider` | [`CiRunnerCloudProvider!`](#cirunnercloudprovider) | Identifier of the cloud provider. | +| <a id="projectrunnercloudprovisioningcloudprojectid"></a>`cloudProjectId` | [`GoogleCloudProject!`](#googlecloudproject) | Identifier of the cloud project. | +| <a id="projectrunnercloudprovisioningprovider"></a>`provider` | [`CiRunnerCloudProvider!`](#cirunnercloudprovider) | Identifier of the cloud provider. | ##### `Project.runners` @@ -34343,13 +34327,13 @@ abstract types. ### Unions -#### `CiRunnerCloudProvisioningOptions` +#### `CiRunnerCloudProvisioning` -Options for runner cloud provisioning. +Information used in runner cloud provisioning. One of: -- [`CiRunnerGoogleCloudProvisioningOptions`](#cirunnergooglecloudprovisioningoptions) +- [`CiRunnerGoogleCloudProvisioning`](#cirunnergooglecloudprovisioning) #### `DependencyLinkMetadata` diff --git a/ee/app/graphql/ee/types/mutation_type.rb b/ee/app/graphql/ee/types/mutation_type.rb index f48f49d78989497d439bb274a88c4cab7394ff72..cf47b7e5d0b5a7eb6f507f8c6698f50c4c36a9ab 100644 --- a/ee/app/graphql/ee/types/mutation_type.rb +++ b/ee/app/graphql/ee/types/mutation_type.rb @@ -112,7 +112,6 @@ module MutationType mount_mutation ::Mutations::AuditEvents::ExternalAuditEventDestinations::Update mount_mutation ::Mutations::Ci::NamespaceCiCdSettingsUpdate mount_mutation ::Mutations::Ci::Runners::ExportUsage, alpha: { milestone: '16.7' } - mount_mutation ::Mutations::Ci::Runners::ProvisionGoogleCloudRunner, alpha: { milestone: '16.10' } mount_mutation ::Mutations::RemoteDevelopment::Workspaces::Create mount_mutation ::Mutations::RemoteDevelopment::Workspaces::Update mount_mutation ::Mutations::AuditEvents::Streaming::Headers::Destroy diff --git a/ee/app/graphql/ee/types/project_type.rb b/ee/app/graphql/ee/types/project_type.rb index df08e41fe429f94efb77c262c150ea3ade4f1bbb..19962064c6cf5f32637fe24dc79bccd272a0da18 100644 --- a/ee/app/graphql/ee/types/project_type.rb +++ b/ee/app/graphql/ee/types/project_type.rb @@ -338,11 +338,11 @@ module ProjectType method: :downstream_project_subscriptions, description: 'Pipeline subscriptions for projects subscribed to the project.' - field :runner_cloud_provisioning_options, - ::Types::Ci::RunnerCloudProvisioningOptionsType, + field :runner_cloud_provisioning, + ::Types::Ci::RunnerCloudProvisioningType, null: true, alpha: { milestone: '16.9' }, - description: 'Options for provisioning the runner on a cloud provider. ' \ + description: 'Information used for provisioning the runner on a cloud provider. ' \ 'Returns `null` if `:google_cloud_runner_provisioning` feature flag is disabled, ' \ 'or the GitLab instance is not a SaaS instance.' do argument :provider, ::Types::Ci::RunnerCloudProviderEnum, required: true, @@ -420,7 +420,7 @@ def compliance_frameworks end end - def runner_cloud_provisioning_options(provider:, cloud_project_id:) + def runner_cloud_provisioning(provider:, cloud_project_id:) return if ::Feature.disabled?(:google_cloud_runner_provisioning, project) { diff --git a/ee/app/graphql/mutations/ci/runners/provision_google_cloud_runner.rb b/ee/app/graphql/mutations/ci/runners/provision_google_cloud_runner.rb deleted file mode 100644 index 8b89946243f16f1f8df052991352c482a7933587..0000000000000000000000000000000000000000 --- a/ee/app/graphql/mutations/ci/runners/provision_google_cloud_runner.rb +++ /dev/null @@ -1,75 +0,0 @@ -# frozen_string_literal: true - -module Mutations - module Ci - module Runners - class ProvisionGoogleCloudRunner < BaseMutation - graphql_name 'ProvisionGoogleCloudRunner' - description 'Provisions a runner in Google Cloud.' - - SINGLE_ELEMENT_QUERY_PARAMS = { max_results: 1 }.freeze - - include FindsProject - - authorize :provision_cloud_runner - - argument :dry_run, ::GraphQL::Types::Boolean, - required: false, - default_value: false, - description: 'If true, returns the Terraform script without executing it. ' \ - 'Defaults to false. True is currently not supported.' - argument :ephemeral_machine_type, ::Types::GoogleCloud::MachineTypeType, - required: true, - description: 'Name of the machine type to use for running jobs.' - argument :project_path, GraphQL::Types::ID, - required: true, - description: 'Project to create the runner in.' - argument :provisioning_project_id, ::Types::GoogleCloud::ProjectType, - required: true, - description: 'Identifier of the project where the runner is provisioned.' - argument :provisioning_region, ::Types::GoogleCloud::RegionType, - required: true, - description: 'Name of the region to provision the runner in.' - argument :provisioning_zone, ::Types::GoogleCloud::ZoneType, - required: true, - description: 'Name of the zone to provision the runner in.' - argument :runner_token, ::GraphQL::Types::String, - required: false, - description: 'Authentication token of the runner.' - - field :provisioning_steps, [Types::Ci::RunnerCloudProvisioningStepType], - null: true, - description: 'Steps used to provision the runner.' - - def ready?(dry_run: nil, **_args) - raise Gitlab::Graphql::Errors::ArgumentError, 'mutation can currently only run in dry-run mode' unless dry_run - - super - end - - def resolve(project_path:, runner_token: nil, **args) - project = authorized_find!(project_path) - - response = ::Ci::Runners::CreateGoogleCloudProvisioningStepsService.new( - project: project, - current_user: current_user, - params: - args.slice(:provisioning_project_id, :provisioning_region, :provisioning_zone, :ephemeral_machine_type) - .merge(runner_token: runner_token) - ).execute - - if response.error? - case response.reason - when :insufficient_permissions, :internal_error - raise_resource_not_available_error!(response.message) - else - return { errors: response.errors } - end - end - - { errors: [], **response.payload } - end - end - end - end -end diff --git a/ee/app/graphql/resolvers/ci/runner_google_cloud_provisioning_steps_resolver.rb b/ee/app/graphql/resolvers/ci/runner_google_cloud_provisioning_steps_resolver.rb new file mode 100644 index 0000000000000000000000000000000000000000..07cf5313ac6286baedf1f3bbe646d193f6fb41d1 --- /dev/null +++ b/ee/app/graphql/resolvers/ci/runner_google_cloud_provisioning_steps_resolver.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module Resolvers + module Ci + class RunnerGoogleCloudProvisioningStepsResolver < BaseResolver + include Gitlab::Graphql::Authorize::AuthorizeResource + + type [Types::Ci::RunnerCloudProvisioningStepType], null: true + description 'Steps used to provision a runner in the cloud.' + + argument :ephemeral_machine_type, ::Types::GoogleCloud::MachineTypeType, + required: true, + description: 'Name of the machine type to use for running jobs.' + argument :region, ::Types::GoogleCloud::RegionType, + required: true, + description: 'Name of the region to provision the runner in.' + argument :runner_token, ::GraphQL::Types::String, + required: false, + default_value: nil, + description: 'Authentication token of the runner.' + argument :zone, ::Types::GoogleCloud::ZoneType, + required: true, + description: 'Name of the zone to provision the runner in.' + + # object is a hash normally sent by EE::Types::ProjectType#runner_cloud_provisioning, containing the + # arguments used in the provisioning. + alias_method :provisioning_args_hash, :object + + def resolve(region:, zone:, ephemeral_machine_type:, runner_token:) + project = provisioning_args_hash[:project] + + unless Ability.allowed?(current_user, :provision_cloud_runner, project) + raise_resource_not_available_error!("You don't have permissions to provision cloud runners") + end + + response = ::Ci::Runners::CreateGoogleCloudProvisioningStepsService.new( + project: project, + current_user: current_user, + params: { + google_cloud_project_id: provisioning_args_hash[:cloud_project_id], runner_token: runner_token, + region: region, zone: zone, ephemeral_machine_type: ephemeral_machine_type + } + ).execute + + raise_resource_not_available_error!(response.message) if response.error? + + response.payload[:provisioning_steps] + end + end + end +end diff --git a/ee/app/graphql/types/ci/runner_cloud_provisioning_machine_type_type.rb b/ee/app/graphql/types/ci/runner_cloud_provisioning_machine_type_type.rb index 990e574db8db58f65398ca723affd6757f11ed39..e08061d04d2cf457625e3e8b4fe9bc08010f0f9a 100644 --- a/ee/app/graphql/types/ci/runner_cloud_provisioning_machine_type_type.rb +++ b/ee/app/graphql/types/ci/runner_cloud_provisioning_machine_type_type.rb @@ -7,10 +7,10 @@ class RunnerCloudProvisioningMachineTypeType < BaseObject graphql_name 'CiRunnerCloudProvisioningMachineType' description 'Machine type used for runner cloud provisioning.' - field :zone, GraphQL::Types::String, + field :zone, Types::GoogleCloud::ZoneType, null: true, description: 'Zone of the machine type.' - field :name, GraphQL::Types::String, + field :name, Types::GoogleCloud::MachineTypeType, null: true, description: 'Name of the machine type.' field :description, GraphQL::Types::String, diff --git a/ee/app/graphql/types/ci/runner_cloud_provisioning_region_type.rb b/ee/app/graphql/types/ci/runner_cloud_provisioning_region_type.rb index 468eb08f9075dd3ce22004de1e583eed8269fab7..32662234671c514de547d091082ebb0738a19731 100644 --- a/ee/app/graphql/types/ci/runner_cloud_provisioning_region_type.rb +++ b/ee/app/graphql/types/ci/runner_cloud_provisioning_region_type.rb @@ -7,7 +7,7 @@ class RunnerCloudProvisioningRegionType < BaseObject graphql_name 'CiRunnerCloudProvisioningRegion' description 'Region used for runner cloud provisioning.' - field :name, GraphQL::Types::String, + field :name, Types::GoogleCloud::RegionType, null: true, description: 'Name of the region.' field :description, GraphQL::Types::String, diff --git a/ee/app/graphql/types/ci/runner_cloud_provisioning_options_type.rb b/ee/app/graphql/types/ci/runner_cloud_provisioning_type.rb similarity index 53% rename from ee/app/graphql/types/ci/runner_cloud_provisioning_options_type.rb rename to ee/app/graphql/types/ci/runner_cloud_provisioning_type.rb index 35e1cca7f429217d2bb98c1496fc1a8180972e71..eafd9d34203bc7280c817f4a51b331860314a96c 100644 --- a/ee/app/graphql/types/ci/runner_cloud_provisioning_options_type.rb +++ b/ee/app/graphql/types/ci/runner_cloud_provisioning_type.rb @@ -2,18 +2,18 @@ module Types module Ci - class RunnerCloudProvisioningOptionsType < BaseUnion - graphql_name 'CiRunnerCloudProvisioningOptions' - description 'Options for runner cloud provisioning.' + class RunnerCloudProvisioningType < BaseUnion + graphql_name 'CiRunnerCloudProvisioning' + description 'Information used in runner cloud provisioning.' UnexpectedProviderType = Class.new(StandardError) - possible_types ::Types::Ci::RunnerGoogleCloudProvisioningOptionsType + possible_types ::Types::Ci::RunnerGoogleCloudProvisioningType def self.resolve_type(object, _context) case object[:provider] when :google_cloud - ::Types::Ci::RunnerGoogleCloudProvisioningOptionsType + ::Types::Ci::RunnerGoogleCloudProvisioningType else raise UnexpectedProviderType, 'Unsupported CI runner cloud provider' end diff --git a/ee/app/graphql/types/ci/runner_cloud_provisioning_zone_type.rb b/ee/app/graphql/types/ci/runner_cloud_provisioning_zone_type.rb index cde0927cb9b20be5c3bff9801597423d513d21d3..b949c4ef76d9a297c69f5647473cb3f7be19326a 100644 --- a/ee/app/graphql/types/ci/runner_cloud_provisioning_zone_type.rb +++ b/ee/app/graphql/types/ci/runner_cloud_provisioning_zone_type.rb @@ -7,7 +7,7 @@ class RunnerCloudProvisioningZoneType < BaseObject graphql_name 'CiRunnerCloudProvisioningZone' description 'Zone used for runner cloud provisioning.' - field :name, GraphQL::Types::String, + field :name, Types::GoogleCloud::ZoneType, null: true, description: 'Name of the zone.' field :description, GraphQL::Types::String, diff --git a/ee/app/graphql/types/ci/runner_google_cloud_provisioning_options_type.rb b/ee/app/graphql/types/ci/runner_google_cloud_provisioning_type.rb similarity index 87% rename from ee/app/graphql/types/ci/runner_google_cloud_provisioning_options_type.rb rename to ee/app/graphql/types/ci/runner_google_cloud_provisioning_type.rb index f724db6148bd20ac40c68a07a520e31cf323e72c..5596fe42fde0ded3f9f5525f94b6fb75fbe3dad7 100644 --- a/ee/app/graphql/types/ci/runner_google_cloud_provisioning_options_type.rb +++ b/ee/app/graphql/types/ci/runner_google_cloud_provisioning_type.rb @@ -2,15 +2,15 @@ module Types module Ci - class RunnerGoogleCloudProvisioningOptionsType < BaseObject - graphql_name 'CiRunnerGoogleCloudProvisioningOptions' - description 'Options for runner Google Cloud provisioning.' + class RunnerGoogleCloudProvisioningType < BaseObject + graphql_name 'CiRunnerGoogleCloudProvisioning' + description 'Information used for runner Google Cloud provisioning.' SHELL_SCRIPT_TEMPLATE_PATH = 'ee/lib/api/templates/google_cloud_integration_runner_project_setup.sh.erb' include Gitlab::Graphql::Authorize::AuthorizeResource - authorize :read_runner_cloud_provisioning_options + authorize :read_runner_cloud_provisioning_info field :regions, Types::Ci::RunnerCloudProvisioningRegionType.connection_type, description: 'Regions available for provisioning a runner.', @@ -25,7 +25,7 @@ class RunnerGoogleCloudProvisioningOptionsType < BaseObject connection_extension: Gitlab::Graphql::Extensions::ForwardOnlyExternallyPaginatedArrayExtension, max_page_size: GoogleCloudPlatform::Compute::ListZonesService::MAX_RESULTS_LIMIT, default_page_size: GoogleCloudPlatform::Compute::ListZonesService::MAX_RESULTS_LIMIT do - argument :region, GraphQL::Types::String, required: false, + argument :region, Types::GoogleCloud::RegionType, required: false, description: 'Region to retrieve zones for. Returns all zones if not specified.' end @@ -36,12 +36,17 @@ class RunnerGoogleCloudProvisioningOptionsType < BaseObject connection_extension: Gitlab::Graphql::Extensions::ForwardOnlyExternallyPaginatedArrayExtension, max_page_size: GoogleCloudPlatform::Compute::ListMachineTypesService::MAX_RESULTS_LIMIT, default_page_size: GoogleCloudPlatform::Compute::ListMachineTypesService::MAX_RESULTS_LIMIT do - argument :zone, GraphQL::Types::String, required: true, description: 'Zone to retrieve machine types for.' + argument :zone, Types::GoogleCloud::ZoneType, required: true, + description: 'Zone to retrieve machine types for.' end field :project_setup_shell_script, GraphQL::Types::String, null: true, description: 'Instructions for setting up a Google Cloud project.' + field :provisioning_steps, + null: true, + resolver: ::Resolvers::Ci::RunnerGoogleCloudProvisioningStepsResolver + def self.authorized?(object, context) super(object[:project], context) end diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index 79f2a12b41203a695bf7c3eda291ea9535d15880..5ac0061c7bafa7c049432e186a8a0421dde815bc 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -797,7 +797,7 @@ module ProjectPolicy rule { status_page_available & can?(:developer_access) }.enable :publish_status_page rule { google_cloud_support_available & can?(:maintainer_access) }.policy do - enable :read_runner_cloud_provisioning_options + enable :read_runner_cloud_provisioning_info enable :provision_cloud_runner end rule { google_cloud_support_available & can?(:reporter_access) }.enable :read_google_cloud_artifact_registry diff --git a/ee/app/services/ci/runners/create_google_cloud_provisioning_steps_service.rb b/ee/app/services/ci/runners/create_google_cloud_provisioning_steps_service.rb index b6ec6414013d22c4d334079e7dc8d72aba6f8ae3..17dd09dcc1e26aba2423feae295ffab2667a15a4 100644 --- a/ee/app/services/ci/runners/create_google_cloud_provisioning_steps_service.rb +++ b/ee/app/services/ci/runners/create_google_cloud_provisioning_steps_service.rb @@ -19,12 +19,12 @@ def execute ServiceResponse.success(payload: { provisioning_steps: [ { - title: 'Save the Terraform script to a file', + title: s_('Runners|Save the Terraform script to a file'), language_identifier: 'terraform', instructions: instructions[:terraform_script] }, { - title: 'Apply the Terraform script', + title: s_('Runners|Apply the Terraform script'), language_identifier: 'shell', instructions: instructions[:shell_script] } @@ -72,9 +72,9 @@ def validate end def deployment_name - # Unique in context of Google Cloud project, no longer than 12 characters - unique_id = runner&.short_sha || Devise.friendly_token(8) - "grit#{unique_id}"[0..DEPLOYMENT_NAME_MAX_LENGTH - 1] + # Unique in context of Google Cloud project, no longer than DEPLOYMENT_NAME_MAX_LENGTH characters + unique_id = runner&.short_sha || Devise.friendly_token(Ci::Runner::RUNNER_SHORT_SHA_LENGTH) + "grit-#{unique_id}"[0..DEPLOYMENT_NAME_MAX_LENGTH - 1] end strong_memoize_attr :deployment_name @@ -113,15 +113,15 @@ def sanitize_value(user_input) end def provisioning_project_id - params[:provisioning_project_id] + params[:google_cloud_project_id] end def provisioning_region - params[:provisioning_region] + params[:region] end def provisioning_zone - params[:provisioning_zone] + params[:zone] end def ephemeral_machine_type diff --git a/ee/app/services/google_cloud_platform/compute/base_service.rb b/ee/app/services/google_cloud_platform/compute/base_service.rb index da59a77959b4b0faf57e51e4713b4bd3d95a4f77..260954bcfa94517e9579370f915558f954bca91a 100644 --- a/ee/app/services/google_cloud_platform/compute/base_service.rb +++ b/ee/app/services/google_cloud_platform/compute/base_service.rb @@ -58,7 +58,7 @@ def validate_before_execute end def allowed? - can?(current_user, :read_runner_cloud_provisioning_options, project) + can?(current_user, :read_runner_cloud_provisioning_info, project) end def valid_order_by?(value) diff --git a/ee/lib/api/templates/ci/google_cloud_integration_grit_provisioning.tf.erb b/ee/lib/api/templates/ci/google_cloud_integration_grit_provisioning.tf.erb index 7bddd0a32eeff13f8f4088457d0a107602dc6d40..276aae2c2b6a35bdde9c0289d5fc00b3b0bc51af 100644 --- a/ee/lib/api/templates/ci/google_cloud_integration_grit_provisioning.tf.erb +++ b/ee/lib/api/templates/ci/google_cloud_integration_grit_provisioning.tf.erb @@ -39,7 +39,6 @@ module "runner-deployment" { google_region = local.google_region google_zone = local.google_zone - # Unique in context of Google Cloud project, no longer than 12 characters name = "<%= deployment_name %>" gitlab_url = "<%= gitlab_url %>" diff --git a/ee/spec/graphql/types/ci/runner_cloud_provisioning_options_type_spec.rb b/ee/spec/graphql/types/ci/runner_cloud_provisioning_type_spec.rb similarity index 76% rename from ee/spec/graphql/types/ci/runner_cloud_provisioning_options_type_spec.rb rename to ee/spec/graphql/types/ci/runner_cloud_provisioning_type_spec.rb index 16d1d8358d8699d09b96a643b79fa3c1734ed2f9..cb97ceb8fa97225d2e5bd9d5924c1f7736a6b207 100644 --- a/ee/spec/graphql/types/ci/runner_cloud_provisioning_options_type_spec.rb +++ b/ee/spec/graphql/types/ci/runner_cloud_provisioning_type_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe GitlabSchema.types['CiRunnerCloudProvisioningOptions'], feature_category: :fleet_visibility do +RSpec.describe GitlabSchema.types['CiRunnerCloudProvisioning'], feature_category: :runner do it 'returns all possible types' do expect(described_class.possible_types).to include( - ::Types::Ci::RunnerGoogleCloudProvisioningOptionsType + ::Types::Ci::RunnerGoogleCloudProvisioningType ) end @@ -13,7 +13,7 @@ using RSpec::Parameterized::TableSyntax where(:provider, :expected_type) do - :google_cloud | ::Types::Ci::RunnerGoogleCloudProvisioningOptionsType + :google_cloud | ::Types::Ci::RunnerGoogleCloudProvisioningType end subject(:resolved_type) do @@ -28,7 +28,7 @@ let(:provider) { :unknown } it 'raises an error' do - expect { resolved_type }.to raise_error(Types::Ci::RunnerCloudProvisioningOptionsType::UnexpectedProviderType) + expect { resolved_type }.to raise_error(Types::Ci::RunnerCloudProvisioningType::UnexpectedProviderType) end end end diff --git a/ee/spec/graphql/types/project_type_spec.rb b/ee/spec/graphql/types/project_type_spec.rb index 5bf0d673208a54ac32019d8c128003f09388d113..e16ddf90a41f17c74bbe3636b7a969e93708f8ab 100644 --- a/ee/spec/graphql/types/project_type_spec.rb +++ b/ee/spec/graphql/types/project_type_spec.rb @@ -30,7 +30,7 @@ security_policy_project_linked_projects security_policy_project_linked_namespaces dependencies merge_requests_disable_committers_approval has_jira_vulnerability_issue_creation_enabled ci_subscriptions_projects ci_subscribed_projects ai_agents ai_agent duo_features_enabled - runner_cloud_provisioning_options google_cloud_artifact_registry_repository + runner_cloud_provisioning google_cloud_artifact_registry_repository ] expect(described_class).to include_graphql_fields(*expected_fields) @@ -492,9 +492,9 @@ it { is_expected.to have_graphql_resolver(Resolvers::Ai::Agents::FindAgentResolver) } end - describe 'runnerCloudProvisioningOptions', feature_category: :runner do - subject { described_class.fields['runnerCloudProvisioningOptions'] } + describe 'runnerCloudProvisioning', feature_category: :runner do + subject { described_class.fields['runnerCloudProvisioning'] } - it { is_expected.to have_graphql_type(::Types::Ci::RunnerCloudProvisioningOptionsType) } + it { is_expected.to have_graphql_type(::Types::Ci::RunnerCloudProvisioningType) } end end diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index 8a2d2ca401592327ba581d093ba9172b06387d7d..98c40537801fb1c04aeaef846cfc404f5ada550b 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -3576,10 +3576,10 @@ def create_member_role(member, abilities = member_role_abilities) end end - describe 'read_runner_cloud_provisioning_options policy' do + describe 'read_runner_cloud_provisioning_info policy' do let(:current_user) { maintainer } - it { is_expected.to be_disallowed(:read_runner_cloud_provisioning_options) } + it { is_expected.to be_disallowed(:read_runner_cloud_provisioning_info) } context 'when SaaS-only feature is available' do before do @@ -3589,13 +3589,13 @@ def create_member_role(member, abilities = member_role_abilities) context 'the user is a maintainer' do let(:current_user) { maintainer } - it { is_expected.to be_allowed(:read_runner_cloud_provisioning_options) } + it { is_expected.to be_allowed(:read_runner_cloud_provisioning_info) } end context 'the user is a guest' do let(:current_user) { guest } - it { is_expected.to be_disallowed(:read_runner_cloud_provisioning_options) } + it { is_expected.to be_disallowed(:read_runner_cloud_provisioning_info) } end end end diff --git a/ee/spec/requests/api/graphql/mutations/ci/runners/provision_google_cloud_runner_spec.rb b/ee/spec/requests/api/graphql/mutations/ci/runners/provision_google_cloud_runner_spec.rb deleted file mode 100644 index a2ccb70c72a766a59994191f3194cd7791e36518..0000000000000000000000000000000000000000 --- a/ee/spec/requests/api/graphql/mutations/ci/runners/provision_google_cloud_runner_spec.rb +++ /dev/null @@ -1,138 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'ProvisionGoogleCloudRunner', feature_category: :fleet_visibility do - include GraphqlHelpers - - let_it_be(:project) { create(:project) } - let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } - let_it_be(:user) { project.owner } - - let(:google_cloud_project_id) { 'google-project-id' } - let(:region) { 'us-central1' } - let(:zone) { 'us-central1-a' } - let(:machine_type) { 'n2d-standard-2' } - let(:runner_token) { runner.token } - let(:dry_run) { true } - let(:mutation_args) do - { - dry_run: dry_run, - project_path: project.full_path, - provisioning_project_id: google_cloud_project_id, - provisioning_region: region, - provisioning_zone: zone, - ephemeral_machine_type: machine_type, - runner_token: runner_token - } - end - - let(:mutation) do - graphql_mutation(:provision_google_cloud_runner, mutation_args) do - <<~QL - provisioningSteps { - title - languageIdentifier - instructions - } - errors - QL - end - end - - subject(:post_response) { post_graphql_mutation(mutation, current_user: user) } - - it 'returns an error' do - post_response - - expect_graphql_errors_to_include("The resource that you are attempting to access does not exist " \ - "or you don't have permission to perform this action") - end - - context 'with saas-only feature enabled' do - before do - stub_saas_features(google_cloud_support: true) - end - - shared_examples 'a request returning an error' do |message| - it 'returns an error' do - post_response - expect(graphql_data_at(:provision_google_cloud_runner, :errors)).to match([message]) - end - end - - it 'returns provisioning steps', :aggregate_failures do - post_response - expect_graphql_errors_to_be_empty - - steps = graphql_data_at(:provision_google_cloud_runner, :provisioning_steps) - expect(steps).to match([ - { - 'instructions' => /google_project += "#{google_cloud_project_id}"/, - 'languageIdentifier' => 'terraform', - 'title' => 'Save the Terraform script to a file' - }, - { - 'instructions' => /gitlab_runner="#{runner_token}"/, - 'languageIdentifier' => 'shell', - 'title' => 'Apply the Terraform script' - } - ]) - end - - context 'with nil runner token' do - let(:runner_token) { nil } - - it 'is successful and generates a unique deployment id' do - post_response - expect_graphql_errors_to_be_empty - - steps = graphql_data_at(:provision_google_cloud_runner, :provisioning_steps) - expect(steps).to match([ - a_hash_including('instructions' => /name = "grit[A-Za-z0-9_\-]{8}"/), - an_instance_of(Hash) - ]) - end - - context 'when user does not have permissions to create runner' do - before do - allow(Ability).to receive(:allowed?).and_call_original - allow(Ability).to receive(:allowed?).with(user, :create_runner, anything).and_return(false) - end - - it 'returns an error' do - post_response - - expect_graphql_errors_to_include('The user is not allowed to create a runner') - end - end - end - - context 'with invalid runner token' do - let(:runner_token) { 'invalid-token' } - - it_behaves_like 'a request returning an error', 'The runner authentication token is invalid' - end - - context 'when user is not authorized' do - let(:user) { create(:user) } - - it 'returns an error' do - post_response - - expect_graphql_errors_to_include("The resource that you are attempting to access does not exist " \ - "or you don't have permission to perform this action") - end - end - end - - context 'with dryRun set to false' do - let(:dry_run) { false } - - it 'returns an error' do - post_response - - expect_graphql_errors_to_include('mutation can currently only run in dry-run mode') - end - end -end diff --git a/ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_options_spec.rb b/ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_spec.rb similarity index 70% rename from ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_options_spec.rb rename to ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_spec.rb index 8dcc4a5368cd44674b91fd26b69c457034178bca..81b2700bda8f1308abec2491d021c39bc2c6aa0e 100644 --- a/ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_options_spec.rb +++ b/ee/spec/requests/api/graphql/project/runner_google_cloud_provisioning_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'runnerGoogleCloudProvisioningOptions', feature_category: :runner do +RSpec.describe 'runnerGoogleCloudProvisioning', feature_category: :runner do include GraphqlHelpers let_it_be_with_refind(:project) { create(:project) } @@ -13,13 +13,13 @@ let(:current_user) { maintainer } let(:google_cloud_project_id) { 'project-id-override' } - let(:inner_fragment) { query_graphql_fragment('CiRunnerGoogleCloudProvisioningOptions') } + let(:inner_fragment) { query_graphql_fragment('CiRunnerGoogleCloudProvisioning') } let(:query) do graphql_query_for( :project, { fullPath: project.full_path }, query_graphql_field( - :runner_cloud_provisioning_options, { provider: :GOOGLE_CLOUD, cloud_project_id: google_cloud_project_id }, - "... on CiRunnerGoogleCloudProvisioningOptions { + :runner_cloud_provisioning, { provider: :GOOGLE_CLOUD, cloud_project_id: google_cloud_project_id }, + "... on CiRunnerGoogleCloudProvisioning { #{inner_fragment} }" ) @@ -28,7 +28,7 @@ let(:options_response) do request - graphql_data_at('project', 'runnerCloudProvisioningOptions') + graphql_data_at('project', 'runnerCloudProvisioning') end subject(:request) do @@ -39,6 +39,16 @@ stub_saas_features(google_cloud_support: true) end + context 'when cloud_project_id is invalid' do + let(:google_cloud_project_id) { 'project_id_override' } + + it 'returns an error' do + request + + expect_graphql_errors_to_include('"project_id_override" is not a valid project name') + end + end + describe 'collections' do let(:client_klass) { GoogleCloudPlatform::Compute::Client } let(:expected_compute_client_args) do @@ -231,13 +241,26 @@ expect_graphql_errors_to_include(/integration not active/) end end + + private + + def google_cloud_object_list(compute_type, returned_nodes, next_page_token:) + item_type = "Google::Cloud::Compute::V1::#{compute_type}" + + # rubocop:disable RSpec/VerifiedDoubles -- these generated objects don't actually expose the methods + double("#{item_type}List", + items: returned_nodes.map { |props| double(item_type, **props) }, + next_page_token: next_page_token + ) + # rubocop:enable RSpec/VerifiedDoubles + end end describe 'projectSetupShellScript' do let(:inner_fragment) { 'projectSetupShellScript' } let(:options_response) do request - graphql_data_at('project', 'runnerCloudProvisioningOptions', 'projectSetupShellScript') + graphql_data_at('project', 'runnerCloudProvisioning', 'projectSetupShellScript') end it 'returns a script' do @@ -249,17 +272,102 @@ end end - context 'when cloud_project_id is invalid' do - let(:google_cloud_project_id) { 'project_id_override' } + describe 'provisioningSteps' do + let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) } - it 'returns an error' do + let(:region) { 'us-central1' } + let(:zone) { 'us-central1-a' } + let(:machine_type) { 'n2d-standard-2' } + let(:runner_token) { runner.token } + let(:args) do + { + region: region, + zone: zone, + ephemeral_machine_type: machine_type, + runner_token: runner_token + } + end + + let(:inner_fragment) do + query_graphql_field(:provisioning_steps, args, + all_graphql_fields_for('CiRunnerCloudProvisioningStep'), '[CiRunnerCloudProvisioningStep!]') + end + + let(:options_response) do request + graphql_data_at('project', 'runnerCloudProvisioning', 'provisioningSteps') + end - expect_graphql_errors_to_include('"project_id_override" is not a valid project name') + it 'returns provisioning steps', :aggregate_failures do + request + expect_graphql_errors_to_be_empty + + expect(options_response).to match([ + { + 'instructions' => /google_project += "#{google_cloud_project_id}"/, + 'languageIdentifier' => 'terraform', + 'title' => 'Save the Terraform script to a file' + }, + { + 'instructions' => /gitlab_runner="#{runner_token}"/, + 'languageIdentifier' => 'shell', + 'title' => 'Apply the Terraform script' + } + ]) + end + + context 'with nil runner token' do + let(:runner_token) { nil } + + it 'is successful and generates a unique deployment id' do + request + expect_graphql_errors_to_be_empty + + expect(options_response).to match([ + a_hash_including('instructions' => /name = "grit-[A-Za-z0-9_\-]{8}"/), + an_instance_of(Hash) + ]) + end + + context 'when user does not have permissions to create runner' do + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(current_user, :create_runner, anything).and_return(false) + end + + it 'returns an error' do + request + + expect_graphql_errors_to_include(s_('Runners|The user is not allowed to create a runner')) + end + end + end + + context 'with invalid runner token' do + let(:runner_token) { 'invalid-token' } + + it 'returns an error' do + request + + expect_graphql_errors_to_include(s_('Runners|The runner authentication token is invalid')) + end + end + + context 'when user cannot provision runners' do + before do + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(current_user, :provision_cloud_runner, project).and_return(false) + end + + it 'returns an error' do + request + + expect_graphql_errors_to_include("You don't have permissions to provision cloud runners") + end end end - context 'when user does not have required permissions' do + context 'when user is not a maintainer or higher' do let(:current_user) { create(:user).tap { |user| project.add_developer(user) } } it { is_expected.to be nil } @@ -280,17 +388,4 @@ it { is_expected.to be nil } end - - private - - def google_cloud_object_list(compute_type, returned_nodes, next_page_token:) - item_type = "Google::Cloud::Compute::V1::#{compute_type}" - - # rubocop:disable RSpec/VerifiedDoubles -- these generated objects don't actually expose the methods - double("#{item_type}List", - items: returned_nodes.map { |props| double(item_type, **props) }, - next_page_token: next_page_token - ) - # rubocop:enable RSpec/VerifiedDoubles - end end diff --git a/ee/spec/services/ci/runners/create_google_cloud_provisioning_steps_service_spec.rb b/ee/spec/services/ci/runners/create_google_cloud_provisioning_steps_service_spec.rb index d8eadbe43af08682daf2f156f42fbea27babb9cb..e22e1c561e56b83bba611994ac358fdaa5b3488c 100644 --- a/ee/spec/services/ci/runners/create_google_cloud_provisioning_steps_service_spec.rb +++ b/ee/spec/services/ci/runners/create_google_cloud_provisioning_steps_service_spec.rb @@ -14,9 +14,9 @@ let(:runner_token) { runner.token } let(:params) do { - provisioning_project_id: google_cloud_project_id, - provisioning_region: region, - provisioning_zone: zone, + google_cloud_project_id: google_cloud_project_id, + region: region, + zone: zone, ephemeral_machine_type: machine_type, runner_token: runner_token } @@ -45,12 +45,12 @@ { instructions: a_string_including("google_project = \"#{google_cloud_project_id}\""), language_identifier: 'terraform', - title: 'Save the Terraform script to a file' + title: s_('Runners|Save the Terraform script to a file') }, { instructions: /gitlab_runner="#{runner_token}"/, language_identifier: 'shell', - title: 'Apply the Terraform script' + title: s_('Runners|Apply the Terraform script') } ]) end @@ -63,14 +63,14 @@ steps = execute.payload[:provisioning_steps] expect(steps).to match([ - a_hash_including(instructions: /name = "grit[A-Za-z0-9_\-]{8}"/), + a_hash_including(instructions: /name = "grit-[A-Za-z0-9_\-]{8}"/), an_instance_of(Hash) ]) end context 'when new deployment name is invalid' do it 'returns internal error' do - expect(Devise).to receive(:friendly_token).with(8).and_return('1234567/') + expect(Devise).to receive(:friendly_token).with(Ci::Runner::RUNNER_SHORT_SHA_LENGTH).and_return('1234567/') expect(execute.status).to eq :error expect(execute.reason).to eq :internal_error diff --git a/ee/spec/support/shared_examples/google_cloud_platform/compute/services_shared_examples.rb b/ee/spec/support/shared_examples/google_cloud_platform/compute/services_shared_examples.rb index ed1a2ed3c0ad45079633b1d1c109599b652efd00..831d871e604ecd813f459c2562db3cb0eb0c46af 100644 --- a/ee/spec/support/shared_examples/google_cloud_platform/compute/services_shared_examples.rb +++ b/ee/spec/support/shared_examples/google_cloud_platform/compute/services_shared_examples.rb @@ -69,7 +69,7 @@ end RSpec.shared_examples 'overriding the google cloud project id' do - let(:google_cloud_project_id) { 'project_id_override' } + let(:google_cloud_project_id) { 'project-id-override' } let(:extra_params) { { google_cloud_project_id: google_cloud_project_id } } it 'returns results by calling the specified project id' do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0220716ce3ccb576670ed1d443a7d2c6149fe733..27293f0f96168d4b29a4e044ec6c72aef5469cc5 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -42623,6 +42623,9 @@ msgstr "" msgid "Runners|An upgrade is recommended for this runner" msgstr "" +msgid "Runners|Apply the Terraform script" +msgstr "" + msgid "Runners|Arch/Platform" msgstr "" @@ -43184,6 +43187,9 @@ msgstr "" msgid "Runners|Runs untagged jobs" msgstr "" +msgid "Runners|Save the Terraform script to a file" +msgstr "" + msgid "Runners|Search description..." msgstr ""