January 26, 2017·5 min read·engineeringterraformprovidersgoogle-cloud

Terraform starts managing the Google project lifecycle

Terraform 0.8.5 changes google_project from a reference to a project lifecycle resource. The compatibility path depends on which identifier field a configuration uses.

A resource named google_project suggests that Terraform can create and delete a Google Cloud project. Before Terraform 0.8.5, the implementation does not fulfil that expectation in the way the name implies. The January 26 release notes explicitly describe the change as actually creating and deleting projects for new configurations and state. Existing configurations and state retain their previous behaviour.

That compatibility distinction is the most consequential part of a release that also adds Alibaba Cloud, ProfitBricks and NS1 providers. More providers expand the APIs Terraform can describe. The Google change alters what an existing resource abstraction means, including whether deleting it can delete the cloud project itself. A familiar resource name is insufficient to determine its lifecycle semantics.

I value Terraform as a common language over infrastructure APIs. That makes accuracy in resource naming and lifecycle behaviour particularly important to me. A project reference and a project owned by the configuration express different operational responsibilities, even when both expose the same project identifier to other resources.

The old identifier did not behave as expected

The project documentation shipped with 0.8.5 explains the old id argument. Terraform's limitations caused that field to look empty, so the implementation fell back to the project configured on the Google provider. A value written in the resource's id field was therefore ignored. The resource ultimately referred to the project used to authenticate Terraform's requests.

This explains why the change requires more than a new create call. A configuration could appear to select one project while the resource actually used another. Preserving old behaviour avoids silently treating every old declaration as instructions to create or delete a project. However, it leaves a transitional interface that readers need to understand explicitly.

The new argument is project_id. The documentation marks id as deprecated and directs users to project_id instead. It also states that creating a new project requires org_id and name. The resource can now represent the project's identity and organizational placement as explicit configuration inputs.

There is an editorial inconsistency in the tagged documentation. Its short example omits name, while the argument reference says the display name is required for new projects. The argument reference supplies the fuller requirement. A new-project example should therefore include the name along with the organization and project identifiers.

resource "google_project" "example" {
  project_id = "replace-with-unique-project-id"
  org_id     = "1234567"
  name       = "Example infrastructure"
}

The values here are placeholders, and provider authentication is outside this snippet. The versioned documentation requires projects created through this resource to belong to an organization. It also requires the service account running Terraform to have roles/resourcemanager.projectCreator. Adding a resource block does not remove those API authorization requirements.

Creation changes the meaning of deletion

Once a resource owns project creation, its removal needs a defined policy. The tagged documentation provides skip_delete, an optional argument that lets Terraform remove the resource without deleting the project through the Google API. This is a specific lifecycle control. It is different from assuming that removing any project resource is always harmless because an older implementation only referenced a project.

The identifier itself also has lifecycle implications. According to the argument reference, changing project_id forces a new project to be created. Changing org_id has the same documented consequence. These values describe identity and placement, so they should not be treated as ordinary labels whose edits necessarily update an existing project in place.

The release's compatibility note needs to stay attached to this discussion. It says old configurations and state should continue to work as before, while new configurations and state exhibit the new behaviour. That is more precise than saying every google_project resource acquires destructive project ownership immediately upon upgrading the Terraform executable.

My preference is to make ownership visible in the configuration's interface. A module that exposes a project identifier should explain whether it creates the project or accepts one managed elsewhere. This release makes creation possible, but the legacy field means a reader still needs to inspect how the declaration identifies its project.

Project configuration becomes more explicit

Terraform 0.8.5 also introduces google_project_iam_policy and google_project_services, according to its release notes. The project resource's policy_data argument is deprecated and no longer supported. Its documentation directs users to the dedicated IAM policy resource instead. The old computed policy_etag attribute likewise has a documented replacement in the policy resource's etag property.

Those changes separate the project's identity from policy management. This gives configuration authors distinct resource names for the cloud project and its IAM policy. The practical benefit is clarity about which declaration controls which API concern. A project can be the target of a policy resource without hiding that policy inside a deprecated field on the project declaration.

The project documentation still lists a services argument for the APIs enabled on a project. Alongside that argument, the release adds the dedicated services resource, so this is a period in which the available configuration choices need careful reading. The changelog establishes that the new resource exists. It does not justify assuming that every existing services configuration must be rewritten as part of this release.

Provider breadth and lifecycle depth

The new providers show the other direction of growth in this release. Alibaba Cloud appears under the provider name alicloud, alongside profitbricks and ns1. Each addition makes another external API available through Terraform's provider model. For users of those services, inclusion in the release is the relevant expansion of support.

The Google work concerns a deeper change in an existing integration. A project is an organizational object with a lifecycle, permissions and configuration of its own. Treating it as something Terraform can create requires the implementation to distinguish new ownership from the legacy reference behaviour. The release notes and versioned documentation describe that distinction directly.

For a configuration author adopting 0.8.5, project_id is therefore the central detail. It replaces a deprecated field whose value the documentation says was ignored, and it participates in a resource that can create and delete projects. The organization and display name requirements complete the new-project declaration. Together these inputs allow the configuration to state which project Terraform should manage and what kind of management the declaration now requests.