Skip to content

Add Google Cloud Compute services

Pedro Pombeiro requested to merge pedropombeiro/438315/add-services into master

What does this MR do and why?

Add Google Cloud Compute services

Adds 3 services for to interact with Google Cloud Compute. These services are gated behind a SaaS-only feature.

Basically, they will build and use the client class but also provide data conversions and additional validations. Among others, check a feature flag.

We have 3 functions that the client exposes, so naturally, we split that into 3 services:

  • list regions
  • list zones
  • list machine types

All 3 services will have a similar validation and error handling, thus we have a base class that will centralize the common logic.

The main user of these services will be GraphQL endpoints (implemented in different MRs).

NOTE: This MR is inspired from David's !143359 (merged) (which does the same for Artifact Registry).

Closes #439569 (closed)

🔬 What does this MR do and why?

  • Add 3 services:
    • GoogleCloudPlatform::Compute::ListRegionsService.
    • GoogleCloudPlatform::Compute::ListZonesService.
    • GoogleCloudPlatform::Compute::ListMachineTypesService.
  • Add a base (common parent) service class: GoogleCloudPlatform::Compute::BaseService.
  • Add the related specs.

The feature is hidden behind the gcp_runner FF: #437901 (closed)

🏎 MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

🦄 Screenshots or screen recordings

These are services so, hu... no impact on the existing UI 😸

How to set up and validate locally

🛠 Setup

Local testing is a bit involved as we need to have an Artifact Registry set up and some other things for the authentication part. Follow !143099 (merged), points 1️⃣ and 2️⃣ and come back here then.

Now, we need to set up the Artifact registry integration. Follow the instructions from !141127 (merged).

Enable the gcp_artifact_registry and gcp_runner feature flags:

$ echo "Feature.enable(:gcp_artifact_registry); Feature.enable(:gcp_runner, type: :wip)" | gdk rails console

All the examples below are to be executed in the rails console and you will need the project_id on which you set up the integration and a user with read_runner_cloud_provisioning_options permission (maintainer+).

1️⃣ Get machine types

GoogleCloudPlatform::Compute::ListRegionsService.new(project: Project.find(<project_id>), current_user: User.first, max_results: 2).execute
=> #<ServiceResponse:0x0000000299017bd8
 @http_status=:ok,
 @message=nil,
 @payload={:items=>[{:name=>"africa-south1", :description=>"africa-south1"}, {:name=>"asia-east1", :description=>"asia-east1"}], :next_page_token=>"Cgphc2lhLWVhc3Qx"},
 @reason=nil,
 @status=:success>

2️⃣ List zones

GoogleCloudPlatform::Compute::ListZonesService.new(project: Project.find(<project_id>), current_user: User.first).execute
=> #<ServiceResponse:0x0000000299014b18
 @http_status=:ok,
 @message=nil,
 @payload={:items=>[{:name=>"africa-south1-b", :description=>"africa-south1-b"}, {:name=>"africa-south1-c", :description=>"africa-south1-c"}], :next_page_token=>"Cg9hZnJpY2Etc291dGgxLWI="},
 @reason=nil,
 @status=:success>

3️⃣ List machine types

> GoogleCloudPlatform::Compute::ListMachineTypesService.new(project: Project.find(43), current_user: User.first, zone: "us-west1-a", max_results: 2).execute
=> #<ServiceResponse:0x00000002a0130568
 @http_status=:ok,
 @message=nil,
 @payload=
  {:items=>
    [{:name=>"c2-standard-16", :description=>"Compute Optimized: 16 vCPUs, 64 GB RAM", :zone=>"us-west1-a"},
     {:name=>"c2-standard-30", :description=>"Compute Optimized: 30 vCPUs, 120 GB RAM", :zone=>"us-west1-a"}],
   :next_page_token=>"Cg5jMi1zdGFuZGFyZC0zMA=="},
 @reason=nil,
 @status=:success>

> GoogleCloudPlatform::Compute::ListMachineTypesService.new(project: Project.find(43), current_user: User.first, zone: "us-west1-a", max_results: 2, page_token: "Cg5jMi1zdGFuZGFyZC0zMA==").execute
=> #<ServiceResponse:0x000000029fabf238
 @http_status=:ok,
 @message=nil,
 @payload=
  {:items=>
    [{:name=>"c2-standard-4", :description=>"Compute Optimized: 4 vCPUs, 16 GB RAM", :zone=>"us-west1-a"},
     {:name=>"c2-standard-60", :description=>"Compute Optimized: 60 vCPUs, 240 GB RAM", :zone=>"us-west1-a"}],
   :next_page_token=>"Cg5jMi1zdGFuZGFyZC02MA=="},
 @reason=nil,
 @status=:success>

4️⃣ Handling errors

Let's play around with erroneous calls:

GoogleCloudPlatform::Compute::ListRegionsService.new(project: Project.find(<project id>), current_user: User.first, order_by: 'id desc').execute
=> #<ServiceResponse:0x00000002a00157f0 @http_status=nil, @message="Invalid order_by value", @payload={}, @reason=nil, @status=:error>

GoogleCloudPlatform::Compute::ListMachineTypesService.new(project: Project.find(43), current_user: User.first, zone: "us-west1")
=> #<ServiceResponse:0x0000000322a5dde8
 @http_status=nil,
 @message="Unsuccessful Google Cloud API request: An error has occurred when making a REST request: Invalid value for field 'zone': 'us-west1'. Unknown zone.",
 @payload={},
 @reason=nil,
 @status=:error>

Let's list regions on a project that doesn't have the integration configured:

GoogleCloudPlatform::Compute::ListRegionsService.new(project: Project.find(44), current_user: User.first, order_by: 'id desc').execute
=> #<ServiceResponse:0x0000000319e9c188 @http_status=nil, @message="Project Artifact Registry integration not set", @payload={}, @reason=nil, @status=:error>
Edited by Pedro Pombeiro

Merge request reports