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

add support for automatically generating query lambda tags #111

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
55 changes: 55 additions & 0 deletions docs/resources/query_lambda_auto_tag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "rockset_query_lambda_auto_tag Resource - rockset"
subcategory: ""
description: |-
Automatically tags a Query Lambda using a name template, which must contain %s, that is replaced with an ever increasing number.
~> On resource delete it will remove all old tags that it created.
---

# rockset_query_lambda_auto_tag (Resource)

Automatically tags a Query Lambda using a name template, which must contain %s, that is replaced with an ever increasing number.

~> On resource delete it will remove all old tags that it created.

## Example Usage

```terraform
resource "rockset_query_lambda" "top-movies" {
name = "top_movies"
workspace = "commons"
sql {
query = file("${path.module}/data/top_movies.sql")
}
}

resource "rockset_query_lambda_auto_tag" "active" {
template = "v%s"
max_tags = 3
query_lambda = rockset_query_lambda.top-movies.name
workspace = rockset_query_lambda.top-movies.workspace
version = rockset_query_lambda.top-movies.version
}
```

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

### Required

- `query_lambda` (String) Unique identifier for the query lambda.
- `template` (String) Template for the tag `name`. Can contain alphanumeric or dash characters. Use `%s` to insert the version.
- `version` (String) Version of the query lambda this tag should point to.
- `workspace` (String) The name of the workspace the query lambda is in.

### Optional

- `max_tags` (Number) Maximum number of previous auto-generated tags to keep.

### Read-Only

- `id` (String) The ID of this resource.
- `name` (String) Unique identifier for the tag, generated from the `template` and `tag_version`.
- `tag_version` (Number) Auto-incremented version number for the tag `name`. Starts at 1 when the tag is created and is incremented every time the tag is updated.
- `tags` (List of String) List of previous auto-generated tags that are kept in accordance with `max_tags`.
15 changes: 15 additions & 0 deletions examples/resources/rockset_query_lambda_auto_tag/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
resource "rockset_query_lambda" "top-movies" {
name = "top_movies"
workspace = "commons"
sql {
query = file("${path.module}/data/top_movies.sql")
}
}

