Terraform 0.12.3 can install modules from GCS
GCS module sources add an authenticated package distribution option, while a map-key lifecycle fix restores a narrower way to share resource management.
Distributing a Terraform module does not always require distributing its version control repository. An archive can be the unit that a configuration consumes, provided the installer knows how to find and authenticate access to it. Terraform 0.12.3, released on June 24, adds Google Cloud Storage to the module installer's supported sources.
This change concerns configuration distribution. A module source tells Terraform where to obtain the code it needs before it can evaluate that module. It is separate from a provider resource that creates a bucket, and separate from a backend that stores state. Those operations can use the same cloud service while requiring different access at different stages.
I value reusable Terraform modules, so their distribution mechanism matters to me. An abstraction becomes easier to adopt when callers can obtain a defined package without needing to share its author's development environment. GCS support gives that package another place to live.
Registering an existing downloader
The implementation in pull request 21254 is small. It registers the go-getter GCS detector and getter in two installer-related locations. Terraform already uses go-getter for module retrieval, and the underlying GCS support exists in the vendored library. This release makes that support available through Terraform's module source handling.
The module source documentation at this tag specifies a gcs:: prefix followed by a bucket object URL. This prefix explicitly selects the storage-aware getter. The documented form can identify a ZIP archive containing the module source.
module "network" {
source = "gcs::https://www.googleapis.com/storage/v1/example-modules/network.zip"
}
This is an illustrative source address with a placeholder bucket and object. It follows the form supported by this release's getter and documented in the source guide. It does not create the bucket or upload the archive. The package must already exist and be accessible to the process installing the module.
The vendored GCS getter shows what happens underneath the URL. Its parser extracts a bucket and object path, then the implementation creates a Google storage client and reads the corresponding object. The download therefore uses the storage client's authentication behavior, instead of treating the address as an arbitrary unauthenticated web download.
Installation has its own credentials
The source guide documents application credentials through GOOGLE_APPLICATION_CREDENTIALS, default credentials on a Google Compute Engine instance, or an application-default login on a developer machine. The relevant identity belongs to the environment doing the module installation. It is not established by arguments inside the module that has yet to be downloaded.
For an interactive machine, the documented login command is straightforward.
gcloud auth application-default login
That command configures application-default credentials. It is an installation prerequisite in this scenario, not Terraform configuration syntax. Automated execution needs its own available identity and access to the module object before the configuration can load successfully.
This ordering has practical consequences for reusable module design. A module can configure infrastructure resources after Terraform reads it, but it cannot rely on those resources to make its own initial source available. Package hosting and the credentials that permit package retrieval are inputs to initialization.
The module source guide also supports subdirectories within a downloaded package. Its double-slash notation selects the module directory after the package location. Terraform still extracts the whole package, allowing local references between modules within that package. This is useful when several related modules share a release archive, although the caller still needs a clear choice of package and subdirectory.
Distribution is separate from release policy
The getter registration supplies access to GCS, not a release policy for module authors. An object path can identify a package, but maintainers still need to decide how package names change when the configuration changes. Replacing the contents behind a familiar path and publishing a new path are operationally different choices.
I prefer module references whose intended contents are clear to a reviewer. That is a judgement about using the new mechanism, not a claim that this patch provides a registry or enforces immutable objects. The implementation adds retrieval support and leaves package publication conventions with the publisher.
A narrower lifecycle exception also returns
Version 0.12.3 includes a separate fix for ignore_changes on a specific map key. Pull request 21788 explains that this behavior was intended for 0.12 but a later parser change broke it. The patch brings in the HCL correction and documents an important limitation.
A resource can use ignore_changes = [tags["Name"]] to ignore an in-place update to an existing tag value. The resource documentation says that adding or removing a key counts as changing the containing map. A placeholder key in configuration lets an external process update its value within the supported case.
That distinction prevents a broad reading of the fix. It restores a specific way to share responsibility over an existing map element, with a boundary around additions and removals. Alongside the GCS installer support, it illustrates the scope of this patch release. One change expands how configurations arrive, and another corrects how a declared lifecycle exception applies to the data inside a resource.