This repository contains a Cookiecutter template to create a new Pulumi provider which wraps an existing Terraform provider.
This repository is part of the guide for authoring and publishing a Pulumi Package.
Learn about the concepts behind Pulumi Packages.
Inside an empty git repository:
nix develop 'github:MaienM/pulumi-tf-provider-cookiecutter' --command cruft-init
$EDITOR init.json
nix develop 'github:MaienM/pulumi-tf-provider-cookiecutter' --command cruft-init
-
Python version
>= 3.7
-
Packaging module
>= 19.0
-
Cookiecutter version
>= 2.1
To create a new Pulumi provider using this template, Cookiecutter must be available with a version >= 2.1 because the template utilizes
local extensions
which was a new feature in version 2.1.You can follow the installation instructions in the Cookiecutter documentation or you can use a Python virtual environment to install Cookiecutter.
A virtual environment has the advantage that Cookiecutter will be installed in that environment and will not clutter up your local machine with software that you might use only once. After done with creating the Pulumi provider the virtual environment can safely removed from the local disk.
Steps to install Cookiecutter in a virtual environment:
Note: the following steps assume a Unix like operating system. To create a virtual environment on Windows refer to an appropriate documentation.
python3 -m venv vcoockiecutter
source vcoockiecutter/bin/activate
python -m pip install -U pip
python -m pip install cookiecutter packaging
To create a new provider start Cookiecutter with a reference to this GitHub repository:
cookiecutter -f gh:tmeckel/pulumi-tf-provider-cookiecutter
Cookiecutter will then create a new (sub-)directory at the current location
using the naming scheme: pulumi-<provider-name>
.
For additional command line options refer to the chapter Command Line Options in the Cookiecutter documentation.
Note: The template only supports Terraform Providers which source code is hosted on GitHub
During execution Cookiecutter will prompt for the following input parameters.
Except for terraform_provider_name
and terraform_provider_org
the template
will propose meaningful values for input parameters derived from the context of
conceived input parameters so far. You can accept the proposed value by hitting
RETURN
.
Note: All input parameters are
required
. If not stated otherwise.
Parameter | Description |
---|---|
terraform_provider_name |
The name of the Terraform provider to wrap. Only use the suffix after terraform-provider Example: terraform-provider-time -> Input: time |
terraform_provider_org |
The GitHub organization which hosts the Terraform provider. Example: GitHub Url: https://github.com/hashicorp/terraform-provider-time -> Input: hashicorp |
terraform_provider_source |
The GitHub Url of the Terraform Provider. Usually, there is no reason not to accept the proposed value. |
terraform_provider_version_or_commit |
The Version of the Terraform provider to initially wrap as a Pulumi provider. Refer to chapter terraform_provider_version_or_commit for a detailed explanation and hints how to decide what type of version reference to use. |
terraform_provider_module |
The value of the first line in the top level go.mod file from source code of the Terraform provider. Ensure to change the proposed value if the value do not match with the one from the top level go.mod file from the Terraform provider repository. |
terraform_provider_package_name |
The Go package path to the provider.go file, or to the .go file which contains the func Provider() *schema.Provider function. |
terraform_sdk_version |
The Terraform SDK version that is in use by the Terraform provider. Possible values: - 1 : Terraform SDK Version 1- 2 : Terraform SDK Version 2- plugin-framework : Terraform Plugin Framework |
provider |
The name of the Pulumi provider. It's recommended to keep the proposed value, because it adheres to the Pulumi provider naming scheme. |
provider_display_name |
The friendly name of the Pulumi Provider. The display name will be shown as title in the Pulumi for the provider. So it's advisable to keep it short and concise. |
provider_github_organization |
The GitHub organization to host the Pulumi provider. |
provider_publisher |
The personal/company name, that shall to be shown on Pulumi Registry |
provider_homepage |
A web-accessible URL to homepage of the provider. |
provider_logoUrl |
A web-accessible URL to a logo for your package (ideally an SVG) |
provider_description |
A concise description of the provider. |
provider_category |
The category of the provider. Categories ease searching insider the Pulumi registry. Cookiecutter prompts the permitted categories of Pulumi Registry. |
provider_download_url |
A web-accessible URL that contains the compiled binary plugin associated with the provider |
provider_javascript_package |
The name of the Javascript package which will be published to NPMJS |
provider_dotnet_rootnamespace |
The root namespace of the Dotnet assembly. The complete Namespace will be generated as <provider_dotnet_rootnamespace>.<provider> |
provider_python_package |
The name of the Python package published to pypi.org |
provider_java_base_package |
The base package name (path) for the Java SDK |
provider_mapping_strategy |
Specifies the strategy how resources and data sources from the upstream Terraform provider are mapped. - automatic (default) The template will emit code to utilize the auto discovery mechanism of Pulumi Terraform Bridge to map resources and data sources. It is still possible to manually map resources and data sources with special configurations. - manual : all resources and data sources must be manually added |
provider_naming_strategy |
Configures the conversion strategy how to create a Pulumi name from a Terraform resource or data source name. Pulumi names are composed of a name for the module and the actual resource or data source name. When creating the language SDKs the module name will become a namespace (module) name under which the resources or data source (function) is created. - singlelevel (default): all resources and data sources will be mapped one level deep into a namespace extracted along the underscores in the Terraform nameTerraform name: dbtcloud_environment_variable_job_override Module: environment Name: VariableJobOverride - structured : resources will be placed in namespaces along the underscores in the Terraform nameTerraform name: dbtcloud_environment_variable_job_override Module: environment/variable/job Name: Override - flat : all resources will be placed in the top-level (nameless) root moduleTerraform name: dbtcloud_environment_variable_job_override Module: empty Name: EnvironmentVariableJobOverride When singlelevel or structured is selected, the template emit dictionary module_overrides in resources.go which can be used to map a generated module name to a fixed module name. |
create_github_workflows |
Per default the template will create preconfigured GitHub actions which automatically creates releases for a new provider version. Answer with no to disable the create of those actions. |
skip_go_mod_tidy |
Per default the template will execute go mod tidy on the new Pulumi Provider package to verify that the Terraform provider can be included as module and to create the required go.sum file. Answer with no to suppress the execution of go mod tidy |
skip_git_init |
Skip the initialization of a Git repository for the new provider. This is not recommended because the build process requires a Git repository to derive the semver version tag for the current build. Answer with no to skip the execution of git init |
Note: Input parameters starting with
pulumi
reflect the attributes of the Pulumi package metadata
After the Cookiecutter template has created the new directory for the Pulumi
provider, you can change to this directory and use the make tfgen
command to
check whether the Terraform provider has been referenced correctly.
Note
For guidance how to further develop the newly created Pulumi provider refer toREADME-DEVELOPMENT.md
in the provider directory especially how to map resources and data sources from the upstream Terraform provider including the possbility to autogenerate hose mappings.
The parameter specifies the initial version of the Terraform provider that should be wrapped as a Pulumi Provider. You can specify a Semver compatible version or a Git commit.
Aside the terraform_provider_source
and the terraform_provider_module
the
version is a vital part of a module reference in Go. A thorough explanation of
how Go manages dependencies is available at
go.dev
.
The following will list a couple of hints when to select a specific version
number or when to use a commit reference as a value for
terraform_provider_version_or_commit
-
If the Terraform provider repository contains a release
< 2.0.0
use the release version. -
If the Terraform provider repository contains a release
>= 2.0.0
and the module name in top levelgo.mod
file ends with the correct version suffix that matches the major version of the provider release, use the version number.Example:
- Repository release
3.5.1
- module name in
go.mod
:github.com/bar/terraform-provider-foo/v3
- Repository release
-
If the Terraform provider repository contains a release
>= 2.0.0
and the module name in top levelgo.mod
does not end with the correct version suffix, use the commit hash of the release version. -
You can always select a commit hash, and the Cookiecutter template will automatically create a valid pseudo-version and add it to the Pulumi provider
go.mod
file.
Note: If values of
terraform_provider_source
,terraform_provider_module
and or the referenced version occur, the Cookiecutter template will do it's best to create correctreplace
statements in thego.mod
file of the Pulumi provider, to reference the Terraform Provider as a valid Go module.
The parameter specifies the package path to the func Provider()
implementation
which returns the schema of the Terraform Provider. The Cookiecutter template is
smart enough to create a SHIM if the provider implementation is hidden inside an
internal
package, because internal/
is a special directory name recognized
by the go tool which will prevent one package from being imported by another
unless both share a common ancestor. Packages within an internal/
directory
are therefore said to be internal packages.