This repository has been archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Hasan Turken <turkenh@gmail.com>
- Loading branch information
Showing
1 changed file
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
# Generating a Crossplane Provider from a Terraform Provider | ||
|
||
## Generate | ||
|
||
In this Guide, we will generate https://registry.terraform.io/providers/integrations/github/latest/docs | ||
|
||
1. Generate a GitHub repository for the Crossplane provider by hitting the | ||
"Use this template" button in [provider-tf-template] repository. | ||
2. Clone the repository to your local. | ||
3. Replace `template` with your provider name. | ||
1. Export variables for your provider name. | ||
|
||
```shell | ||
export ProviderNameLower=github | ||
export ProviderNameUpper=GitHub | ||
``` | ||
|
||
2. Replace all occurrences of `template` with your provider name. | ||
|
||
```shell | ||
git grep -l 'template' -- './*' ':!build/**' ':!go.sum' | xargs sed -i.bak "s/template/${ProviderNameLower}/g" | ||
git grep -l 'Template' -- './*' ':!build/**' ':!go.sum' | xargs sed -i.bak "s/Template/${ProviderNameUpper}/g" | ||
# Clean up the .bak files created by sed | ||
git clean -fd | ||
mv "internal/clients/template.go" "internal/clients/${ProviderNameLower}.go" | ||
mv "cluster/images/provider-tf-template" "cluster/images/provider-tf-${ProviderNameLower}" | ||
mv "cluster/images/provider-tf-template-controller" "cluster/images/provider-tf-${ProviderNameLower}-controller" | ||
``` | ||
|
||
4. Configure your repo with Terraform provider and schema: | ||
1. Update Makefile variables for Terraform Provider (`TERRAFORM_PROVIDER_*`) | ||
|
||
```makefile | ||
export TERRAFORM_PROVIDER_SOURCE := integrations/github | ||
export TERRAFORM_PROVIDER_VERSION := 4.17.0 | ||
export TERRAFORM_PROVIDER_DOWNLOAD_NAME := terraform-provider-github | ||
export TERRAFORM_PROVIDER_DOWNLOAD_URL_PREFIX := https://releases.hashicorp.com/terraform-provider-github/4.17.0 | ||
``` | ||
Check the Dockerfile at cluster/images/provider-tf-${ProviderNameLower}-controller/Dockerfile | ||
to see how download URL of the Terraform provider plugin binary | ||
constructed using these variables. | ||
|
||
2. Find go repository of the Terraform provider set import path for the | ||
package with function `func Provider() terraform.ResourceProvider` and | ||
set as import path for `tf` alias in `config/provider.go`. | ||
```go | ||
package config | ||
import ( | ||
tjconfig "github.com/crossplane-contrib/terrajet/pkg/config" | ||
tf "github.com/turkenh/terraform-provider-github/v4/github" | ||
) | ||
const resourcePrefix = "github" | ||
``` | ||
4. If your provider uses an old version (<v2) of | ||
`github.com/hashicorp/terraform-plugin-sdk`, initialize a Terrajet provider | ||
configuration as follows: | ||
```go | ||
pc := tjconfig.NewProvider(tjconfig.GetV2ResourceMap(tf.Provider()), resourcePrefix, "github.com/crossplane-contrib/provider-tf-github") | ||
``` | ||
6. Implement `ProviderConfig` logic. In provider-tf-template, there is already | ||
a boilerplate code in file `internal/clients/${ProviderNameLower}.go` which | ||
takes care of properly fetching secret data referenced from `ProviderConfig` | ||
resource. | ||
For our GitHub provider, we need to check [Terraform documentation for provider | ||
configuration] and provide the keys there: | ||
```go | ||
const ( | ||
keyBaseURL = "base_url" | ||
keyOwner = "owner" | ||
keyToken = "token" | ||
// GitHub credentials environment variable names | ||
envToken = "GITHUB_TOKEN" | ||
) | ||
func TerraformSetupBuilder(version, providerSource, providerVersion string) terraform.SetupFn { | ||
... | ||
// set provider configuration | ||
ps.Configuration = map[string]interface{}{} | ||
if v, ok := githubCreds[keyBaseURL]; ok { | ||
ps.Configuration[keyBaseURL] = v | ||
} | ||
if v, ok := githubCreds[keyOwner]; ok { | ||
ps.Configuration[keyOwner] = v | ||
} | ||
// set environment variables for sensitive provider configuration | ||
ps.Env = []string{ | ||
fmt.Sprintf(fmtEnvVar, envToken, githubCreds[keyToken]), | ||
} | ||
... | ||
``` | ||
6. Before generating all resource that the provider has, let's go step by step | ||
and only start with generating `github_repository` and `github_branch` | ||
resources. | ||
To limit the resources to be generated, we need to provide an include list | ||
option with `tjconfig.WithIncludeList` in file `config/provider.go`: | ||
```go | ||
pc := tjconfig.NewProvider(tjconfig.GetV2ResourceMap(tf.Provider()), resourcePrefix, "github.com/crossplane-contrib/provider-tf-github", | ||
tjconfig.WithIncludeList([]string{ | ||
"github_repository$", | ||
"github_branch$", | ||
})) | ||
``` | ||
7. Finally, we would need to add some custom configurations for these two | ||
resources as follows: | ||
1. Create group customization directories: | ||
```shell | ||
# Create custom configuration directory for whole repository group | ||
mkdir config/repository | ||
# Create custom configuration directory for whole branch group | ||
mkdir config/branch | ||
``` | ||
2. Create resources customizations for `github_repository` and `github_branch`: | ||
```shell | ||
cat <<EOF > config/repository/config.go | ||
package repository | ||
import "github.com/crossplane-contrib/terrajet/pkg/config" | ||
func Customize(p config.Provider) { | ||
p.AddResourceConfigurator("github_repository", func(r *config.Resource) { | ||
r.Group = "repository" | ||
}) | ||
} | ||
EOF | ||
``` | ||
```shell | ||
cat <<EOF > config/branch/config.go | ||
package branch | ||
import "github.com/crossplane-contrib/terrajet/pkg/config" | ||
func Customize(p config.Provider) { | ||
p.AddResourceConfigurator("github_branch", func(r *config.Resource) { | ||
r.Group = "branch" | ||
r.ExternalName = config.IdentifierFromProvider | ||
r.References["repository"] = config.Reference{ | ||
Type: "github.com/crossplane-contrib/provider-tf-github/apis/repository/v1alpha1.Repository", | ||
} | ||
}) | ||
} | ||
EOF | ||
``` | ||
3. Register these group customization functions in `config/provider.go` | ||
```go | ||
// GetProvider returns provider configuration | ||
func GetProvider() tjconfig.Provider { | ||
... | ||
for _, configure := range []func(provider tjconfig.Provider){ | ||
repository.Customize, | ||
branch.Customize, | ||
} { | ||
configure(pc) | ||
} | ||
... | ||
} | ||
``` | ||
8. Now we can generate our Terrajet Provider: | ||
```shell | ||
make generate | ||
``` | ||
## Test | ||
## Package | ||
[provider-tf-template]: https://github.com/crossplane-contrib/provider-tf-template | ||
[Terraform documentation for provider configuration]: https://registry.terraform.io/providers/integrations/github/latest/docs#argument-reference |