Dormeto
ENFR

Getting started

Google Cloud

Dormeto's router runs in your Google Cloud project as a service account of its own, with two custom roles and a few predefined ones. Dormeto never creates them itself: the CLI does, with your own account, and prints every IAM change it makes. This page lists everything the router needs and everything the CLI changes, permission by permission. It then says how to check it and how to remove it.

14 min readManager 0.21.0

How far Google Cloud has been tried
  • Accepted on a real project (2026-10-30). dormeto gcp check, install, uninstall, status and workloads. Also Compute Engine VMs (unmanaged and managed groups, suspended when possible) behind a global external Application Load Balancer.
  • Built and reviewed, its acceptance not run yet. Regional and classic load balancers, zonal network endpoint groups, schedules and pauses, IP lists. Some of their behavior was measured on Google, and no more than that.
  • Written, never run against Google. Cloud SQL companions and GKE. Try them in a project you can lose. The CLI prints a warning when you use them, and goes on.

There is no public router image: you build your own and push it to your Artifact Registry. There is no dashboard or manager for Google Cloud yet, and the branded waiting page does not apply to it. Router 0.35.0 and CLI 0.8.0 carry all of this code.

What it needs

What it isWhereWhat it is for
The APIsThe projectTen APIs (the list). dormeto gcp install turns them on and never turns one off.
Two custom rolesThe projectdormetoRouter reads the load balancers, VMs and groups and manages the waker backend services. dormetoRouterBackends starts, stops, suspends and resumes the VMs and groups that carry the tag (every permission).
The router's service accountThe projectdmtr-<region>@<project>.iam.gserviceaccount.com: the only identity the router's Cloud Run services and tasks use (its grants).
The secure tagThe projectdormeto=managed. The router starts and stops only the VMs and groups that carry it. You bind it when you onboard a workload. The router itself holds no permission to tag, or it could tag any VM and stop it.
The router's stateThe router's regionA Firestore database dmtr-<region> (Native mode, delete protection off) and a Cloud Tasks queue dmtr-<region>. The database also holds the install record, which uninstall reads.
The routerThe router's region, with --imageTwo Cloud Run services, dmtr-<region>-waker and dmtr-<region>-controller, the waker's network endpoint group dmtr-<region>-waker and the Cloud Scheduler job dmtr-<region>-check (every 5 minutes).
Each workloadYour load balancerA backend service dmtr-<region>-<workload> that sends the waiting page, and the tag on the workload's VMs and groups. Onboarding adds a route /_dormeto/* to that backend service for good. Offboarding restores every reference. If Terraform writes your load balancer or VMs, it needs to ignore what changes.
Optional accessThe project, if you ask for itCloud SQL and GKE have their own API and roles, from router 0.35.0 (what each adds).

The APIs

dormeto gcp install turns on these ten APIs, .googleapis.com each, in the project. uninstall turns none off: other things in the project may use them.

APIService
compute.googleapis.comCompute Engine
run.googleapis.comCloud Run
firestore.googleapis.comFirestore
cloudtasks.googleapis.comCloud Tasks
cloudscheduler.googleapis.comCloud Scheduler
monitoring.googleapis.comCloud Monitoring
artifactregistry.googleapis.comArtifact Registry
iam.googleapis.comIdentity and Access Management
cloudresourcemanager.googleapis.comCloud Resource Manager
logging.googleapis.comCloud Logging

The roles

Two custom roles, created in the project, and four predefined roles. Every permission below is in the manifest the router and the CLI share. The router's tests check that each Google Cloud call it makes is covered by one of them.

dormetoRouter

Dormeto router. Lets a Dormeto router read its workloads' load balancers, VMs and groups, and update their URL maps. It can create and delete their waker backend services, and turn their autoscalers off and back on. It reads their request counts.

