Files
unkin-agent d2451eb650
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Add estate CI, release and Makefile; use git.unkin.net/unkin/binarylane source
2026-10-12 00:40:26 +11:00

238 lines
5.0 KiB
Markdown

# Contributing
## Local development
### First time setup
Based on [this example from the terraform docs](https://developer.hashicorp.com/terraform/plugin/code-generation/workflow-example),
1. `go mod tidy`
2. Run `go generate` to fetch/transform the OpenAPI spec in `internal/binarylane/openapi.json`
3. Create or modify `~/.terraformrc` in your home directory
```hcl
provider_installation {
dev_overrides {
# Example GOBIN path, will need to be replaced with your own GOBIN path. Default is $GOPATH/bin
"git.unkin.net/unkin/binarylane" = "/path/to/terraform-provider-binarylane/bin"
}
direct {}
}
```
4. Build and test the provider
```sh
go build -o bin/terraform-provider-binarylane
go install
cd examples/basic
terraform plan
terraform apply
```
### Testing
```sh
cp .env.example .env
# Add your API token to .env
eval export $(cat .env)
go test -v ./internal/provider/...
```
To run Sweepers:
```sh
go test -v ./internal/provider/... -sweep=all
```
### Update modules
```sh
go get -u && go mod tidy && go generate
```
### Adding resources/data sources to the provider
1. Make any changes to `provider_gen_config.yml` (see https://developer.hashicorp.com/terraform/plugin/code-generation/openapi-generator#generator-config)
2. Update generated files
```sh
go generate
```
3. Scaffold any new resources and data sources
```sh
tfplugingen-framework scaffold resource \
--output-dir ./internal/provider \
--name REPLACE_ME # eg. server
```
```sh
tfplugingen-framework scaffold data-source \
--output-dir ./internal/provider \
--name REPLACE_ME
```
4. Populate the template scaffolding:
#### Resource
Define the interfaces that the resource should implement:
```diff
- var _ resource.Resource = (*exampleResource)(nil)
+ var (
+ _ resource.Resource = &exampleResource{}
+ _ resource.ResourceWithConfigure = &exampleResource{}
+ _ resource.ResourceWithImportState = &exampleResource{}
+ )
```
Add the API client to the resource:
```diff
- type exampleResource struct{}
+ type exampleResource struct {
+ bc *BinarylaneClient
+ }
```
Extend the resource model from the generated `resources.*Model`.
```diff
type exampleResourceModel struct {
- Id types.String `tfsdk:"id"`
+ resources.ExampleModel
+ // Add any additional fields here
}
```
Add a `Configure` method to the resource:
```diff
+ func (d *exampleResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
+ if req.ProviderData == nil {
+ return
+ }
+ bc, ok := req.ProviderData.(BinarylaneClient)
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Resource Configure Type",
+ fmt.Sprintf("Expected *BinarylaneClient, got: %T.", req.ProviderData),
+ )
+ return
+ }
+ d.bc = &bc
+ }
```
```diff
+ func (r *exampleResource) ImportState(
+ ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse,
+ ) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+ }
```
Add the new resource to `provider.go`:
```diff
return []func() resource.Resource{
# ...
+ NewExampleResource,
}
```
#### Data Source
Define the interfaces that the data source should implement:
```diff
- var _ resource.Resource = (*exampleDataSource)(nil)
+ var (
+ _ datasource.DataSource = &exampleDataSource{}
+ _ datasource.DataSourceWithConfigure = &exampleDataSource{}
+ )
Add the API client to the data source:
```diff
- type exampleDataSource struct{}
+ type exampleDataSource struct {
+ bc *BinarylaneClient
+ }
```
Derive the data source model from the generated `resources.*Model`.
```diff
type exampleDataSourceModel struct {
- Id types.String `tfsdk:"id"`
+ resources.ExampleModel
}
```
Add a `Configure` method to the data source.
```diff
+ func (d *exampleDataSource) Configure(
+ _ context.Context,
+ req datasource.ConfigureRequest,
+ resp *datasource.ConfigureResponse,
+ ) {
+ if req.ProviderData == nil {
+ return
+ }
+
+ bc, ok := req.ProviderData.(BinarylaneClient)
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Data Source Configure Type",
+ fmt.Sprintf("Expected *BinarylaneClient, got: %T.", req.ProviderData))
+ return
+ }
+
+ d.bc = &bc
+ }
```
Use the generated schema to define the data source schema.
```diff
func (d *exampleDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
- resp.Schema = schema.Schema{
- Attributes: map[string]schema.Attribute{
- "id": schema.StringAttribute{
- Computed: true,
- },
- },
- }
+ ds, err := convertResourceSchemaToDataSourceSchema(
+ resources.ExampleResourceSchema(ctx)
+ AttributeConfig{
+ RequiredAttributes: &[]string{"id"},
+ },
+ )
+ if err != nil {
+ resp.Diagnostics.AddError("Failed to convert resource schema to data source schema", err.Error())
+ return
+ }
+ resp.Schema = *ds
+ // resp.Schema.Description = "TODO"
}
```
Add the data source to `provider.go`:
```diff
return []func() datasource.DataSource{
# ...
+ NewExampleDataSource,
}