Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add databricks_app resource #4099

Merged
merged 116 commits into from
Dec 12, 2024
Merged
Changes from 1 commit
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
c8859e2
added `databricks_app` resource
nkvuong Oct 12, 2024
962d9f2
wip
nkvuong Oct 16, 2024
2e9137a
add doc
nkvuong Oct 29, 2024
91b5166
alias
nkvuong Oct 29, 2024
bcf2a97
Merge branch 'main' into feature/app
nkvuong Oct 29, 2024
35b85eb
fix
nkvuong Oct 29, 2024
9c7ad60
fix test
nkvuong Oct 30, 2024
863fa37
fix test
nkvuong Oct 30, 2024
2d7b38c
fix
nkvuong Oct 30, 2024
b733ee9
Merge branch 'main' into feature/app
nkvuong Nov 14, 2024
ff8bee8
feedback
nkvuong Nov 14, 2024
0daeea1
fix test
nkvuong Nov 15, 2024
7449b45
Merge branch 'main' into feature/app
nkvuong Nov 15, 2024
eda8a91
feedback
nkvuong Nov 15, 2024
f254176
feedback
nkvuong Nov 16, 2024
18b3520
Merge branch 'main' into feature/app
nkvuong Nov 19, 2024
be96f91
feedback
nkvuong Nov 21, 2024
8338d09
add app permission
nkvuong Nov 22, 2024
c6ee7ea
Merge branch 'main' into feature/app
nkvuong Nov 22, 2024
07ea8b7
fix test
nkvuong Nov 22, 2024
3b1f6e2
Merge branch 'feature/app' of https://github.com/databricks/terraform…
nkvuong Nov 22, 2024
9e41c69
more computed fields
nkvuong Nov 22, 2024
0ad4294
feedback
nkvuong Nov 26, 2024
8bdcda9
fix test
nkvuong Nov 26, 2024
2bac7aa
feedback
nkvuong Nov 27, 2024
17e1923
work
mgyucht Nov 28, 2024
731469e
Remove unused configuration from blocks
mgyucht Nov 29, 2024
7dd91f4
add test
mgyucht Nov 29, 2024
14fea49
fix
mgyucht Nov 29, 2024
6bd77aa
Add ConvertToAttribute() support
mgyucht Dec 2, 2024
25ae4ba
small typos
mgyucht Dec 2, 2024
7ba55dd
Merge branch 'main' into add-convert-to-attribute
mgyucht Dec 3, 2024
a62a65f
Merge branch 'main' into feature/app
mgyucht Dec 3, 2024
08d4111
Merge branch 'add-convert-to-attribute' into feature/app
mgyucht Dec 3, 2024
1628cb8
work
mgyucht Dec 3, 2024
e30e677
wip first commit
mgyucht Dec 4, 2024
b9f8e65
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 4, 2024
6e44632
maybe
mgyucht Dec 4, 2024
29d73dd
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 4, 2024
ff11182
fixes
mgyucht Dec 5, 2024
8af1c31
works
mgyucht Dec 5, 2024
dac1bab
Merge branch 'main' into use-tftypes-everywhere
mgyucht Dec 5, 2024
c4c9375
work
mgyucht Dec 5, 2024
3e26f55
some work
mgyucht Dec 5, 2024
7336447
working
mgyucht Dec 5, 2024
cfdec91
more work
mgyucht Dec 5, 2024
4b36d53
fix
mgyucht Dec 5, 2024
93763a8
more work
mgyucht Dec 5, 2024
37d3f1b
work
mgyucht Dec 5, 2024
3b5015b
go mod tidy
mgyucht Dec 5, 2024
123432c
comment
mgyucht Dec 5, 2024
b84854a
cleanup
mgyucht Dec 5, 2024
6222b90
add coverage for object types
mgyucht Dec 5, 2024
295c972
more comments
mgyucht Dec 5, 2024
6a39e1b
more comments
mgyucht Dec 5, 2024
e4aff40
clean up resource_sahre
mgyucht Dec 5, 2024
c5a1181
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 5, 2024
2c3ed47
fix
mgyucht Dec 5, 2024
5b52d77
fix
mgyucht Dec 5, 2024
edc1d4c
work
mgyucht Dec 5, 2024
30398da
it passes a test
mgyucht Dec 5, 2024
560ce27
work
mgyucht Dec 6, 2024
687996c
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 6, 2024
5779ece
works again
mgyucht Dec 6, 2024
b3634bd
work
mgyucht Dec 6, 2024
32cba97
fix
mgyucht Dec 6, 2024
4fdd72b
work
mgyucht Dec 6, 2024
0619e2e
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 6, 2024
a9f12b6
bugfix
mgyucht Dec 9, 2024
2feedf4
improve error message
mgyucht Dec 9, 2024
4feb053
fix go to tf conversion
mgyucht Dec 9, 2024
d10447f
fixes
mgyucht Dec 9, 2024
ed7246e
fmt
mgyucht Dec 9, 2024
0d49760
fix types.Object handling
mgyucht Dec 9, 2024
a0297e6
Merge branch 'use-tftypes-everywhere' into feature/app
mgyucht Dec 9, 2024
adb9746
Merge branch 'main' into feature/app
mgyucht Dec 11, 2024
5adec2e
revert sharing change
mgyucht Dec 11, 2024
6496607
remove extra file
mgyucht Dec 11, 2024
285c29f
work
mgyucht Dec 11, 2024
ed7b0ec
Panic if the provided path is invalid
mgyucht Dec 11, 2024
853622c
Merge branch 'panic-on-invalid-path' into feature/app
mgyucht Dec 11, 2024
9588149
fix
mgyucht Dec 11, 2024
07a77bc
Expose several integration test helpers for use in plugin framework i…
mgyucht Dec 11, 2024
c3ef933
more
mgyucht Dec 11, 2024
5da3a69
Merge branch 'expose-integration-test-helpers' into feature/app
mgyucht Dec 11, 2024
ecd7d29
tests
mgyucht Dec 11, 2024
f138239
Merge branch 'main' into feature/app
mgyucht Dec 11, 2024
b929583
first attempt
mgyucht Dec 11, 2024
5c4a1c7
Merge branch 'use-attributes-by-default' into feature/app
mgyucht Dec 11, 2024
ec950fb
fix
mgyucht Dec 11, 2024
eaf71eb
work
mgyucht Dec 11, 2024
7f8a845
work
mgyucht Dec 11, 2024
d16ec81
fixes
mgyucht Dec 11, 2024
29aa7e9
Merge branch 'readonly-and-list-validators' into use-attributes-by-de…
mgyucht Dec 11, 2024
7c539b8
some work
mgyucht Dec 11, 2024
e282b55
work
mgyucht Dec 11, 2024
223acf8
fix formatting
mgyucht Dec 11, 2024
92dbbe9
fix formatting
mgyucht Dec 11, 2024
3ba9694
Merge branch 'main' into use-attributes-by-default
mgyucht Dec 12, 2024
8d42b08
less unnecessary diff
mgyucht Dec 12, 2024
f0117c8
work
mgyucht Dec 12, 2024
28c6acc
fix
mgyucht Dec 12, 2024
361cec4
update contributing
mgyucht Dec 12, 2024
402f40a
docs
mgyucht Dec 12, 2024
c425508
docs
mgyucht Dec 12, 2024
fc9e4c8
tests and better error
mgyucht Dec 12, 2024
10c456e
rename
mgyucht Dec 12, 2024
86b8cce
fix test
mgyucht Dec 12, 2024
5f107cf
Merge branch 'use-attributes-by-default' into feature/app
mgyucht Dec 12, 2024
c414f8a
improve integration test
mgyucht Dec 12, 2024
a9e438c
Merge branch 'main' into feature/app
mgyucht Dec 12, 2024
66fe1b9
import
mgyucht Dec 12, 2024
59e16d5
add import test
mgyucht Dec 12, 2024
e0dd84d
sort
mgyucht Dec 12, 2024
9114ea1
data sources
mgyucht Dec 12, 2024
52e975c
fast app
mgyucht Dec 12, 2024
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
Prev Previous commit
Next Next commit
Add ConvertToAttribute() support
mgyucht committed Dec 2, 2024

