Google provider 1.13 changes how project APIs are managed
The Service Usage API becomes a prerequisite for managing project services. The provider's singular and plural resources express different ownership contracts.
Managing which APIs a project can call requires an API of its own. Google provider 1.13.0 changes that dependency for google_project_service and google_project_services. The May 24 release notes state that both resources now use the Service Usage API and that users must enable it. Existing resource declarations can therefore acquire a new prerequisite even when their configuration text has not changed.
The change is a useful example of what an infrastructure abstraction can preserve and what it cannot hide. Terraform keeps a configuration model for enabled services, but the provider implements that model against Google's management interface. If that interface changes, the environment in which the provider runs may need a corresponding change. A stable resource name does not mean its backend dependencies remain identical.
I value Terraform's ability to put reusable configuration over infrastructure APIs. This release also illustrates why provider releases deserve attention independently of the core executable. The provider determines how a declaration becomes a remote operation, including which management service has to be available before that operation can succeed.
One resource owns one enabled service
The versioned documentation for google_project_service describes management of a single API service in an existing project. Each declaration requires a service name. Its project can be explicit or inherited from the provider configuration.
resource "google_project_service" "iam" {
project = "example-project"
service = "iam.googleapis.com"
disable_on_destroy = false
}
This declaration concerns the IAM API in the named project. It does not claim that every other enabled service is unwanted. The explicit destruction setting leaves the API enabled when Terraform destroys this resource. The documented default is true, so omitting the argument gives removal from Terraform a different effect on the project's enabled services.
The resource implementation makes that lifecycle concrete. Creation enables the service, records a project-and-service identifier, and reads back its state. Reading searches the enabled-service list and clears the resource identifier if the service is missing. Deletion checks disable_on_destroy before deciding whether to call the disabling operation.
Changing that flag alone requires no remote API operation. The implementation's update method is a no-op because the setting determines later deletion behavior. This is a useful distinction between a property of the cloud service and a property of Terraform's management relationship with it. Both can appear as arguments in the same declaration.
The plural resource claims the service set
The google_project_services documentation describes a broader contract. It treats its configured list as authoritative and removes enabled services absent from that list. The documentation explicitly warns against combining it with singular service resources because they will disagree about what should remain enabled.
That conflict follows from their ownership models. A singular resource can keep a service enabled while a plural resource, which does not list it, tries to disable it. Neither needs a bug to produce this disagreement. Each can correctly enforce its own configuration while making the other configuration false.
The plural resource also has to contend with APIs enabled as side effects of other operations. Its documentation calls out that source of conflict. The implementation maintains a specific ignore list for services enabled through other services, keeping those names out of its configuration comparison. The comparison is therefore an implemented ownership policy, not simply a raw list copied from a response.
For a project shared by several configurations or tools, authoritative ownership requires coordination across all of them. A smaller declaration is not automatically a smaller claim. One plural resource can control a broader set of project capabilities than several singular declarations. The resource name and reconciliation algorithm explain that difference more clearly than the number of lines in the configuration.
Completion includes observing enablement
The provider's Service Usage implementation lists services under the project with a filter for enabled state. It follows pagination and extracts service names from the returned resource names. Reconciliation compares that observed set with configuration, disables names absent from the desired set, and enables the missing desired services.
Enabling multiple services uses a batch request, while a single service uses an individual enable request. The implementation waits for the returned operation and then lists enabled services again. If requested names are still absent, it returns a retryable error internally. Its error text identifies eventual consistency, distinguishing this case from an actual remote 503 response.
I find that final observation step as significant as the new API dependency. A successful request and a completed operation are not necessarily enough to make the desired state visible to subsequent reads. The provider incorporates that distinction into the resource lifecycle instead of leaving every configuration author to reproduce it.
For this release, the immediate prerequisite is enabling Service Usage for the affected project-management workflow. The lasting configuration decision concerns ownership. A declaration that ensures one required API remains enabled has different consequences from a declaration that defines the complete permitted set, especially when other actions can enable additional services.