Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
95 changes: 95 additions & 0 deletions docs/resources/account_audit_log_sink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "temporalcloud_account_audit_log_sink Resource - terraform-provider-temporalcloud"
subcategory: ""
description: |-
Provisions an account audit log sink.
---

# temporalcloud_account_audit_log_sink (Resource)

Provisions an account audit log sink.

## Example Usage

```terraform
terraform {
required_providers {
temporalcloud = {
source = "temporalio/temporalcloud"
}
}
}

provider "temporalcloud" {

}

# Example with Kinesis
resource "temporalcloud_account_audit_log_sink" "kinesis_sink" {
sink_name = "my-kinesis-sink"
enabled = true
kinesis = {
role_name = "arn:aws:iam::123456789012:role/TemporalCloudKinesisRole"
destination_uri = "arn:aws:kinesis:us-east-1:123456789012:stream/my-audit-stream"
region = "us-east-1"
}
}

# Example with PubSub
resource "temporalcloud_account_audit_log_sink" "pubsub_sink" {
sink_name = "my-pubsub-sink"
enabled = true
pubsub = {
service_account_id = "my-service-account-id"
topic_name = "temporal-audit-logs"
gcp_project_id = "my-gcp-project"
}
}
```

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

### Required

- `sink_name` (String) The unique name of the audit log sink, it can't be changed once set.

### Optional