ResourcePermissions
compute.urlMapscompute.urlMaps.get, compute.urlMaps.list, compute.urlMaps.update
compute.backendServicescompute.backendServices.get, compute.backendServices.use, compute.backendServices.create, compute.backendServices.delete
compute.regionNetworkEndpointGroupscompute.regionNetworkEndpointGroups.use
compute.globalForwardingRulescompute.globalForwardingRules.list
compute.targetHttpProxiescompute.targetHttpProxies.list
compute.targetHttpsProxiescompute.targetHttpsProxies.list
compute.instancescompute.instances.get
compute.instanceGroupscompute.instanceGroups.get
compute.instanceGroupManagerscompute.instanceGroupManagers.get
compute.autoscalerscompute.autoscalers.get, compute.autoscalers.update
compute.machineTypescompute.machineTypes.get
compute.globalOperationscompute.globalOperations.get
compute.zoneOperationscompute.zoneOperations.get
compute.regionOperationscompute.regionOperations.get
monitoring.timeSeriesmonitoring.timeSeries.list
compute.networkEndpointGroupscompute.networkEndpointGroups.get
compute.regionUrlMapscompute.regionUrlMaps.get, compute.regionUrlMaps.list, compute.regionUrlMaps.update
compute.regionBackendServicescompute.regionBackendServices.get, compute.regionBackendServices.use, compute.regionBackendServices.create, compute.regionBackendServices.delete
compute.regionTargetHttpProxiescompute.regionTargetHttpProxies.list
compute.regionTargetHttpsProxiescompute.regionTargetHttpsProxies.list
compute.forwardingRulescompute.forwardingRules.list

Google marks compute.urlMaps.get, compute.urlMaps.list and compute.urlMaps.update as testing in custom roles: usable, not recommended for production by Google. No narrower predefined role holds them, so dormetoRouter keeps them. An autoscaler cannot carry a tag, so compute.autoscalers.update is here, without the tag condition.

dormetoRouterBackends

Dormeto router backends. Lets a Dormeto router start, stop, suspend and resume its workloads' VMs and managed instance groups. Granted on the condition that the resource has the tag dormeto=managed.

ResourcePermissions
compute.instancescompute.instances.start, compute.instances.stop, compute.instances.suspend, compute.instances.resume
compute.instanceGroupManagerscompute.instanceGroupManagers.update, compute.instanceGroupManagers.use

Granted on the condition that the resource has the tag dormeto=managed. An autoscaler's change names its group, so compute.instanceGroupManagers.update and .use are checked on the group's tag.

Predefined roles

Granted as described in the grants. Dormeto relies on these permissions of each:

RolePermissions
roles/datastore.userdatastore.entities.get, datastore.entities.list, datastore.entities.create, datastore.entities.update, datastore.entities.delete
roles/cloudtasks.enqueuercloudtasks.tasks.create
roles/run.invokerrun.routes.invoke
roles/iam.serviceAccountUseriam.serviceAccounts.actAs

The grants

The router runs as the service account dmtr-<region>@<project>.iam.gserviceaccount.com. The CLI adds exactly these bindings, and only these. It never changes or removes a binding it did not add. In a condition, {project} is the project's ID and {database} is the router's database, dmtr-<region>.

RoleWhereConditionWhat it allows
projects/{project}/roles/dormetoRouterThe projectNoneReads and manages the load balancers, VMs and groups of the workloads.
projects/{project}/roles/dormetoRouterBackendsThe projectDormeto-managed resources: resource.matchTag('{project}/dormeto', 'managed')Starts and stops what carries the tag.
roles/datastore.userThe projectThe router's database: resource.name == "projects/{project}/databases/{database}"Reads and writes the router's Firestore documents.
roles/cloudtasks.enqueuerThe queue dmtr-<region>NoneCreates tasks in the router's queue.
roles/run.invokerThe Cloud Run service dmtr-<region>-controllerNoneCalls the controller. The Cloud Scheduler job and the tasks do, as the service account.
roles/iam.serviceAccountUserThe service account itselfNoneSigns the tasks' OIDC tokens as itself.

What Google adds

Turning APIs on and creating resources makes Google add bindings of its own to the project's IAM policy. Dormeto uses none of them for its own work. The CLI prints each one as Google's, with the step it appeared after, and records it. Seen on a real project, seven were added during the install, and an eighth when the image's repository was created:

