This repository is a boilerplate showing how to create a native Pulumi provider using:
pulschemato convert an OpenAPI spec to Pulumi schemapulumi-provider-frameworkto make HTTP requests against the cloud provider API. It uses the metadata returned bypulschemaas one of the outputs from converting an OpenAPI spec.
Follow this link to see what a Pulumi native provider is comprised of.
A Pulumi Resource Provider:
- is a gRPC server which allows for the Pulumi engine to create resources in a specific cloud
- holds the lifecycle logic for these cloud resources
- holds a pulumi JSON schema that describes the provider
- provides language-specific SDKs so resources can be created in whichever language you prefer
When we speak of a "native" provider, we mean that all implementation is native to Pulumi, as opposed to Terraform-based providers.
This boilerplate creates a working Pulumi-owned provider named xyz.
Ensure the following tools are installed and present in your $PATH:
pulumictl- Go 1.21 or 1.latest
- NodeJS 18.x. We recommend using nvm to manage NodeJS installations.
- Yarn
- TypeScript
- Python (called as
python3) - .NET
Pulumi offers this repository as a GitHub template repository for convenience. From this repository:
- Click "Use this template".
- Set the following options:
- Owner:
<your GH organization> - Repository name: pulumi-xyz (replace "xyz" with the name of your provider)
- Providers built from Cloudy Sky Software's templates are always native providers, by default.
- However, if there is already a TF-bridged provider with that name, you should add the suffix
-nativeso that the package name in some package registries do not conflict with the other providers.
- Description: Pulumi provider for xyz
- Repository type: Public
- Owner:
- Clone the generated repository.
From the templated repository:
Search-replace the following occurrences with the corresponding names.
| Search | Replace With |
|---|---|
| xyz | Lower-cased name of the provider |
| Xyz | Pascal-case name of the provider |
| XYZ | Upper-cased name of the provider |
| x_y_z | Lower snake-cased name of the provider if the provider name has multiple words |
$ make build installThis will:
- Create the SDK codegen binary and place it in a
./binfolder (gitignored) - Create the provider binary and place it in the
./binfolder (gitignored) - Generate the dotnet, Go, Node, and Python SDKs and place them in the
./sdkfolder - Install the provider on your machine.
$ cd examples/simple
$ yarn link @pulumi/xyz
$ yarn install
$ pulumi stack init test
$ pulumi upNow that you have completed all of the above steps, you have a working provider that generates a random string for you.
You now have:
- A
provider/folder containing the building and implementation logiccmd/pulumi-gen-xyz/- generates language SDKs from the schemapulumi-resource-xyz/- holds the package schema, injects the package version, and starts the gRPC server
pkgprovider- holds the gRPC methods (and for now, the sample implementation logic) required by the Pulumi engineversion- semver package to be consumed by build processes
sdk- holds the generated code libraries created bypulumi-gen-xyz/main.goexamplesa folder of Pulumi programs to try locally and/or use in CI.- A
Makefileand thisREADME.
You will find a mostly blank implementation of these in pkg/provider/provider.go.
Note that these methods do not link 1:1 to the Pulumi resource provider interface
because pulumi-provider-framework provides a convenient callback mechanism
and handles all other responsibilities. You should use the callback methods
to alter the HTTP request (in Pre* methods) or the response (in Post*) as
needed. If you don't need any customization, then you don't need to do
anything at all. Yep! The framework handles it all.
Create an example program using the resources defined in your provider, and place it in the examples/ folder.
You can now repeat the steps for build, install, and test.
Please follow this guide to add documentation to your provider.
Import IDs should satisfy all ID segments in the GET endpoint for the resource
you are importing. The IDs required in the path should be separated by /.
First, start by identifying the GET endpoint in the OpenAPI spec
for the provider.
For example, let's assume such a GET endpoint path for some resource is: /services/{serviceId}/someResource/{someResourceId}.
Thus, the pulumi import command to run is:
# The resource type token can be easily found by using your IDEs
# Go To Definition functionality for the resource and looking at the type
# property defined in the custom resource's class definition.
pulumi import {resourceTypeToken} {resourceName} /{serviceId}/{someResourceId}Alternatively, you can also import using the import Pulumi resource option.
Run pulumi up to import the resource into your stack's state. Once imported,
you should remove the import resource option.
const someResource = new SomeResource(
"myResourceName",
{ //inputs for the reosurce },
{
protect: true,
import: `/{serviceId}/{someResourceId}`,
}
);Refer to the Pulumi docs for importing a resource.
- Follow the instructions laid out in the deployment templates.