From 38543ed82cddee8f933995297d69a7aa3cc4bd99 Mon Sep 17 00:00:00 2001
From: Dariusz Porowski <3431813+DariuszPorowski@users.noreply.github.com>
Date: Wed, 8 Jan 2025 19:30:35 -0800
Subject: [PATCH] feat(fabricitem)!: enable multi-format support
---
.../unreleased/added-20241223-094847.yaml | 7 +
.../unreleased/breaking-20241223-094847.yaml | 7 +
docs/data-sources/eventhouse.md | 4 +-
docs/data-sources/notebook.md | 5 +-
docs/data-sources/report.md | 5 +-
docs/data-sources/semantic_model.md | 5 +-
docs/data-sources/spark_job_definition.md | 5 +-
docs/resources/data_pipeline.md | 4 +-
docs/resources/eventhouse.md | 4 +-
docs/resources/notebook.md | 6 +-
docs/resources/report.md | 6 +-
docs/resources/semantic_model.md | 6 +-
docs/resources/spark_job_definition.md | 6 +-
.../fabric_notebook/data-source.tf | 1 +
.../data-sources/fabric_report/data-source.tf | 1 +
.../fabric_semantic_model/data-source.tf | 1 +
.../data-source.tf | 1 +
.../resources/fabric_notebook/resource.tf | 2 +
examples/resources/fabric_report/resource.tf | 2 +
.../fabric_semantic_model/resource.tf | 2 +
.../fabric_spark_job_definition/resource.tf | 2 +
.../regexp_if_attribute_is_one_of.go | 144 ++++++++++++++++++
internal/pkg/fabricitem/base.go | 4 +-
.../pkg/fabricitem/data_item_definition.go | 19 ++-
internal/pkg/fabricitem/data_schema.go | 42 ++---
internal/pkg/fabricitem/definition.go | 106 +++++++++++++
.../pkg/fabricitem/models_resource_item.go | 8 +-
.../models_resource_item_definition.go | 22 ++-
...ource_item_config_definition_properties.go | 6 +-
.../fabricitem/resource_item_definition.go | 9 +-
.../resource_item_definition_properties.go | 6 +-
internal/pkg/fabricitem/resource_schema.go | 35 +++--
internal/provider/utils/values.go | 12 +-
internal/services/datapipeline/base.go | 9 +-
.../datapipeline/resource_data_pipeline.go | 7 +-
internal/services/eventhouse/base.go | 14 +-
.../services/eventhouse/data_eventhouse.go | 3 +-
.../eventhouse/resource_eventhouse.go | 6 +-
internal/services/kqldatabase/base.go | 14 +-
internal/services/notebook/base.go | 37 +++--
internal/services/notebook/data_notebook.go | 5 +-
.../services/notebook/data_notebook_test.go | 52 +++++++
.../services/notebook/resource_notebook.go | 8 +-
.../notebook/resource_notebook_test.go | 140 +++++++++++++++--
internal/services/report/base.go | 17 ++-
internal/services/report/data_report.go | 3 +-
internal/services/report/data_report_test.go | 1 +
internal/services/report/resource_report.go | 24 ++-
.../services/report/resource_report_test.go | 10 ++
internal/services/semanticmodel/base.go | 17 ++-
.../semanticmodel/data_semantic_model.go | 3 +-
.../semanticmodel/data_semantic_model_test.go | 1 +
.../semanticmodel/resource_semantic_model.go | 24 ++-
.../resource_semantic_model_test.go | 10 ++
internal/services/sparkjobdefinition/base.go | 12 +-
.../data_spark_job_definition.go | 3 +-
.../data_spark_job_definition_test.go | 1 +
.../resource_spark_job_definition.go | 6 +-
.../resource_spark_job_definition_test.go | 10 ++
.../workspace/resource_workspace_git.go | 2 +-
.../fixtures/notebook/notebook.py.tmpl | 22 +++
61 files changed, 776 insertions(+), 180 deletions(-)
create mode 100644 .changes/unreleased/added-20241223-094847.yaml
create mode 100644 .changes/unreleased/breaking-20241223-094847.yaml
create mode 100644 internal/framework/validators/regexp_if_attribute_is_one_of.go
create mode 100644 internal/pkg/fabricitem/definition.go
create mode 100644 internal/testhelp/fixtures/notebook/notebook.py.tmpl
diff --git a/.changes/unreleased/added-20241223-094847.yaml b/.changes/unreleased/added-20241223-094847.yaml
new file mode 100644
index 00000000..3e7c6a5c
--- /dev/null
+++ b/.changes/unreleased/added-20241223-094847.yaml
@@ -0,0 +1,7 @@
+kind: added
+body: |
+ Added support for multi-format Notebook Resource/Data-Source.
+ By using `format` attribute, you can now define the format of the Notebook Resource/Data-Source. Accepted values are `jpynb`, and `py`.
+time: 2024-12-23T09:48:47.1324573-08:00
+custom:
+ Issue: "168"
diff --git a/.changes/unreleased/breaking-20241223-094847.yaml b/.changes/unreleased/breaking-20241223-094847.yaml
new file mode 100644
index 00000000..050da5f0
--- /dev/null
+++ b/.changes/unreleased/breaking-20241223-094847.yaml
@@ -0,0 +1,7 @@
+kind: breaking
+body: |
+ The `format` attribute is now REQUIRED for Resources/Data-Sources with definition support.
+ Currently applicable to the following Resources/Data-Sources: Report, Notebook, Semantic Model, and Spark Job Definition.
+time: 2024-12-23T09:48:47.1324573-08:00
+custom:
+ Issue: "111"
diff --git a/docs/data-sources/eventhouse.md b/docs/data-sources/eventhouse.md
index 2e060250..1444594d 100644
--- a/docs/data-sources/eventhouse.md
+++ b/docs/data-sources/eventhouse.md
@@ -66,6 +66,7 @@ output "example_definition_content_object" {
### Optional
- `display_name` (String) The Eventhouse display name.
+- `format` (String) The Eventhouse format. Possible values: `Default`
- `id` (String) The Eventhouse ID.
- `output_definition` (Boolean) Output definition parts as gzip base64 content? Default: `false`
@@ -75,9 +76,8 @@ output "example_definition_content_object" {
### Read-Only
-- `definition` (Attributes Map) Definition parts. Possible path keys: `EventhouseProperties.json`. (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Possible path keys: **Default** format: `EventhouseProperties.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Eventhouse description.
-- `format` (String) The Eventhouse format. Possible values: `NotApplicable`
- `properties` (Attributes) The Eventhouse properties. (see [below for nested schema](#nestedatt--properties))
diff --git a/docs/data-sources/notebook.md b/docs/data-sources/notebook.md
index bcbc6358..a3b3552a 100644
--- a/docs/data-sources/notebook.md
+++ b/docs/data-sources/notebook.md
@@ -36,6 +36,7 @@ data "fabric_notebook" "example_by_id" {
data "fabric_notebook" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "ipynb"
output_definition = true
}
@@ -68,6 +69,7 @@ output "example_definition_content_object" {
### Optional
- `display_name` (String) The Notebook display name.
+- `format` (String) The Notebook format. Possible values: `ipynb`, `py`
- `id` (String) The Notebook ID.
- `output_definition` (Boolean) Output definition parts as gzip base64 content? Default: `false`
@@ -77,9 +79,8 @@ output "example_definition_content_object" {
### Read-Only
-- `definition` (Attributes Map) Definition parts. Possible path keys: `notebook-content.ipynb`. (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Possible path keys: **ipynb** format: `notebook-content.ipynb` **py** format: `notebook-content.py` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Notebook description.
-- `format` (String) The Notebook format. Possible values: `ipynb`.
diff --git a/docs/data-sources/report.md b/docs/data-sources/report.md
index d1a463b1..20c36438 100644
--- a/docs/data-sources/report.md
+++ b/docs/data-sources/report.md
@@ -29,6 +29,7 @@ data "fabric_report" "example" {
data "fabric_report" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "PBIR-Legacy"
output_definition = true
}
@@ -56,6 +57,7 @@ output "example_definition_report_object" {
### Optional
+- `format` (String) The Report format. Possible values: `PBIR-Legacy`, `PBIR`
- `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.
@@ -64,10 +66,9 @@ output "example_definition_report_object" {
### Read-Only
-- `definition` (Attributes Map) Definition parts. Possible path keys: `report.json`, `definition.pbir`, `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`. (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Possible path keys: **PBIR-Legacy** format: `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`, `definition.pbir`, `report.json` **PBIR** format: `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`, `definition.pbir`, `definition/pages/*.json`, `definition/report.json`, `definition/version.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Report description.
- `display_name` (String) The Report display name.
-- `format` (String) The Report format. Possible values: `PBIR-Legacy`.
diff --git a/docs/data-sources/semantic_model.md b/docs/data-sources/semantic_model.md
index ddd44af7..7e725747 100644
--- a/docs/data-sources/semantic_model.md
+++ b/docs/data-sources/semantic_model.md
@@ -29,6 +29,7 @@ data "fabric_semantic_model" "example" {
data "fabric_semantic_model" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "TMSL"
output_definition = true
}
@@ -53,6 +54,7 @@ output "example_definition_bim_object" {
### Optional
+- `format` (String) The Semantic Model format. Possible values: `TMSL`, `TMDL`
- `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.
@@ -61,10 +63,9 @@ output "example_definition_bim_object" {
### Read-Only
-- `definition` (Attributes Map) Definition parts. Possible path keys: `model.bim`, `definition.pbism`, `diagramLayout.json`. (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Possible path keys: **TMSL** format: `definition.pbism`, `diagramLayp.json`, `model.bim` **TMDL** format: `definition.pbism`, `definition/database.tmdl`, `definition/model.tmdl`, `definition/tables/*.tmdl`, `diagramLayp.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Semantic Model description.
- `display_name` (String) The Semantic Model display name.
-- `format` (String) The Semantic Model format. Possible values: `TMSL`.
diff --git a/docs/data-sources/spark_job_definition.md b/docs/data-sources/spark_job_definition.md
index 935ea756..3d6cc75e 100644
--- a/docs/data-sources/spark_job_definition.md
+++ b/docs/data-sources/spark_job_definition.md
@@ -36,6 +36,7 @@ data "fabric_spark_job_definition" "example_by_name" {
data "fabric_spark_job_definition" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "SparkJobDefinitionV1"
output_definition = true
}
@@ -68,6 +69,7 @@ output "example_definition_content_object" {
### Optional
- `display_name` (String) The Spark Job Definition display name.
+- `format` (String) The Spark Job Definition format. Possible values: `SparkJobDefinitionV1`
- `id` (String) The Spark Job Definition ID.
- `output_definition` (Boolean) Output definition parts as gzip base64 content? Default: `false`
@@ -77,9 +79,8 @@ output "example_definition_content_object" {
### Read-Only
-- `definition` (Attributes Map) Definition parts. Possible path keys: `SparkJobDefinitionV1.json`. (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Possible path keys: **SparkJobDefinitionV1** format: `SparkJobDefinitionV1.json` (see [below for nested schema](#nestedatt--definition))
- `description` (String) The Spark Job Definition description.
-- `format` (String) The Spark Job Definition format. Possible values: `SparkJobDefinitionV1`.
- `properties` (Attributes) The Spark Job Definition properties. (see [below for nested schema](#nestedatt--properties))
diff --git a/docs/resources/data_pipeline.md b/docs/resources/data_pipeline.md
index 4e13f1eb..fd73d0ce 100644
--- a/docs/resources/data_pipeline.md
+++ b/docs/resources/data_pipeline.md
@@ -67,14 +67,14 @@ resource "fabric_data_pipeline" "example_definition_update" {
### Optional
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `pipeline-content.json`. Read more about [Data Pipeline definition part paths](https://learn.microsoft.com/fabric/data-factory/pipeline-rest-api). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Data Pipeline definition part paths](https://learn.microsoft.com/fabric/data-factory/pipeline-rest-api). Accepted path keys: **Default** format: `pipeline-content.json` (see [below for nested schema](#nestedatt--definition))
- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
- `description` (String) The Data Pipeline description.
+- `format` (String) The Data Pipeline format. Possible values: `Default`
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
-- `format` (String) The Data Pipeline format. Possible values: `NotApplicable`
- `id` (String) The Data Pipeline ID.
diff --git a/docs/resources/eventhouse.md b/docs/resources/eventhouse.md
index 4b2dae98..74938e9e 100644
--- a/docs/resources/eventhouse.md
+++ b/docs/resources/eventhouse.md
@@ -64,14 +64,14 @@ resource "fabric_eventhouse" "example_definition_update" {
### Optional
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `EventhouseProperties.json`. Read more about [Eventhouse definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/eventhouse-definition). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Eventhouse definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/eventhouse-definition). Accepted path keys: **Default** format: `EventhouseProperties.json` (see [below for nested schema](#nestedatt--definition))
- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
- `description` (String) The Eventhouse description.
+- `format` (String) The Eventhouse format. Possible values: `Default`
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
-- `format` (String) The Eventhouse format. Possible values: `NotApplicable`
- `id` (String) The Eventhouse ID.
- `properties` (Attributes) The Eventhouse properties. (see [below for nested schema](#nestedatt--properties))
diff --git a/docs/resources/notebook.md b/docs/resources/notebook.md
index ae607466..1cb89c82 100644
--- a/docs/resources/notebook.md
+++ b/docs/resources/notebook.md
@@ -31,6 +31,7 @@ resource "fabric_notebook" "example_definition_bootstrap" {
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "ipynb"
definition = {
"notebook-content.ipynb" = {
source = "${local.path}/notebook.ipynb.tmpl"
@@ -43,6 +44,7 @@ resource "fabric_notebook" "example_definition_update" {
display_name = "example"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "ipynb"
definition = {
"notebook-content.ipynb" = {
source = "${local.path}/notebook.ipynb.tmpl"
@@ -65,14 +67,14 @@ resource "fabric_notebook" "example_definition_update" {
### Optional
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `notebook-content.ipynb`. Read more about [Notebook definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/notebook-definition). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Notebook definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/notebook-definition). Accepted path keys: **ipynb** format: `notebook-content.ipynb` **py** format: `notebook-content.py` (see [below for nested schema](#nestedatt--definition))
- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
- `description` (String) The Notebook description.
+- `format` (String) The Notebook format. Possible values: `ipynb`, `py`
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
-- `format` (String) The Notebook format. Possible values: `ipynb`.
- `id` (String) The Notebook ID.
diff --git a/docs/resources/report.md b/docs/resources/report.md
index 84123323..97238537 100644
--- a/docs/resources/report.md
+++ b/docs/resources/report.md
@@ -24,6 +24,7 @@ resource "fabric_report" "example_bootstrap" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "PBIR-Legacy"
definition = {
"report.json" = {
source = "${local.path}/report.json"
@@ -44,6 +45,7 @@ resource "fabric_report" "example_bootstrap" {
resource "fabric_report" "example_update" {
display_name = "example with update"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "PBIR-Legacy"
definition = {
"report.json" = {
source = "${local.path}/report.json"
@@ -66,8 +68,9 @@ resource "fabric_report" "example_update" {
### Required
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `report.json`, `definition.pbir`, `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`. Read more about [Report definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/report-definition). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Report definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/report-definition). Accepted path keys: **PBIR** format: `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`, `definition.pbir`, `definition/pages/*.json`, `definition/report.json`, `definition/version.json` **PBIR-Legacy** format: `StaticResources/RegisteredResources/*`, `StaticResources/SharedResources/*`, `definition.pbir`, `report.json` (see [below for nested schema](#nestedatt--definition))
- `display_name` (String) The Report display name.
+- `format` (String) The Report format. Possible values: `PBIR-Legacy`, `PBIR`
- `workspace_id` (String) The Workspace ID.
### Optional
@@ -78,7 +81,6 @@ resource "fabric_report" "example_update" {
### Read-Only
-- `format` (String) The Report format. Possible values: `PBIR-Legacy`.
- `id` (String) The Report ID.
diff --git a/docs/resources/semantic_model.md b/docs/resources/semantic_model.md
index f3aa4e58..87d9b6d0 100644
--- a/docs/resources/semantic_model.md
+++ b/docs/resources/semantic_model.md
@@ -24,6 +24,7 @@ resource "fabric_semantic_model" "example_bootstrap" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "TMSL"
definition = {
"model.bim" = {
source = "${local.path}/model.bim.tmpl"
@@ -38,6 +39,7 @@ resource "fabric_semantic_model" "example_bootstrap" {
resource "fabric_semantic_model" "example_update" {
display_name = "example with update"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "TMSL"
definition = {
"model.bim" = {
source = "${local.path}/model.bim.tmpl"
@@ -57,8 +59,9 @@ resource "fabric_semantic_model" "example_update" {
### Required
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `model.bim`, `definition.pbism`, `diagramLayout.json`. Read more about [Semantic Model definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/semantic-model-definition). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Semantic Model definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/semantic-model-definition). Accepted path keys: **TMSL** format: `definition.pbism`, `diagramLayp.json`, `model.bim` **TMDL** format: `definition.pbism`, `definition/database.tmdl`, `definition/model.tmdl`, `definition/tables/*.tmdl`, `diagramLayp.json` (see [below for nested schema](#nestedatt--definition))
- `display_name` (String) The Semantic Model display name.
+- `format` (String) The Semantic Model format. Possible values: `TMSL`, `TMDL`
- `workspace_id` (String) The Workspace ID.
### Optional
@@ -69,7 +72,6 @@ resource "fabric_semantic_model" "example_update" {
### Read-Only
-- `format` (String) The Semantic Model format. Possible values: `TMSL`.
- `id` (String) The Semantic Model ID.
diff --git a/docs/resources/spark_job_definition.md b/docs/resources/spark_job_definition.md
index 047c6665..50a53016 100644
--- a/docs/resources/spark_job_definition.md
+++ b/docs/resources/spark_job_definition.md
@@ -31,6 +31,7 @@ resource "fabric_spark_job_definition" "example_definition_bootstrap" {
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "SparkJobDefinitionV1"
definition = {
"SparkJobDefinitionV1.json" = {
source = "${local.path}/SparkJobDefinitionV1.json.tmpl"
@@ -43,6 +44,7 @@ resource "fabric_spark_job_definition" "example_definition_update" {
display_name = "example3"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "SparkJobDefinitionV1"
definition = {
"SparkJobDefinitionV1.json" = {
source = "${local.path}/SparkJobDefinitionV1.json.tmpl"
@@ -65,14 +67,14 @@ resource "fabric_spark_job_definition" "example_definition_update" {
### Optional
-- `definition` (Attributes Map) Definition parts. Accepted path keys: `SparkJobDefinitionV1.json`. Read more about [Spark Job Definition definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/spark-job-definition). (see [below for nested schema](#nestedatt--definition))
+- `definition` (Attributes Map) Definition parts. Read more about [Spark Job Definition definition part paths](https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/spark-job-definition). Accepted path keys: **SparkJobDefinitionV1** format: `SparkJobDefinitionV1.json` (see [below for nested schema](#nestedatt--definition))
- `definition_update_enabled` (Boolean) Update definition on change of source content. Default: `true`.
- `description` (String) The Spark Job Definition description.
+- `format` (String) The Spark Job Definition format. Possible values: `SparkJobDefinitionV1`
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))
### Read-Only
-- `format` (String) The Spark Job Definition format. Possible values: `SparkJobDefinitionV1`.
- `id` (String) The Spark Job Definition ID.
- `properties` (Attributes) The Spark Job Definition properties. (see [below for nested schema](#nestedatt--properties))
diff --git a/examples/data-sources/fabric_notebook/data-source.tf b/examples/data-sources/fabric_notebook/data-source.tf
index f3faf46b..e7210117 100644
--- a/examples/data-sources/fabric_notebook/data-source.tf
+++ b/examples/data-sources/fabric_notebook/data-source.tf
@@ -15,6 +15,7 @@ data "fabric_notebook" "example_by_id" {
data "fabric_notebook" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "ipynb"
output_definition = true
}
diff --git a/examples/data-sources/fabric_report/data-source.tf b/examples/data-sources/fabric_report/data-source.tf
index 677ba505..6fa4b5e6 100644
--- a/examples/data-sources/fabric_report/data-source.tf
+++ b/examples/data-sources/fabric_report/data-source.tf
@@ -8,6 +8,7 @@ data "fabric_report" "example" {
data "fabric_report" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "PBIR-Legacy"
output_definition = true
}
diff --git a/examples/data-sources/fabric_semantic_model/data-source.tf b/examples/data-sources/fabric_semantic_model/data-source.tf
index bc1d2b3a..a965feed 100644
--- a/examples/data-sources/fabric_semantic_model/data-source.tf
+++ b/examples/data-sources/fabric_semantic_model/data-source.tf
@@ -8,6 +8,7 @@ data "fabric_semantic_model" "example" {
data "fabric_semantic_model" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "TMSL"
output_definition = true
}
diff --git a/examples/data-sources/fabric_spark_job_definition/data-source.tf b/examples/data-sources/fabric_spark_job_definition/data-source.tf
index 0540e7a1..a3aaa5f6 100644
--- a/examples/data-sources/fabric_spark_job_definition/data-source.tf
+++ b/examples/data-sources/fabric_spark_job_definition/data-source.tf
@@ -15,6 +15,7 @@ data "fabric_spark_job_definition" "example_by_name" {
data "fabric_spark_job_definition" "example_definition" {
id = "11111111-1111-1111-1111-111111111111"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "SparkJobDefinitionV1"
output_definition = true
}
diff --git a/examples/resources/fabric_notebook/resource.tf b/examples/resources/fabric_notebook/resource.tf
index 2f6e58dd..80f6fc2f 100644
--- a/examples/resources/fabric_notebook/resource.tf
+++ b/examples/resources/fabric_notebook/resource.tf
@@ -10,6 +10,7 @@ resource "fabric_notebook" "example_definition_bootstrap" {
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "ipynb"
definition = {
"notebook-content.ipynb" = {
source = "${local.path}/notebook.ipynb.tmpl"
@@ -22,6 +23,7 @@ resource "fabric_notebook" "example_definition_update" {
display_name = "example"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "ipynb"
definition = {
"notebook-content.ipynb" = {
source = "${local.path}/notebook.ipynb.tmpl"
diff --git a/examples/resources/fabric_report/resource.tf b/examples/resources/fabric_report/resource.tf
index 846b03f5..4faf413e 100644
--- a/examples/resources/fabric_report/resource.tf
+++ b/examples/resources/fabric_report/resource.tf
@@ -3,6 +3,7 @@ resource "fabric_report" "example_bootstrap" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "PBIR-Legacy"
definition = {
"report.json" = {
source = "${local.path}/report.json"
@@ -23,6 +24,7 @@ resource "fabric_report" "example_bootstrap" {
resource "fabric_report" "example_update" {
display_name = "example with update"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "PBIR-Legacy"
definition = {
"report.json" = {
source = "${local.path}/report.json"
diff --git a/examples/resources/fabric_semantic_model/resource.tf b/examples/resources/fabric_semantic_model/resource.tf
index 8d536ef3..abe5e017 100644
--- a/examples/resources/fabric_semantic_model/resource.tf
+++ b/examples/resources/fabric_semantic_model/resource.tf
@@ -3,6 +3,7 @@ resource "fabric_semantic_model" "example_bootstrap" {
display_name = "example"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "TMSL"
definition = {
"model.bim" = {
source = "${local.path}/model.bim.tmpl"
@@ -17,6 +18,7 @@ resource "fabric_semantic_model" "example_bootstrap" {
resource "fabric_semantic_model" "example_update" {
display_name = "example with update"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "TMSL"
definition = {
"model.bim" = {
source = "${local.path}/model.bim.tmpl"
diff --git a/examples/resources/fabric_spark_job_definition/resource.tf b/examples/resources/fabric_spark_job_definition/resource.tf
index e71733e3..511033ca 100644
--- a/examples/resources/fabric_spark_job_definition/resource.tf
+++ b/examples/resources/fabric_spark_job_definition/resource.tf
@@ -10,6 +10,7 @@ resource "fabric_spark_job_definition" "example_definition_bootstrap" {
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
+ format = "SparkJobDefinitionV1"
definition = {
"SparkJobDefinitionV1.json" = {
source = "${local.path}/SparkJobDefinitionV1.json.tmpl"
@@ -22,6 +23,7 @@ resource "fabric_spark_job_definition" "example_definition_update" {
display_name = "example3"
description = "example with definition update when source or tokens changed"
workspace_id = "00000000-0000-0000-0000-000000000000"
+ format = "SparkJobDefinitionV1"
definition = {
"SparkJobDefinitionV1.json" = {
source = "${local.path}/SparkJobDefinitionV1.json.tmpl"
diff --git a/internal/framework/validators/regexp_if_attribute_is_one_of.go b/internal/framework/validators/regexp_if_attribute_is_one_of.go
new file mode 100644
index 00000000..8815e2ad
--- /dev/null
+++ b/internal/framework/validators/regexp_if_attribute_is_one_of.go
@@ -0,0 +1,144 @@
+// Copyright (c) Microsoft Corporation
+// SPDX-License-Identifier: MPL-2.0
+
+package validators
+
+import (
+ "context"
+ "fmt"
+ "regexp"
+ "strings"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/helpers/validatordiag"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+)
+
+var _ validator.String = RegexpIfAttributeIsOneOfValidator{}
+
+type RegexpIfAttributeIsOneOfValidator struct {
+ pathExpression path.Expression
+ exceptedValues []attr.Value
+ patterns []string
+ message string
+}
+
+func RegexpIfAttributeIsOneOf(p path.Expression, exceptedValue []attr.Value, patterns []string, message string) RegexpIfAttributeIsOneOfValidator {
+ return RegexpIfAttributeIsOneOfValidator{
+ pathExpression: p,
+ exceptedValues: exceptedValue,
+ patterns: patterns,
+ message: message,
+ }
+}
+
+func (v RegexpIfAttributeIsOneOfValidator) Description(_ context.Context) string {
+ if v.message != "" {
+ return v.message
+ }
+
+ return fmt.Sprintf("value must match pattern expression '%s'", strings.Join(v.patterns, ", "))
+}
+
+func (v RegexpIfAttributeIsOneOfValidator) MarkdownDescription(ctx context.Context) string {
+ return v.Description(ctx)
+}
+
+func (v RegexpIfAttributeIsOneOfValidator) ValidateString(ctx context.Context, req validator.StringRequest, resp *validator.StringResponse) {
+ paths, diags := req.Config.PathMatches(ctx, req.PathExpression.Merge(v.pathExpression))
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+
+ return
+ }
+
+ if len(paths) == 0 {
+ resp.Diagnostics.AddError(
+ fmt.Sprintf("Invalid configuration for attribute %s", req.Path),
+ "Path must be set",
+ )
+
+ return
+ }
+
+ p := paths[0]
+
+ // mpVal is the value of the attribute in the path
+ var mpVal attr.Value
+ resp.Diagnostics.Append(req.Config.GetAttribute(ctx, p, &mpVal)...)
+
+ if resp.Diagnostics.HasError() {
+ resp.Diagnostics.AddError(
+ fmt.Sprintf("Invalid configuration for attribute %s", req.Path),
+ fmt.Sprintf("Unable to retrieve attribute path: %q", p),
+ )
+
+ return
+ }
+
+ // If the target attribute configuration is unknown or null, there is nothing else to validate
+ if mpVal.IsNull() || mpVal.IsUnknown() {
+ return
+ }
+
+ for _, expectedValue := range v.exceptedValues {
+ // If the value of the target attribute is equal to one of the expected values, we need to validate the value of the current attribute
+ if mpVal.Equal(expectedValue) || mpVal.String() == expectedValue.String() {
+ if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
+ resp.Diagnostics.AddAttributeError(
+ p,
+ fmt.Sprintf("Invalid configuration for attribute %s", req.Path),
+ "Value is empty. "+v.Description(ctx),
+ )
+
+ return
+ }
+
+ re, err := v.convertPatternsToRegexp(v.patterns)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ fmt.Sprintf("Invalid configuration for attribute %s", req.Path),
+ fmt.Sprintf("Unable to compile regular expression: %q", err),
+ )
+
+ return
+ }
+
+ value := req.ConfigValue.ValueString()
+
+ if !re.MatchString(value) {
+ resp.Diagnostics.Append(validatordiag.InvalidAttributeValueMatchDiagnostic(
+ req.Path,
+ v.Description(ctx),
+ value,
+ ))
+ }
+ }
+ }
+}
+
+func (v RegexpIfAttributeIsOneOfValidator) convertPatternsToRegexp(patterns []string) (*regexp.Regexp, error) {
+ p := make([]string, 0)
+
+ p = append(p, "^(")
+
+ for _, pattern := range patterns {
+ p = append(p, regexp.QuoteMeta(pattern))
+ if pattern != patterns[len(patterns)-1] {
+ p = append(p, "|")
+ }
+ }
+
+ p = append(p, ")$")
+
+ out := strings.Join(p, "")
+ out = strings.ReplaceAll(out, `\*`, ".+")
+
+ re, err := regexp.Compile(out)
+ if err != nil {
+ return nil, err
+ }
+
+ return re, nil
+}
diff --git a/internal/pkg/fabricitem/base.go b/internal/pkg/fabricitem/base.go
index 45c8c196..20f4db0c 100644
--- a/internal/pkg/fabricitem/base.go
+++ b/internal/pkg/fabricitem/base.go
@@ -3,4 +3,6 @@
package fabricitem
-const DefinitionFormatNotApplicable = "NotApplicable"
+const (
+ DefinitionFormatDefault = "Default"
+)
diff --git a/internal/pkg/fabricitem/data_item_definition.go b/internal/pkg/fabricitem/data_item_definition.go
index 41dd22d6..5ac8b7a0 100644
--- a/internal/pkg/fabricitem/data_item_definition.go
+++ b/internal/pkg/fabricitem/data_item_definition.go
@@ -36,8 +36,7 @@ type DataSourceFabricItemDefinition struct {
MarkdownDescription string
IsDisplayNameUnique bool
FormatTypeDefault string
- FormatTypes []string
- DefinitionPathKeys []string
+ DefinitionFormats []DefinitionFormat
}
func NewDataSourceFabricItemDefinition(config DataSourceFabricItemDefinition) datasource.DataSource {
@@ -120,10 +119,12 @@ func (d *DataSourceFabricItemDefinition) Read(ctx context.Context, req datasourc
return
}
- data.Format = types.StringNull()
-
- if d.FormatTypeDefault != "" {
- data.Format = types.StringValue(d.FormatTypeDefault)
+ if data.Format.IsNull() || data.Format.IsUnknown() {
+ if d.FormatTypeDefault != "" {
+ data.Format = types.StringValue(d.FormatTypeDefault)
+ } else {
+ data.Format = types.StringNull()
+ }
}
resp.Diagnostics.Append(resp.State.Set(ctx, data)...)
@@ -203,7 +204,11 @@ func (d *DataSourceFabricItemDefinition) getDefinition(ctx context.Context, mode
respGetOpts := &fabcore.ItemsClientBeginGetItemDefinitionOptions{}
if !model.Format.IsNull() {
- respGetOpts.Format = model.Format.ValueStringPointer()
+ apiFormat := getDefinitionFormatAPI(d.DefinitionFormats, model.Format.ValueString())
+
+ if apiFormat != "" {
+ respGetOpts.Format = azto.Ptr(apiFormat)
+ }
}
respGet, err := d.client.GetItemDefinition(ctx, model.WorkspaceID.ValueString(), model.ID.ValueString(), respGetOpts)
diff --git a/internal/pkg/fabricitem/data_schema.go b/internal/pkg/fabricitem/data_schema.go
index 69d3761c..c6bf4471 100644
--- a/internal/pkg/fabricitem/data_schema.go
+++ b/internal/pkg/fabricitem/data_schema.go
@@ -8,8 +8,14 @@ import (
"fmt"
"github.com/hashicorp/terraform-plugin-framework-timeouts/datasource/timeouts"
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
supertypes "github.com/orange-cloudavenue/terraform-plugin-framework-supertypes"
+ superstringvalidator "github.com/orange-cloudavenue/terraform-plugin-framework-validators/stringvalidator"
"github.com/microsoft/terraform-provider-fabric/internal/framework/customtypes"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/utils"
@@ -27,7 +33,7 @@ func getDataSourceFabricItemSchema(ctx context.Context, d DataSourceFabricItem)
func getDataSourceFabricItemDefinitionSchema(ctx context.Context, d DataSourceFabricItemDefinition) schema.Schema {
attributes := getDataSourceFabricItemBaseAttributes(ctx, d.Name, d.IsDisplayNameUnique)
- for key, value := range getDataSourceFabricItemDefinitionAttributes(ctx, d.Name, d.FormatTypes, d.DefinitionPathKeys) {
+ for key, value := range getDataSourceFabricItemDefinitionAttributes(ctx, d.Name, d.DefinitionFormats) {
attributes[key] = value
}
@@ -51,7 +57,7 @@ func getDataSourceFabricItemDefinitionPropertiesSchema[Ttfprop, Titemprop any](c
attributes := getDataSourceFabricItemBaseAttributes(ctx, d.Name, d.IsDisplayNameUnique)
attributes["properties"] = getDataSourceFabricItemPropertiesNestedAttr[Ttfprop](ctx, d.Name, d.PropertiesAttributes)
- for key, value := range getDataSourceFabricItemDefinitionAttributes(ctx, d.Name, d.FormatTypes, d.DefinitionPathKeys) {
+ for key, value := range getDataSourceFabricItemDefinitionAttributes(ctx, d.Name, d.DefinitionFormats) {
attributes[key] = value
}
@@ -105,21 +111,25 @@ func getDataSourceFabricItemBaseAttributes(ctx context.Context, itemName string,
}
// Helper function to get Fabric Item data-source definition attributes.
-func getDataSourceFabricItemDefinitionAttributes(ctx context.Context, name string, formatTypes, definitionPathKeys []string) map[string]schema.Attribute {
+func getDataSourceFabricItemDefinitionAttributes(ctx context.Context, name string, definitionFormats []DefinitionFormat) map[string]schema.Attribute {
attributes := make(map[string]schema.Attribute)
- if len(formatTypes) > 0 {
- attributes["format"] = schema.StringAttribute{
- MarkdownDescription: fmt.Sprintf("The %s format. Possible values: %s.", name, utils.ConvertStringSlicesToString(formatTypes, true, false)),
- Computed: true,
- }
- } else {
- attributes["format"] = schema.StringAttribute{
- MarkdownDescription: fmt.Sprintf("The %s format. Possible values: `%s`", name, DefinitionFormatNotApplicable),
- Computed: true,
- }
+ formatTypes := getDefinitionFormats(definitionFormats)
+ definitionFormatsDocs := getDefinitionFormatsPathsDocs(definitionFormats)
+
+ // format attribute
+ attrFormat := schema.StringAttribute{}
+
+ attrFormat.MarkdownDescription = fmt.Sprintf("The %s format. Possible values: %s", name, utils.ConvertStringSlicesToString(formatTypes, true, false))
+ attrFormat.Optional = true
+ attrFormat.Validators = []validator.String{
+ stringvalidator.OneOf(formatTypes...),
+ superstringvalidator.RequireIfAttributeIsOneOf(path.MatchRoot("output_definition"), []attr.Value{types.BoolValue(true)}),
}
+ attributes["format"] = attrFormat
+
+ // output_definition attribute
attributes["output_definition"] = schema.BoolAttribute{
MarkdownDescription: "Output definition parts as gzip base64 content? Default: `false`\n\n" +
"!> Your terraform state file may grow a lot if you output definition content. Only use it when you must use data from the definition.",
@@ -141,11 +151,7 @@ func getDataSourceFabricItemDefinitionAttributes(ctx context.Context, name strin
},
}
- if len(definitionPathKeys) > 0 {
- attrDefinition.MarkdownDescription = "Definition parts. Possible path keys: " + utils.ConvertStringSlicesToString(definitionPathKeys, true, false) + "."
- } else {
- attrDefinition.MarkdownDescription = "Definition parts."
- }
+ attrDefinition.MarkdownDescription = "Definition parts. Possible path keys: " + definitionFormatsDocs
attributes["definition"] = attrDefinition
diff --git a/internal/pkg/fabricitem/definition.go b/internal/pkg/fabricitem/definition.go
new file mode 100644
index 00000000..672d96d3
--- /dev/null
+++ b/internal/pkg/fabricitem/definition.go
@@ -0,0 +1,106 @@
+// Copyright (c) Microsoft Corporation
+// SPDX-License-Identifier: MPL-2.0
+
+package fabricitem
+
+import (
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ superstringvalidator "github.com/orange-cloudavenue/terraform-plugin-framework-validators/stringvalidator"
+
+ "github.com/microsoft/terraform-provider-fabric/internal/pkg/utils"
+)
+
+type DefinitionFormat struct {
+ Type string
+ API string
+ Paths []string
+}
+
+func getDefinitionFormats(values []DefinitionFormat) []string {
+ results := make([]string, len(values))
+
+ for i, value := range values {
+ results[i] = value.Type
+ }
+
+ return results
+}
+
+func getDefinitionFormatsPaths(values []DefinitionFormat) map[string][]string {
+ results := make(map[string][]string)
+
+ for _, v := range values {
+ results[v.Type] = v.Paths
+ }
+
+ return results
+}
+
+func getDefinitionFormatsPathsDocs(values []DefinitionFormat) string {
+ elements := getDefinitionFormatsPaths(values)
+
+ var results string
+
+ i := 0
+
+ for k, v := range elements {
+ results += "**" + k + "** format: "
+ results += utils.ConvertStringSlicesToString(v, true, true)
+
+ if i != len(elements)-1 {
+ results += " "
+ }
+
+ i++
+ }
+
+ return results
+}
+
+func GetDefinitionFormatPaths(values []DefinitionFormat, format string) []string {
+ for _, value := range values {
+ if value.Type == format {
+ return value.Paths
+ }
+ }
+
+ return nil
+}
+
+func getDefinitionFormatAPI(values []DefinitionFormat, format string) string {
+ for _, value := range values {
+ if value.Type == format {
+ return value.API
+ }
+ }
+
+ return ""
+}
+
+func DefinitionPathKeysValidator(values []DefinitionFormat) []validator.String {
+ results := make([]validator.String, 0, len(values))
+
+ for _, value := range values {
+ paths := []superstringvalidator.OneOfWithDescriptionIfAttributeIsOneOfValues{}
+
+ for _, p := range value.Paths {
+ paths = append(paths, superstringvalidator.OneOfWithDescriptionIfAttributeIsOneOfValues{
+ Value: p,
+ Description: p,
+ })
+ }
+
+ stringValidator := superstringvalidator.OneOfWithDescriptionIfAttributeIsOneOf(
+ path.MatchRoot("format"),
+ []attr.Value{types.StringValue(value.Type)},
+ paths...,
+ )
+
+ results = append(results, stringValidator)
+ }
+
+ return results
+}
diff --git a/internal/pkg/fabricitem/models_resource_item.go b/internal/pkg/fabricitem/models_resource_item.go
index fc98cfca..fa8cca46 100644
--- a/internal/pkg/fabricitem/models_resource_item.go
+++ b/internal/pkg/fabricitem/models_resource_item.go
@@ -40,11 +40,11 @@ func (to *requestCreateFabricItem) setType(v fabcore.ItemType) {
to.Type = &v
}
-func (to *requestCreateFabricItem) setDefinition(ctx context.Context, definition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], format types.String, definitionUpdateEnabled types.Bool) diag.Diagnostics {
+func (to *requestCreateFabricItem) setDefinition(ctx context.Context, definition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], format types.String, definitionUpdateEnabled types.Bool, definitionFormats []DefinitionFormat) diag.Diagnostics {
if !definition.IsNull() && !definition.IsUnknown() {
var def fabricItemDefinition
- def.setFormat(format)
+ def.setFormat(format, definitionFormats)
if diags := def.setParts(ctx, definition, "", []string{}, definitionUpdateEnabled, false); diags.HasError() {
return diags
@@ -104,9 +104,9 @@ func fabricItemCheckUpdate(planDisplayName, planDescription, stateDisplayName, s
return !reflect.DeepEqual(reqUpdatePlan.UpdateItemRequest, reqUpdateState.UpdateItemRequest)
}
-func fabricItemCheckUpdateDefinition(ctx context.Context, planDefinition, stateDefinition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], planFormat types.String, planDefinitionUpdateEnabled types.Bool, definitionEmpty string, definitionPaths []string, reqUpdate *requestUpdateFabricItemDefinition) (bool, diag.Diagnostics) {
+func fabricItemCheckUpdateDefinition(ctx context.Context, planDefinition, stateDefinition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], planFormat types.String, planDefinitionUpdateEnabled types.Bool, definitionEmpty string, definitionFormats []DefinitionFormat, reqUpdate *requestUpdateFabricItemDefinition) (bool, diag.Diagnostics) {
if !planDefinition.Equal(stateDefinition) && planDefinitionUpdateEnabled.ValueBool() {
- if diags := reqUpdate.setDefinition(ctx, planDefinition, planFormat, planDefinitionUpdateEnabled, definitionEmpty, definitionPaths); diags.HasError() {
+ if diags := reqUpdate.setDefinition(ctx, planDefinition, planFormat, planDefinitionUpdateEnabled, definitionEmpty, definitionFormats); diags.HasError() {
return false, diags
}
diff --git a/internal/pkg/fabricitem/models_resource_item_definition.go b/internal/pkg/fabricitem/models_resource_item_definition.go
index ccb25ba2..1c622fb3 100644
--- a/internal/pkg/fabricitem/models_resource_item_definition.go
+++ b/internal/pkg/fabricitem/models_resource_item_definition.go
@@ -35,9 +35,13 @@ type fabricItemDefinition struct {
fabcore.ItemDefinition
}
-func (to *fabricItemDefinition) setFormat(v types.String) {
- if v.ValueString() != DefinitionFormatNotApplicable && v.ValueString() != "" {
- to.Format = v.ValueStringPointer()
+func (to *fabricItemDefinition) setFormat(v types.String, definitionFormats []DefinitionFormat) {
+ if v.ValueString() != DefinitionFormatDefault && v.ValueString() != "" {
+ apiFormat := getDefinitionFormatAPI(definitionFormats, v.ValueString())
+
+ if apiFormat != "" {
+ to.Format = &apiFormat
+ }
}
}
@@ -62,7 +66,7 @@ func (to *fabricItemDefinition) setParts(ctx context.Context, definition superty
}
to.Parts = append(to.Parts, fabcore.ItemDefinitionPart{
- Path: azto.Ptr(definitionPaths[0]),
+ Path: &definitionPaths[0],
Payload: &content,
PayloadType: azto.Ptr(fabcore.PayloadTypeInlineBase64),
})
@@ -78,7 +82,7 @@ func (to *fabricItemDefinition) setParts(ctx context.Context, definition superty
}
to.Parts = append(to.Parts, fabcore.ItemDefinitionPart{
- Path: azto.Ptr(defPartKey),
+ Path: &defPartKey,
Payload: payloadB64,
PayloadType: azto.Ptr(fabcore.PayloadTypeInlineBase64),
})
@@ -92,12 +96,14 @@ type requestUpdateFabricItemDefinition struct {
fabcore.UpdateItemDefinitionRequest
}
-func (to *requestUpdateFabricItemDefinition) setDefinition(ctx context.Context, definition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], format types.String, definitionUpdateEnabled types.Bool, definitionEmpty string, definitionPaths []string) diag.Diagnostics {
+func (to *requestUpdateFabricItemDefinition) setDefinition(ctx context.Context, definition supertypes.MapNestedObjectValueOf[resourceFabricItemDefinitionPartModel], format types.String, definitionUpdateEnabled types.Bool, definitionEmpty string, definitionFormats []DefinitionFormat) diag.Diagnostics {
var def fabricItemDefinition
- def.setFormat(format)
+ def.setFormat(format, definitionFormats)
+
+ definitionPathKeys := GetDefinitionFormatPaths(definitionFormats, format.ValueString())
- if diags := def.setParts(ctx, definition, definitionEmpty, definitionPaths, definitionUpdateEnabled, true); diags.HasError() {
+ if diags := def.setParts(ctx, definition, definitionEmpty, definitionPathKeys, definitionUpdateEnabled, true); diags.HasError() {
return diags
}
diff --git a/internal/pkg/fabricitem/resource_item_config_definition_properties.go b/internal/pkg/fabricitem/resource_item_config_definition_properties.go
index 2c80ac5b..59ad5541 100644
--- a/internal/pkg/fabricitem/resource_item_config_definition_properties.go
+++ b/internal/pkg/fabricitem/resource_item_config_definition_properties.go
@@ -74,7 +74,7 @@ func (r *ResourceFabricItemConfigDefinitionProperties[Ttfprop, Titemprop, Ttfcon
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
@@ -157,7 +157,7 @@ func (r *ResourceFabricItemConfigDefinitionProperties[Ttfprop, Titemprop, Ttfcon
reqCreate.setDescription(plan.Description)
reqCreate.setType(r.Type)
- if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled)...); resp.Diagnostics.HasError() {
+ if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionFormats)...); resp.Diagnostics.HasError() {
return
}
@@ -283,7 +283,7 @@ func (r *ResourceFabricItemConfigDefinitionProperties[Ttfprop, Titemprop, Ttfcon
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
diff --git a/internal/pkg/fabricitem/resource_item_definition.go b/internal/pkg/fabricitem/resource_item_definition.go
index 2b864ef6..e949d339 100644
--- a/internal/pkg/fabricitem/resource_item_definition.go
+++ b/internal/pkg/fabricitem/resource_item_definition.go
@@ -42,12 +42,11 @@ type ResourceFabricItemDefinition struct {
DisplayNameMaxLength int
DescriptionMaxLength int
FormatTypeDefault string
- FormatTypes []string
DefinitionPathDocsURL string
- DefinitionPathKeys []string
DefinitionPathKeysValidator []validator.Map
DefinitionRequired bool
DefinitionEmpty string
+ DefinitionFormats []DefinitionFormat
}
func NewResourceFabricItemDefinition(config ResourceFabricItemDefinition) resource.Resource {
@@ -80,7 +79,7 @@ func (r *ResourceFabricItemDefinition) ModifyPlan(ctx context.Context, req resou
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
@@ -150,7 +149,7 @@ func (r *ResourceFabricItemDefinition) Create(ctx context.Context, req resource.
reqCreate.setDescription(plan.Description)
reqCreate.setType(r.Type)
- if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled)...); resp.Diagnostics.HasError() {
+ if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionFormats)...); resp.Diagnostics.HasError() {
return
}
@@ -262,7 +261,7 @@ func (r *ResourceFabricItemDefinition) Update(ctx context.Context, req resource.
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
diff --git a/internal/pkg/fabricitem/resource_item_definition_properties.go b/internal/pkg/fabricitem/resource_item_definition_properties.go
index 37e2d440..b0389696 100644
--- a/internal/pkg/fabricitem/resource_item_definition_properties.go
+++ b/internal/pkg/fabricitem/resource_item_definition_properties.go
@@ -69,7 +69,7 @@ func (r *ResourceFabricItemDefinitionProperties[Ttfprop, Titemprop]) ModifyPlan(
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
@@ -139,7 +139,7 @@ func (r *ResourceFabricItemDefinitionProperties[Ttfprop, Titemprop]) Create(ctx
reqCreate.setDescription(plan.Description)
reqCreate.setType(r.Type)
- if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled)...); resp.Diagnostics.HasError() {
+ if resp.Diagnostics.Append(reqCreate.setDefinition(ctx, plan.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionFormats)...); resp.Diagnostics.HasError() {
return
}
@@ -258,7 +258,7 @@ func (r *ResourceFabricItemDefinitionProperties[Ttfprop, Titemprop]) Update(ctx
var reqUpdateDefinition requestUpdateFabricItemDefinition
- doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionPathKeys, &reqUpdateDefinition)
+ doUpdateDefinition, diags := fabricItemCheckUpdateDefinition(ctx, plan.Definition, state.Definition, plan.Format, plan.DefinitionUpdateEnabled, r.DefinitionEmpty, r.DefinitionFormats, &reqUpdateDefinition)
if resp.Diagnostics.Append(diags...); resp.Diagnostics.HasError() {
return
}
diff --git a/internal/pkg/fabricitem/resource_schema.go b/internal/pkg/fabricitem/resource_schema.go
index dcc03955..94efa66b 100644
--- a/internal/pkg/fabricitem/resource_schema.go
+++ b/internal/pkg/fabricitem/resource_schema.go
@@ -22,6 +22,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
supertypes "github.com/orange-cloudavenue/terraform-plugin-framework-supertypes"
+ superstringvalidator "github.com/orange-cloudavenue/terraform-plugin-framework-validators/stringvalidator"
"github.com/microsoft/terraform-provider-fabric/internal/framework/customtypes"
"github.com/microsoft/terraform-provider-fabric/internal/framework/planmodifiers"
@@ -40,7 +41,7 @@ func getResourceFabricItemSchema(ctx context.Context, r ResourceFabricItem) sche
func getResourceFabricItemDefinitionSchema(ctx context.Context, r ResourceFabricItemDefinition) schema.Schema {
attributes := getResourceFabricItemBaseAttributes(ctx, r.Name, r.DisplayNameMaxLength, r.DescriptionMaxLength, r.NameRenameAllowed)
- for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.FormatTypes, r.DefinitionPathDocsURL, r.DefinitionPathKeys, r.DefinitionPathKeysValidator, r.DefinitionRequired, false) {
+ for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.DefinitionPathDocsURL, r.DefinitionFormats, r.DefinitionPathKeysValidator, r.DefinitionRequired, false) {
attributes[key] = value
}
@@ -64,7 +65,7 @@ func getResourceFabricItemDefinitionPropertiesSchema[Ttfprop, Titemprop any](ctx
attributes := getResourceFabricItemBaseAttributes(ctx, r.Name, r.DisplayNameMaxLength, r.DescriptionMaxLength, r.NameRenameAllowed)
attributes["properties"] = getResourceFabricItemPropertiesNestedAttr[Ttfprop](ctx, r.Name, r.PropertiesAttributes)
- for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.FormatTypes, r.DefinitionPathDocsURL, r.DefinitionPathKeys, r.DefinitionPathKeysValidator, r.DefinitionRequired, false) {
+ for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.DefinitionPathDocsURL, r.DefinitionFormats, r.DefinitionPathKeysValidator, r.DefinitionRequired, false) {
attributes[key] = value
}
@@ -98,7 +99,7 @@ func getResourceFabricItemConfigDefinitionPropertiesSchema[Ttfprop, Titemprop, T
attributes["configuration"] = attrConfiguration
attributes["properties"] = getResourceFabricItemPropertiesNestedAttr[Ttfprop](ctx, r.Name, r.PropertiesAttributes)
- for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.FormatTypes, r.DefinitionPathDocsURL, r.DefinitionPathKeys, r.DefinitionPathKeysValidator, r.DefinitionRequired, true) {
+ for key, value := range getResourceFabricItemDefinitionAttributes(ctx, r.Name, r.FormatTypeDefault, r.DefinitionPathDocsURL, r.DefinitionFormats, r.DefinitionPathKeysValidator, r.DefinitionRequired, true) {
attributes[key] = value
}
@@ -188,7 +189,7 @@ func getResourceFabricItemBaseAttributes(ctx context.Context, name string, displ
}
// Helper function to get Fabric Item definition attributes.
-func getResourceFabricItemDefinitionAttributes(ctx context.Context, name, formatTypeDefault string, formatTypes []string, definitionPathDocsURL string, definitionPathKeys []string, definitionPathKeysValidator []validator.Map, definitionRequired, alongConfiguration bool) map[string]schema.Attribute { //revive:disable-line:flag-parameter,argument-limit
+func getResourceFabricItemDefinitionAttributes(ctx context.Context, name, formatTypeDefault, definitionPathDocsURL string, definitionFormats []DefinitionFormat, definitionPathKeysValidator []validator.Map, definitionRequired, alongConfiguration bool) map[string]schema.Attribute { //revive:disable-line:flag-parameter,argument-limit
attributes := make(map[string]schema.Attribute)
attrDefinitionUpdateEnabled := schema.BoolAttribute{}
@@ -206,27 +207,33 @@ func getResourceFabricItemDefinitionAttributes(ctx context.Context, name, format
attributes["definition_update_enabled"] = attrDefinitionUpdateEnabled
+ formatTypes := getDefinitionFormats(definitionFormats)
+ definitionFormatsDocs := getDefinitionFormatsPathsDocs(definitionFormats)
+
attrFormat := schema.StringAttribute{}
- attrFormat.Computed = true
- if len(formatTypes) > 0 {
- attrFormat.MarkdownDescription = fmt.Sprintf("The %s format. Possible values: %s.", name, utils.ConvertStringSlicesToString(formatTypes, true, false))
- attrFormat.Default = stringdefault.StaticString(formatTypeDefault)
+ attrFormat.MarkdownDescription = fmt.Sprintf("The %s format. Possible values: %s", name, utils.ConvertStringSlicesToString(formatTypes, true, false))
+ attrFormat.Validators = []validator.String{
+ stringvalidator.OneOf(utils.ConvertEnumsToStringSlices(formatTypes, true)...),
+ superstringvalidator.RequireIfAttributeIsSet(path.MatchRoot("definition")),
+ }
+
+ if definitionRequired {
+ attrFormat.Required = true
} else {
- attrFormat.MarkdownDescription = fmt.Sprintf("The %s format. Possible values: `%s`", name, DefinitionFormatNotApplicable)
- attrFormat.Default = stringdefault.StaticString(DefinitionFormatNotApplicable)
+ attrFormat.Optional = true
+ attrFormat.Computed = true
+ attrFormat.Default = stringdefault.StaticString(formatTypeDefault)
}
if alongConfiguration {
- attrFormat.Validators = []validator.String{
- stringvalidator.ConflictsWith(path.MatchRoot("configuration")),
- }
+ attrFormat.Validators = append(attrFormat.Validators, stringvalidator.ConflictsWith(path.MatchRoot("configuration")))
}
attributes["format"] = attrFormat
attrDefinition := schema.MapNestedAttribute{}
- attrDefinition.MarkdownDescription = fmt.Sprintf("Definition parts. Accepted path keys: %s. Read more about [%s definition part paths](%s).", utils.ConvertStringSlicesToString(definitionPathKeys, true, false), name, definitionPathDocsURL)
+ attrDefinition.MarkdownDescription = fmt.Sprintf("Definition parts. Read more about [%s definition part paths](%s). Accepted path keys: %s", name, definitionPathDocsURL, definitionFormatsDocs)
attrDefinition.CustomType = supertypes.NewMapNestedObjectTypeOf[resourceFabricItemDefinitionPartModel](ctx)
attrDefinition.Validators = definitionPathKeysValidator
attrDefinition.NestedObject = getResourceFabricItemDefinitionPartSchema(ctx)
diff --git a/internal/provider/utils/values.go b/internal/provider/utils/values.go
index cf6877df..5fe05cad 100644
--- a/internal/provider/utils/values.go
+++ b/internal/provider/utils/values.go
@@ -16,10 +16,10 @@ import (
func GetValueOrFileValue(attValue, attFile string, value, file types.String) (string, error) {
valueResult := value.ValueString()
- if path := file.ValueString(); path != "" {
- fileRaw, err := os.ReadFile(path)
+ if p := file.ValueString(); p != "" {
+ fileRaw, err := os.ReadFile(p)
if err != nil {
- return "", fmt.Errorf("reading '%s' from file %q: %w", attFile, path, err)
+ return "", fmt.Errorf("reading '%s' from file %q: %w", attFile, p, err)
}
fileResult := strings.TrimSpace(string(fileRaw))
@@ -36,10 +36,10 @@ func GetValueOrFileValue(attValue, attFile string, value, file types.String) (st
func GetCertOrFileCert(attValue, attFile string, value, file types.String) (string, error) {
valueResult := strings.TrimSpace(value.ValueString())
- if path := file.ValueString(); path != "" {
- b64, err := auth.ConvertFileToBase64(path)
+ if p := file.ValueString(); p != "" {
+ b64, err := auth.ConvertFileToBase64(p)
if err != nil {
- return "", fmt.Errorf("reading '%s' from file %q: %w", attFile, path, err)
+ return "", fmt.Errorf("reading '%s' from file %q: %w", attFile, p, err)
}
fileResult := strings.TrimSpace(b64)
diff --git a/internal/services/datapipeline/base.go b/internal/services/datapipeline/base.go
index 89ec5804..61a906c5 100644
--- a/internal/services/datapipeline/base.go
+++ b/internal/services/datapipeline/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -21,4 +22,10 @@ const (
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/fabric/data-factory/pipeline-rest-api"
)
-var ItemDefinitionPaths = []string{"pipeline-content.json"} //nolint:gochecknoglobals
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: fabricitem.DefinitionFormatDefault,
+ API: "",
+ Paths: []string{"pipeline-content.json"},
+ },
+}
diff --git a/internal/services/datapipeline/resource_data_pipeline.go b/internal/services/datapipeline/resource_data_pipeline.go
index 2730140b..78b4efff 100644
--- a/internal/services/datapipeline/resource_data_pipeline.go
+++ b/internal/services/datapipeline/resource_data_pipeline.go
@@ -23,16 +23,15 @@ func NewResourceDataPipeline() resource.Resource {
ItemDocsSPNSupport,
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
- FormatTypeDefault: "",
- FormatTypes: []string{},
+ FormatTypeDefault: fabricitem.DefinitionFormatDefault,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPaths,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtMost(1),
- mapvalidator.KeysAre(stringvalidator.OneOf(ItemDefinitionPaths...)),
+ mapvalidator.KeysAre(stringvalidator.OneOf(fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, fabricitem.DefinitionFormatDefault)...)),
},
DefinitionRequired: false,
DefinitionEmpty: ItemDefinitionEmpty,
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewResourceFabricItemDefinition(config)
diff --git a/internal/services/eventhouse/base.go b/internal/services/eventhouse/base.go
index 8d30857e..6934e326 100644
--- a/internal/services/eventhouse/base.go
+++ b/internal/services/eventhouse/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -17,12 +18,15 @@ const (
ItemType = fabcore.ItemTypeEventhouse
ItemDocsSPNSupport = common.DocsSPNSupported
ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/eventhouse"
- ItemFormatTypeDefault = ""
+ ItemFormatTypeDefault = fabricitem.DefinitionFormatDefault
ItemDefinitionEmpty = `{}`
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/eventhouse-definition"
)
-var (
- ItemFormatTypes = []string{} //nolint:gochecknoglobals
- ItemDefinitionPaths = []string{"EventhouseProperties.json"} //nolint:gochecknoglobals
-)
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: fabricitem.DefinitionFormatDefault,
+ API: "",
+ Paths: []string{"EventhouseProperties.json"},
+ },
+}
diff --git a/internal/services/eventhouse/data_eventhouse.go b/internal/services/eventhouse/data_eventhouse.go
index 78e43261..75a258c0 100644
--- a/internal/services/eventhouse/data_eventhouse.go
+++ b/internal/services/eventhouse/data_eventhouse.go
@@ -79,8 +79,7 @@ func NewDataSourceEventhouse(ctx context.Context) datasource.DataSource {
ItemDocsSPNSupport,
IsDisplayNameUnique: true,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
- DefinitionPathKeys: ItemDefinitionPaths,
+ DefinitionFormats: itemDefinitionFormats,
},
PropertiesAttributes: getDataSourceEventhousePropertiesAttributes(ctx),
PropertiesSetter: propertiesSetter,
diff --git a/internal/services/eventhouse/resource_eventhouse.go b/internal/services/eventhouse/resource_eventhouse.go
index 91ad8da0..4ccec754 100644
--- a/internal/services/eventhouse/resource_eventhouse.go
+++ b/internal/services/eventhouse/resource_eventhouse.go
@@ -7,7 +7,6 @@ import (
"context"
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
- "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -62,15 +61,14 @@ func NewResourceEventhouse(ctx context.Context) resource.Resource {
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPaths,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtMost(1),
- mapvalidator.KeysAre(stringvalidator.OneOf(ItemDefinitionPaths...)),
+ mapvalidator.KeysAre(fabricitem.DefinitionPathKeysValidator(itemDefinitionFormats)...),
},
DefinitionRequired: false,
DefinitionEmpty: ItemDefinitionEmpty,
+ DefinitionFormats: itemDefinitionFormats,
},
PropertiesAttributes: getResourceEventhousePropertiesAttributes(ctx),
PropertiesSetter: propertiesSetter,
diff --git a/internal/services/kqldatabase/base.go b/internal/services/kqldatabase/base.go
index e54e5de9..c82c7a7b 100644
--- a/internal/services/kqldatabase/base.go
+++ b/internal/services/kqldatabase/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -17,11 +18,14 @@ const (
ItemType = fabcore.ItemTypeKQLDatabase
ItemDocsSPNSupport = common.DocsSPNSupported
ItemDocsURL = "https://learn.microsoft.com/fabric/real-time-intelligence/create-database"
- ItemFormatTypeDefault = ""
+ ItemFormatTypeDefault = fabricitem.DefinitionFormatDefault
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/kql-database-definition"
)
-var (
- ItemFormatTypes = []string{""} //nolint:gochecknoglobals
- ItemDefinitionPaths = []string{"DatabaseProperties.json", "DatabaseSchema.kql"} //nolint:gochecknoglobals
-)
+// var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+// {
+// Type: fabricitem.DefinitionFormatDefault,
+// API: "",
+// Paths: []string{"DatabaseProperties.json", "DatabaseSchema.kql"},
+// },
+// }
diff --git a/internal/services/notebook/base.go b/internal/services/notebook/base.go
index 881e382d..a771ffaf 100644
--- a/internal/services/notebook/base.go
+++ b/internal/services/notebook/base.go
@@ -7,22 +7,31 @@ 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 = "Notebook"
- ItemTFName = "notebook"
- ItemsName = "Notebooks"
- ItemsTFName = "notebooks"
- ItemType = fabcore.ItemTypeNotebook
- ItemDocsSPNSupport = common.DocsSPNSupported
- ItemDocsURL = "https://learn.microsoft.com/fabric/data-engineering/how-to-use-notebook"
- ItemFormatTypeDefault = "ipynb"
- ItemDefinitionEmptyIPYNB = `{"cells":[{"cell_type":"code","metadata":{},"source":["# Welcome to your notebook"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":5}`
- ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/notebook-definition"
+ ItemName = "Notebook"
+ ItemTFName = "notebook"
+ ItemsName = "Notebooks"
+ ItemsTFName = "notebooks"
+ ItemType = fabcore.ItemTypeNotebook
+ ItemDocsSPNSupport = common.DocsSPNSupported
+ ItemDocsURL = "https://learn.microsoft.com/fabric/data-engineering/how-to-use-notebook"
+ ItemDefinitionFormatTypeDefault = "ipynb"
+ ItemDefinitionEmptyIPYNB = `{"cells":[{"cell_type":"code","metadata":{},"source":["# Welcome to your notebook"]}],"metadata":{"language_info":{"name":"python"}},"nbformat":4,"nbformat_minor":5}`
+ ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/notebook-definition"
)
-var (
- ItemFormatTypes = []string{"ipynb"} //nolint:gochecknoglobals
- ItemDefinitionPathsIPYNB = []string{"notebook-content.ipynb"} //nolint:gochecknoglobals
-)
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: "ipynb",
+ API: "ipynb",
+ Paths: []string{"notebook-content.ipynb"},
+ },
+ {
+ Type: "py",
+ API: "",
+ Paths: []string{"notebook-content.py"},
+ },
+}
diff --git a/internal/services/notebook/data_notebook.go b/internal/services/notebook/data_notebook.go
index d3c9e299..50907fb7 100644
--- a/internal/services/notebook/data_notebook.go
+++ b/internal/services/notebook/data_notebook.go
@@ -18,9 +18,8 @@ func NewDataSourceNotebook() datasource.DataSource {
"Use this data source to fetch a [" + ItemName + "](" + ItemDocsURL + ").\n\n" +
ItemDocsSPNSupport,
IsDisplayNameUnique: true,
- FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
- DefinitionPathKeys: ItemDefinitionPathsIPYNB,
+ FormatTypeDefault: ItemDefinitionFormatTypeDefault,
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewDataSourceFabricItemDefinition(config)
diff --git a/internal/services/notebook/data_notebook_test.go b/internal/services/notebook/data_notebook_test.go
index cd7a7816..3bd2700d 100644
--- a/internal/services/notebook/data_notebook_test.go
+++ b/internal/services/notebook/data_notebook_test.go
@@ -173,6 +173,7 @@ func TestAcc_NotebookDataSource(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 id - not found
@@ -200,6 +201,7 @@ func TestAcc_NotebookDataSource(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 +215,55 @@ func TestAcc_NotebookDataSource(t *testing.T) {
),
ExpectError: regexp.MustCompile(common.ErrorReadHeader),
},
+ // read by id with definition - default
+ {
+ 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 - py
+ {
+ Config: at.CompileConfig(
+ testDataSourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "id": entityID,
+ "output_definition": true,
+ "format": "py",
+ },
+ ),
+ 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.notebook-content.py.content"),
+ ),
+ },
+ // read by id with definition - ipynb
+ {
+ Config: at.CompileConfig(
+ testDataSourceItemHeader,
+ map[string]any{
+ "workspace_id": workspaceID,
+ "id": entityID,
+ "output_definition": true,
+ "format": "ipynb",
+ },
+ ),
+ 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.notebook-content.ipynb.content"),
+ ),
+ },
}))
}
diff --git a/internal/services/notebook/resource_notebook.go b/internal/services/notebook/resource_notebook.go
index 48e72528..98fbc5b8 100644
--- a/internal/services/notebook/resource_notebook.go
+++ b/internal/services/notebook/resource_notebook.go
@@ -5,7 +5,6 @@ package notebook
import (
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
- "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -23,16 +22,15 @@ func NewResourceNotebook() resource.Resource {
ItemDocsSPNSupport,
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
- FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
+ FormatTypeDefault: ItemDefinitionFormatTypeDefault,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPathsIPYNB,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtMost(1),
- mapvalidator.KeysAre(stringvalidator.OneOf(ItemDefinitionPathsIPYNB...)),
+ mapvalidator.KeysAre(fabricitem.DefinitionPathKeysValidator(itemDefinitionFormats)...),
},
DefinitionRequired: false,
DefinitionEmpty: ItemDefinitionEmptyIPYNB,
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewResourceFabricItemDefinition(config)
diff --git a/internal/services/notebook/resource_notebook_test.go b/internal/services/notebook/resource_notebook_test.go
index 0839a038..32b1bd2f 100644
--- a/internal/services/notebook/resource_notebook_test.go
+++ b/internal/services/notebook/resource_notebook_test.go
@@ -28,12 +28,18 @@ var testHelperLocals = at.CompileLocalsConfig(map[string]any{
"path": testhelp.GetFixturesDirPath("notebook"),
})
-var testHelperDefinition = map[string]any{
+var testHelperDefinitionIPYNB = map[string]any{
`"notebook-content.ipynb"`: map[string]any{
"source": "${local.path}/notebook.ipynb.tmpl",
},
}
+var testHelperDefinitionPY = map[string]any{
+ `"notebook-content.py"`: map[string]any{
+ "source": "${local.path}/notebook.py.tmpl",
+ },
+}
+
func TestUnit_NotebookResource_Attributes(t *testing.T) {
resource.ParallelTest(t, testhelp.NewTestUnitCase(t, &testResourceItemFQN, fakes.FakeServer.ServerFactory, nil, []resource.TestStep{
// error - no attributes
@@ -58,7 +64,8 @@ func TestUnit_NotebookResource_Attributes(t *testing.T) {
map[string]any{
"workspace_id": "invalid uuid",
"display_name": "test",
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
ExpectError: regexp.MustCompile(customtypes.UUIDTypeErrorInvalidStringHeader),
@@ -74,7 +81,8 @@ func TestUnit_NotebookResource_Attributes(t *testing.T) {
"workspace_id": "00000000-0000-0000-0000-000000000000",
"display_name": "test",
"unexpected_attr": "test",
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
ExpectError: regexp.MustCompile(`An argument named "unexpected_attr" is not expected here`),
@@ -88,7 +96,8 @@ func TestUnit_NotebookResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"display_name": "test",
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
ExpectError: regexp.MustCompile(`The argument "workspace_id" is required, but no definition was found.`),
@@ -102,7 +111,8 @@ func TestUnit_NotebookResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"workspace_id": "00000000-0000-0000-0000-000000000000",
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
ExpectError: regexp.MustCompile(`The argument "display_name" is required, but no definition was found.`),
@@ -125,7 +135,8 @@ func TestUnit_NotebookResource_ImportState(t *testing.T) {
map[string]any{
"workspace_id": *entity.WorkspaceID,
"display_name": *entity.DisplayName,
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
))
@@ -202,7 +213,8 @@ func TestUnit_NotebookResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityExist.WorkspaceID,
"display_name": *entityExist.DisplayName,
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
ExpectError: regexp.MustCompile(common.ErrorCreateHeader),
@@ -217,7 +229,8 @@ func TestUnit_NotebookResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityBefore.DisplayName,
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
Check: resource.ComposeAggregateTestCheckFunc(
@@ -236,7 +249,8 @@ func TestUnit_NotebookResource_CRUD(t *testing.T) {
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityAfter.DisplayName,
"description": *entityAfter.Description,
- "definition": testHelperDefinition,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
},
)),
Check: resource.ComposeAggregateTestCheckFunc(
@@ -268,7 +282,110 @@ func TestAcc_NotebookResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityCreateDisplayName,
- "definition": testHelperDefinition,
+ },
+ )),
+ 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_NotebookDefinitionIPYNBResource_CRUD(t *testing.T) {
+ workspace := testhelp.WellKnown()["Workspace"].(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,
+ "format": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
+ },
+ )),
+ 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": "ipynb",
+ "definition": testHelperDefinitionIPYNB,
+ },
+ )),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(testResourceItemFQN, "display_name", entityUpdateDisplayName),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "description", entityUpdateDescription),
+ resource.TestCheckResourceAttr(testResourceItemFQN, "definition_update_enabled", "true"),
+ ),
+ },
+ },
+ ))
+}
+
+func TestAcc_NotebookDefinitionPYResource_CRUD(t *testing.T) {
+ workspace := testhelp.WellKnown()["Workspace"].(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,
+ "format": "py",
+ "definition": testHelperDefinitionPY,
},
)),
Check: resource.ComposeAggregateTestCheckFunc(
@@ -288,7 +405,8 @@ func TestAcc_NotebookResource_CRUD(t *testing.T) {
"workspace_id": workspaceID,
"display_name": entityUpdateDisplayName,
"description": entityUpdateDescription,
- "definition": testHelperDefinition,
+ "format": "py",
+ "definition": testHelperDefinitionPY,
},
)),
Check: resource.ComposeAggregateTestCheckFunc(
diff --git a/internal/services/report/base.go b/internal/services/report/base.go
index 84e3c701..bebbe73b 100644
--- a/internal/services/report/base.go
+++ b/internal/services/report/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -21,7 +22,15 @@ const (
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/report-definition"
)
-var (
- ItemFormatTypes = []string{"PBIR-Legacy"} //nolint:gochecknoglobals
- ItemDefinitionPathsPBIRLegacy = []string{"report.json", "definition.pbir", "StaticResources/RegisteredResources/*", "StaticResources/SharedResources/*"} //nolint:gochecknoglobals
-)
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: "PBIR-Legacy",
+ API: "PBIR-Legacy",
+ Paths: []string{"report.json", "definition.pbir", "StaticResources/RegisteredResources/*", "StaticResources/SharedResources/*"},
+ },
+ {
+ Type: "PBIR",
+ API: "PBIR",
+ Paths: []string{"definition/report.json", "definition/version.json", "definition.pbir", "definition/pages/*.json", "StaticResources/RegisteredResources/*", "StaticResources/SharedResources/*"},
+ },
+}
diff --git a/internal/services/report/data_report.go b/internal/services/report/data_report.go
index fd6e4002..cf359c73 100644
--- a/internal/services/report/data_report.go
+++ b/internal/services/report/data_report.go
@@ -19,8 +19,7 @@ func NewDataSourceReport() datasource.DataSource {
ItemDocsSPNSupport,
IsDisplayNameUnique: false,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
- DefinitionPathKeys: ItemDefinitionPathsPBIRLegacy,
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewDataSourceFabricItemDefinition(config)
diff --git a/internal/services/report/data_report_test.go b/internal/services/report/data_report_test.go
index 3a2b32c2..791d89b5 100644
--- a/internal/services/report/data_report_test.go
+++ b/internal/services/report/data_report_test.go
@@ -156,6 +156,7 @@ func TestAcc_ReportDataSource(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"id": entityID,
+ "format": "PBIR-Legacy",
"output_definition": true,
},
),
diff --git a/internal/services/report/resource_report.go b/internal/services/report/resource_report.go
index 37935f31..e1548674 100644
--- a/internal/services/report/resource_report.go
+++ b/internal/services/report/resource_report.go
@@ -4,13 +4,14 @@
package report
import (
- "regexp"
-
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
- "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ fwvalidators "github.com/microsoft/terraform-provider-fabric/internal/framework/validators"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/fabricitem"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/utils"
)
@@ -27,20 +28,27 @@ func NewResourceReport() resource.Resource {
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPathsPBIRLegacy,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtLeast(3),
mapvalidator.KeysAre(
- stringvalidator.RegexMatches(
- regexp.MustCompile(`^(report\.json|definition\.pbir|StaticResources/RegisteredResources/.*|StaticResources/SharedResources/.*)$`),
- "Definition path must match one of the following: "+utils.ConvertStringSlicesToString(ItemDefinitionPathsPBIRLegacy, true, false),
+ fwvalidators.RegexpIfAttributeIsOneOf(
+ path.MatchRoot("format"),
+ []attr.Value{types.StringValue("PBIR-Legacy")},
+ fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "PBIR-Legacy"),
+ "Definition path must match one of the following: "+utils.ConvertStringSlicesToString(fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "PBIR-Legacy"), true, false),
+ ),
+ fwvalidators.RegexpIfAttributeIsOneOf(
+ path.MatchRoot("format"),
+ []attr.Value{types.StringValue("PBIR")},
+ fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "PBIR"),
+ "Definition path must match one of the following: "+utils.ConvertStringSlicesToString(fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "PBIR"), true, false),
),
),
},
DefinitionRequired: true,
DefinitionEmpty: "",
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewResourceFabricItemDefinition(config)
diff --git a/internal/services/report/resource_report_test.go b/internal/services/report/resource_report_test.go
index ff56b02b..328193b5 100644
--- a/internal/services/report/resource_report_test.go
+++ b/internal/services/report/resource_report_test.go
@@ -68,6 +68,7 @@ func TestUnit_ReportResource_Attributes(t *testing.T) {
map[string]any{
"workspace_id": "invalid uuid",
"display_name": "test",
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -84,6 +85,7 @@ func TestUnit_ReportResource_Attributes(t *testing.T) {
"workspace_id": "00000000-0000-0000-0000-000000000000",
"display_name": "test",
"unexpected_attr": "test",
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -98,6 +100,7 @@ func TestUnit_ReportResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"display_name": "test",
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -112,6 +115,7 @@ func TestUnit_ReportResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"workspace_id": "00000000-0000-0000-0000-000000000000",
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -149,6 +153,7 @@ func TestUnit_ReportResource_ImportState(t *testing.T) {
map[string]any{
"workspace_id": *entity.WorkspaceID,
"display_name": *entity.DisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
))
@@ -231,6 +236,7 @@ func TestUnit_ReportResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityExist.WorkspaceID,
"display_name": *entityExist.DisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -246,6 +252,7 @@ func TestUnit_ReportResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityBefore.DisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -265,6 +272,7 @@ func TestUnit_ReportResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityAfter.DisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -300,6 +308,7 @@ func TestAcc_ReportResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityCreateDisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
@@ -319,6 +328,7 @@ func TestAcc_ReportResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityUpdateDisplayName,
+ "format": "PBIR-Legacy",
"definition": testHelperDefinition,
},
)),
diff --git a/internal/services/semanticmodel/base.go b/internal/services/semanticmodel/base.go
index b28d72dd..cecd3143 100644
--- a/internal/services/semanticmodel/base.go
+++ b/internal/services/semanticmodel/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -21,7 +22,15 @@ const (
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/semantic-model-definition"
)
-var (
- ItemFormatTypes = []string{"TMSL"} //nolint:gochecknoglobals
- ItemDefinitionPathsTMSL = []string{"model.bim", "definition.pbism", "diagramLayout.json"} //nolint:gochecknoglobals
-)
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: "TMSL",
+ API: "TMSL",
+ Paths: []string{"model.bim", "definition.pbism", "diagramLayp.json"},
+ },
+ {
+ Type: "TMDL",
+ API: "TMDL",
+ Paths: []string{"definition/database.tmdl", "definition/model.tmdl", "definition.pbism", "diagramLayp.json", "definition/tables/*.tmdl"},
+ },
+}
diff --git a/internal/services/semanticmodel/data_semantic_model.go b/internal/services/semanticmodel/data_semantic_model.go
index b0ed23bb..fcd7bbdd 100644
--- a/internal/services/semanticmodel/data_semantic_model.go
+++ b/internal/services/semanticmodel/data_semantic_model.go
@@ -19,8 +19,7 @@ func NewDataSourceSemanticModel() datasource.DataSource {
ItemDocsSPNSupport,
IsDisplayNameUnique: false,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
- DefinitionPathKeys: ItemDefinitionPathsTMSL,
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewDataSourceFabricItemDefinition(config)
diff --git a/internal/services/semanticmodel/data_semantic_model_test.go b/internal/services/semanticmodel/data_semantic_model_test.go
index 302f8865..0ea4792e 100644
--- a/internal/services/semanticmodel/data_semantic_model_test.go
+++ b/internal/services/semanticmodel/data_semantic_model_test.go
@@ -156,6 +156,7 @@ func TestAcc_SemanticModelDataSource(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"id": entityID,
+ "format": "TMSL",
"output_definition": true,
},
),
diff --git a/internal/services/semanticmodel/resource_semantic_model.go b/internal/services/semanticmodel/resource_semantic_model.go
index 8cfcfafa..022608c1 100644
--- a/internal/services/semanticmodel/resource_semantic_model.go
+++ b/internal/services/semanticmodel/resource_semantic_model.go
@@ -5,11 +5,15 @@ package semanticmodel
import (
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
- "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ fwvalidators "github.com/microsoft/terraform-provider-fabric/internal/framework/validators"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/fabricitem"
+ "github.com/microsoft/terraform-provider-fabric/internal/pkg/utils"
)
func NewResourceSemanticModel() resource.Resource {
@@ -24,15 +28,27 @@ func NewResourceSemanticModel() resource.Resource {
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPathsTMSL,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtLeast(2),
- mapvalidator.KeysAre(stringvalidator.OneOf(ItemDefinitionPathsTMSL...)),
+ mapvalidator.KeysAre(
+ fwvalidators.RegexpIfAttributeIsOneOf(
+ path.MatchRoot("format"),
+ []attr.Value{types.StringValue("TMSL")},
+ fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "TMSL"),
+ "Definition path must match one of the following: "+utils.ConvertStringSlicesToString(fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "TMSL"), true, false),
+ ),
+ fwvalidators.RegexpIfAttributeIsOneOf(
+ path.MatchRoot("format"),
+ []attr.Value{types.StringValue("TMDL")},
+ fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "TMDL"),
+ "Definition path must match one of the following: "+utils.ConvertStringSlicesToString(fabricitem.GetDefinitionFormatPaths(itemDefinitionFormats, "TMDL"), true, false),
+ ),
+ ),
},
DefinitionRequired: true,
DefinitionEmpty: "",
+ DefinitionFormats: itemDefinitionFormats,
}
return fabricitem.NewResourceFabricItemDefinition(config)
diff --git a/internal/services/semanticmodel/resource_semantic_model_test.go b/internal/services/semanticmodel/resource_semantic_model_test.go
index 40af2ada..d35a51cb 100644
--- a/internal/services/semanticmodel/resource_semantic_model_test.go
+++ b/internal/services/semanticmodel/resource_semantic_model_test.go
@@ -64,6 +64,7 @@ func TestUnit_SemanticModelResource_Attributes(t *testing.T) {
map[string]any{
"workspace_id": "invalid uuid",
"display_name": "test",
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -80,6 +81,7 @@ func TestUnit_SemanticModelResource_Attributes(t *testing.T) {
"workspace_id": "00000000-0000-0000-0000-000000000000",
"display_name": "test",
"unexpected_attr": "test",
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -94,6 +96,7 @@ func TestUnit_SemanticModelResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"display_name": "test",
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -108,6 +111,7 @@ func TestUnit_SemanticModelResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"workspace_id": "00000000-0000-0000-0000-000000000000",
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -145,6 +149,7 @@ func TestUnit_SemanticModelResource_ImportState(t *testing.T) {
map[string]any{
"workspace_id": *entity.WorkspaceID,
"display_name": *entity.DisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
))
@@ -222,6 +227,7 @@ func TestUnit_SemanticModelResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityExist.WorkspaceID,
"display_name": *entityExist.DisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -237,6 +243,7 @@ func TestUnit_SemanticModelResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityBefore.DisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -256,6 +263,7 @@ func TestUnit_SemanticModelResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityAfter.DisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -286,6 +294,7 @@ func TestAcc_SemanticModelResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityCreateDisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
@@ -305,6 +314,7 @@ func TestAcc_SemanticModelResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityUpdateDisplayName,
+ "format": "TMSL",
"definition": testHelperDefinition,
},
)),
diff --git a/internal/services/sparkjobdefinition/base.go b/internal/services/sparkjobdefinition/base.go
index 5a9ed42a..3ac1e2db 100644
--- a/internal/services/sparkjobdefinition/base.go
+++ b/internal/services/sparkjobdefinition/base.go
@@ -7,6 +7,7 @@ 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 (
@@ -22,7 +23,10 @@ const (
ItemDefinitionPathDocsURL = "https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/spark-job-definition"
)
-var (
- ItemFormatTypes = []string{"SparkJobDefinitionV1"} //nolint:gochecknoglobals
- ItemDefinitionPaths = []string{"SparkJobDefinitionV1.json"} //nolint:gochecknoglobals
-)
+var itemDefinitionFormats = []fabricitem.DefinitionFormat{ //nolint:gochecknoglobals
+ {
+ Type: "SparkJobDefinitionV1",
+ API: "SparkJobDefinitionV1",
+ Paths: []string{"SparkJobDefinitionV1.json"},
+ },
+}
diff --git a/internal/services/sparkjobdefinition/data_spark_job_definition.go b/internal/services/sparkjobdefinition/data_spark_job_definition.go
index 386396e5..e8125332 100644
--- a/internal/services/sparkjobdefinition/data_spark_job_definition.go
+++ b/internal/services/sparkjobdefinition/data_spark_job_definition.go
@@ -79,8 +79,7 @@ func NewDataSourceSparkJobDefinition() datasource.DataSource {
ItemDocsSPNSupport,
IsDisplayNameUnique: true,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
- DefinitionPathKeys: ItemDefinitionPaths,
+ DefinitionFormats: itemDefinitionFormats,
},
PropertiesAttributes: getDataSourceSparkJobDefinitionPropertiesAttributes(),
PropertiesSetter: propertiesSetter,
diff --git a/internal/services/sparkjobdefinition/data_spark_job_definition_test.go b/internal/services/sparkjobdefinition/data_spark_job_definition_test.go
index cb6d1700..d2e952c0 100644
--- a/internal/services/sparkjobdefinition/data_spark_job_definition_test.go
+++ b/internal/services/sparkjobdefinition/data_spark_job_definition_test.go
@@ -227,6 +227,7 @@ func TestAcc_SparkJobDefinitionDataSource(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"id": entityID,
+ "format": "SparkJobDefinitionV1",
"output_definition": true,
},
),
diff --git a/internal/services/sparkjobdefinition/resource_spark_job_definition.go b/internal/services/sparkjobdefinition/resource_spark_job_definition.go
index 3c22c21c..2836dfe4 100644
--- a/internal/services/sparkjobdefinition/resource_spark_job_definition.go
+++ b/internal/services/sparkjobdefinition/resource_spark_job_definition.go
@@ -7,7 +7,6 @@ import (
"context"
"github.com/hashicorp/terraform-plugin-framework-validators/mapvalidator"
- "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
@@ -62,15 +61,14 @@ func NewResourceSparkJobDefinition() resource.Resource {
DisplayNameMaxLength: 123,
DescriptionMaxLength: 256,
FormatTypeDefault: ItemFormatTypeDefault,
- FormatTypes: ItemFormatTypes,
DefinitionPathDocsURL: ItemDefinitionPathDocsURL,
- DefinitionPathKeys: ItemDefinitionPaths,
DefinitionPathKeysValidator: []validator.Map{
mapvalidator.SizeAtMost(1),
- mapvalidator.KeysAre(stringvalidator.OneOf(ItemDefinitionPaths...)),
+ mapvalidator.KeysAre(fabricitem.DefinitionPathKeysValidator(itemDefinitionFormats)...),
},
DefinitionRequired: false,
DefinitionEmpty: ItemDefinitionEmpty,
+ DefinitionFormats: itemDefinitionFormats,
},
PropertiesAttributes: getResourceSparkJobDefinitionPropertiesAttributes(),
PropertiesSetter: propertiesSetter,
diff --git a/internal/services/sparkjobdefinition/resource_spark_job_definition_test.go b/internal/services/sparkjobdefinition/resource_spark_job_definition_test.go
index 057529af..75c7ff0e 100644
--- a/internal/services/sparkjobdefinition/resource_spark_job_definition_test.go
+++ b/internal/services/sparkjobdefinition/resource_spark_job_definition_test.go
@@ -58,6 +58,7 @@ func TestUnit_SparkJobDefinitionResource_Attributes(t *testing.T) {
map[string]any{
"workspace_id": "invalid uuid",
"display_name": "test",
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -74,6 +75,7 @@ func TestUnit_SparkJobDefinitionResource_Attributes(t *testing.T) {
"workspace_id": "00000000-0000-0000-0000-000000000000",
"display_name": "test",
"unexpected_attr": "test",
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -88,6 +90,7 @@ func TestUnit_SparkJobDefinitionResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"display_name": "test",
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -102,6 +105,7 @@ func TestUnit_SparkJobDefinitionResource_Attributes(t *testing.T) {
testResourceItemHeader,
map[string]any{
"workspace_id": "00000000-0000-0000-0000-000000000000",
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -125,6 +129,7 @@ func TestUnit_SparkJobDefinitionResource_ImportState(t *testing.T) {
map[string]any{
"workspace_id": *entity.WorkspaceID,
"display_name": *entity.DisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
))
@@ -202,6 +207,7 @@ func TestUnit_SparkJobDefinitionResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityExist.WorkspaceID,
"display_name": *entityExist.DisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -217,6 +223,7 @@ func TestUnit_SparkJobDefinitionResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityBefore.DisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -236,6 +243,7 @@ func TestUnit_SparkJobDefinitionResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": *entityBefore.WorkspaceID,
"display_name": *entityAfter.DisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -267,6 +275,7 @@ func TestAcc_SparkJobDefinitionResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityCreateDisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
@@ -287,6 +296,7 @@ func TestAcc_SparkJobDefinitionResource_CRUD(t *testing.T) {
map[string]any{
"workspace_id": workspaceID,
"display_name": entityUpdateDisplayName,
+ "format": "SparkJobDefinitionV1",
"definition": testHelperDefinition,
},
)),
diff --git a/internal/services/workspace/resource_workspace_git.go b/internal/services/workspace/resource_workspace_git.go
index 871aeb08..ade465b8 100644
--- a/internal/services/workspace/resource_workspace_git.go
+++ b/internal/services/workspace/resource_workspace_git.go
@@ -315,7 +315,7 @@ func (r *resourceWorkspaceGit) Read(ctx context.Context, req resource.ReadReques
return
}
- resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
+ resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
tflog.Debug(ctx, "READ", map[string]any{
"action": "end",
diff --git a/internal/testhelp/fixtures/notebook/notebook.py.tmpl b/internal/testhelp/fixtures/notebook/notebook.py.tmpl
new file mode 100644
index 00000000..6e270f50
--- /dev/null
+++ b/internal/testhelp/fixtures/notebook/notebook.py.tmpl
@@ -0,0 +1,22 @@
+# Fabric notebook source
+
+# METADATA ********************
+
+# META {
+# META "kernel_info": {
+# META "name": "synapse_pyspark"
+# META },
+# META "dependencies": {}
+# META }
+
+# CELL ********************
+
+# Welcome to your new notebook
+# Type here in the cell editor to add code!
+
+# METADATA ********************
+
+# META {
+# META "language": "python",
+# META "language_group": "synapse_pyspark"
+# META }