RoleMemberAppeared afterWhose
roles/cloudscheduler.serviceAgentserviceAccount:service-<project number>@gcp-sa-cloudscheduler.iam.gserviceaccount.comapisCloud Scheduler's service agent
roles/cloudtasks.serviceAgentserviceAccount:service-<project number>@gcp-sa-cloudtasks.iam.gserviceaccount.comapisCloud Tasks' service agent
roles/containerregistry.ServiceAgentserviceAccount:service-<project number>@containerregistry.iam.gserviceaccount.comapisContainer Registry's service agent
roles/pubsub.serviceAgentserviceAccount:service-<project number>@gcp-sa-pubsub.iam.gserviceaccount.comapisPub/Sub's service agent
roles/run.serviceAgentserviceAccount:service-<project number>@serverless-robot-prod.iam.gserviceaccount.comapisCloud Run's service agent
roles/firestore.serviceAgentserviceAccount:service-<project number>@gcp-sa-firestore.iam.gserviceaccount.comdatabaseFirestore's service agent
roles/firebaserules.systemserviceAccount:service-<project number>@firebase-rules.iam.gserviceaccount.comprojectBindingsFirebase Rules' system account, added late, from the database
roles/artifactregistry.serviceAgentserviceAccount:service-<project number>@gcp-sa-artifactregistry.iam.gserviceaccount.comCreating the image's repository, which the CLI doesn't doArtifact Registry's service agent. The CLI's next run shows it as seen later

The step names are those of the operator's table. The service agents are Google's to manage: leave them. uninstall leaves them too, and lists them as left in place. Compute Engine's own service agents, already there once Compute Engine is on, are Google's as well.

The default service account's Editor

Take a project outside an organization that enforces the constraint iam.automaticIamGrantsForDefaultServiceAccounts. When Compute Engine is turned on, Google gives its default service account, <project number>-compute@developer.gserviceaccount.com, the role roles/editor on the whole project. Dormeto does not use it: the router's Cloud Run services run as dmtr-<region>. dormeto gcp check reports the grant as a warning and leaves it: it is yours to remove. Before you do, check which VMs, instance templates and services run as that account, since they lose what Editor gave them:

gcloud compute instances list --format="table(name,zone.basename(),serviceAccounts[].email)"
gcloud projects remove-iam-policy-binding my-project \
  --member="serviceAccount:123456789012-compute@developer.gserviceaccount.com" \
  --role="roles/editor"

To keep Google from granting it again in your next projects, enforce iam.automaticIamGrantsForDefaultServiceAccounts on the organization or the folder.

The operator's permissions

You run the CLI with your gcloud account (its active configuration, or --gcloud-configuration). Each command tests the permissions of its steps before it changes anything: one missing stops it with nothing changed. roles/owner holds all of them. The tables list the steps of each command, as the manifest does.

dormeto gcp check

StepWhat forPermissions
readRead the project, its IAM policy and the APIs that are onresourcemanager.projects.get, resourcemanager.projects.getIamPolicy, serviceusage.services.list, serviceusage.services.use

dormeto gcp install

