Skip to content

Commit

Permalink
feat: implement index ImportState (#10)
Browse files Browse the repository at this point in the history
* chore: gitignore

* chore: ignore `logs.jsonl`

* feat: implement `ImportState`

* chore: README
  • Loading branch information
thiskevinwang committed Oct 7, 2023
1 parent b2703d9 commit c89de60
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 17 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
.terraform
.terraform.lock.hcl
.tfvars
terraform.tfvars
terraform.tfstate
terraform.tfstate.backup
.env
logs.jsonl

# Ignore goreleaser artifacts
dist/*

# Ignore go tools artifacts
bin/*
bin/*
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ go test -v ./...

## Documenting

This uses `./tools/tools.go` to in stall [`tfplugindocs`](github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs)
This project relies on `./tools/tools.go` to install [`tfplugindocs`](github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs).

```console
export GOBIN=$PWD/bin
Expand All @@ -32,22 +32,27 @@ go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
which tfplugindocs
```

Generate docs, and preview them at https://registry.terraform.io/tools/doc-preview
Run `tfplugindocs` to generate docs, and preview individual files at https://registry.terraform.io/tools/doc-preview

## Release
## Releasing

https://developer.hashicorp.com/terraform/registry/providers/publishing#publishing-to-the-registry
There are a few one time steps that have been done already and will not be covered in this README. See the following footnote for more information. [^release]

- Sign in to https://registry.terraform.io/publish/provider/github/thiskevinwang/terraform-provider-pinecone
- Ensure repo has `.goreleaser.yml`
- gpg --armor --export "[EMAIL]"
- add this to registry signing keys
- gpg --armor --detach-sign
- git tag v0.1.1
- GITHUB_TOKEN=$(gh auth token) goreleaser release --clean
[^release]: Docs on publishing: https://developer.hashicorp.com/terraform/registry/providers/publishing#publishing-to-the-registry

To release a new version of the provider to the registry, a new GitHub release needs to be created.
Use the following steps to proceed.

1. Ideally you’re on `main`, and have a clean working tree.
2. Ensure the commit (aka HEAD) you're about to release is tagged.
- `git tag v0.1.2`
- `git push origin v0.1.2`
3. Run `goreleaser`: `GITHUB_TOKEN=$(gh auth token) goreleaser release --clean`
- This will create a new GitHub release which should be detected by the Terraform registry shortly after.

## Appendix

- https://thekevinwang.com/2023/10/05/build-publish-terraform-provider
- https://docs.pinecone.io/
- https://github.com/hashicorp/terraform-plugin-framework
- https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider
Expand Down
52 changes: 47 additions & 5 deletions internal/resources/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,16 @@ type indexResourceModel struct {
}

// Metadata returns the resource type name.
func (r *indexResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
func (r *indexResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
tflog.Debug(ctx, "indexResource.Metadata", map[string]any{"req": req, "resp": resp})

resp.TypeName = req.ProviderTypeName + "_index"
}

// Schema defines the schema for the resource.
func (r *indexResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
func (r *indexResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
tflog.Debug(ctx, "indexResource.Schema", map[string]any{"req": req, "resp": resp})

resp.Schema = schema.Schema{
Description: "Manages an index.",
Attributes: map[string]schema.Attribute{
Expand Down Expand Up @@ -100,7 +104,8 @@ func (r *indexResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
}

// Configure adds the provider configured client to the resource.
func (r *indexResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
func (r *indexResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
tflog.Debug(ctx, "indexResource.Configure", map[string]any{"req": req, "resp": resp})
if req.ProviderData == nil {
return
}
Expand All @@ -122,6 +127,7 @@ func (r *indexResource) Configure(_ context.Context, req resource.ConfigureReque

// Create a new resource.
func (r *indexResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
tflog.Debug(ctx, "indexResource.Create", map[string]any{"req": req, "resp": resp})
var plan indexResourceModel

// Read Terraform plan data into the model
Expand Down Expand Up @@ -185,6 +191,8 @@ func (r *indexResource) Create(ctx context.Context, req resource.CreateRequest,

// Read resource information.
func (r *indexResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
tflog.Debug(ctx, "indexResource.Read", map[string]any{"req": req, "resp": resp})

// Get current state
// Read data from Terraform state
var state indexResourceModel
Expand All @@ -200,7 +208,7 @@ func (r *indexResource) Read(ctx context.Context, req resource.ReadRequest, resp
if err != nil {
resp.Diagnostics.AddError(
"Failed to describe index",
fmt.Sprintf("Failed to describe index: %s", err),
err.Error(),
)
return
}
Expand All @@ -220,6 +228,8 @@ func (r *indexResource) Read(ctx context.Context, req resource.ReadRequest, resp

// Update resource information.
func (r *indexResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
tflog.Debug(ctx, "indexResource.Update", map[string]any{"req": req, "resp": resp})

var plan indexResourceModel

// Read Terraform plan data into the model
Expand Down Expand Up @@ -249,6 +259,8 @@ func (r *indexResource) Update(ctx context.Context, req resource.UpdateRequest,

// Delete resource information.
func (r *indexResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
tflog.Debug(ctx, "indexResource.Delete", map[string]any{"req": req, "resp": resp})

var state indexResourceModel

// Read Terraform plan data into the model
Expand All @@ -274,7 +286,37 @@ func (r *indexResource) Delete(ctx context.Context, req resource.DeleteRequest,
}

func (r *indexResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
tflog.Info(ctx, "Import state", map[string]any{"ID": req.ID})
tflog.Debug(ctx, "indexResource.ImportState", map[string]any{"req": req, "resp": resp})

// fetch a fresh index from pinecone
// req.ID appears to be our only way to get the index name
indexName := req.ID
// note that what gets fetched from pinecone, based on purely
// the index name, may differ from the rest of whatever is
// specified in the resource stanza in HCL

// Get fresh state from Pinecone
response, err := r.client.DescribeIndex(indexName)
if err != nil {
resp.Diagnostics.AddError(
"Failed to describe index",
err.Error(),
)
return
}

// TODO(kevinwang) wait for the index to be in a ready state
state := indexResourceModel{}
state.Dimension = types.Int64Value(response.Database.Dimension)
state.Metric = types.StringValue(response.Database.Metric)
state.Replicas = types.Int64Value(response.Database.Replicas)
state.Pods = types.Int64Value(response.Database.Pods)
state.Name = types.StringValue(response.Database.Name)

// Save data into Terraform state
diags := resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

// Retrieve import ID and save to id attribute
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}
3 changes: 3 additions & 0 deletions internal/services/pinecone.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ type DescribeIndexResponse struct {
// https://controller.{environment}.pinecone.io/databases/{indexName}
// Get a description of an index.
func (p *Pinecone) DescribeIndex(name string) (*DescribeIndexResponse, error) {
if name == "" {
return nil, fmt.Errorf("DescribeIndex failed: name argument was not specified")
}
url := fmt.Sprintf(baseUrl+"/databases/%s", p.Environment, name)

// initialize a request
Expand Down
8 changes: 8 additions & 0 deletions learning/log.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,11 @@ Login to https://registry.terraform.io/publish/provider/github/thiskevinwang
Visit https://developer.hashicorp.com/terraform/registry/providers/publishing

10-05-2023 2:35pm Publishing...

10-07-2023 12:41am Logging

Regexp to grok `.jsonl` file

`"indexResource.[a-z]+".+tf_rpc`

`TF_LOG=json TF_LOG_PROVIDER=info TF_LOG_PATH=logs.jsonl terraform apply`

0 comments on commit c89de60

Please sign in to comment.