Objectives
- learn more about terraform internals, particularly how the core integrates and interacts with providers
- learn how to use terraform providers in own tools
Scope of a provider
A typical provider is a separate executable.
When the provider program is run, it can be communicated with using a gRPC.
Usually the provider then interacts with external systems based on that communication.
The provider exposes operations like GetProviderSchema, ConfigureProvider,
or PlanResourceChange (and more) over gRPC. For a full list take a look at
the .proto file for the plugin protocol version you need to use, e.g.
the terraform plugin protocol version
Using those operations, the provider can provide
- resource configuration and state schemas (it can describe it’s own data)
- validation and configuration
- planning information and rules (e.g. replacement needed based on changes?)
- operations on resources
Scope of the caller
Handling of the provider’s lifecycle and keeping track of the state.
Simplified an exchange between caller (e.g. opentofu) and the provider might look like this:
- recall the previous state
- call
ReadResource - process the refreshed state
- take in new proposed state and call
PlanResourceChangeto get planned state and replacement requirements - use planned state and the previous state to call
ApplyResourceChangeto get the resulting state (and the side-effects we are after) - record resulting state for later calls
A shallow look at the protocol
The used protocol is generic and powerful enough to allow other programs such as Pulumi (see pulumi’s terraform bridge and any terraform provider feature).
It went through multiple iterations (currently in version 6), and terraform, opentofu, and pulumi are well established as IaC tools. It seems to be able to capture many particularities of resource management well judging by the large supply in providers, many of which are made by and/or integrate with major companies.
Looking at the wire format specification and the plugin protocol itself, it is apparent that the valuable distinction between something being unknown and known to be absent is well engrained.
Minimal providers
A minimal, yet fully functional provider would be a good starting point to actually get our feet wet with running and interacting with providers directly.
Luckily there are a few official providers we can use for that
- random generates random values locally; example on how values propagate
- null provides constructs that intentionally do nothing; basic lifecycle and replacement
- local manages local files; get actual tangible effects on something that is easy to manipulate
- hashicups hashicorp’s development tutorial provider; lifecycle, setup, integration work
- We could also have a look at the scaffolding framework which seems to be the official starting template containing some examples
(and a lot more official ones on github)