Skip to content

Commit

Permalink
adds tembo_instance_secrets data source
Browse files Browse the repository at this point in the history
  • Loading branch information
shahadarsh committed Oct 12, 2023
1 parent 7ff1183 commit 45a6d35
Show file tree
Hide file tree
Showing 28 changed files with 3,492 additions and 8 deletions.
33 changes: 33 additions & 0 deletions docs/data-sources/instance_secrets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "tembo_instance_secrets Data Source - terraform-provider-tembo"
subcategory: ""
description: |-
Data Source for Tembo Instance Secrets.
---

# tembo_instance_secrets (Data Source)

Data Source for Tembo Instance Secrets.



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

### Required

- `instance_id` (String) Unique ID for the instance generated by Tembo
- `org_id` (String) Unique ID for the instance generated by Tembo

### Read-Only

- `available_secrets` (Attributes List) (see [below for nested schema](#nestedatt--available_secrets))

<a id="nestedatt--available_secrets"></a>
### Nested Schema for `available_secrets`

Optional:

- `name` (String) Unique ID for the instance generated by Tembo
- `possible_keys` (List of String)
10 changes: 10 additions & 0 deletions examples/resource-creation/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ resource "tembo_instance" "test_db" {
}]
}

data "tembo_instance_secrets" "test" {
org_id = "org_2UdhszNbCVhLAXkZm30nz8pL778"
instance_id = tembo_instance.test_db.instance_id
}


output "instance" {
value = tembo_instance.test_db
}

output "data" {
value = data.tembo_instance_secrets.test
}
3 changes: 2 additions & 1 deletion go.work
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ go 1.20
use (
.
./internal/provider/temboclient
)
./internal/provider/tembodataclient
)
161 changes: 161 additions & 0 deletions internal/provider/instance_secrets_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
tembodataclient "github.com/tembo-io/terraform-provider-tembo/tembodataclient"
)

// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &temboInstanceSecretsDataSource{}
_ datasource.DataSourceWithConfigure = &temboInstanceSecretsDataSource{}
)

// NewTemboInstanceSecretsDataSource is a helper function to simplify the provider implementation.
func NewTemboInstanceSecretsDataSource() datasource.DataSource {
return &temboInstanceSecretsDataSource{}
}

// TemboInstanceSecretsDataSource is the data source implementation.
type temboInstanceSecretsDataSource struct {
temboInstanceSecretsConfig instanceSecretsConfig
}

// Tembo Cluster Configuration.
type instanceSecretsConfig struct {
client *tembodataclient.APIClient
accessToken string
}

// Metadata returns the data source type name.
func (d *temboInstanceSecretsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_instance_secrets"
}

// Schema defines the schema for the data source.
func (d *temboInstanceSecretsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Data Source for Tembo Instance Secrets.",
Attributes: map[string]schema.Attribute{
"org_id": schema.StringAttribute{
MarkdownDescription: "Unique ID for the instance generated by Tembo",
Required: true,
},
"instance_id": schema.StringAttribute{
MarkdownDescription: "Unique ID for the instance generated by Tembo",
Required: true,
},
"available_secrets": schema.ListNestedAttribute{
Computed: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"name": schema.StringAttribute{
MarkdownDescription: "Unique ID for the instance generated by Tembo",
Optional: true,
},
"possible_keys": schema.ListAttribute{
Optional: true,
ElementType: types.StringType,
},
},
},
},
},
}
}

// Configure adds the provider configured client to the data source.
func (d *temboInstanceSecretsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

temboInstanceSecretsConfig, ok := req.ProviderData.(instanceSecretsConfig)

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

return
}

d.temboInstanceSecretsConfig = temboInstanceSecretsConfig
}

// temboInstanceSecretsDataSourceModel maps the data source schema data.
type temboInstanceSecretsDataSourceModel struct {
OrgId types.String `tfsdk:"org_id"`
InstanceId types.String `tfsdk:"instance_id"`
AvailableSecrets []availableSecret `tfsdk:"available_secrets"`
}

// availableSecretsModel maps instanceSecrets schema data.
type availableSecret struct {
// The name of an available secret
Name types.String `tfsdk:"name"`
// For this secret, available keys
PossibleKeys []types.String `tfsdk:"possible_keys"`
}

// Read refreshes the Terraform state with the latest data.
func (d *temboInstanceSecretsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// Get current state
var state temboInstanceSecretsDataSourceModel

ctx = context.WithValue(ctx, tembodataclient.ContextAccessToken, d.temboInstanceSecretsConfig.accessToken)

var orgId string
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("org_id"), &orgId)...)

var instanceId string
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("instance_id"), &instanceId)...)

if resp.Diagnostics.HasError() {
tflog.Error(ctx, fmt.Sprintf("error reading terraform plan %v", resp.Diagnostics.Errors()))
return
}

// Get refreshed Instance value from API
availableSecrets, _, err := d.temboInstanceSecretsConfig.client.SecretsApi.GetSecretNamesV1(ctx, orgId, instanceId).Execute()
if err != nil {
resp.Diagnostics.AddError(
"Unable to Read Tembo Instance Available Secrets",
err.Error(),
)
return
}

if len(availableSecrets) > 0 {
for _, aSecret := range availableSecrets {
state.AvailableSecrets = append(state.AvailableSecrets, availableSecret{Name: types.StringValue(aSecret.Name), PossibleKeys: getPossibleKeys(aSecret.PossibleKeys)})
}
}

