Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/unreleased/added-20251209-215321.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: added
body: Onboard new `shortcut_conflict_policy` in `fabric_shortcut`
time: 2025-12-09T21:53:21.029793074Z
custom:
Issue: "765"
12 changes: 8 additions & 4 deletions docs/resources/shortcut.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ The Shortcut resource allows you to manage a Fabric [Shortcut](https://learn.mic
```terraform
# Example of using the fabric_shortcut resource
resource "fabric_shortcut" "onelake" {
workspace_id = "00000000-0000-0000-0000-000000000000"
item_id = "00000000-0000-0000-0000-000000000000"
name = "MyShortcutName"
find = "MyShortcutPath"
workspace_id = "00000000-0000-0000-0000-000000000000"
item_id = "00000000-0000-0000-0000-000000000000"
shortcut_conflict_policy = "GenerateUniqueName"
name = "MyShortcutName"
find = "MyShortcutPath"
target = {
onelake = {
workspace_id = "00000000-0000-0000-0000-000000000000"
Expand Down Expand Up @@ -121,6 +122,8 @@ resource "fabric_shortcut" "azure_blob_storage" {
}
}
}

#Note: if shortcut_conflict_policy is not specified, it defaults to "Abort"
```

<!-- schema generated by tfplugindocs -->
Expand All @@ -136,6 +139,7 @@ resource "fabric_shortcut" "azure_blob_storage" {

### Optional

- `shortcut_conflict_policy` (String) When provided, it defines the action to take when a shortcut with the same name and path already exists. The default action is 'Abort'. Value must be one of : `Abort`, `CreateOrOverwrite`, `GenerateUniqueName`, `OverwriteOnly`.
- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts))

### Read-Only
Expand Down
11 changes: 7 additions & 4 deletions examples/resources/fabric_shortcut/resource.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Example of using the fabric_shortcut resource
resource "fabric_shortcut" "onelake" {
workspace_id = "00000000-0000-0000-0000-000000000000"
item_id = "00000000-0000-0000-0000-000000000000"
name = "MyShortcutName"
find = "MyShortcutPath"
workspace_id = "00000000-0000-0000-0000-000000000000"
item_id = "00000000-0000-0000-0000-000000000000"
shortcut_conflict_policy = "GenerateUniqueName"
name = "MyShortcutName"
find = "MyShortcutPath"
target = {
onelake = {
workspace_id = "00000000-0000-0000-0000-000000000000"
Expand Down Expand Up @@ -100,3 +101,5 @@ resource "fabric_shortcut" "azure_blob_storage" {
}
}
}

#Note: if shortcut_conflict_policy is not specified, it defaults to "Abort"
18 changes: 18 additions & 0 deletions internal/services/shortcut/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@
return nil
}

func (to *resourceShortcutModel) set(ctx context.Context, workspaceID, itemID string, shortcutConflictPolicy *string, from fabcore.Shortcut) diag.Diagnostics {
if shortcutConflictPolicy != nil {
to.ShortcutConflictPolicy = types.StringValue(*shortcutConflictPolicy)
}

return to.baseShortcutModel.set(ctx, workspaceID, itemID, from)
}

