Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement index ImportState #10

Merged
merged 4 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`
Loading