Skip to content

Commit

Permalink
feat(eventstream): add definition support (#216)
Browse files Browse the repository at this point in the history
# 📥 Pull Request

close #159
close #160

## ❓ What are you trying to address

Add definition support to the Eventstream
  • Loading branch information
DariuszPorowski authored Jan 30, 2025
1 parent b10f459 commit c943bf3
Show file tree
Hide file tree
Showing 15 changed files with 474 additions and 93 deletions.
5 changes: 5 additions & 0 deletions .changes/unreleased/added-20250125-122542.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: added
body: Definition support in the `fabric_eventstream` Resource
time: 2025-01-25T12:25:42.2660272+01:00
custom:
Issue: "159"
5 changes: 5 additions & 0 deletions .changes/unreleased/added-20250125-122543.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: added
body: Definition support in the `fabric_eventstream` Data-Source
time: 2025-01-25T12:25:43.2660272+01:00
custom:
Issue: "160"
45 changes: 42 additions & 3 deletions docs/data-sources/eventstream.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ description: |-
Get a Fabric Eventstream.
Use this data source to fetch a Eventstream https://learn.microsoft.com/fabric/real-time-intelligence/event-streams/overview.
-> This item supports Service Principal authentication.
~> This data-source is in preview. To access it, you must explicitly enable the preview mode in the provider level configuration.
---

# fabric_eventstream (Data Source)
Expand All @@ -16,17 +17,40 @@ Use this data source to fetch a [Eventstream](https://learn.microsoft.com/fabric

-> This item supports Service Principal authentication.

~> This data-source is in **preview**. To access it, you must explicitly enable the `preview` mode in the provider level configuration.

## Example Usage

```terraform
# Get item details by name
data "fabric_eventstream" "example_by_name" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
}
# Get item details by id
data "fabric_eventstream" "example_by_id" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
}
data "fabric_eventstream" "example_by_name" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
# Get item details with definition
# Examples uses `id` but `display_name` can be used as well
data "fabric_eventstream" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
format = "Default"
output_definition = true
}
# Access the content of the definition with JSONPath expression
output "example_definition_content_jsonpath" {
value = provider::fabric::content_decode(data.fabric_eventstream.example_definition.definition["eventstream.json"].content, ".destinations[0].properties")
}
# Access the content of the definition as JSON object
output "example_definition_content_object" {
value = provider::fabric::content_decode(data.fabric_eventstream.example_definition.definition["eventstream.json"].content).destinations[0].properties
}
# This is an invalid data source
Expand All @@ -48,11 +72,17 @@ data "fabric_eventstream" "example_by_name" {
### Optional

- `display_name` (String) The Eventstream display name.
- `format` (String) The Eventstream format. Possible values: `Default`
- `id` (String) The Eventstream ID.
- `output_definition` (Boolean) Output definition parts as gzip base64 content? Default: `false`

!> Your terraform state file may grow a lot if you output definition content. Only use it when you must use data from the definition.

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

### Read-Only

- `definition` (Attributes Map) Definition parts. Possible path keys: **Default** format: `eventstream.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Eventstream description.

<a id="nestedatt--timeouts"></a>
Expand All @@ -62,3 +92,12 @@ data "fabric_eventstream" "example_by_name" {
Optional:

- `read` (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).

<a id="nestedatt--definition"></a>

### Nested Schema for `definition`

Read-Only:

- `content` (String) Gzip base64 content of definition part.
Use [`provider::fabric::content_decode`](../functions/content_decode.md) function to decode content.
56 changes: 56 additions & 0 deletions docs/resources/eventstream.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ description: |-
Manage a Fabric Eventstream.
Use this resource to manage Eventstream https://learn.microsoft.com/fabric/real-time-intelligence/event-streams/overview.
-> This item supports Service Principal authentication.
~> This resource is in preview. To access it, you must explicitly enable the preview mode in the provider level configuration.
---

# fabric_eventstream (Resource)
Expand All @@ -16,13 +17,47 @@ Use this resource to manage [Eventstream](https://learn.microsoft.com/fabric/rea

-> This item supports Service Principal authentication.

~> This resource is in **preview**. To access it, you must explicitly enable the `preview` mode in the provider level configuration.

## Example Usage

```terraform
# Example 1 - Item without definition
resource "fabric_eventstream" "example" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
}
# Example 2 - Item with definition bootstrapping only
resource "fabric_eventstream" "example_definition_bootstrap" {
display_name = "example"
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
format = "Default"
definition = {
"eventstream.json" = {
source = "${local.path}/eventstream.json.tmpl"
}
}
}
# Example 3 - Item with definition update when source or tokens changed
resource "fabric_eventstream" "example_definition_update" {
display_name = "example"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
format = "Default"
definition = {
"eventstream.json" = {
source = "${local.path}/eventstream.json.tmpl"
tokens = {
"LakehouseWorkspaceID" = "11111111-1111-1111-1111-111111111111"
"LakehouseID" = "22222222-2222-2222-2222-222222222222"
}
}
}
}
```

<!-- schema generated by tfplugindocs -->
Expand All @@ -35,13 +70,34 @@ resource "fabric_eventstream" "example" {

### Optional

- `definition` (Attributes Map) Definition parts. Read more about [Eventstream definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/eventstream-definition). Accepted path keys: **Default** format: `eventstream.json` (see [below for nested schema](#nestedatt--definition))
- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
- `description` (String) The Eventstream description.
- `format` (String) The Eventstream format. Possible values: `Default`
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))

### Read-Only

- `id` (String) The Eventstream ID.

<a id="nestedatt--definition"></a>

### Nested Schema for `definition`

Required:

- `source` (String) Path to the file with source of the definition part.

The source content may include placeholders for token substitution. Use the dot with the token name `{{ .TokenName }}`.

Optional:

- `tokens` (Map of String) A map of key/value pairs of tokens substitutes in the source.

Read-Only:

- `source_content_sha256` (String) SHA256 of source's content of definition part.

<a id="nestedatt--timeouts"></a>

### Nested Schema for `timeouts`
Expand Down
27 changes: 24 additions & 3 deletions examples/data-sources/fabric_eventstream/data-source.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
# Get item details by name
data "fabric_eventstream" "example_by_name" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
}

# Get item details by id
data "fabric_eventstream" "example_by_id" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
}

data "fabric_eventstream" "example_by_name" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
# Get item details with definition
# Examples uses `id` but `display_name` can be used as well
data "fabric_eventstream" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
format = "Default"
output_definition = true
}

# Access the content of the definition with JSONPath expression
output "example_definition_content_jsonpath" {
value = provider::fabric::content_decode(data.fabric_eventstream.example_definition.definition["eventstream.json"].content, ".destinations[0].properties")
}

# Access the content of the definition as JSON object
output "example_definition_content_object" {
value = provider::fabric::content_decode(data.fabric_eventstream.example_definition.definition["eventstream.json"].content).destinations[0].properties
}

# This is an invalid data source
Expand Down
32 changes: 32 additions & 0 deletions examples/resources/fabric_eventstream/resource.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,36 @@
# Example 1 - Item without definition
resource "fabric_eventstream" "example" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
}

# Example 2 - Item with definition bootstrapping only
resource "fabric_eventstream" "example_definition_bootstrap" {
display_name = "example"
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
format = "Default"
definition = {
"eventstream.json" = {
source = "${local.path}/eventstream.json.tmpl"
}
}
}

# Example 3 - Item with definition update when source or tokens changed
resource "fabric_eventstream" "example_definition_update" {
display_name = "example"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
format = "Default"
definition = {
"eventstream.json" = {
source = "${local.path}/eventstream.json.tmpl"
tokens = {
"LakehouseWorkspaceID" = "11111111-1111-1111-1111-111111111111"
"LakehouseID" = "22222222-2222-2222-2222-222222222222"
}
}
}
}
26 changes: 19 additions & 7 deletions internal/services/eventstream/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,26 @@ import (
fabcore "github.com/microsoft/fabric-sdk-go/fabric/core"

"github.com/microsoft/terraform-provider-fabric/internal/common"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/fabricitem"
)

const (
ItemName = "Eventstream"
ItemTFName = "eventstream"
ItemsName = "Eventstreams"
ItemsTFName = "eventstreams"
ItemType = fabcore.ItemTypeEventstream
ItemDocsSPNSupport = common.DocsSPNSupported
ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/event-streams/overview"
ItemName = "Eventstream"
ItemTFName = "eventstream"
ItemsName = "Eventstreams"
ItemsTFName = "eventstreams"
ItemType = fabcore.ItemTypeEventstream
ItemDocsSPNSupport = common.DocsSPNSupported
ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/event-streams/overview"
ItemDefinitionEmpty = `{"sources":[],"destinations":[],"streams":[],"operators":[],"compatibilityLevel":"1.0"}`
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/eventstream-definition"
ItemPreview = true
)

var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
{
Type: fabricitem.DefinitionFormatDefault,
API: "",
Paths: []string{"eventstream.json"},
},
}
21 changes: 21 additions & 0 deletions internal/services/eventstream/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,32 @@
package eventstream_test