- `enabled` (Boolean) A flag indicating whether the audit log sink is enabled or not.
- `kinesis` (Attributes) The Kinesis configuration details when destination_type is Kinesis. (see [below for nested schema](#nestedatt--kinesis))
- `pubsub` (Attributes) The PubSub configuration details when destination_type is PubSub. (see [below for nested schema](#nestedatt--pubsub))
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `id` (String) The unique identifier of the account audit log sink.

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

Required:

- `destination_uri` (String) The destination URI of the Kinesis stream where Temporal will send data.
- `region` (String) The region of the Kinesis stream.
- `role_name` (String) The IAM role that Temporal Cloud assumes for writing records to the customer's Kinesis stream.


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

Required:

- `gcp_project_id` (String) The GCP project ID of the PubSub topic and service account.
- `service_account_id` (String) The customer service account ID that Temporal Cloud impersonates for writing records to the customer's PubSub topic.
- `topic_name` (String) The destination PubSub topic name for Temporal.


<a id="nestedblock--timeouts"></a>
### Nested Schema for `timeouts`

Optional:

- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours).
- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
terraform {
required_providers {
temporalcloud = {
source = "temporalio/temporalcloud"
}
}
}

provider "temporalcloud" {

}

# Example with Kinesis
resource "temporalcloud_account_audit_log_sink" "kinesis_sink" {
sink_name = "my-kinesis-sink"
enabled = true
kinesis = {
role_name = "arn:aws:iam::123456789012:role/TemporalCloudKinesisRole"
destination_uri = "arn:aws:kinesis:us-east-1:123456789012:stream/my-audit-stream"
region = "us-east-1"
}
}

# Example with PubSub
resource "temporalcloud_account_audit_log_sink" "pubsub_sink" {
sink_name = "my-pubsub-sink"
enabled = true
pubsub = {
service_account_id = "my-service-account-id"
topic_name = "temporal-audit-logs"
gcp_project_id = "my-gcp-project"
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,5 @@ require (
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace go.temporal.io/cloud-sdk => github.com/temporalio/cloud-sdk-go v0.6.1-0.20251031194819-5117604c8a4f
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: remove this after API update

4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/temporalio/cloud-sdk-go v0.6.1-0.20251031194819-5117604c8a4f h1:i8w+OmC4ocK72/LdwKXnXawHC6CCMHrtzVNYI4+6tGk=
github.com/temporalio/cloud-sdk-go v0.6.1-0.20251031194819-5117604c8a4f/go.mod h1:AueDDyuayosk+zalfrnuftRqnRQTHwD0HYwNgEQc0YE=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
Expand Down Expand Up @@ -238,8 +240,6 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.temporal.io/api v1.53.0 h1:6vAFpXaC584AIELa6pONV56MTpkm4Ha7gPWL2acNAjo=
go.temporal.io/api v1.53.0/go.mod h1:iaxoP/9OXMJcQkETTECfwYq4cw/bj4nwov8b3ZLVnXM=
go.temporal.io/cloud-sdk v0.5.0 h1:6PdA6D8I/PiFLLpYwinre7ffPTct49zhapMAN5rJjmw=
go.temporal.io/cloud-sdk v0.5.0/go.mod h1:AueDDyuayosk+zalfrnuftRqnRQTHwD0HYwNgEQc0YE=
go.temporal.io/sdk v1.36.0 h1:WO9zetpybBNK7xsQth4Z+3Zzw1zSaM9MOUGrnnUjZMo=
go.temporal.io/sdk v1.36.0/go.mod h1:8BxGRF0LcQlfQrLLGkgVajbsKUp/PY7280XTdcKc18Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down
207 changes: 207 additions & 0 deletions internal/provider/account_audit_log_sink_datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/temporalio/terraform-provider-temporalcloud/internal/client"
"github.com/temporalio/terraform-provider-temporalcloud/internal/provider/enums"
internaltypes "github.com/temporalio/terraform-provider-temporalcloud/internal/types"
accountv1 "go.temporal.io/cloud-sdk/api/account/v1"
cloudservicev1 "go.temporal.io/cloud-sdk/api/cloudservice/v1"
)

var (
_ datasource.DataSource = &accountAuditLogSinkDataSource{}
_ datasource.DataSourceWithConfigure = &accountAuditLogSinkDataSource{}
)

func NewAccountAuditLogSinkDataSource() datasource.DataSource {
return &accountAuditLogSinkDataSource{}
}

type (
accountAuditLogSinkDataSource struct {
client *client.Client
}

accountAuditLogSinkDataModel struct {
ID types.String `tfsdk:"id"`
SinkName types.String `tfsdk:"sink_name"`
Enabled types.Bool `tfsdk:"enabled"`
Kinesis types.Object `tfsdk:"kinesis"`
PubSub types.Object `tfsdk:"pubsub"`
State types.String `tfsdk:"state"`
}
)

func accountAuditLogSinkDataSourceSchema(idRequired bool) map[string]schema.Attribute {
idAttribute := schema.StringAttribute{
Description: "The unique identifier of the account audit log sink.",
}

switch idRequired {
case true:
idAttribute.Required = true
case false:
idAttribute.Computed = true
}

return map[string]schema.Attribute{
"id": idAttribute,
"sink_name": schema.StringAttribute{
Description: "The unique name of the audit log sink.",
Required: true,
},
"enabled": schema.BoolAttribute{
Description: "A flag indicating whether the audit log sink is enabled or not.",
Computed: true,
},
"kinesis": schema.SingleNestedAttribute{
Description: "The Kinesis configuration details when destination_type is Kinesis.",
Computed: true,
Attributes: map[string]schema.Attribute{
"role_name": schema.StringAttribute{
Description: "The IAM role that Temporal Cloud assumes for writing records to the customer's Kinesis stream.",
Computed: true,
},
"destination_uri": schema.StringAttribute{
Description: "The destination URI of the Kinesis stream where Temporal will send data.",
Computed: true,
},
"region": schema.StringAttribute{
Description: "The region of the Kinesis stream.",
Computed: true,
},
},
},
"pubsub": schema.SingleNestedAttribute{
Description: "The PubSub configuration details when destination_type is PubSub.",
Computed: true,
Attributes: map[string]schema.Attribute{
"service_account_id": schema.StringAttribute{
Description: "The customer service account ID that Temporal Cloud impersonates for writing records to the customer's PubSub topic.",
Computed: true,
},
"topic_name": schema.StringAttribute{
Description: "The destination PubSub topic name for Temporal.",
Computed: true,
},
"gcp_project_id": schema.StringAttribute{
Description: "The GCP project ID of the PubSub topic and service account.",
Computed: true,
},
},
},
"state": schema.StringAttribute{
Description: "The current state of the audit log sink.",
Computed: true,
},
}
}

func (d *accountAuditLogSinkDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_account_audit_log_sink"
}

func (d *accountAuditLogSinkDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

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

d.client = client
}

func (d *accountAuditLogSinkDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: "Fetches details about an account audit log sink.",
Attributes: accountAuditLogSinkDataSourceSchema(true),
}
}

func (d *accountAuditLogSinkDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var input accountAuditLogSinkDataModel
resp.Diagnostics.Append(req.Config.Get(ctx, &input)...)
if resp.Diagnostics.HasError() {
return
}

if len(input.SinkName.ValueString()) == 0 {
resp.Diagnostics.AddError("invalid account audit log sink sink_name", "account audit log sink sink_name is required")
return
}

auditLogSinkResp, err := d.client.CloudService().GetAccountAuditLogSink(ctx, &cloudservicev1.GetAccountAuditLogSinkRequest{
Name: input.SinkName.ValueString(),
})
if err != nil {
resp.Diagnostics.AddError("Failed to get account audit log sink", err.Error())
return
}

model, diags := accountAuditLogSinkToAccountAuditLogSinkDataModel(ctx, auditLogSinkResp.GetSink())
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

diags = resp.State.Set(ctx, model)
resp.Diagnostics.Append(diags...)
}

func accountAuditLogSinkToAccountAuditLogSinkDataModel(ctx context.Context, auditLogSink *accountv1.AuditLogSink) (*accountAuditLogSinkDataModel, diag.Diagnostics) {
var diags diag.Diagnostics
stateStr, err := enums.FromResourceState(auditLogSink.State)
if err != nil {
diags.AddError("Failed to convert resource state", err.Error())
return nil, diags
}

model := new(accountAuditLogSinkDataModel)
model.ID = types.StringValue(auditLogSink.GetName())
model.SinkName = types.StringValue(auditLogSink.GetName())
model.Enabled = types.BoolValue(auditLogSink.GetSpec().GetEnabled())
model.State = types.StringValue(stateStr)

kinesisObj := types.ObjectNull(internaltypes.KinesisSpecModelAttrTypes)
if auditLogSink.GetSpec().GetKinesisSink() != nil {
kinesisSpec := internaltypes.KinesisSpecModel{
RoleName: types.StringValue(auditLogSink.GetSpec().GetKinesisSink().GetRoleName()),
DestinationUri: types.StringValue(auditLogSink.GetSpec().GetKinesisSink().GetDestinationUri()),
Region: types.StringValue(auditLogSink.GetSpec().GetKinesisSink().GetRegion()),
}

kinesisObj, diags = types.ObjectValueFrom(ctx, internaltypes.KinesisSpecModelAttrTypes, kinesisSpec)
if diags.HasError() {
return nil, diags
}
}

pubsubObj := types.ObjectNull(internaltypes.PubSubSpecModelAttrTypes)
if auditLogSink.GetSpec().GetPubSubSink() != nil {
pubsubSpec := internaltypes.PubSubSpecModel{
ServiceAccountId: types.StringValue(auditLogSink.GetSpec().GetPubSubSink().GetServiceAccountId()),
TopicName: types.StringValue(auditLogSink.GetSpec().GetPubSubSink().GetTopicName()),
GcpProjectId: types.StringValue(auditLogSink.GetSpec().GetPubSubSink().GetGcpProjectId()),
}

pubsubObj, diags = types.ObjectValueFrom(ctx, internaltypes.PubSubSpecModelAttrTypes, pubsubSpec)
if diags.HasError() {
return nil, diags
}
}

model.Kinesis = kinesisObj
model.PubSub = pubsubObj
return model, diags
}
Loading
Loading