Verified

This commit was signed with the committer’s verified signature.
mgyucht Miles Yucht
commit 6bd77aade0942ba9a2ee38da8d6cd2c4bd9f1ed9
6 changes: 6 additions & 0 deletions internal/providers/pluginfw/tfschema/block_builder.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,12 @@ import (
// This common interface prevents us from keeping two copies of StructToSchema and CustomizableSchema.
type BlockBuilder interface {
BaseSchemaBuilder

// ToAttribute converts a block to its corresponding attribute type. Currently, ResourceStructToSchema converts all
// nested struct fields and slices to blocks. This method is used to convert those blocks to their corresponding
// attribute type. The resulting attribute will not have any of the Computed/Optional/Required/Sensitive flags set.
ToAttribute() AttributeBuilder

BuildDataSourceBlock() dataschema.Block
BuildResourceBlock() schema.Block
}
66 changes: 61 additions & 5 deletions internal/providers/pluginfw/tfschema/customizable_schema.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import (
)

// CustomizableSchema is a wrapper struct on top of BaseSchemaBuilder that can be used to navigate through nested schema add customizations.
// The methods of CustomizableSchema that modify the underlying schema should return the same CustomizableSchema object to allow chaining.
type CustomizableSchema struct {
attr BaseSchemaBuilder
}
@@ -199,8 +200,63 @@ func (s *CustomizableSchema) SetReadOnly(path ...string) *CustomizableSchema {
return s
}

// ConvertToAttribute converts the last element of the path from a block to an attribute.
// It panics if the path is empty, if the path does not exist in the schema, or if the path
// points to an attribute, not a block.
func (s *CustomizableSchema) ConvertToAttribute(path ...string) *CustomizableSchema {
if len(path) == 0 {
panic(fmt.Errorf("ToAttribute called on root schema. %s", common.TerraformBugErrorMessage))
}
field := path[len(path)-1]

cb := func(attr BaseSchemaBuilder) BaseSchemaBuilder {
switch a := attr.(type) {
case ListNestedBlockBuilder:
elem, ok := a.NestedObject.Blocks[field]
if !ok {
panic(fmt.Errorf("field %s does not exist in nested block", field))
}
if a.NestedObject.Attributes == nil {
a.NestedObject.Attributes = make(map[string]AttributeBuilder)
}
a.NestedObject.Attributes[field] = elem.ToAttribute()
delete(a.NestedObject.Blocks, field)
if len(a.NestedObject.Blocks) == 0 {
a.NestedObject.Blocks = nil
}
return a
case SingleNestedBlockBuilder:
elem, ok := a.NestedObject.Blocks[field]
if !ok {
panic(fmt.Errorf("field %s does not exist in nested block", field))
}
if a.NestedObject.Attributes == nil {
a.NestedObject.Attributes = make(map[string]AttributeBuilder)
}
a.NestedObject.Attributes[field] = elem.ToAttribute()
delete(a.NestedObject.Blocks, field)
if len(a.NestedObject.Blocks) == 0 {
a.NestedObject.Blocks = nil
}
return a
default:
panic(fmt.Errorf("ConvertToAttribute called on invalid attribute type: %s. %s", reflect.TypeOf(attr).String(), common.TerraformBugErrorMessage))
}
}

// We have to go only as far as the second-to-last entry, since we need to change the parent schema
// by moving the last entry from a block to an attribute.
if len(path) == 1 {
s.attr = cb(s.attr)
} else {
navigateSchemaWithCallback(&s.attr, cb, path[0:len(path)-1]...)
}

return s
}

// navigateSchemaWithCallback navigates through schema attributes and executes callback on the target, panics if path does not exist or invalid.
func navigateSchemaWithCallback(s *BaseSchemaBuilder, cb func(BaseSchemaBuilder) BaseSchemaBuilder, path ...string) (BaseSchemaBuilder, error) {
func navigateSchemaWithCallback(s *BaseSchemaBuilder, cb func(BaseSchemaBuilder) BaseSchemaBuilder, path ...string) {
currentScm := s
for i, p := range path {
m := attributeToNestedBlockObject(currentScm)
@@ -211,22 +267,22 @@ func navigateSchemaWithCallback(s *BaseSchemaBuilder, cb func(BaseSchemaBuilder)
if i == len(path)-1 {
newV := cb(v).(AttributeBuilder)
mAttr[p] = newV
return mAttr[p], nil
return
}
castedV := v.(BaseSchemaBuilder)
currentScm = &castedV
} else if v, ok := mBlock[p]; ok {
if i == len(path)-1 {
newV := cb(v).(BlockBuilder)
mBlock[p] = newV
return mBlock[p], nil
return
}
castedV := v.(BaseSchemaBuilder)
currentScm = &castedV
} else {
return nil, fmt.Errorf("missing key %s", p)
panic(fmt.Errorf("missing key %s", p))
}

}
return nil, fmt.Errorf("path %v is incomplete", path)
panic(fmt.Errorf("path %v is incomplete", path))
}
217 changes: 217 additions & 0 deletions internal/providers/pluginfw/tfschema/customizable_schema_test.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"testing"

"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"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"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -175,3 +176,219 @@ func TestCustomizeSchema_SetComputed_PanicOnBlock(t *testing.T) {
})
})
}