import (
"testing"

at "github.com/dcarbone/terraform-plugin-framework-utils/v3/acctest"

"github.com/microsoft/terraform-provider-fabric/internal/services/eventstream"
"github.com/microsoft/terraform-provider-fabric/internal/testhelp"
)

const (
itemTFName = eventstream.ItemTFName
itemsTFName = eventstream.ItemsTFName
itemType = eventstream.ItemType
)

func lakehouseResource(t *testing.T, workspaceID string) (resourceHCL, resourceFQN string) {
t.Helper()

resourceHCL = at.CompileConfig(
at.ResourceHeader(testhelp.TypeName("fabric", "lakehouse"), "test"),
map[string]any{
"display_name": testhelp.RandomName(),
"workspace_id": workspaceID,
},
)

resourceFQN = testhelp.ResourceFQN("fabric", "lakehouse", "test")

return resourceHCL, resourceFQN
}
6 changes: 4 additions & 2 deletions internal/services/eventstream/data_eventstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import (
)

func NewDataSourceEventstream() datasource.DataSource {
config := fabricitem.DataSourceFabricItem{
config := fabricitem.DataSourceFabricItemDefinition{
Type: ItemType,
Name: ItemName,
TFName: ItemTFName,
MarkdownDescription: "Get a Fabric " + ItemName + ".\n\n" +
"Use this data source to fetch a [" + ItemName + "](" + ItemDocsURL + ").\n\n" +
ItemDocsSPNSupport,
IsDisplayNameUnique: true,
DefinitionFormats: itemDefinitionFormats,
IsPreview: ItemPreview,
}

return fabricitem.NewDataSourceFabricItem(config)
return fabricitem.NewDataSourceFabricItemDefinition(config)
}
34 changes: 33 additions & 1 deletion internal/services/eventstream/data_eventstream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func TestUnit_EventstreamDataSource(t *testing.T) {
"id": *entity.ID,
},
),
ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`),
ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found`),
},
// read by id
{
Expand Down Expand Up @@ -200,6 +200,7 @@ func TestAcc_EventstreamDataSource(t *testing.T) {
resource.TestCheckResourceAttr(testDataSourceItemFQN, "id", entityID),
resource.TestCheckResourceAttr(testDataSourceItemFQN, "display_name", entityDisplayName),
resource.TestCheckResourceAttr(testDataSourceItemFQN, "description", entityDescription),
resource.TestCheckNoResourceAttr(testDataSourceItemFQN, "definition"),
),
},
// read by name - not found
Expand All @@ -213,5 +214,36 @@ func TestAcc_EventstreamDataSource(t *testing.T) {
),
ExpectError: regexp.MustCompile(common.ErrorReadHeader),
},
// read by id with definition - no format
{
Config: at.CompileConfig(
testDataSourceItemHeader,
map[string]any{
"workspace_id": workspaceID,
"id": entityID,
"output_definition": true,
},
),
ExpectError: regexp.MustCompile("Invalid configuration for attribute format"),
},
// read by id with definition
{
Config: at.CompileConfig(
testDataSourceItemHeader,
map[string]any{
"workspace_id": workspaceID,
"id": entityID,
"output_definition": true,
"format": "Default",
},
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(testDataSourceItemFQN, "workspace_id", workspaceID),
resource.TestCheckResourceAttr(testDataSourceItemFQN, "id", entityID),
resource.TestCheckResourceAttr(testDataSourceItemFQN, "display_name", entityDisplayName),
resource.TestCheckResourceAttr(testDataSourceItemFQN, "description", entityDescription),
resource.TestCheckResourceAttrSet(testDataSourceItemFQN, "definition.eventstream.json.content"),
),
},
}))
}
Loading

0 comments on commit c943bf3

Please sign in to comment.