func (to *targetModel) set(ctx context.Context, from fabcore.Target) {
to.Type = types.StringPointerValue((*string)(from.Type))
to.Onelake = supertypes.NewSingleNestedObjectValueOfNull[oneLakeModel](ctx)
Expand Down Expand Up @@ -232,13 +240,23 @@
type resourceShortcutModel struct {
baseShortcutModel

ShortcutConflictPolicy types.String `tfsdk:"shortcut_conflict_policy"`

Timeouts timeoutsR.Value `tfsdk:"timeouts"`
}

type requestCreateShortcut struct {
fabcore.CreateShortcutRequest
}

type requestCreateShortcutOptions struct {
fabcore.OneLakeShortcutsClientCreateShortcutOptions
}

func (to *requestCreateShortcutOptions) set(ctx context.Context, from resourceShortcutModel) {

Check failure on line 256 in internal/services/shortcut/models.go

View workflow job for this annotation

GitHub Actions / 🏗️ Check Build

unused-parameter: parameter 'ctx' seems to be unused, consider removing or renaming it as _ (revive)
to.ShortcutConflictPolicy = (*fabcore.ShortcutConflictPolicy)(from.ShortcutConflictPolicy.ValueStringPointer())
}

func (to *requestCreateShortcut) set(ctx context.Context, from resourceShortcutModel) diag.Diagnostics {
to.Name = from.Name.ValueStringPointer()
to.Path = from.Path.ValueStringPointer()
Expand Down
18 changes: 14 additions & 4 deletions internal/services/shortcut/resource_shortcut.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,22 @@ func (r *resourceShortcut) Create(ctx context.Context, req resource.CreateReques
return
}

respCreate, err := r.client.CreateShortcut(ctx, plan.WorkspaceID.ValueString(), plan.ItemID.ValueString(), reqCreate.CreateShortcutRequest, nil)
var reqCreateOptions requestCreateShortcutOptions

reqCreateOptions.set(ctx, plan)

respCreate, err := r.client.CreateShortcut(
ctx,
plan.WorkspaceID.ValueString(),
plan.ItemID.ValueString(),
reqCreate.CreateShortcutRequest,
&reqCreateOptions.OneLakeShortcutsClientCreateShortcutOptions,
)
if resp.Diagnostics.Append(utils.GetDiagsFromError(ctx, err, utils.OperationCreate, nil)...); resp.Diagnostics.HasError() {
return
}

if resp.Diagnostics.Append(state.set(ctx, plan.WorkspaceID.ValueString(), plan.ItemID.ValueString(), respCreate.Shortcut)...); resp.Diagnostics.HasError() {
if resp.Diagnostics.Append(state.set(ctx, plan.WorkspaceID.ValueString(), plan.ItemID.ValueString(), plan.ShortcutConflictPolicy.ValueStringPointer(), respCreate.Shortcut)...); resp.Diagnostics.HasError() {
return
}

Expand Down Expand Up @@ -170,7 +180,7 @@ func (r *resourceShortcut) Update(ctx context.Context, req resource.UpdateReques
return
}

if resp.Diagnostics.Append(state.set(ctx, plan.WorkspaceID.ValueString(), plan.ItemID.ValueString(), respCreate.Shortcut)...); resp.Diagnostics.HasError() {
if resp.Diagnostics.Append(state.set(ctx, plan.WorkspaceID.ValueString(), plan.ItemID.ValueString(), plan.ShortcutConflictPolicy.ValueStringPointer(), respCreate.Shortcut)...); resp.Diagnostics.HasError() {
return
}

Expand Down Expand Up @@ -319,7 +329,7 @@ func (r *resourceShortcut) get(ctx context.Context, model *resourceShortcutModel
return diags
}

model.set(ctx, model.WorkspaceID.ValueString(), model.ItemID.ValueString(), respGet.Shortcut)
model.set(ctx, model.WorkspaceID.ValueString(), model.ItemID.ValueString(), model.ShortcutConflictPolicy.ValueStringPointer(), respGet.Shortcut)

return nil
}
10 changes: 6 additions & 4 deletions internal/services/shortcut/resource_shortcut_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
at "github.com/dcarbone/terraform-plugin-framework-utils/v3/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
fabcore "github.com/microsoft/fabric-sdk-go/fabric/core"

"github.com/microsoft/terraform-provider-fabric/internal/common"
"github.com/microsoft/terraform-provider-fabric/internal/framework/customtypes"
Expand Down Expand Up @@ -443,10 +444,11 @@ func TestAcc_ShortcutResource_CRUD(t *testing.T) {
Config: at.CompileConfig(
testResourceItemHeader,
map[string]any{
"item_id": lakehouseID,
"workspace_id": workspaceID,
"name": entityCreateDisplayName,
"path": "Tables",
"item_id": lakehouseID,
"workspace_id": workspaceID,
"name": entityCreateDisplayName,
"shortcut_conflict_policy": string(fabcore.ShortcutConflictPolicyGenerateUniqueName),
"path": "Tables",
Comment on lines +450 to +451
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The test should verify that the shortcut_conflict_policy attribute is properly set in the resource. Consider adding a test assertion after line 450 to check that the attribute value matches the expected value, for example:

resource.TestCheckResourceAttr(testResourceItemFQN, "shortcut_conflict_policy", string(fabcore.ShortcutConflictPolicyGenerateUniqueName)),

This ensures the new attribute is properly persisted and can be read back from the state.

Copilot uses AI. Check for mistakes.
"target": map[string]any{
"onelake": map[string]any{
"workspace_id": workspaceID,
Expand Down
11 changes: 11 additions & 0 deletions internal/services/shortcut/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
fabcore "github.com/microsoft/fabric-sdk-go/fabric/core"
superschema "github.com/orange-cloudavenue/terraform-plugin-framework-superschema"

"github.com/microsoft/terraform-provider-fabric/internal/framework/customtypes"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/fabricitem"
"github.com/microsoft/terraform-provider-fabric/internal/pkg/utils"
)

func itemSchema(isList bool) superschema.Schema { //revive:disable-line:flag-parameter
Expand Down Expand Up @@ -79,6 +81,15 @@ func itemSchema(isList bool) superschema.Schema { //revive:disable-line:flag-par
Required: true,
},
},
"shortcut_conflict_policy": superschema.StringAttribute{
Resource: &schemaR.StringAttribute{
MarkdownDescription: "When provided, it defines the action to take when a shortcut with the same name and path already exists. The default action is 'Abort'",
Optional: true,
Validators: []validator.String{
stringvalidator.OneOf(utils.ConvertEnumsToStringSlices(fabcore.PossibleShortcutConflictPolicyValues(), true)...),
},
},
},
"path": superschema.StringAttribute{
Common: &schemaR.StringAttribute{
MarkdownDescription: `A string representing the full path where the shortcut is created, including either "Files" or "Tables".`,
Expand Down
Loading