type mockPlanModifier struct{}

// Description implements planmodifier.List.
func (m mockPlanModifier) Description(context.Context) string {
panic("unimplemented")
}

// MarkdownDescription implements planmodifier.List.
func (m mockPlanModifier) MarkdownDescription(context.Context) string {
panic("unimplemented")
}

// PlanModifyList implements planmodifier.List.
func (m mockPlanModifier) PlanModifyList(context.Context, planmodifier.ListRequest, *planmodifier.ListResponse) {
panic("unimplemented")
}

// PlanModifyList implements planmodifier.List.
func (m mockPlanModifier) PlanModifyObject(context.Context, planmodifier.ObjectRequest, *planmodifier.ObjectResponse) {
panic("unimplemented")
}

var _ planmodifier.List = mockPlanModifier{}
var _ planmodifier.Object = mockPlanModifier{}

type mockValidator struct{}

// Description implements validator.List.
func (m mockValidator) Description(context.Context) string {
panic("unimplemented")
}

// MarkdownDescription implements validator.List.
func (m mockValidator) MarkdownDescription(context.Context) string {
panic("unimplemented")
}

// ValidateList implements validator.List.
func (m mockValidator) ValidateList(context.Context, validator.ListRequest, *validator.ListResponse) {
panic("unimplemented")
}

