Skip to content

Commit

Permalink
Add streaming tenant tokens datasource (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
emerkle826 authored Nov 17, 2022
1 parent ec9e325 commit db9c1d1
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 14 deletions.
61 changes: 61 additions & 0 deletions docs/data-sources/streaming_tenant_tokens.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astra_streaming_tenant_tokens Data Source - terraform-provider-astra"
subcategory: ""
description: |-
astra_streaming_tenant_tokens provides a datasource that lists streaming tenant tokens.
---

# astra_streaming_tenant_tokens (Data Source)

`astra_streaming_tenant_tokens` provides a datasource that lists streaming tenant tokens.

## Example Usage

```terraform
data "astra_streaming_tenant_tokens" "tokens" {
tenant_name = "mytenant"
cluster_name = "pulsar-gcp-useast4"
}
// Example referencing astra_streaming_tenant
resource "astra_streaming_tenant" "tenant" {
tenant_name = "mytenant"
topic = "topic1"
region = "us-east4"
cloud_provider = "gcp"
user_email = "user@example.com"
}
data "astra_streaming_tenant_tokens" "tokens" {
tenant_name = astra_streaming_tenant.tenant.tenant_name
cluster_name = astra_streaming_tenant.tenant.cluster_name
}
```

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

### Required

- `cluster_name` (String) Name of the Pulsar Cluster. Format: `pulsar-<cloud provider>-<cloud region>`. Example: `pulsar-gcp-useast1`
- `tenant_name` (String) Name of the streaming tenant for which to fetch tokens.

### Read-Only

- `id` (String) The ID of this resource.
- `tokens` (List of Object) The list of tokens for the specified tenant. (see [below for nested schema](#nestedatt--tokens))

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

Read-Only:

- `iat` (Number)
- `iss` (String)
- `sub` (String)
- `token` (String)
- `token_id` (String)


3 changes: 2 additions & 1 deletion docs/resources/streaming_tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ resource "astra_streaming_tenant" "streaming_tenant-1" {
### Read-Only

- `broker_service_url` (String) The Pulsar Binary Protocol URL used for production and consumption of messages.
- `cluster_name` (String) Pulsar cluster name.
- `id` (String) The ID of this resource.
- `pulsar_token` (String, Sensitive) The JWT token used for authentication in all Astra Streaming operations.
- `tenant_id` (String) UUID for the tenant.
- `user_metrics_url` (String) URL for metrics.
- `web_service_url` (String) URL used for administrative operations.
- `web_socket_query_param_url` (String) URL used for web socket query parameter operations.
Expand Down
19 changes: 19 additions & 0 deletions examples/data-sources/astra_streaming_tenant_tokens/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
data "astra_streaming_tenant_tokens" "tokens" {
tenant_name = "mytenant"
cluster_name = "pulsar-gcp-useast4"
}


// Example referencing astra_streaming_tenant
resource "astra_streaming_tenant" "tenant" {
tenant_name = "mytenant"
topic = "topic1"
region = "us-east4"
cloud_provider = "gcp"
user_email = "user@example.com"
}

data "astra_streaming_tenant_tokens" "tokens" {
tenant_name = astra_streaming_tenant.tenant.tenant_name
cluster_name = astra_streaming_tenant.tenant.cluster_name
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/datastax/terraform-provider-astra/v2
go 1.18

require (
github.com/datastax/astra-client-go/v2 v2.2.43
github.com/datastax/astra-client-go/v2 v2.2.44
github.com/google/uuid v1.3.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-retryablehttp v0.7.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/datastax/astra-client-go/v2 v2.2.43 h1:sisgeDHhwLAasmW2O64+o7lHqDqeChg9rl7nYNDArO4=
github.com/datastax/astra-client-go/v2 v2.2.43/go.mod h1:6hGGp0A29qfgnhtMZm3GT16hDt7cQqTAJHHR6T5bQH8=
github.com/datastax/astra-client-go/v2 v2.2.44 h1:EIOGsqVHV4Rq3ti3ik3nk0ZuADVqaWl/BJmIlcOzXhU=
github.com/datastax/astra-client-go/v2 v2.2.44/go.mod h1:6hGGp0A29qfgnhtMZm3GT16hDt7cQqTAJHHR6T5bQH8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
129 changes: 129 additions & 0 deletions internal/provider/data_source_streaming_tenant_tokens.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package provider

import (
"context"
"fmt"
"net/http"

astrastreaming "github.com/datastax/astra-client-go/v2/astra-streaming"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceStreamingTenantTokens() *schema.Resource {
return &schema.Resource {
Description: "`astra_streaming_tenant_tokens` provides a datasource that lists streaming tenant tokens.",

ReadContext: dataSourceStreamingTenantTokensRead,

Schema: map[string]*schema.Schema{
// Required
"cluster_name": {
Description: "Name of the Pulsar Cluster. Format: `pulsar-<cloud provider>-<cloud region>`. Example: `pulsar-gcp-useast1`",
Type: schema.TypeString,
Required: true,
},
"tenant_name": {
Description: "Name of the streaming tenant for which to fetch tokens.",
Type: schema.TypeString,
Required: true,
},
// Computed
"tokens": {
Type: schema.TypeList,
Description: "The list of tokens for the specified tenant.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"iat": {
Description: "IAT of the token.",
Type: schema.TypeInt,
Computed: true,
},
"iss": {
Description: "ISS of the token.",
Type: schema.TypeString,
Computed: true,
},
"sub": {
Description: "Client subscriber of the token.",
Type: schema.TypeString,
Computed: true,
},
"token_id": {
Description: "ID of the token.",
Type: schema.TypeString,
Computed: true,
},
"token": {
Description: "Pulsar JWT token.",
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},
},
},
},
},
}
}

func dataSourceStreamingTenantTokensRead (ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
streamingClient := meta.(astraClients).astraStreamingClient.(*astrastreaming.ClientWithResponses)

tenantName := d.Get("tenant_name").(string)
clusterName := d.Get("cluster_name").(string)

params := astrastreaming.IdListTenantTokensParams{
XDataStaxPulsarCluster: clusterName,
}
tokenResponse, err := streamingClient.IdListTenantTokensWithResponse(ctx, tenantName, &params)

if err != nil {
return diag.FromErr(err)
}

if tokenResponse.StatusCode() != http.StatusOK {
return diag.Errorf("Failed to get list of tenants. ResponseCode: %d, message = %s.", tokenResponse.StatusCode(), string(tokenResponse.Body))
}

if err := setTenantTokensData(ctx, d, streamingClient, *tokenResponse.JSON200); err != nil {
return diag.FromErr(err)
}

d.SetId(tenantName)

return nil
}

func setTenantTokensData(ctx context.Context, d *schema.ResourceData, streamingClient *astrastreaming.ClientWithResponses, tokenList []astrastreaming.TenantToken) error {
tenantName := d.Get("tenant_name").(string)
clusterName := d.Get("cluster_name").(string)
params := astrastreaming.GetTokenByIDParams{
XDataStaxPulsarCluster: clusterName,
}
tokens := make([]map[string]interface{}, 0, len(tokenList))
for _, token := range tokenList {
tokenMap := map[string]interface{} {
"token_id" : token.TokenID,
"iat" : token.Iat,
"iss" : token.Iss,
"sub" : token.Sub,
}
// now fetch the JWT token
tokenResponse, err := streamingClient.GetTokenByIDWithResponse(ctx, tenantName, *token.TokenID, &params)
if err != nil {
return err
}
if tokenResponse.StatusCode() != http.StatusOK {
return fmt.Errorf("Failed to fetch token by ID. Token ID: %s, Tenant Name: %s, Cluster Name: %s.", *token.TokenID, tenantName, clusterName)
}
tokenMap["token"] = string(tokenResponse.Body)
tokens = append(tokens, tokenMap)
}
if err := d.Set("tokens", tokens); err != nil {
return err
}

return nil
}
4 changes: 3 additions & 1 deletion internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package provider
import (
"context"
"fmt"
"net/http"

astrarestapi "github.com/datastax/astra-client-go/v2/astra-rest-api"
astrastreaming "github.com/datastax/astra-client-go/v2/astra-streaming"
"net/http"

"github.com/datastax/astra-client-go/v2/astra"
"github.com/hashicorp/go-retryablehttp"
Expand Down Expand Up @@ -45,6 +46,7 @@ func New(version string) func() *schema.Provider {
"astra_role": dataSourceRole(),
"astra_roles": dataSourceRoles(),
"astra_users": dataSourceUsers(),
"astra_streaming_tenant_tokens": dataSourceStreamingTenantTokens(),
},
ResourcesMap: map[string]*schema.Resource{
"astra_database": resourceDatabase(),
Expand Down
41 changes: 32 additions & 9 deletions internal/provider/resource_streaming_tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,22 @@ func resourceStreamingTenant() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"pulsar_token": {
Description: "The JWT token used for authentication in all Astra Streaming operations.",
"cluster_name": {
Description: "Pulsar cluster name.",
Type: schema.TypeString,
Sensitive: true,
Computed: true,
},
// The fields below are only filled in after creating the tenant and then retrieving the tenant info from the DevOps API
"user_metrics_url": {
Description: "URL for metrics.",
Type: schema.TypeString,
Computed: true,
},
"tenant_id": {
Description: "UUID for the tenant.",
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand Down Expand Up @@ -203,7 +208,7 @@ func resourceStreamingTenantRead(ctx context.Context, resourceData *schema.Resou
diag.FromErr(err)
}
if !strings.HasPrefix(getTenantResponse.HTTPResponse.Status, "2") {
tflog.Info(ctx, fmt.Sprintf("Tenant not found with ID: %s", tenantID))
tflog.Info(ctx, fmt.Sprintf("Tenant not found with Name: %s", tenantID))
resourceData.SetId("")
return nil
}
Expand Down Expand Up @@ -289,8 +294,16 @@ func resourceStreamingTenantCreate(ctx context.Context, resourceData *schema.Res
return diag.Errorf("Error creating tenant. Status Code: %d, Message: %s", tenantCreationResponse.StatusCode(), string(tenantCreationResponse.Body))
}

streamingTenant := *tenantCreationResponse.JSON200
setStreamingTenantData(ctx, resourceData, streamingTenant)
// Now let's fetch the tenant again so that it fills in the missing fields (like userMetricsUrl and tenant ID)
streamingTenantResponse, err := streamingClient.GetStreamingTenantWithResponse(ctx, org.ID, tenantName)
if err != nil{
diag.FromErr(err)
}
if streamingTenantResponse.StatusCode() != http.StatusOK {
return diag.Errorf("Unexpected response fetching tenant: %s. Response code: %d, message = %s", tenantName, streamingTenantResponse.StatusCode(), string(streamingTenantResponse.Body))
}

setStreamingTenantData(ctx, resourceData, *streamingTenantResponse.JSON200)

return nil
}
Expand All @@ -307,7 +320,7 @@ func setStreamingTenantData(ctx context.Context, d *schema.ResourceData, tenantR
if err := d.Set("web_service_url", *tenantResponse.AdminURL); err != nil {
return err
}
if err := d.Set("pulsar_token", *tenantResponse.TenantPulsarToken); err != nil {
if err := d.Set("cluster_name", *tenantResponse.ClusterName); err != nil {
return err
}
if err := d.Set("web_socket_url", *tenantResponse.WebsocketURL); err != nil {
Expand All @@ -316,8 +329,18 @@ func setStreamingTenantData(ctx context.Context, d *schema.ResourceData, tenantR
if err := d.Set("web_socket_query_param_url", *tenantResponse.WebsocketQueryParamURL); err != nil {
return err
}
if err:= d.Set("user_metrics_url", *&tenantResponse.UserMetricsURL); err != nil {
return err
// only set these if they aren't nil or empty
metricsUrl := *tenantResponse.UserMetricsURL
if len(metricsUrl) > 0 {
if err := d.Set("user_metrics_url", metricsUrl); err != nil {
return err
}
}
tennantId := *&tenantResponse.Id
if len(*tennantId) > 0 {
if err := d.Set("tenant_id", tennantId); err != nil {
return err
}
}
return nil
}
Expand Down

0 comments on commit db9c1d1

Please sign in to comment.