diff --git a/.changes/unreleased/added-20250125-145244.yaml b/.changes/unreleased/added-20250125-145244.yaml
new file mode 100644
index 00000000..4e290dbd
--- /dev/null
+++ b/.changes/unreleased/added-20250125-145244.yaml
@@ -0,0 +1,5 @@
+kind: added
+body: "New Resource: `fabric_kql_queryset`"
+time: 2025-01-25T14:52:44.1990994+01:00
+custom:
+ Issue: "130"
diff --git a/.changes/unreleased/added-20250125-145341.yaml b/.changes/unreleased/added-20250125-145341.yaml
new file mode 100644
index 00000000..d522f1d9
--- /dev/null
+++ b/.changes/unreleased/added-20250125-145341.yaml
@@ -0,0 +1,5 @@
+kind: added
+body: Definition support in the `fabric_kql_queryset` Data-Source
+time: 2025-01-25T14:53:41.6482592+01:00
+custom:
+ Issue: "131"
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a7bb8868..6f73fc3f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -324,7 +324,7 @@ jobs:
- cli: terraform
version: "1.9"
- cli: tofu
- version: "1.8"
+ version: "1.8"
- cli: tofu
version: "1.10"
steps:
diff --git a/docs/data-sources/kql_queryset.md b/docs/data-sources/kql_queryset.md
index 3c900e30..e28baef3 100644
--- a/docs/data-sources/kql_queryset.md
+++ b/docs/data-sources/kql_queryset.md
@@ -6,6 +6,7 @@ description: |-
Get a Fabric KQL Queryset.
Use this data source to fetch a KQL Queryset https://learn.microsoft.com/fabric/real-time-intelligence/kusto-query-set.
-> 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_kql_queryset (Data Source)
@@ -16,17 +17,40 @@ Use this data source to fetch a [KQL Queryset](https://learn.microsoft.com/fabri
-> 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_kql_queryset" "example_by_name" {
+ display_name = "example"
+ workspace_id = "00000000-0000-0000-0000-000000000000"
+}
+
+# Get item details by id
data "fabric_kql_queryset" "example_by_id" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
}
-data "fabric_kql_queryset" "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_kql_queryset" "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_kql_queryset.example_definition.definition["RealTimeQueryset.json"].content, ".payload.tabs[0]")
+}
+
+# Access the content of the definition as JSON object
+output "example_definition_content_object" {
+ value = provider::fabric::content_decode(data.fabric_kql_queryset.example_definition.definition["RealTimeQueryset.json"].content).payload.tabs[0]
}
# This is an invalid data source
@@ -48,11 +72,17 @@ data "fabric_kql_queryset" "example_by_name" {
### Optional
- `display_name` (String) The KQL Queryset display name.
+- `format` (String) The KQL Queryset format. Possible values: `Default`
- `id` (String) The KQL Queryset 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: `RealTimeQueryset.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The KQL Queryset description.
@@ -62,3 +92,12 @@ data "fabric_kql_queryset" "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).
+
+
+
+### 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.
diff --git a/docs/resources/kql_queryset.md b/docs/resources/kql_queryset.md
new file mode 100644
index 00000000..c5af36ae
--- /dev/null
+++ b/docs/resources/kql_queryset.md
@@ -0,0 +1,119 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "fabric_kql_queryset Resource - terraform-provider-fabric"
+subcategory: ""
+description: |-
+ Manage a Fabric KQL Queryset.
+ Use this resource to manage KQL Queryset https://learn.microsoft.com/fabric/real-time-intelligence/kusto-query-set.
+ -> 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_kql_queryset (Resource)
+
+Manage a Fabric KQL Queryset.
+
+Use this resource to manage [KQL Queryset](https://learn.microsoft.com/fabric/real-time-intelligence/kusto-query-set).
+
+-> 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_kql_queryset" "example" {
+ display_name = "example"
+ workspace_id = "00000000-0000-0000-0000-000000000000"
+}
+
+# Example 2 - Item with definition bootstrapping only
+resource "fabric_kql_queryset" "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 = {
+ "RealTimeQueryset.json" = {
+ source = "${local.path}/RealTimeQueryset.json"
+ }
+ }
+}
+
+# Example 3 - Item with definition update when source or tokens changed
+resource "fabric_kql_queryset" "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 = {
+ "RealTimeQueryset.json" = {
+ source = "${local.path}/RealTimeQueryset.json.tmpl"
+ tokens = {
+ "MyValue1" = "my value 1"
+ "MyValue2" = "my value 2"
+ }
+ }
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `display_name` (String) The KQL Queryset display name.
+- `workspace_id` (String) The Workspace ID.
+
+### Optional
+
+- `definition` (Attributes Map) Definition parts. Read more about [KQL Queryset definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/kql-queryset-definition). Accepted path keys: **Default** format: `RealTimeQueryset.json` (see [below for nested schema](#nestedatt--definition))
+- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
+- `description` (String) The KQL Queryset description.
+- `format` (String) The KQL Queryset format. Possible values: `Default`
+- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
+
+### Read-Only
+
+- `id` (String) The KQL Queryset ID.
+
+
+
+### 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.
+
+
+
+### 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.
+- `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). Read operations occur during any refresh or planning operation when refresh is enabled.
+- `update` (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).
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# terraform import fabric_kql_queryset.example "/"
+terraform import fabric_kql_queryset.example "00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111"
+```
diff --git a/examples/data-sources/fabric_kql_queryset/data-source.tf b/examples/data-sources/fabric_kql_queryset/data-source.tf
index d5d64aad..60bb3c95 100644
--- a/examples/data-sources/fabric_kql_queryset/data-source.tf
+++ b/examples/data-sources/fabric_kql_queryset/data-source.tf
@@ -1,11 +1,32 @@
+# Get item details by name
+data "fabric_kql_queryset" "example_by_name" {
+ display_name = "example"
+ workspace_id = "00000000-0000-0000-0000-000000000000"
+}
+
+# Get item details by id
data "fabric_kql_queryset" "example_by_id" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
}
-data "fabric_kql_queryset" "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_kql_queryset" "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_kql_queryset.example_definition.definition["RealTimeQueryset.json"].content, ".payload.tabs[0]")
+}
+
+# Access the content of the definition as JSON object
+output "example_definition_content_object" {
+ value = provider::fabric::content_decode(data.fabric_kql_queryset.example_definition.definition["RealTimeQueryset.json"].content).payload.tabs[0]
}
# This is an invalid data source
diff --git a/examples/resources/fabric_kql_queryset/import.sh b/examples/resources/fabric_kql_queryset/import.sh
new file mode 100644
index 00000000..236742ee
--- /dev/null
+++ b/examples/resources/fabric_kql_queryset/import.sh
@@ -0,0 +1,2 @@
+# terraform import fabric_kql_queryset.example "/"
+terraform import fabric_kql_queryset.example "00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111"
diff --git a/examples/resources/fabric_kql_queryset/outputs.tf b/examples/resources/fabric_kql_queryset/outputs.tf
new file mode 100644
index 00000000..b38877cb
--- /dev/null
+++ b/examples/resources/fabric_kql_queryset/outputs.tf
@@ -0,0 +1,3 @@
+output "example" {
+ value = resource.fabric_kql_queryset.example
+}
diff --git a/examples/resources/fabric_kql_queryset/providers.tf b/examples/resources/fabric_kql_queryset/providers.tf
new file mode 100644
index 00000000..0c8bdbf5
--- /dev/null
+++ b/examples/resources/fabric_kql_queryset/providers.tf
@@ -0,0 +1,11 @@
+terraform {
+ required_version = ">= 1.8, < 2.0"
+ required_providers {
+ fabric = {
+ source = "microsoft/fabric"
+ version = "0.0.0" # Check for the latest version on the Terraform Registry
+ }
+ }
+}
+
+provider "fabric" {}
diff --git a/examples/resources/fabric_kql_queryset/resource.tf b/examples/resources/fabric_kql_queryset/resource.tf
new file mode 100644
index 00000000..568be8d0
--- /dev/null
+++ b/examples/resources/fabric_kql_queryset/resource.tf
@@ -0,0 +1,36 @@
+# Example 1 - Item without definition
+resource "fabric_kql_queryset" "example" {
+ display_name = "example"
+ workspace_id = "00000000-0000-0000-0000-000000000000"
+}
+
+# Example 2 - Item with definition bootstrapping only
+resource "fabric_kql_queryset" "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 = {
+ "RealTimeQueryset.json" = {
+ source = "${local.path}/RealTimeQueryset.json"
+ }
+ }
+}
+
+# Example 3 - Item with definition update when source or tokens changed
+resource "fabric_kql_queryset" "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 = {
+ "RealTimeQueryset.json" = {
+ source = "${local.path}/RealTimeQueryset.json.tmpl"
+ tokens = {
+ "MyValue1" = "my value 1"
+ "MyValue2" = "my value 2"
+ }
+ }
+ }
+}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 02d3bfeb..6b562eb8 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -368,6 +368,7 @@ func (p *FabricProvider) Resources(ctx context.Context) []func() resource.Resour
func() resource.Resource { return eventhouse.NewResourceEventhouse(ctx) },
eventstream.NewResourceEventstream,
kqldatabase.NewResourceKQLDatabase,
+ kqlqueryset.NewResourceKQLQueryset,
func() resource.Resource { return lakehouse.NewResourceLakehouse(ctx) },
mlexperiment.NewResourceMLExperiment,
mlmodel.NewResourceMLModel,
diff --git a/internal/services/kqlqueryset/base.go b/internal/services/kqlqueryset/base.go
index 139d98bb..9bbf0648 100644
--- a/internal/services/kqlqueryset/base.go
+++ b/internal/services/kqlqueryset/base.go
@@ -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 = "KQL Queryset"
- ItemTFName = "kql_queryset"
- ItemsName = "KQL Querysets"
- ItemsTFName = "kql_querysets"
- ItemType = fabcore.ItemTypeKQLQueryset
- ItemDocsSPNSupport = common.DocsSPNSupported
- ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/kusto-query-set"
+ ItemName = "KQL Queryset"
+ ItemTFName = "kql_queryset"
+ ItemsName = "KQL Querysets"
+ ItemsTFName = "kql_querysets"
+ ItemType = fabcore.ItemTypeKQLQueryset
+ ItemDocsSPNSupport = common.DocsSPNSupported
+ ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/kusto-query-set"
+ ItemDefinitionEmpty = `{}`
+ ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/kql-queryset-definition"
+ ItemPreview = true
)
+
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: fabricitem.DefinitionFormatDefault,
+ API: "",
+ Paths: []string{"RealTimeQueryset.json"},
+ },
+}
diff --git a/internal/services/kqlqueryset/data_kql_queryset.go b/internal/services/kqlqueryset/data_kql_queryset.go
index aac1b90d..51eb7055 100644
--- a/internal/services/kqlqueryset/data_kql_queryset.go
+++ b/internal/services/kqlqueryset/data_kql_queryset.go
@@ -10,7 +10,7 @@ import (
)
func NewDataSourceKQLQueryset() datasource.DataSource {
- config := fabricitem.DataSourceFabricItem{
+ config := fabricitem.DataSourceFabricItemDefinition{
Type: ItemType,
Name: ItemName,
TFName: ItemTFName,
@@ -18,7 +18,9 @@ func NewDataSourceKQLQueryset() datasource.DataSource {
"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)
}
diff --git a/internal/services/kqlqueryset/data_kql_queryset_test.go b/internal/services/kqlqueryset/data_kql_queryset_test.go
index d5ce7b9b..342ee8ab 100644
--- a/internal/services/kqlqueryset/data_kql_queryset_test.go
+++ b/internal/services/kqlqueryset/data_kql_queryset_test.go
@@ -89,7 +89,7 @@ func TestUnit_KQLQuerysetDataSource(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
{
@@ -200,6 +200,7 @@ func TestAcc_KQLQuerysetDataSource(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
@@ -213,5 +214,36 @@ func TestAcc_KQLQuerysetDataSource(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.RealTimeQueryset.json.content"),
+ ),
+ },
}))
}
diff --git a/internal/services/kqlqueryset/data_kql_querysets.go b/internal/services/kqlqueryset/data_kql_querysets.go
index 1bb1405d..0b9738bf 100644
--- a/internal/services/kqlqueryset/data_kql_querysets.go
+++ b/internal/services/kqlqueryset/data_kql_querysets.go
@@ -18,6 +18,7 @@ func NewDataSourceKQLQuerysets() datasource.DataSource {
MarkdownDescription: "List a Fabric " + ItemsName + ".\n\n" +
"Use this data source to list [" + ItemsName + "](" + ItemDocsURL + ").\n\n" +
ItemDocsSPNSupport,
+ IsPreview: ItemPreview,
}
return fabricitem.NewDataSourceFabricItems(config)
diff --git a/internal/services/kqlqueryset/resource_kql_queryset.go b/internal/services/kqlqueryset/resource_kql_queryset.go
new file mode 100644
index 00000000..9cf19291
--- /dev/null
+++ b/internal/services/kqlqueryset/resource_kql_queryset.go
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft Corporation
+// SPDX-License-Identifier: MPL-2.0
+
+package kqlqueryset
+
+import (
+ "github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+
+ "github.com/microsoft/terraform-provider-fabric/internal/pkg/fabricitem"
+)
+
+func NewResourceKQLQueryset() resource.Resource {
+ config := fabricitem.ResourceFabricItemDefinition{
+ Type: ItemType,
+ Name: ItemName,
+ NameRenameAllowed: true,
+ TFName: ItemTFName,
+ MarkdownDescription: "Manage a Fabric " + ItemName + ".\n\n" +
+ "Use this resource to manage [" + ItemName + "](" + ItemDocsURL + ").\n\n" +
+ ItemDocsSPNSupport,
+ DisplayNameMaxLength: 123,
+ DescriptionMaxLength: 256,
+ DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
+ DefinitionPathKeysValidator: []validator.Map{
+ mapvalidator.SizeAtMost(1),
+ mapvalidator.KeysAre(fabricitem.DefinitionPathKeysValidator(itemDefinitionFormats)...),
+ },
+ DefinitionRequired: false,
+ DefinitionEmpty: ItemDefinitionEmpty,
+ DefinitionFormats: itemDefinitionFormats,
+ IsPreview: ItemPreview,
+ }
+
+ return fabricitem.NewResourceFabricItemDefinition(config)
+}
diff --git a/internal/services/kqlqueryset/resource_kql_queryset_test.go b/internal/services/kqlqueryset/resource_kql_queryset_test.go
new file mode 100644
index 00000000..b3d823b3
--- /dev/null
+++ b/internal/services/kqlqueryset/resource_kql_queryset_test.go
@@ -0,0 +1,342 @@
+// Copyright (c) Microsoft Corporation
+// SPDX-License-Identifier: MPL-2.0
+
+package kqlqueryset_test
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "testing"
+
+ at "github.com/dcarbone/terraform-plugin-framework-utils/v3/acctest"
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+
+ "github.com/microsoft/terraform-provider-fabric/internal/common"
+ "github.com/microsoft/terraform-provider-fabric/internal/framework/customtypes"
+ "github.com/microsoft/terraform-provider-fabric/internal/testhelp"
+ "github.com/microsoft/terraform-provider-fabric/internal/testhelp/fakes"
+)
+
+var (
+ testResourceItemFQN = testhelp.ResourceFQN("fabric", itemTFName, "test")
+ testResourceItemHeader = at.ResourceHeader(testhelp.TypeName("fabric", itemTFName), "test")
+)
+
+var testHelperLocals = at.CompileLocalsConfig(map[string]any{
+ "path": testhelp.GetFixturesDirPath("kql_queryset"),
+})
+
+func TestUnit_KQLQuerysetResource_Attributes(t *testing.T) {
+ resource.ParallelTest(t, testhelp.NewTestUnitCase(t, &testResourceItemFQN, fakes.FakeServer.ServerFactory, nil, []resource.TestStep{
+ // error - no attributes
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{},
+ ),
+ ),
+ ExpectError: regexp.MustCompile(`Missing required argument`),
+ },
+ // error - workspace_id - invalid UUID
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": "invalid uuid",
+ "display_name": "test",
+ },
+ )),
+ ExpectError: regexp.MustCompile(customtypes.UUIDTypeErrorInvalidStringHeader),
+ },
+ // error - unexpected attribute
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": "00000000-0000-0000-0000-000000000000",
+ "unexpected_attr": "test",
+ },
+ )),
+ ExpectError: regexp.MustCompile(`An argument named "unexpected_attr" is not expected here`),
+ },
+ // error - no required attributes
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "display_name": "test",
+ },
+ )),
+ ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`),
+ },
+ // error - no required attributes
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": "00000000-0000-0000-0000-000000000000",
+ },
+ )),
+ ExpectError: regexp.MustCompile(`The argument "display_name" is required, but no definition was found.`),
+ },
+ }))
+}
+
+func TestUnit_KQLQuerysetResource_ImportState(t *testing.T) {
+ workspaceID := testhelp.RandomUUID()
+ entity := fakes.NewRandomItemWithWorkspace(itemType, workspaceID)
+
+ fakes.FakeServer.Upsert(fakes.NewRandomItemWithWorkspace(itemType, workspaceID))
+ fakes.FakeServer.Upsert(entity)
+ fakes.FakeServer.Upsert(fakes.NewRandomItemWithWorkspace(itemType, workspaceID))
+
+ testCase := at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": *entity.WorkspaceID,
+ "display_name": *entity.DisplayName,
+ },
+ ))
+
+ resource.Test(t, testhelp.NewTestUnitCase(t, &testResourceItemFQN, fakes.FakeServer.ServerFactory, nil, []resource.TestStep{
+ {
+ ResourceName: testResourceItemFQN,
+ Config: testCase,
+ ImportStateId: "not-valid",
+ ImportState: true,
+ ExpectError: regexp.MustCompile(fmt.Sprintf(common.ErrorImportIdentifierDetails, fmt.Sprintf("WorkspaceID/%sID", string(itemType)))),
+ },
+ {
+ ResourceName: testResourceItemFQN,
+ Config: testCase,
+ ImportStateId: "test/id",
+ ImportState: true,
+ ExpectError: regexp.MustCompile(customtypes.UUIDTypeErrorInvalidStringHeader),
+ },
+ {
+ ResourceName: testResourceItemFQN,
+ Config: testCase,
+ ImportStateId: fmt.Sprintf("%s/%s", "test", *entity.ID),
+ ImportState: true,
+ ExpectError: regexp.MustCompile(customtypes.UUIDTypeErrorInvalidStringHeader),
+ },
+ {
+ ResourceName: testResourceItemFQN,
+ Config: testCase,
+ ImportStateId: fmt.Sprintf("%s/%s", *entity.WorkspaceID, "test"),
+ ImportState: true,
+ ExpectError: regexp.MustCompile(customtypes.UUIDTypeErrorInvalidStringHeader),
+ },
+ // Import state testing
+ {
+ ResourceName: testResourceItemFQN,
+ Config: testCase,
+ ImportStateId: fmt.Sprintf("%s/%s", *entity.WorkspaceID, *entity.ID),
+ ImportState: true,
+ ImportStatePersist: true,
+ ImportStateCheck: func(is []*terraform.InstanceState) error {
+ if len(is) != 1 {
+ return errors.New("expected one instance state")
+ }
+
+ if is[0].ID != *entity.ID {
+ return errors.New(testResourceItemFQN + ": unexpected ID")
+ }
+
+ return nil
+ },
+ },
+ }))
+}
+
+func TestUnit_KQLQuerysetResource_CRUD(t *testing.T) {
+ workspaceID := testhelp.RandomUUID()
+ entityExist := fakes.NewRandomItemWithWorkspace(itemType, workspaceID)
+ entityBefore := fakes.NewRandomItemWithWorkspace(itemType, workspaceID)
+ entityAfter := fakes.NewRandomItemWithWorkspace(itemType, workspaceID)
+
+ fakes.FakeServer.Upsert(fakes.NewRandomItemWithWorkspace(itemType, workspaceID))
+ fakes.FakeServer.Upsert(entityExist)
+ fakes.FakeServer.Upsert(entityAfter)
+ fakes.FakeServer.Upsert(fakes.NewRandomItemWithWorkspace(itemType, workspaceID))
+
+ resource.Test(t, testhelp.NewTestUnitCase(t, &testResourceItemFQN, fakes.FakeServer.ServerFactory, nil, []resource.TestStep{
+ // error - create - existing entity
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": *entityExist.WorkspaceID,
+ "display_name": *entityExist.DisplayName,
+ },
+ )),
+ ExpectError: regexp.MustCompile(common.ErrorCreateHeader),
+ },
+ // Create and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": *entityBefore.WorkspaceID,
+ "display_name": *entityBefore.DisplayName,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttrPtr(testResourceItemFQN, "display_name", entityBefore.DisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", ""),
+ ),
+ },
+ // Update and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": *entityBefore.WorkspaceID,
+ "display_name": *entityAfter.DisplayName,
+ "description": *entityAfter.Description,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttrPtr(testResourceItemFQN, "display_name", entityAfter.DisplayName),
+ resource.TestCheckResourceAttrPtr(testResourceItemFQN, "description", entityAfter.Description),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ }))
+}
+
+func TestAcc_KQLQuerysetResource_CRUD(t *testing.T) {
+ workspace := testhelp.WellKnown()["WorkspaceRS"].(map[string]any)
+ workspaceID := workspace["id"].(string)
+
+ entityCreateDisplayName := testhelp.RandomName()
+ entityUpdateDisplayName := testhelp.RandomName()
+ entityUpdateDescription := testhelp.RandomName()
+
+ resource.Test(t, testhelp.NewTestAccCase(t, &testResourceItemFQN, nil, []resource.TestStep{
+ // Create and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "display_name": entityCreateDisplayName,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(testResourceItemFQN, "display_name", entityCreateDisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", ""),
+ ),
+ },
+ // Update and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "display_name": entityUpdateDisplayName,
+ "description": entityUpdateDescription,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(testResourceItemFQN, "display_name", entityUpdateDisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", entityUpdateDescription),
+ ),
+ },
+ },
+ ))
+}
+
+func TestAcc_KQLQuerysetDefinitionResource_CRUD(t *testing.T) {
+ workspace := testhelp.WellKnown()["Workspace"].(map[string]any)
+ workspaceID := workspace["id"].(string)
+
+ entityCreateDisplayName := testhelp.RandomName()
+ entityUpdateDisplayName := testhelp.RandomName()
+ entityUpdateDescription := testhelp.RandomName()
+
+ testHelperDefinition := map[string]any{
+ `"RealTimeQueryset.json"`: map[string]any{
+ "source": "${local.path}/RealTimeQueryset.json",
+ },
+ }
+
+ resource.Test(t, testhelp.NewTestAccCase(t, &testResourceItemFQN, nil, []resource.TestStep{
+ // Create and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "display_name": entityCreateDisplayName,
+ "format": "Default",
+ "definition": testHelperDefinition,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(testResourceItemFQN, "display_name", entityCreateDisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", ""),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "definition_update_enabled", "true"),
+ ),
+ },
+ // Update and Read
+ {
+ ResourceName: testResourceItemFQN,
+ Config: at.JoinConfigs(
+ testHelperLocals,
+ at.CompileConfig(
+ testResourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "display_name": entityUpdateDisplayName,
+ "description": entityUpdateDescription,
+ "format": "Default",
+ "definition": testHelperDefinition,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(testResourceItemFQN, "display_name", entityUpdateDisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", entityUpdateDescription),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "definition_update_enabled", "true"),
+ ),
+ },
+ },
+ ))
+}
diff --git a/internal/testhelp/fixtures/kql_queryset/RealTimeQueryset.json b/internal/testhelp/fixtures/kql_queryset/RealTimeQueryset.json
new file mode 100644
index 00000000..38e3c3cf
--- /dev/null
+++ b/internal/testhelp/fixtures/kql_queryset/RealTimeQueryset.json
@@ -0,0 +1,28 @@
+{
+ "payload": {
+ "tabs": [
+ {
+ "id": "ad801b9d-1091-4264-8f7a-8e4928b9e138",
+ "queryRange": {
+ "startLineNumber": 1,
+ "startColumn": 1,
+ "endLineNumber": 1,
+ "endColumn": 9
+ },
+ "text": "print 10",
+ "commandInContext": "print 10",
+ "executionStatus": "notStarted",
+ "clientRequestId": null,
+ "commandType": "Query",
+ "commandWithoutLeadingComments": "print 10",
+ "hideEmptyColumns": false,
+ "cursorPosition": {
+ "lineNumber": 1,
+ "column": 9
+ }
+ }
+ ],
+ "tabInContext": "ad801b9d-1091-4264-8f7a-8e4928b9e138",
+ "connections": {}
+ }
+}