resource "rockset_query_lambda_auto_tag" "active" {
template = "v%s"
max_tags = 3
query_lambda = rockset_query_lambda.top-movies.name
workspace = rockset_query_lambda.top-movies.workspace
version = rockset_query_lambda.top-movies.version
}
51 changes: 26 additions & 25 deletions rockset/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,32 @@ func Provider() *schema.Provider {
schema.DescriptionKind = schema.StringMarkdown
return &schema.Provider{
ResourcesMap: map[string]*schema.Resource{
"rockset_alias": resourceAlias(),
"rockset_api_key": resourceApiKey(),
"rockset_autoscaling_policy": resourceAutoScalingPolicy(),
"rockset_collection": resourceCollection(),
"rockset_collection_mount": resourceCollectionMount(),
"rockset_dynamodb_collection": resourceDynamoDBCollection(),
"rockset_dynamodb_integration": resourceDynamoDBIntegration(),
"rockset_gcs_collection": resourceGCSCollection(),
"rockset_gcs_integration": resourceGCSIntegration(),
"rockset_kafka_collection": resourceKafkaCollection(),
"rockset_kafka_integration": resourceKafkaIntegration(),
"rockset_kinesis_collection": resourceKinesisCollection(),
"rockset_kinesis_integration": resourceKinesisIntegration(),
"rockset_mongodb_collection": resourceMongoDBCollection(),
"rockset_mongodb_integration": resourceMongoDBIntegration(),
"rockset_query_lambda": resourceQueryLambda(),
"rockset_query_lambda_tag": resourceQueryLambdaTag(),
"rockset_role": resourceRole(),
"rockset_s3_collection": resourceS3Collection(),
"rockset_s3_integration": resourceS3Integration(),
"rockset_user": resourceUser(),
"rockset_view": resourceView(),
"rockset_virtual_instance": resourceVirtualInstance(),
"rockset_workspace": resourceWorkspace(),
"rockset_scheduled_lambda": resourceScheduledLambda(),
"rockset_alias": resourceAlias(),
"rockset_api_key": resourceApiKey(),
"rockset_autoscaling_policy": resourceAutoScalingPolicy(),
"rockset_collection": resourceCollection(),
"rockset_collection_mount": resourceCollectionMount(),
"rockset_dynamodb_collection": resourceDynamoDBCollection(),
"rockset_dynamodb_integration": resourceDynamoDBIntegration(),
"rockset_gcs_collection": resourceGCSCollection(),
"rockset_gcs_integration": resourceGCSIntegration(),
"rockset_kafka_collection": resourceKafkaCollection(),
"rockset_kafka_integration": resourceKafkaIntegration(),
"rockset_kinesis_collection": resourceKinesisCollection(),
"rockset_kinesis_integration": resourceKinesisIntegration(),
"rockset_mongodb_collection": resourceMongoDBCollection(),
"rockset_mongodb_integration": resourceMongoDBIntegration(),
"rockset_query_lambda": resourceQueryLambda(),
"rockset_query_lambda_tag": resourceQueryLambdaTag(),
"rockset_query_lambda_auto_tag": resourceQueryLambdaAutoTag(),
"rockset_role": resourceRole(),
"rockset_s3_collection": resourceS3Collection(),
"rockset_s3_integration": resourceS3Integration(),
"rockset_user": resourceUser(),
"rockset_view": resourceView(),
"rockset_virtual_instance": resourceVirtualInstance(),
"rockset_workspace": resourceWorkspace(),
"rockset_scheduled_lambda": resourceScheduledLambda(),
},
DataSourcesMap: map[string]*schema.Resource{
"rockset_account": dataSourceRocksetAccount(),
Expand Down
229 changes: 229 additions & 0 deletions rockset/resource_query_lambda_auto_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package rockset

import (
"context"
"errors"
"regexp"
"strconv"
"strings"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/rockset/rockset-go-client"
rockerr "github.com/rockset/rockset-go-client/errors"
)

func resourceQueryLambdaAutoTag() *schema.Resource {
percentS := regexp.MustCompile("%s")

return &schema.Resource{
Description: `Automatically tags a Query Lambda using a name template, which must contain %s, that is replaced with an ever increasing number.

~> On resource delete it will remove all old tags that it created.`,

CreateContext: resourceQueryLambdaAutoTagCreate,
ReadContext: resourceQueryLambdaAutoTagRead,
DeleteContext: resourceQueryLambdaAutoTagDelete,
UpdateContext: resourceQueryLambdaTagUpdate,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"name": {
Description: "Unique identifier for the tag, generated from the `template` and `tag_version`.",
Type: schema.TypeString,
Computed: true,
},
"template": {
Description: "Template for the tag `name`. Can contain alphanumeric or dash characters. Use `%s` to insert the version.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringMatch(percentS, "must contain %s"),
},
"tag_version": {
Description: "Auto-incremented version number for the tag `name`. Starts at 1 when the tag is created and is incremented every time the tag is updated.",
Type: schema.TypeInt,
Computed: true,
},
"max_tags": {
Description: "Maximum number of previous auto-generated tags to keep.",
Type: schema.TypeInt,
Optional: true,
Default: 5,
ValidateFunc: validation.IntBetween(1, 20),
},
"workspace": {
Description: "The name of the workspace the query lambda is in.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"query_lambda": {
Description: "Unique identifier for the query lambda.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: rocksetNameValidator,
},
"version": {
Description: "Version of the query lambda this tag should point to.",
Type: schema.TypeString,
Required: true,
ValidateFunc: rocksetNameValidator,
},
"tags": {
Description: "List of previous auto-generated tags that are kept in accordance with `max_tags`.",
Type: schema.TypeList,
Computed: true,
// this is used to keep track of the tags that were created by this resource, so they can be deleted on destroy
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func resourceQueryLambdaAutoTagCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
rc := meta.(*rockset.RockClient)
var diags diag.Diagnostics

workspace := d.Get("workspace").(string)
template := d.Get("template").(string)
tagName := strings.ReplaceAll(template, "%s", "1")
version := d.Get("version").(string)
queryLambdaName := d.Get("query_lambda").(string)

d.SetId(toQueryLambdaTagID(workspace, queryLambdaName, template))
_ = d.Set("tag_version", 1)
_ = d.Set("name", tagName)
_ = d.Set("tags", []string{}) // the current tag is not included in the list of old tags

_, err := rc.CreateQueryLambdaTag(ctx, workspace, queryLambdaName, version, tagName)
if err != nil {
return DiagFromErr(err)
}
tflog.Info(ctx, "Created query lambda auto tag", map[string]interface{}{
"workspace": workspace,
"name": queryLambdaName,
"tag": tagName,
"version": version,
})

return diags
}

func resourceQueryLambdaTagUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
rc := meta.(*rockset.RockClient)
var diags diag.Diagnostics

workspace, queryLambdaName, template := fromQueryLambdaTagID(d.Id())
tagVersion := d.Get("tag_version").(int)
oldTagName := strings.ReplaceAll(template, "%s", strconv.Itoa(tagVersion))
tagVersion++
tagName := strings.ReplaceAll(template, "%s", strconv.Itoa(tagVersion))
version := d.Get("version").(string)

maxTags := d.Get("max_tags").(int)
tags := toStringArray(d.Get("tags").([]interface{}))

var err error
if len(tags) >= maxTags {
// remove the oldest tag so we make room for the new one
oldest := tags[0]
if err = rc.DeleteQueryLambdaTag(ctx, workspace, queryLambdaName, oldest); err != nil {
return diag.Errorf("failed to delete oldest tag %s.%s %s: %v", workspace, queryLambdaName, oldest, err)
}
tflog.Debug(ctx, "Deleted oldest query lambda auto tag", map[string]interface{}{
"workspace": workspace,
"name": queryLambdaName,
"tag": oldest,
})
tags = tags[1:]
}

if _, err = rc.CreateQueryLambdaTag(ctx, workspace, queryLambdaName, version, tagName); err != nil {
return DiagFromErr(err)
}
_ = d.Set("tag_version", tagVersion)
_ = d.Set("name", tagName)
tags = append(tags, oldTagName)
_ = d.Set("tags", tags)

tflog.Info(ctx, "Updated query lambda auto tag", map[string]interface{}{
"workspace": workspace,
"name": queryLambdaName,
"tag": tagName,
"version": version,
"tags": tags,
})

return diags
}

func resourceQueryLambdaAutoTagRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
rc := meta.(*rockset.RockClient)
var diags diag.Diagnostics

workspace, queryLambdaName, template := fromQueryLambdaTagID(d.Id())
tagVersion := d.Get("tag_version").(int)
tagName := strings.ReplaceAll(template, "%s", strconv.Itoa(tagVersion))

queryLambdaTag, err := rc.GetQueryLambdaVersionByTag(ctx, workspace, queryLambdaName, tagName)
if err != nil {
return checkForNotFoundError(d, err)
}

err = parseQueryLambdaTag(&queryLambdaTag, d)
if err != nil {
return DiagFromErr(err)
}

return diags
}

func resourceQueryLambdaAutoTagDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
rc := meta.(*rockset.RockClient)
var diags diag.Diagnostics

workspace, queryLambdaName, template := fromQueryLambdaTagID(d.Id())
tagVersion := d.Get("tag_version").(int)
tagName := strings.ReplaceAll(template, "%s", strconv.Itoa(tagVersion))

err := rc.DeleteQueryLambdaTag(ctx, workspace, queryLambdaName, tagName)
if err != nil {
return diag.Errorf("failed to delete query lambda auto tag %s.%s:%s: %v", workspace, queryLambdaName, tagName, err)
}
tflog.Info(ctx, "Created query lambda auto tag", map[string]interface{}{
"workspace": workspace,
"name": queryLambdaName,
"tag": tagName,
"version": tagVersion,
})

tags := toStringArray(d.Get("tags").([]interface{}))
for _, tag := range tags {
if err = rc.DeleteQueryLambdaTag(ctx, workspace, queryLambdaName, tag); err != nil {
var re rockerr.Error
if errors.As(err, &re) && re.IsNotFoundError() {
// we ignore not found errors, as the tag is already gone and we want it gone
tflog.Error(ctx, "Failed to delete old tag", map[string]interface{}{
"workspace": workspace,
"name": queryLambdaName,
"tag": tag,
"error": err,
})
continue
}

return diag.Errorf("failed to delete old tag %s: %v", tag, err)
}
}

return diags
}
Loading
Loading