Skip to content

Commit

Permalink
feat: Implemented alias resource
Browse files Browse the repository at this point in the history
  • Loading branch information
adanylenko committed Apr 1, 2024
1 parent 78f47be commit 16cfd8c
Show file tree
Hide file tree
Showing 6 changed files with 246 additions and 1 deletion.
40 changes: 40 additions & 0 deletions docs/resources/alias.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "typesense_alias Resource - typesense"
subcategory: ""
description: |-
Alias
---

# typesense_alias (Resource)

Alias

## Example Usage

```terraform
resource "typesense_alias" "my_alias" {
name = "my-alias"
collection_name = typesense_collection.my_collection.name
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `collection_name` (String) Collection name
- `name` (String) Name identifier

### Read-Only

- `id` (String) Id identifier

## Import

Import is supported using the following syntax:

```shell
terraform import typesense_alias.my_alias my-alias
```
2 changes: 1 addition & 1 deletion docs/resources/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ resource "typesense_collection" "my_collection" {

- `default_sorting_field` (String) Default sorting field
- `enable_nested_fields` (Boolean) Enable nested fields, must be enabled to use object/object[] types
- `fields` (Block List) (see [below for nested schema](#nestedblock--fields))
- `fields` (Block Set) (see [below for nested schema](#nestedblock--fields))

### Read-Only

Expand Down
1 change: 1 addition & 0 deletions examples/resources/typesense_alias/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import typesense_alias.my_alias my-alias
4 changes: 4 additions & 0 deletions examples/resources/typesense_alias/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "typesense_alias" "my_alias" {
name = "my-alias"
collection_name = typesense_collection.my_collection.name
}
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ func (p *TypesenseProvider) Resources(_ context.Context) []func() resource.Resou
NewCollectionResource,
NewSynonymResource,
NewDocumentResource,
NewAliasResource,
}
}

Expand Down
199 changes: 199 additions & 0 deletions internal/provider/resource_alias.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package provider

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/typesense/typesense-go/typesense"
"github.com/typesense/typesense-go/typesense/api"
)

// Ensure provider defined types fully satisfy framework interfaces.
var _ resource.Resource = &AliasResource{}
var _ resource.ResourceWithImportState = &AliasResource{}

func NewAliasResource() resource.Resource {
return &AliasResource{}
}

type AliasResource struct {
client *typesense.Client
}

type AliasResourceModel struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
CollectionName types.String `tfsdk:"collection_name"`
}

func (r *AliasResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_alias"
}

func (r *AliasResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "An alias is a virtual collection name that points to a real collection. If you're familiar with symbolic links on Linux, it's very similar to that.",

Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Id identifier",
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
"name": schema.StringAttribute{
MarkdownDescription: "Name identifier",
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"collection_name": schema.StringAttribute{
MarkdownDescription: "Collection name",
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
},
}
}

func (r *AliasResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*typesense.Client)

if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)

return
}

r.client = client
}

func (r *AliasResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data AliasResourceModel

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

body := &api.CollectionAliasSchema{CollectionName: data.CollectionName.ValueString()}

alias, err := r.client.Aliases().Upsert(ctx, data.Name.ValueString(), body)

if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create alias, got error: %s", err))
return
}

data.Id = types.StringPointerValue(alias.Name)

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *AliasResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data AliasResourceModel

// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

alias, err := r.client.Alias(data.Id.ValueString()).Retrieve(ctx)

if err != nil {
if strings.Contains(err.Error(), "Not Found") {
resp.State.RemoveResource(ctx)
resp.Diagnostics.AddWarning("Resource Not Found", fmt.Sprintf("Unable to find alias %s, removing from state", data.Id.ValueString()))
} else {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to retrieve alias, got error: %s", err))
}

return
}

data.Name = types.StringPointerValue(alias.Name)
data.CollectionName = types.StringValue(alias.CollectionName)

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *AliasResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data AliasResourceModel

// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

body := &api.CollectionAliasSchema{CollectionName: data.CollectionName.ValueString()}

alias, err := r.client.Aliases().Upsert(ctx, data.Name.ValueString(), body)

if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create alias, got error: %s", err))
return
}

data.Name = types.StringPointerValue(alias.Name)
data.CollectionName = types.StringValue(alias.CollectionName)

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r *AliasResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data AliasResourceModel

// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

tflog.Warn(ctx, "###Delete alias with id="+data.Id.ValueString())

_, err := r.client.Alias(data.Id.ValueString()).Delete(ctx)

if err != nil {
if strings.Contains(err.Error(), "Not Found") {
resp.State.RemoveResource(ctx)
} else {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete alias, got error: %s", err))
}

return
}

data.Id = types.StringValue("")
}

func (r *AliasResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}

0 comments on commit 16cfd8c

Please sign in to comment.