Terraform fixes cloud-init MIME formatting with replacement consequences
Terraform 0.9.4 adds cloud providers, but its cloud-init formatting correction can also change immutable resource inputs. A missing blank line connects protocol correctness to infrastructure replacement.
A missing blank line in generated configuration can change an infrastructure plan. Terraform 0.9.4 corrects the MIME formatting produced by template_cloudinit_config. The corrected output differs from the previous output even when the configuration author changes nothing. A resource that treats that output as an immutable input can therefore require replacement after the Terraform upgrade.
The April 26 release notes put this correction in their compatibility notes. They identify aws_launch_configuration as an example of an immutable consumer. The same release adds Oracle Public Cloud and 1&1 providers, but the small serialization change is the part that can alter an existing deployment's plan.
I value Terraform's ability to make API-backed infrastructure reusable through configuration. This fix illustrates why the generated bytes are part of that abstraction's contract. A configuration can preserve its apparent intent while a corrected renderer changes the exact value handed to another resource.
The header boundary was incomplete
The fix in pull request 13752 adds an extra carriage-return and line-feed pair after the top-level MIME-Version header. Previously, the code wrote one pair. The corrected code writes two, leaving an empty line between the message headers and the multipart body.
This is a distinction in the structure of the message. A multipart body contains its own boundary markers and headers for individual parts. The outer message must first finish its header section. Without the empty line, a parser has to tolerate malformed input or interpret the following bytes under the wrong structural assumptions.
The contributor explains that Python's email parser accepts the old output and that cloud-init uses that parser. Other languages' parsers can have trouble with it. That makes this a compatibility fix for the generated MIME message even when an existing cloud-init consumer happens to accept the old message.
The patch also changes the expected output in renderer tests. The expected strings show the extra line break immediately before the first multipart boundary. Content inside the part remains the same. This is useful evidence of the scope of the correction because it distinguishes a message-envelope fix from a rewrite of the shell script inside a part.
The data source produces an artifact
The tagged data-source reference describes template_cloudinit_config as a renderer for multipart cloud-init configuration. Each part supplies content and can provide a filename or content type. Multiple parts preserve their configuration order in the rendered result.
The rendered attribute is the finished artifact consumed elsewhere. The data source also supports gzip compression and base64 encoding, both enabled by default. For inspecting the MIME text itself, disabling those transformations makes the structural boundary visible.
data "template_cloudinit_config" "example" {
gzip = false
base64_encode = false
part {
filename = "bootstrap.sh"
content_type = "text/x-shellscript"
content = "#!/bin/sh\necho bootstrap\n"
}
}
output "cloud_init_message" {
value = "${data.template_cloudinit_config.example.rendered}"
}
This example renders one shell-script part and exposes the result as an output. It deliberately stops before attaching that artifact to a cloud resource. The data-source behavior and the consumer's lifecycle rules are different concerns, even though an interpolation can connect them in a single line of configuration.
Compression or encoding does not remove the underlying change. Those operations transform the rendered message. If the input message changes, the consumer can still receive a changed value even though the human-readable difference was only an empty line.
An unchanged script can produce a changed resource input
The release notes say the data source itself is not broken by the correction. The replacement consequence comes from references to its output. An immutable resource cannot necessarily accept an updated value through an in-place API operation, so Terraform may need to construct a replacement object.
That distinction explains why the compatibility note belongs to a renderer fix. A provider does not have to change the resource schema to change a plan. It can change the value of a computed input that another resource already treats as replacement-sensitive.
For an author reading a resulting plan, the relevant question is where the changed value originated. A user-data difference can come from a change to the script, a template variable or the renderer's serialization. This release supplies a concrete case of the third possibility. Attributing every user-data difference to an intentional script edit would miss the cause.
It also matters which resource consumes the artifact. The changelog names launch configurations and similar immutable resources. It does not claim that every resource receiving cloud-init data will be replaced, or that every instance will be recreated merely because Terraform starts using 0.9.4. The plan depends on the actual references and the lifecycle rules of the consuming resources.
I prefer release notes that state this consequence explicitly. A protocol correction is still correct when it changes resource inputs, but an operator needs to understand why an executable upgrade can produce infrastructure work.
The optional filename belongs to a part and appears in its MIME metadata. It does not replace the message boundary between the outer headers and body. Likewise, a content type describes how a recipient should interpret that part, while the missing blank line concerns where the outer message starts its body. These levels of structure explain why changing the shell script cannot repair the original envelope defect.
Broader API support shares the same release
Terraform 0.9.4 introduces the opc provider for Oracle Public Cloud and the oneandone provider. The release notes also list data sources for Google Compute networks and subnetworks. These additions expand which external objects configurations can manage or inspect.
Their relationship to the MIME correction is architectural. Terraform configurations connect provider results through a shared expression language. An output from one integration can become an input to another, so compatibility has to account for values crossing those connections. The launch-configuration example shows a template provider affecting the proposed lifecycle of an AWS resource.
The useful detail in this release is therefore the dependency between serialization and ownership. The renderer now emits the required header separation. A consuming resource can observe that correction as an input change, and its documented update behavior determines whether that difference requires a replacement. The script inside the message need not change for that chain of effects to occur.