Skip to content

Commit

Permalink
feat(fabricitem): enable multi-format support
Browse files Browse the repository at this point in the history
  • Loading branch information
DariuszPorowski committed Jan 9, 2025
1 parent edb6fa7 commit e597bc8
Show file tree
Hide file tree
Showing 26 changed files with 276 additions and 85 deletions.
4 changes: 2 additions & 2 deletions docs/data-sources/eventhouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand All @@ -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))

<a id="nestedatt--timeouts"></a>
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/notebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ output "example_definition_content_object" {

### Read-Only

- `definition` (Attributes Map) Definition parts. Possible path keys: `notebook-content.ipynb`, `notebook-content.py`. (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.

<a id="nestedatt--timeouts"></a>
Expand Down
4 changes: 2 additions & 2 deletions docs/data-sources/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ output "example_definition_report_object" {

### Optional

- `format` (String) The Report format. Possible values: `PBIR-Legacy`
- `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.
Expand All @@ -66,7 +66,7 @@ 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.

Expand Down
4 changes: 2 additions & 2 deletions docs/data-sources/semantic_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ output "example_definition_bim_object" {

### Optional

- `format` (String) The Semantic Model format. Possible values: `TMSL`
- `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.
Expand All @@ -63,7 +63,7 @@ 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.

Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/spark_job_definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ 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.
- `properties` (Attributes) The Spark Job Definition properties. (see [below for nested schema](#nestedatt--properties))

Expand Down
4 changes: 2 additions & 2 deletions docs/resources/data_pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<a id="nestedatt--definition"></a>
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/eventhouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/notebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ resource "fabric_notebook" "example_definition_update" {

### Optional

- `definition` (Attributes Map) Definition parts. Accepted path keys: `notebook-content.ipynb`, `notebook-content.py`. 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`
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +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`
- `format` (String) The Report format. Possible values: `PBIR-Legacy`, `PBIR`
- `workspace_id` (String) The Workspace ID.

### Optional
Expand Down
4 changes: 2 additions & 2 deletions docs/resources/semantic_model.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +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`
- `format` (String) The Semantic Model format. Possible values: `TMSL`, `TMDL`
- `workspace_id` (String) The Workspace ID.

### Optional
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/spark_job_definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ 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`
Expand Down
141 changes: 141 additions & 0 deletions internal/framework/validators/regexp_if_attribute_is_one_of.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
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
}
4 changes: 3 additions & 1 deletion internal/pkg/fabricitem/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@

package fabricitem

const DefinitionFormatNotApplicable = "NotApplicable"
const (
DefinitionFormatDefault = "Default"
)
2 changes: 1 addition & 1 deletion internal/pkg/fabricitem/data_item_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func (d *DataSourceFabricItemDefinition) getDefinition(ctx context.Context, mode
respGetOpts := &fabcore.ItemsClientBeginGetItemDefinitionOptions{}

if !model.Format.IsNull() {
apiFormat := GetDefinitionFormatAPI(d.DefinitionFormats, model.Format.ValueString())
apiFormat := getDefinitionFormatAPI(d.DefinitionFormats, model.Format.ValueString())

if apiFormat != "" {
respGetOpts.Format = azto.Ptr(apiFormat)
Expand Down
25 changes: 8 additions & 17 deletions internal/pkg/fabricitem/data_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,17 @@ func getDataSourceFabricItemBaseAttributes(ctx context.Context, itemName string,
func getDataSourceFabricItemDefinitionAttributes(ctx context.Context, name string, definitionFormats []DefinitionFormat) map[string]schema.Attribute {
attributes := make(map[string]schema.Attribute)

formatTypes := GetDefinitionFormats(definitionFormats)
definitionPathKeys := GetDefinitionFormatsPaths(definitionFormats)
formatTypes := getDefinitionFormats(definitionFormats)
definitionFormatsDocs := getDefinitionFormatsPathsDocs(definitionFormats)

// format attribute
attrFormat := schema.StringAttribute{}

if len(formatTypes) > 1 || (len(formatTypes) == 1 && formatTypes[0] != "") {
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)}),
}
} else {
attrFormat.MarkdownDescription = fmt.Sprintf("The %s format. Possible values: `%s`", name, DefinitionFormatNotApplicable)
attrFormat.Computed = true
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
Expand All @@ -156,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

Expand Down
Loading

0 comments on commit e597bc8

Please sign in to comment.