// Set refreshed state
diags := resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

func getPossibleKeys(possibleKeys []string) []basetypes.StringValue {
var localPossibleKeys []basetypes.StringValue
if len(possibleKeys) > 0 {
for _, possibleKey := range possibleKeys {
localPossibleKeys = append(localPossibleKeys, types.StringValue(possibleKey))
}
}
return localPossibleKeys
}
56 changes: 50 additions & 6 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
temboclient "github.com/tembo-io/terraform-provider-tembo/temboclient"
tembodataclient "github.com/tembo-io/terraform-provider-tembo/tembodataclient"
)

// Ensure the implementation satisfies the expected interfaces.
Expand Down Expand Up @@ -39,6 +40,7 @@ type temboProvider struct {
// temboProviderModel maps provider schema data to a Go type.
type temboProviderModel struct {
Host types.String `tfsdk:"host"`
DataHost types.String `tfsdk:"data_host"`
AccessToken types.String `tfsdk:"access_token"`
}

Expand All @@ -57,6 +59,10 @@ func (p *temboProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp
MarkdownDescription: "Tembo API the provider should connect to. By default it connects to Tembo Cloud Production API.",
Optional: true,
},
"data_host": schema.StringAttribute{
MarkdownDescription: "Tembo Data API the provider should connect to. By default it connects to Tembo Data Cloud Production API.",
Optional: true,
},
"access_token": schema.StringAttribute{
MarkdownDescription: "Access Token generated using steps [here](https://tembo.io/docs/tembo-cloud/api#create-a-long-lived-api-token).",
Optional: true,
Expand All @@ -81,16 +87,25 @@ func (p *temboProvider) Configure(ctx context.Context, req provider.ConfigureReq
if config.Host.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("host"),
"Unknown tembo API Host",
"The provider cannot create the tembo API client as there is an unknown configuration value for the tembo API host. "+
"Either target apply the source of the value first, set the value statically in the configuration, or use the tembo_HOST environment variable.",
"Unknown Tembo API Host",
"The provider cannot create the tembo API client as there is an unknown configuration value for the tembo API Host. "+
"Either target apply the source of the value first, set the value statically in the configuration, or use the TEMBO_HOST environment variable.",
)
}

if config.Host.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("data_host"),
"Unknown Tembo API Data Host",
"The provider cannot create the tembo API client as there is an unknown configuration value for the Tembo API Data Host. "+
"Either target apply the source of the value first, set the value statically in the configuration, or use the TEMBO_DATA_HOST environment variable.",
)
}

if config.AccessToken.IsUnknown() {
resp.Diagnostics.AddAttributeError(
path.Root("access_token"),
"Unknown tembo API Access Token",
"Unknown Tembo API Access Token",
"The provider cannot create the tembo API client as there is an unknown configuration value for the tembo API password. "+
"Either target apply the source of the value first, set the value statically in the configuration, or use the tembo_PASSWORD environment variable.",
)
Expand All @@ -104,6 +119,7 @@ func (p *temboProvider) Configure(ctx context.Context, req provider.ConfigureReq
// with Terraform configuration value if set.

host := os.Getenv("TEMBO_HOST")
data_host := os.Getenv("TEMBO_DATA_HOST")
access_token := os.Getenv("TEMBO_ACCESS_TOKEN")

if !config.Host.IsNull() {
Expand All @@ -114,6 +130,14 @@ func (p *temboProvider) Configure(ctx context.Context, req provider.ConfigureReq
host = "https://api.coredb.io"
}

if !config.DataHost.IsNull() {
data_host = config.DataHost.ValueString()
}

if data_host == "" {
data_host = "https://api.data-1.use1.tembo.io"
}

if !config.AccessToken.IsNull() {
access_token = config.AccessToken.ValueString()
}
Expand Down Expand Up @@ -159,9 +183,27 @@ func (p *temboProvider) Configure(ctx context.Context, req provider.ConfigureReq
// Create a new tembo client using the configuration values
client := temboclient.NewAPIClient(configuration)

data_configuration := tembodataclient.NewConfiguration()

dataHostUrl, err := url.Parse(data_host)
if err != nil {
panic(err)
}

data_configuration.Scheme = "https"

data_configuration.Host = dataHostUrl.Host

// Create a new tembo data client using the configuration values
dataclient := tembodataclient.NewAPIClient(data_configuration)

// Make the tembo client available during DataSource and Resource
// type Configure methods.
resp.DataSourceData = client
resp.DataSourceData = instanceSecretsConfig{
client: dataclient,
accessToken: access_token,
}

resp.ResourceData = instanceConfig{
client: client,
accessToken: access_token,
Expand All @@ -170,7 +212,9 @@ func (p *temboProvider) Configure(ctx context.Context, req provider.ConfigureReq

// DataSources defines the data sources implemented in the provider.
func (p *temboProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
return []func() datasource.DataSource{
NewTemboInstanceSecretsDataSource,
}
}

// Resources defines the resources implemented in the provider.
Expand Down
2 changes: 1 addition & 1 deletion internal/provider/temboclient/go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/GIT_USER_ID/GIT_REPO_ID
module github.com/tembo-io/terraform-provider-tembo/temboclient

go 1.18

Expand Down
24 changes: 24 additions & 0 deletions internal/provider/tembodataclient/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof
23 changes: 23 additions & 0 deletions internal/provider/tembodataclient/.openapi-generator-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
Loading

0 comments on commit 45a6d35

Please sign in to comment.