Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Add guide for generating a provider
Browse files Browse the repository at this point in the history
Signed-off-by: Hasan Turken <turkenh@gmail.com>
  • Loading branch information
turkenh committed Nov 1, 2021
1 parent f8eb1be commit 5dcead1
Showing 1 changed file with 188 additions and 0 deletions.
188 changes: 188 additions & 0 deletions docs/generating-a-provider.md
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

0 comments on commit 5dcead1

Please sign in to comment.