StepWhat forPermissions
readRead the project, its IAM policy and the APIs that are onresourcemanager.projects.get, resourcemanager.projects.getIamPolicy, serviceusage.services.list, serviceusage.services.use
apisTurn the APIs onserviceusage.services.enable, serviceusage.operations.get
rolesCreate or update the custom roles (a deleted role's ID cannot be reused for 37 days: the CLI undeletes it)iam.roles.get, iam.roles.create, iam.roles.update, iam.roles.undelete
serviceAccountCreate the router's service account and bind itiam.serviceAccounts.get, iam.serviceAccounts.create, iam.serviceAccounts.getIamPolicy, iam.serviceAccounts.setIamPolicy, iam.serviceAccounts.actAs
projectBindingsRead the IAM policy, add Dormeto's bindings, write it with its etagresourcemanager.projects.getIamPolicy, resourcemanager.projects.setIamPolicy
tagCreate the secure tagresourcemanager.tagKeys.create, resourcemanager.tagKeys.get, resourcemanager.tagValues.create, resourcemanager.tagValues.get
databaseCreate the Firestore database, write the install recorddatastore.databases.create, datastore.databases.get, datastore.operations.get, datastore.entities.create, datastore.entities.get, datastore.entities.update
queueCreate the task queue and bind itcloudtasks.queues.create, cloudtasks.queues.get, cloudtasks.queues.update, cloudtasks.queues.getIamPolicy, cloudtasks.queues.setIamPolicy

dormeto gcp install --image

Added to install when you give the router's image.

StepWhat forPermissions
imageRead the router's image in Artifact Registryartifactregistry.repositories.get, artifactregistry.repositories.downloadArtifacts, artifactregistry.dockerimages.get
cloudRunCreate the two Cloud Run services, turn the waker's invoker check offrun.services.create, run.services.get, run.services.update, run.services.getIamPolicy, run.services.setIamPolicy, run.operations.get, run.routes.invoke, iam.serviceAccounts.actAs
negCreate the waker's network endpoint groupcompute.regionNetworkEndpointGroups.create, compute.regionNetworkEndpointGroups.get, compute.regionOperations.get
jobCreate the check jobcloudscheduler.jobs.create, cloudscheduler.jobs.get, cloudscheduler.jobs.update, iam.serviceAccounts.actAs

dormeto gcp uninstall

StepWhat forPermissions
readRead the project, the install record and the workloadsresourcemanager.projects.get, resourcemanager.projects.getIamPolicy, serviceusage.services.list, serviceusage.services.use, datastore.databases.list, datastore.databases.get, datastore.entities.get, datastore.entities.list, run.routes.invoke
jobDelete the check jobcloudscheduler.jobs.get, cloudscheduler.jobs.delete
negDelete the network endpoint groupcompute.regionNetworkEndpointGroups.get, compute.regionNetworkEndpointGroups.delete, compute.regionOperations.get
cloudRunDelete the Cloud Run servicesrun.services.get, run.services.delete, run.operations.get
queueDelete the queuecloudtasks.queues.get, cloudtasks.queues.delete
databaseDelete the databasedatastore.databases.get, datastore.databases.delete, datastore.operations.get
projectBindingsRemove the bindings the install addedresourcemanager.projects.getIamPolicy, resourcemanager.projects.setIamPolicy
tagDelete the tag, unless another router lists itresourcemanager.tagKeys.get, resourcemanager.tagKeys.delete, resourcemanager.tagValues.get, resourcemanager.tagValues.delete
serviceAccountDelete the service accountiam.serviceAccounts.get, iam.serviceAccounts.delete
rolesDelete the custom roles, unless another router lists themiam.roles.get, iam.roles.delete

dormeto gcp workloads list

Also show, nap and wake: they call the router's controller with your identity token.

StepWhat forPermissions
invokeCall the router's controllerrun.routes.invoke

dormeto gcp workloads onboard

StepWhat forPermissions
invokeCall the router's controllerrun.routes.invoke
tagBind the tag to the workload's VMs and groupsresourcemanager.tagValues.get, resourcemanager.tagValueBindings.create, resourcemanager.tagValueBindings.delete, compute.instances.listTagBindings, compute.instances.createTagBinding, compute.instances.deleteTagBinding, compute.instanceGroupManagers.listTagBindings, compute.instanceGroupManagers.createTagBinding, compute.instanceGroupManagers.deleteTagBinding

dormeto gcp workloads offboard

StepWhat forPermissions
invokeCall the router's controllerrun.routes.invoke
tagRemove the tag bindingsresourcemanager.tagValues.get, resourcemanager.tagValueBindings.delete, compute.instances.listTagBindings, compute.instances.deleteTagBinding, compute.instanceGroupManagers.listTagBindings, compute.instanceGroupManagers.deleteTagBinding

A custom role for a narrower operator

If roles/owner is too much, create a role with the permissions of the commands this operator runs. This one holds every permission of the tables above:

title: Dormeto operator
description: Runs dormeto gcp in this project
stage: GA
includedPermissions:
- artifactregistry.dockerimages.get
- artifactregistry.repositories.downloadArtifacts
- artifactregistry.repositories.get
- cloudscheduler.jobs.create
- cloudscheduler.jobs.delete
- cloudscheduler.jobs.get
- cloudscheduler.jobs.update
- cloudtasks.queues.create
- cloudtasks.queues.delete
- cloudtasks.queues.get
- cloudtasks.queues.getIamPolicy
- cloudtasks.queues.setIamPolicy
- cloudtasks.queues.update
- compute.instanceGroupManagers.createTagBinding
- compute.instanceGroupManagers.deleteTagBinding
- compute.instanceGroupManagers.listTagBindings
- compute.instances.createTagBinding
- compute.instances.deleteTagBinding
- compute.instances.listTagBindings
- compute.regionNetworkEndpointGroups.create
- compute.regionNetworkEndpointGroups.delete
- compute.regionNetworkEndpointGroups.get
- compute.regionOperations.get
- datastore.databases.create
- datastore.databases.delete
- datastore.databases.get
- datastore.databases.list
- datastore.entities.create
- datastore.entities.get
- datastore.entities.list
- datastore.entities.update
- datastore.operations.get
- iam.roles.create
- iam.roles.delete
- iam.roles.get
- iam.roles.undelete
- iam.roles.update
- iam.serviceAccounts.actAs
- iam.serviceAccounts.create
- iam.serviceAccounts.delete
- iam.serviceAccounts.get
- iam.serviceAccounts.getIamPolicy
- iam.serviceAccounts.setIamPolicy
- resourcemanager.projects.get
- resourcemanager.projects.getIamPolicy
- resourcemanager.projects.setIamPolicy
- resourcemanager.tagKeys.create
- resourcemanager.tagKeys.delete
- resourcemanager.tagKeys.get
- resourcemanager.tagValueBindings.create
- resourcemanager.tagValueBindings.delete
- resourcemanager.tagValues.create
- resourcemanager.tagValues.delete
- resourcemanager.tagValues.get
- run.operations.get
- run.routes.invoke
- run.services.create
- run.services.delete
- run.services.get
- run.services.getIamPolicy
- run.services.setIamPolicy
- run.services.update
- serviceusage.operations.get
- serviceusage.services.enable
- serviceusage.services.list
- serviceusage.services.use
gcloud iam roles create dormetoOperator --project=my-project --file=operator-role.yaml
gcloud projects add-iam-policy-binding my-project \
  --member="user:you@example.com" --role="projects/my-project/roles/dormetoOperator"

Drop the permissions of the commands you do not give, and check the result with dormeto gcp check, which lists what is missing for each command. Note that resourcemanager.projects.setIamPolicy lets its holder grant themselves any role in the project. Give this role for the time of the install and take it back after. Or keep it for the few people who run it.

Google lists three of these permissions as TESTING in custom roles, like compute.urlMaps.*: cloudtasks.queues.getIamPolicy, cloudtasks.queues.setIamPolicy and serviceusage.operations.get. They are usable and none is refused.

Optional access

From router 0.35.0 and CLI 0.8.0. Turning on the Cloud SQL or GKE API makes Google add its own service agents. A project that uses neither should not get them. So you ask for each by name:

dormeto gcp install --with cloud-sql,gke

The install record keeps your choice. A later run with more adds to it. A run without --with keeps what is there. Only uninstall removes a feature. dormeto gcp check tests a feature only when --with names it or the record has it. The CLI's next run prints any binding Google added.

cloud-sql

Never run against Google yet. A companion database that a nap stops and a wake starts. API: sqladmin.googleapis.com.

RolePermissionsWhereCondition
dormetoRouterDatabasesReadprojects/{project}/roles/dormetoRouterDatabasesReadcloudsql.instances.get, cloudsql.instances.listThe projectNone
dormetoRouterDatabasesprojects/{project}/roles/dormetoRouterDatabasescloudsql.instances.updateThe projectDormeto-managed resources: resource.matchTag('{project}/dormeto', 'managed')
CommandStepPermissions
gcp workloads onboardtagcloudsql.instances.get, cloudsql.instances.listTagBindings, cloudsql.instances.createTagBinding, cloudsql.instances.deleteTagBinding, datastore.entities.get
gcp workloads offboardtagcloudsql.instances.get, cloudsql.instances.listTagBindings, cloudsql.instances.deleteTagBinding

gke

Never run against Google yet. Pods behind standalone network endpoint groups, on a load balancer you own. API: container.googleapis.com.

RolePermissionsWhereCondition
dormetoRouterKubernetesprojects/{project}/roles/dormetoRouterKubernetescontainer.clusters.get, container.clusters.connectThe projectNone

The role grants nothing inside the cluster. When you onboard a workload, the CLI reads the cluster as you. It then prints, asks and applies a Role and a RoleBinding named dormeto-<workload>, in the workload's namespace, for the router's service account. Nothing is cluster-wide, and offboarding removes both. The rules:

  • get on deployments, statefulsets.
  • list on replicasets.
  • patch on deployments/scale, statefulsets/scale.
  • list on pods, events.
  • list, patch on scaledobjects.

Kubernetes lets you grant only what you hold, so the operator needs container.roles.escalate and container.roles.bind. Google lists container.roles.escalate as TESTING in custom roles.

CommandStepPermissions
gcp workloads onboardclustercontainer.clusters.get, container.roles.create, container.roles.update, container.roleBindings.create, container.roleBindings.update, container.services.get, container.roles.escalate, container.roles.bind, container.clusters.connect, container.replicaSets.list, container.pods.list, container.roles.get, container.roleBindings.get, container.roles.delete, container.roleBindings.delete, datastore.databases.get, datastore.entities.get, datastore.entities.update
gcp workloads offboardclustercontainer.roles.delete, container.roleBindings.delete, container.roleBindings.update, container.roles.bind, container.clusters.connect, container.clusters.get, container.roles.get, container.roleBindings.get, datastore.databases.get, datastore.entities.get, datastore.entities.update

IP lists

From router 0.35.0. With --ip-list name=<n>,url=<u>[,refresh=<hours>], repeatable, a visit from an address on the list never wakes a workload. An API client's POST /_dormeto/wake still does. --no-ip-lists clears them. They need no extra role. A list's URL, query string included, is printed and stored in the plan, the install record and the services' environment. Keep tokens out of it. A URL with credentials is refused.

If Terraform writes your load balancer and VMs

Terraform doesn't know what the router writes, so every plan offers to undo it. After such an apply, the router's check repairs the URL map within 5 minutes. Until then, a sleeping workload shows the load balancer's own error page and doesn't wake from a browser. Ignore these fields on the resources you wrote, with lifecycle { ignore_changes = [...] }:

ResourceFieldsWhy
google_compute_url_maphost_rule, path_matcherThe route /_dormeto/*, the nap's custom error response policy and, when the map's own default names the service, a host rule and a path matcher.
google_compute_instance_group_manager, google_compute_region_instance_group_managertarget_size, target_stopped_size, target_suspended_sizeA nap moves the group's VMs from its target size to its stopped or suspended size. An apply would move them back, and could create new VMs.
google_compute_autoscaler, google_compute_region_autoscalerautoscaling_policy[0].modeA nap turns the autoscaler off, and a wake turns it back on.
google_compute_instancedesired_statusOnly if you set it: an apply would start a napped VM.
google_compute_region_url_map, and a classic load balancer's google_compute_url_mapdefault_service, default_route_action, host_rule, path_matcherFrom router 0.35.0: a nap swaps the map's references to the waker.
google_sql_database_instancesettings[0].activation_policyFrom router 0.35.0, a Cloud SQL companion: a nap sets it to NEVER, a wake to ALWAYS.
kubernetes_deployment_v1, kubernetes_stateful_set_v1spec[0].replicasFrom router 0.35.0, GKE: a nap scales the workload to 0.

With the path matchers ignored, Terraform stops applying your own edits to them. Remove the ignore for that apply. That also removes what the router wrote until its check writes it back. The tag's binding is not a field of these resources, so it needs nothing.

Check

dormeto gcp check is read-only. For each command it prints a tick when you hold every permission it needs, and a cross with the missing ones otherwise. It then prints the project's parent, the APIs already on, and the warnings (the default service account's Editor). It exits 1 when a command lacks a permission. With no role in the project it says so and lists every permission as missing. --json prints the report.

dormeto gcp check --project my-project --region europe-west1

dormeto gcp status shows the router's record and live state: version, services, controller health, queue, job, database and grants.

Remove

dormeto gcp uninstall removes exactly what the install added, in reverse order, from its record. It refuses while workloads are onboarded. --force offboards each one first, tag bindings included. It keeps the custom roles and the tag while another router of the project lists them. It turns no API off. It lists the APIs and Google's bindings as left in place.

dormeto gcp uninstall --project my-project --region europe-west1
dormeto gcp uninstall --project my-project --region europe-west1 --force   # workloads still onboarded

Then, if nothing else in the project needs them, turn the APIs off yourself, and remove the default service account's Editor as above:

gcloud services disable \
  compute.googleapis.com \
  run.googleapis.com \
  firestore.googleapis.com \
  cloudtasks.googleapis.com \
  cloudscheduler.googleapis.com \
  monitoring.googleapis.com \
  artifactregistry.googleapis.com \
  iam.googleapis.com \
  cloudresourcemanager.googleapis.com \
  logging.googleapis.com \
  --project my-project

Google may refuse to turn an API off while another service depends on it, or ask for --force. Decide for each one: these APIs may serve other things in the project.

A deleted queue's name stays blocked for up to 3 days and a deleted database's ID for about 5 minutes. Installing again before then fails, and the CLI says so.