// ValidateList implements validator.Object.
func (m mockValidator) ValidateObject(context.Context, validator.ObjectRequest, *validator.ObjectResponse) {
panic("unimplemented")
}

var _ validator.List = mockValidator{}
var _ validator.Object = mockValidator{}

func TestCustomizeSchema_ToAttribute(t *testing.T) {
v := mockValidator{}
pm := mockPlanModifier{}
testCases := []struct {
name string
baseSchema NestedBlockObject
path []string
want NestedBlockObject
expectPanic bool
}{
{
name: "ListNestedBlock",
baseSchema: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"list": ListNestedBlockBuilder{
NestedObject: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
DeprecationMessage: "deprecated",
Validators: []validator.List{v},
PlanModifiers: []planmodifier.List{pm},
},
},
},
path: []string{"list"},
want: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"list": ListNestedAttributeBuilder{
NestedObject: NestedAttributeObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
DeprecationMessage: "deprecated",
Validators: []validator.List{v},
PlanModifiers: []planmodifier.List{pm},
},
},
},
},
{
name: "ListNestedBlock/CalledOnInnerBlock",
baseSchema: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"list": ListNestedBlockBuilder{
NestedObject: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"nested_block": ListNestedBlockBuilder{
NestedObject: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
},
},
},
},
},
},
path: []string{"list", "nested_block"},
want: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"list": ListNestedBlockBuilder{
NestedObject: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"nested_block": ListNestedAttributeBuilder{
NestedObject: NestedAttributeObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
},
},
},
},
},
},
},
{
name: "SingleNestedBlock",
baseSchema: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"single": SingleNestedBlockBuilder{
NestedObject: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
DeprecationMessage: "deprecated",
Validators: []validator.Object{v},
PlanModifiers: []planmodifier.Object{pm},
},
},
},
path: []string{"single"},
want: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"single": SingleNestedAttributeBuilder{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
DeprecationMessage: "deprecated",
Validators: []validator.Object{v},
PlanModifiers: []planmodifier.Object{pm},
},
},
},
},
{
name: "SingleNestedBlock/RecursiveBlocks",
baseSchema: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"single": SingleNestedBlockBuilder{
NestedObject: NestedBlockObject{
Blocks: map[string]BlockBuilder{
"nested_block": ListNestedBlockBuilder{
NestedObject: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
},
},
},
},
},
},
path: []string{"single"},
want: NestedBlockObject{
Attributes: map[string]AttributeBuilder{
"single": SingleNestedAttributeBuilder{
Attributes: map[string]AttributeBuilder{
"nested_block": ListNestedAttributeBuilder{
NestedObject: NestedAttributeObject{
Attributes: map[string]AttributeBuilder{
"attr": StringAttributeBuilder{},
},
},
},
},
},
},
},
},
{
name: "PanicOnEmptyPath",
path: nil,
expectPanic: true,
},
}
for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
if c.expectPanic {
assert.Panics(t, func() {
ConstructCustomizableSchema(c.baseSchema).ConvertToAttribute(c.path...)
})
} else {
got := ConstructCustomizableSchema(c.baseSchema).ConvertToAttribute(c.path...)
assert.Equal(t, c.want, got.attr.(SingleNestedBlockBuilder).NestedObject)
}
})
}
}
9 changes: 9 additions & 0 deletions internal/providers/pluginfw/tfschema/list_nested_block.go
Original file line number Diff line number Diff line change
@@ -16,6 +16,15 @@ type ListNestedBlockBuilder struct {
PlanModifiers []planmodifier.List
}

func (a ListNestedBlockBuilder) ToAttribute() AttributeBuilder {
return ListNestedAttributeBuilder{
NestedObject: a.NestedObject.ToNestedAttributeObject(),
DeprecationMessage: a.DeprecationMessage,
Validators: a.Validators,
PlanModifiers: a.PlanModifiers,
}
}

func (a ListNestedBlockBuilder) BuildDataSourceBlock() dataschema.Block {
return dataschema.ListNestedBlock{
NestedObject: a.NestedObject.BuildDataSourceAttribute(),
13 changes: 13 additions & 0 deletions internal/providers/pluginfw/tfschema/nested_block_object.go
Original file line number Diff line number Diff line change
@@ -11,6 +11,19 @@ type NestedBlockObject struct {
Blocks map[string]BlockBuilder
}

func (a NestedBlockObject) ToNestedAttributeObject() NestedAttributeObject {
attributes := make(map[string]AttributeBuilder)
for k, v := range a.Attributes {
attributes[k] = v
}
for k, v := range a.Blocks {
attributes[k] = v.ToAttribute()
}
return NestedAttributeObject{
Attributes: attributes,
}
}

func (a NestedBlockObject) BuildDataSourceAttribute() dataschema.NestedBlockObject {
dataSourceAttributes := BuildDataSourceAttributeMap(a.Attributes)
dataSourceBlocks := BuildDataSourceBlockMap(a.Blocks)
9 changes: 9 additions & 0 deletions internal/providers/pluginfw/tfschema/single_nested_block.go
Original file line number Diff line number Diff line change
@@ -18,6 +18,15 @@ type SingleNestedBlockBuilder struct {
PlanModifiers []planmodifier.Object
}

func (a SingleNestedBlockBuilder) ToAttribute() AttributeBuilder {
return SingleNestedAttributeBuilder{
Attributes: a.NestedObject.ToNestedAttributeObject().Attributes,
DeprecationMessage: a.DeprecationMessage,
Validators: a.Validators,
PlanModifiers: a.PlanModifiers,
}
}

func (a SingleNestedBlockBuilder) BuildDataSourceAttribute() dataschema.Attribute {
panic(fmt.Errorf("BuildDataSourceBlock should never be called for SingleNestedBlockBuilder. %s", common.TerraformBugErrorMessage))
}