diff --git a/common/customizable_schema_plugin_framework.go b/common/customizable_schema_plugin_framework.go index ae0571b827..b4f7edd764 100644 --- a/common/customizable_schema_plugin_framework.go +++ b/common/customizable_schema_plugin_framework.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/hashicorp/terraform-plugin-framework/provider/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" ) type CustomizableSchemaPluginFramework struct { diff --git a/common/customizable_schema_plugin_framework_test.go b/common/customizable_schema_plugin_framework_test.go index 3d0b31b0e9..fc49e6f1c9 100644 --- a/common/customizable_schema_plugin_framework_test.go +++ b/common/customizable_schema_plugin_framework_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform-plugin-framework/provider/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/stretchr/testify/assert" ) @@ -46,7 +46,7 @@ func (v stringLengthBetweenValidator) ValidateString(ctx context.Context, req va } func TestCustomizeSchema(t *testing.T) { - scm := pluginFrameworkStructToSchema(DummyTfSdk{}, func(c CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework { + scm := PluginFrameworkResourceStructToSchema(DummyTfSdk{}, func(c CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework { c.AddNewField("new_field", schema.StringAttribute{Required: true}) c.AddNewField("new_field", schema.StringAttribute{Required: true}, "nested") c.AddNewField("to_be_removed", schema.StringAttribute{Required: true}, "nested") diff --git a/common/reflect_resource_plugin_framework.go b/common/reflect_resource_plugin_framework.go index 71b57e6227..ea0a2f3ae5 100644 --- a/common/reflect_resource_plugin_framework.go +++ b/common/reflect_resource_plugin_framework.go @@ -6,7 +6,7 @@ import ( "reflect" "strings" - "github.com/hashicorp/terraform-plugin-framework/provider/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -297,7 +297,7 @@ func checkTheStringInForceSendFields(fieldName string, forceSendFields []string) return false } -func pluginFrameworkTypeToSchema(v reflect.Value) map[string]schema.Attribute { +func pluginFrameworkResourceTypeToSchema(v reflect.Value) map[string]schema.Attribute { scm := map[string]schema.Attribute{} rk := v.Kind() if rk == reflect.Ptr { @@ -320,7 +320,7 @@ func pluginFrameworkTypeToSchema(v reflect.Value) map[string]schema.Attribute { if kind == reflect.Ptr { elem := typeField.Type.Elem() sv := reflect.New(elem).Elem() - nestedScm := pluginFrameworkTypeToSchema(sv) + nestedScm := pluginFrameworkResourceTypeToSchema(sv) scm[fieldName] = schema.SingleNestedAttribute{Attributes: nestedScm, Optional: isOptional, Required: !isOptional} } else if kind == reflect.Slice { elem := typeField.Type.Elem() @@ -341,7 +341,7 @@ func pluginFrameworkTypeToSchema(v reflect.Value) map[string]schema.Attribute { scm[fieldName] = schema.ListAttribute{ElementType: types.StringType, Optional: isOptional, Required: !isOptional} default: // Nested struct - nestedScm := pluginFrameworkTypeToSchema(reflect.New(elem).Elem()) + nestedScm := pluginFrameworkResourceTypeToSchema(reflect.New(elem).Elem()) scm[fieldName] = schema.ListNestedAttribute{NestedObject: schema.NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional} } } else if kind == reflect.Map { @@ -363,7 +363,7 @@ func pluginFrameworkTypeToSchema(v reflect.Value) map[string]schema.Attribute { scm[fieldName] = schema.MapAttribute{ElementType: types.StringType, Optional: isOptional, Required: !isOptional} default: // Nested struct - nestedScm := pluginFrameworkTypeToSchema(reflect.New(elem).Elem()) + nestedScm := pluginFrameworkResourceTypeToSchema(reflect.New(elem).Elem()) scm[fieldName] = schema.MapNestedAttribute{NestedObject: schema.NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional} } } else if kind == reflect.Struct { @@ -384,7 +384,7 @@ func pluginFrameworkTypeToSchema(v reflect.Value) map[string]schema.Attribute { // If it is a real stuct instead of a tfsdk type, recursively resolve it. elem := typeField.Type sv := reflect.New(elem) - nestedScm := pluginFrameworkTypeToSchema(sv) + nestedScm := pluginFrameworkResourceTypeToSchema(sv) scm[fieldName] = schema.SingleNestedAttribute{Attributes: nestedScm, Optional: isOptional, Required: !isOptional} } } else if kind == reflect.String { @@ -402,13 +402,18 @@ func fieldIsOptional(field reflect.StructField) bool { return strings.Contains(tagValue, "optional") } -func pluginFrameworkStructToSchema(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) schema.Schema { - attributes := pluginFrameworkTypeToSchema(reflect.ValueOf(v)) +func PluginFrameworkResourceStructToSchema(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) schema.Schema { + attributes := PluginFrameworkResourceStructToSchemaMap(v, customizeSchema) + return schema.Schema{Attributes: attributes} +} + +func PluginFrameworkResourceStructToSchemaMap(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) map[string]schema.Attribute { + attributes := pluginFrameworkResourceTypeToSchema(reflect.ValueOf(v)) if customizeSchema != nil { cs := customizeSchema(*ConstructCustomizableSchema(attributes)) - return schema.Schema{Attributes: cs.ToAttributeMap()} + return cs.ToAttributeMap() } else { - return schema.Schema{Attributes: attributes} + return attributes } } diff --git a/common/reflect_resource_plugin_framework_test.go b/common/reflect_resource_plugin_framework_test.go index 88fc0a30cf..e9a7f8dc5d 100644 --- a/common/reflect_resource_plugin_framework_test.go +++ b/common/reflect_resource_plugin_framework_test.go @@ -140,7 +140,7 @@ var tfSdkStruct = DummyTfSdk{ func TestGetAndSetPluginFramework(t *testing.T) { // Also test StructToSchema. - scm := pluginFrameworkStructToSchema(DummyTfSdk{}, nil) + scm := PluginFrameworkResourceStructToSchema(DummyTfSdk{}, nil) state := tfsdk.State{ Schema: scm, } diff --git a/go.mod b/go.mod index 30427dec11..07feed51c5 100644 --- a/go.mod +++ b/go.mod @@ -19,18 +19,20 @@ require ( golang.org/x/mod v0.19.0 ) +require golang.org/x/sync v0.7.0 // indirect + require ( - cloud.google.com/go/auth v0.4.2 // indirect + cloud.google.com/go/auth v0.6.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cloud.google.com/go/compute/metadata v0.3.0 // indirect - github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect + cloud.google.com/go/compute/metadata v0.4.0 // indirect + github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - github.com/cloudflare/circl v1.3.7 // indirect + github.com/cloudflare/circl v1.3.9 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.16.0 // indirect + github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -42,12 +44,12 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-plugin v1.6.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.6.4 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/hc-install v0.7.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect github.com/hashicorp/terraform-json v0.22.1 // indirect @@ -68,22 +70,22 @@ require ( github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.18.0 // indirect - google.golang.org/api v0.182.0 // indirect + golang.org/x/tools v0.22.0 // indirect + google.golang.org/api v0.187.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e // indirect - google.golang.org/grpc v1.64.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 46a0f91844..91d8fd82ee 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,17 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/auth v0.4.2 h1:sb0eyLkhRtpq5jA+a8KWw0W70YcdVca7KJ8TM0AFYDg= -cloud.google.com/go/auth v0.4.2/go.mod h1:Kqvlz1cf1sNA0D+sYJnkPQOP+JMHkuHeIgVmCRtZOLc= +cloud.google.com/go/auth v0.6.1 h1:T0Zw1XM5c1GlpN2HYr2s+m3vr1p2wy+8VN+Z1FKxW38= +cloud.google.com/go/auth v0.6.1/go.mod h1:eFHG7zDzbXHKmjJddFG/rBlcGp6t25SwRUiEQSlO4x4= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c= +cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg= -github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton h1:0RXAi0EJFs81j+MMsqvHNuAUGWzeVfCO9LnHAfoQ8NA= +github.com/ProtonMail/go-crypto v1.1.0-alpha.3-proton/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= @@ -21,8 +21,8 @@ github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZ github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE= +github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -38,8 +38,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= -github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -49,8 +49,8 @@ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgF github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= @@ -95,8 +95,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= -github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -107,19 +107,19 @@ github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9n github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= +github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= +github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.6.4 h1:QLqlM56/+SIIGvGcfFiwMY3z5WGXT066suo/v9Km8e0= -github.com/hashicorp/hc-install v0.6.4/go.mod h1:05LWLy8TD842OtgcfBbOT0WMoInBMUSHjmDx10zuBIA= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hc-install v0.7.0 h1:Uu9edVqjKQxxuD28mR5TikkKDd/p55S8vzPC1659aBk= +github.com/hashicorp/hc-install v0.7.0/go.mod h1:ELmmzZlGnEcqoUMKUuykHaPCIR1sYLYX+KSggWSKZuA= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.21.0 h1:lve4q/o/2rqwYOgUg3y3V2YPyD1/zkCLGjIV74Jit14= @@ -216,19 +216,19 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= @@ -247,11 +247,11 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -273,19 +273,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -295,12 +295,12 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= -golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.182.0 h1:if5fPvudRQ78GeRx3RayIoiuV7modtErPIZC/T2bIvE= -google.golang.org/api v0.182.0/go.mod h1:cGhjy4caqA5yXRzEhkHI8Y9mfyC2VLTlER2l08xaqtM= +google.golang.org/api v0.187.0 h1:Mxs7VATVC2v7CY+7Xwm4ndkX71hpElcvx0D1Ji/p1eo= +google.golang.org/api v0.187.0/go.mod h1:KIHlTc4x7N7gKKuVsdmfBXN13yEEWXWFURWY6SBp2gk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -308,15 +308,15 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e h1:Elxv5MwEkCI9f5SkoL6afed6NTdxaGoAo39eANBwHL8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -328,8 +328,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/main.go b/main.go index b64453db94..57fb72d6ad 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "github.com/databricks/terraform-provider-databricks/common" "github.com/databricks/terraform-provider-databricks/exporter" "github.com/databricks/terraform-provider-databricks/provider" + "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tfprotov6/tf6server" "github.com/hashicorp/terraform-plugin-mux/tf5to6server" @@ -49,10 +50,17 @@ func main() { log.Fatal(err) } + pluginFrameworkProvider := provider.GetDatabricksProviderPluginFramework() + + providers := []func() tfprotov6.ProviderServer{ + func() tfprotov6.ProviderServer { + return upgradedSdkPluginProvider + }, + providerserver.NewProtocol6(pluginFrameworkProvider), + } + ctx := context.Background() - muxServer, err := tf6muxserver.NewMuxServer(ctx, func() tfprotov6.ProviderServer { - return upgradedSdkPluginProvider - }) + muxServer, err := tf6muxserver.NewMuxServer(ctx, providers...) if err != nil { log.Fatal(err) diff --git a/pluginframework/data_source.go b/pluginframework/data_source.go new file mode 100644 index 0000000000..532fa1665d --- /dev/null +++ b/pluginframework/data_source.go @@ -0,0 +1,21 @@ +package pluginframework + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/datasource" +) + +var _ datasource.DataSource = (*DatabricksDataSource)(nil) + +type DatabricksDataSource struct { +} + +func (d *DatabricksDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { +} + +func (d *DatabricksDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { +} + +func (d *DatabricksDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { +} diff --git a/pluginframework/data_volumes.go b/pluginframework/data_volumes.go new file mode 100644 index 0000000000..e3ba7a82c9 --- /dev/null +++ b/pluginframework/data_volumes.go @@ -0,0 +1,94 @@ +package pluginframework + +import ( + "context" + "fmt" + + "github.com/databricks/databricks-sdk-go/service/catalog" + "github.com/databricks/terraform-provider-databricks/common" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func DataSourceVolumes() func() datasource.DataSource { + return func() datasource.DataSource { + return &VolumesDataSource{} + } +} + +var _ datasource.DataSource = &VolumesDataSource{} + +type VolumesDataSource struct { + Client *common.DatabricksClient +} + +type VolumesList struct { + CatalogName types.String `tfsdk:"catalog_name"` + SchemaName types.String `tfsdk:"schema_name"` + Ids []types.String `tfsdk:"ids" tf:"optional"` +} + +func (d *VolumesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = "databricks_volumes_pluginframework" +} + +func (d *VolumesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + // TODO: Use StructToSchemaMap to generate the schema once it supports schema for data sources + Attributes: map[string]schema.Attribute{ + "catalog_name": schema.StringAttribute{ + Required: true, + }, + "schema_name": schema.StringAttribute{ + Required: true, + }, + "ids": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + }, + } +} + +func (d *VolumesDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*common.DatabricksClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *common.DatabricksClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + d.Client = client +} + +func (d *VolumesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + client := d.Client + w, err := client.WorkspaceClient() + if err != nil { + resp.Diagnostics.AddError("Failed to get workspace client", err.Error()) + return + } + var volumesList VolumesList + diags := req.Config.Get(ctx, &volumesList) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + volumes, err := w.Volumes.ListAll(ctx, catalog.ListVolumesRequest{ + CatalogName: volumesList.CatalogName.ValueString(), + SchemaName: volumesList.SchemaName.ValueString(), + }) + if err != nil { + resp.Diagnostics.AddError("Failed to get volumes for the catalog and schema", err.Error()) + return + } + for _, v := range volumes { + volumesList.Ids = append(volumesList.Ids, types.StringValue(v.FullName)) + } + resp.State.Set(ctx, volumesList) +} diff --git a/pluginframework/resource.go b/pluginframework/resource.go new file mode 100644 index 0000000000..4f9d6ed981 --- /dev/null +++ b/pluginframework/resource.go @@ -0,0 +1,30 @@ +package pluginframework + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource" +) + +var _ resource.Resource = (*DatabricksResource)(nil) + +type DatabricksResource struct { +} + +func (r *DatabricksResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { +} + +func (r *DatabricksResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +} + +func (r *DatabricksResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { +} + +func (r *DatabricksResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { +} + +func (r *DatabricksResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { +} + +func (r *DatabricksResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { +} diff --git a/pluginframework/resource_quality_monitor.go b/pluginframework/resource_quality_monitor.go new file mode 100644 index 0000000000..5dbc1bf1c2 --- /dev/null +++ b/pluginframework/resource_quality_monitor.go @@ -0,0 +1,196 @@ +package pluginframework + +import ( + "context" + "fmt" + "time" + + "github.com/databricks/databricks-sdk-go" + "github.com/databricks/databricks-sdk-go/service/catalog" + "github.com/databricks/terraform-provider-databricks/common" + "github.com/databricks/terraform-provider-databricks/service/catalog_tf" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" +) + +const qualityMonitorDefaultProvisionTimeout = 15 * time.Minute + +func WaitForMonitor(w *databricks.WorkspaceClient, ctx context.Context, monitorName string) error { + return retry.RetryContext(ctx, qualityMonitorDefaultProvisionTimeout, func() *retry.RetryError { + endpoint, err := w.QualityMonitors.GetByTableName(ctx, monitorName) + if err != nil { + return retry.NonRetryableError(err) + } + + switch endpoint.Status { + case catalog.MonitorInfoStatusMonitorStatusActive: + return nil + case catalog.MonitorInfoStatusMonitorStatusError, catalog.MonitorInfoStatusMonitorStatusFailed: + return retry.NonRetryableError(fmt.Errorf("monitor status retrund %s for monitor: %s", endpoint.Status, monitorName)) + } + return retry.RetryableError(fmt.Errorf("monitor %s is still pending", monitorName)) + }) +} + +var _ resource.Resource = &QualityMonitorResource{} + +func ResourceQualityMonitor() func() resource.Resource { + return func() resource.Resource { + return &QualityMonitorResource{} + } +} + +type QualityMonitorResource struct { + Client *common.DatabricksClient +} + +func (r *QualityMonitorResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "databricks_lakehouse_monitor_pluginframework" +} + +func (r *QualityMonitorResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Terraform schema for Databricks Lakehouse Monitor. MonitorInfo struct is used to create the schema", + Attributes: common.PluginFrameworkResourceStructToSchemaMap(catalog_tf.MonitorInfo{}, func(c common.CustomizableSchemaPluginFramework) common.CustomizableSchemaPluginFramework { + c.AddNewField("skip_builtin_dashboard", schema.BoolAttribute{Optional: true, Required: false}) + c.AddNewField("warehouse_id", schema.StringAttribute{Optional: true, Required: false}) + c.SetRequired("assets_dir") + c.SetRequired("output_schema_name") + c.SetRequired("table_name") + // TODO: Uncomment this once SetReadOnly is supported in the plugin framework + // c.SetReadOnly("monitor_version") + // c.SetReadOnly("drift_metrics_table_name") + // c.SetReadOnly("profile_metrics_table_name") + // c.SetReadOnly("status") + // c.SetReadOnly("dashboard_id") + // c.SetReadOnly("schedule", "pause_status") + return c + }), + } +} + +func (d *QualityMonitorResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + client, ok := req.ProviderData.(*common.DatabricksClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *common.DatabricksClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + d.Client = client +} + +func (r *QualityMonitorResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + w, err := r.Client.WorkspaceClient() + if err != nil { + resp.Diagnostics.AddError("Failed to get workspace client", err.Error()) + return + } + var createMonitorTfSDK catalog_tf.CreateMonitor + diags := req.Plan.Get(ctx, &createMonitorTfSDK) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var createMonitorGoSDK catalog.CreateMonitor + err = common.TfSdkToGoSdkStruct(createMonitorTfSDK, &createMonitorGoSDK, ctx) + if err != nil { + resp.Diagnostics.AddError("Failed to convert Tf SDK struct to Go SDK struct", err.Error()) + return + } + endpoint, err := w.QualityMonitors.Create(ctx, createMonitorGoSDK) + if err != nil { + resp.Diagnostics.AddError("Failed to get create monitor", err.Error()) + return + } + err = WaitForMonitor(w, ctx, endpoint.TableName) + if err != nil { + resp.Diagnostics.AddError("Failed to get newly created monitor", err.Error()) + return + } +} + +func (r *QualityMonitorResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + w, err := r.Client.WorkspaceClient() + if err != nil { + resp.Diagnostics.AddError("Failed to get workspace client", err.Error()) + return + } + var getMonitor catalog_tf.GetQualityMonitorRequest + diags := req.State.Get(ctx, &getMonitor) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + endpoint, err := w.QualityMonitors.GetByTableName(ctx, getMonitor.TableName.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Failed to get monitor", err.Error()) + return + } + var monitorInfoTfSDK catalog_tf.MonitorInfo + err = common.GoSdkToTfSdkStruct(endpoint, &monitorInfoTfSDK, ctx) + if err != nil { + resp.Diagnostics.AddError("Failed to convert Go SDK struct to TF SDK struct", err.Error()) + } + diags = resp.State.Set(ctx, monitorInfoTfSDK) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +func (r *QualityMonitorResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + w, err := r.Client.WorkspaceClient() + if err != nil { + resp.Diagnostics.AddError("Failed to get workspace client", err.Error()) + return + } + var updateMonitorTfSDK catalog_tf.UpdateMonitor + diags := req.Plan.Get(ctx, &updateMonitorTfSDK) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + var updateMonitorGoSDK catalog.UpdateMonitor + err = common.TfSdkToGoSdkStruct(updateMonitorTfSDK, &updateMonitorGoSDK, ctx) + if err != nil { + resp.Diagnostics.AddError("Failed to convert Tf SDK struct to Go SDK struct", err.Error()) + return + } + _, err = w.QualityMonitors.Update(ctx, updateMonitorGoSDK) + if err != nil { + resp.Diagnostics.AddError("Failed to update monitor", err.Error()) + return + } + err = WaitForMonitor(w, ctx, updateMonitorGoSDK.TableName) + if err != nil { + resp.Diagnostics.AddError("Failed to get updated monitor", err.Error()) + return + } +} + +func (r *QualityMonitorResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + w, err := r.Client.WorkspaceClient() + if err != nil { + resp.Diagnostics.AddError("Failed to get workspace client", err.Error()) + return + } + var deleteRequest catalog_tf.DeleteQualityMonitorRequest + diags := req.State.Get(ctx, &deleteRequest) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + err = w.QualityMonitors.DeleteByTableName(ctx, deleteRequest.TableName.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Failed to delete monitor", err.Error()) + return + } +} diff --git a/pluginframework/test/data/volumes/volumes.tf b/pluginframework/test/data/volumes/volumes.tf new file mode 100644 index 0000000000..3ff475d826 --- /dev/null +++ b/pluginframework/test/data/volumes/volumes.tf @@ -0,0 +1,55 @@ +terraform { + required_providers { + databricks = { + source = "databricks/databricks" + } + } +} + +provider "databricks" { + profile = "aws-prod-ucws" +} + +resource "databricks_catalog" "testcatalog" { + name = "testcatalog-25july" + comment = "Plugin Framework PoC" + properties = { + purpose = "testing" + } +} + +resource "databricks_schema" "testschema" { + catalog_name = databricks_catalog.testcatalog.name + name = "testschema-25july" + comment = "Plugin Framework PoC" + properties = { + purpose = "testing" + } +} + +resource "databricks_volume" "testvolume1" { + name = "testvolume1-25july" + catalog_name = databricks_catalog.testcatalog.name + schema_name = databricks_schema.testschema.name + volume_type = "MANAGED" + comment = "Plugin Framework PoC" +} + +resource "databricks_volume" "testvolume2" { + name = "testvolume2-25july" + catalog_name = databricks_catalog.testcatalog.name + schema_name = databricks_schema.testschema.name + volume_type = "MANAGED" + comment = "Plugin Framework PoC" +} + +data "databricks_volumes_pluginframework" "testvolumes" { + catalog_name = databricks_catalog.testcatalog.name + schema_name = databricks_schema.testschema.name +} + +output "all_volumes" { + value = data.databricks_volumes_pluginframework.testvolumes +} + + diff --git a/pluginframework/test/resource/quality-monitor/quality_monitor.tf b/pluginframework/test/resource/quality-monitor/quality_monitor.tf new file mode 100644 index 0000000000..e98b118ebb --- /dev/null +++ b/pluginframework/test/resource/quality-monitor/quality_monitor.tf @@ -0,0 +1,47 @@ +terraform { + required_providers { + databricks = { + source = "databricks/databricks" + } + } +} + +provider "databricks" { + profile = "aws-prod-ucws" +} + +resource "databricks_catalog" "testcatalog" { + name = "testcatalog" + comment = "Plugin Framework PoC" + properties = { + purpose = "testing" + } +} + +resource "databricks_schema" "testschema" { + catalog_name = databricks_catalog.testcatalog.name + name = "testSchema" + comment = "Plugin Framework PoC" + properties = { + purpose = "testing" + } +} + +resource "databricks_sql_table" "testtable" { + catalog_name = databricks_catalog.testcatalog.name + schema_name = databricks_schema.testschema.name + name = "testTable" + table_type = "MANAGED" + data_source_format = "DELTA" + + column { + name = "timestamp" + type = "int" + } +} + +# TODO: Uncomment once SetReadOnly is supported in the plugin framework and add the necessary fields +# resource "databricks_lakehouse_monitor_pluginframework" "testmonitor" { +# table_name = "${databricks_catalog.testcatalog.name}.${databricks_schema.testschema.name}.${databricks_sql_table.testtable.name}" +# } + diff --git a/provider/provider_plugin_framework.go b/provider/provider_plugin_framework.go new file mode 100644 index 0000000000..acfc115354 --- /dev/null +++ b/provider/provider_plugin_framework.go @@ -0,0 +1,177 @@ +package provider + +import ( + "context" + "fmt" + "log" + "reflect" + "sort" + "strings" + + "github.com/databricks/databricks-sdk-go/client" + "github.com/databricks/databricks-sdk-go/config" + "github.com/databricks/databricks-sdk-go/useragent" + "github.com/databricks/terraform-provider-databricks/commands" + "github.com/databricks/terraform-provider-databricks/common" + "github.com/databricks/terraform-provider-databricks/pluginframework" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/provider" + "github.com/hashicorp/terraform-plugin-framework/provider/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +var pluginFrameworkProviderName = "databricks-tf-provider-pluginframework" + +func init() { + // IMPORTANT: this line cannot be changed, because it's used for + // internal purposes at Databricks. + useragent.WithProduct(pluginFrameworkProviderName, common.Version()) +} + +func GetDatabricksProviderPluginFramework() provider.Provider { + p := &DatabricksProviderPluginFramework{} + return p +} + +type DatabricksProviderPluginFramework struct { +} + +var _ provider.Provider = (*DatabricksProviderPluginFramework)(nil) + +func (p *DatabricksProviderPluginFramework) Resources(ctx context.Context) []func() resource.Resource { + return []func() resource.Resource{ + pluginframework.ResourceQualityMonitor(), + } +} + +func (p *DatabricksProviderPluginFramework) DataSources(ctx context.Context) []func() datasource.DataSource { + return []func() datasource.DataSource{ + pluginframework.DataSourceVolumes(), + } +} + +func (p *DatabricksProviderPluginFramework) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { + resp.Schema = providerSchemaPluginFramework() +} + +func (p *DatabricksProviderPluginFramework) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { + resp.TypeName = pluginFrameworkProviderName + resp.Version = common.Version() +} + +func (p *DatabricksProviderPluginFramework) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + client := configureDatabricksClient_PluginFramework(ctx, req, resp) + resp.DataSourceData = client + resp.ResourceData = client +} + +func providerSchemaPluginFramework() schema.Schema { + ps := map[string]schema.Attribute{} + for _, attr := range config.ConfigAttributes { + switch attr.Kind { + case reflect.Bool: + ps[attr.Name] = schema.BoolAttribute{ + Optional: true, + Sensitive: attr.Sensitive, + } + case reflect.String: + ps[attr.Name] = schema.StringAttribute{ + Optional: true, + Sensitive: attr.Sensitive, + } + case reflect.Int: + ps[attr.Name] = schema.Int64Attribute{ + Optional: true, + Sensitive: attr.Sensitive, + } + } + } + return schema.Schema{ + Attributes: ps, + } +} + +func configureDatabricksClient_PluginFramework(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) any { + cfg := &config.Config{} + attrsUsed := []string{} + authsUsed := map[string]bool{} + for _, attr := range config.ConfigAttributes { + switch attr.Kind { + case reflect.Bool: + var attrValue types.Bool + diags := req.Config.GetAttribute(ctx, path.Root(attr.Name), &attrValue) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return nil + } + err := attr.Set(cfg, attrValue.ValueBool()) + if err != nil { + resp.Diagnostics.Append(diag.NewErrorDiagnostic("Failed to set attribute", err.Error())) + return nil + } + case reflect.Int: + var attrValue types.Int64 + diags := req.Config.GetAttribute(ctx, path.Root(attr.Name), &attrValue) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return nil + } + err := attr.Set(cfg, int(attrValue.ValueInt64())) + if err != nil { + resp.Diagnostics.Append(diag.NewErrorDiagnostic("Failed to set attribute", err.Error())) + return nil + } + case reflect.String: + var attrValue types.String + diags := req.Config.GetAttribute(ctx, path.Root(attr.Name), &attrValue) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return nil + } + err := attr.Set(cfg, attrValue.ValueString()) + if err != nil { + resp.Diagnostics.Append(diag.NewErrorDiagnostic("Failed to set attribute", err.Error())) + return nil + } + } + if attr.Kind == reflect.String { + attrsUsed = append(attrsUsed, attr.Name) + } + if attr.Auth != "" { + authsUsed[attr.Auth] = true + } + } + sort.Strings(attrsUsed) + tflog.Info(ctx, fmt.Sprintf("Explicit and implicit attributes: %s", strings.Join(attrsUsed, ", "))) + if cfg.AuthType != "" { + // mapping from previous Google authentication types + // and current authentication types from Databricks Go SDK + oldToNewerAuthType := map[string]string{ + "google-creds": "google-credentials", + "google-accounts": "google-id", + "google-workspace": "google-id", + } + newer, ok := oldToNewerAuthType[cfg.AuthType] + if ok { + log.Printf("[INFO] Changing required auth_type from %s to %s", cfg.AuthType, newer) + cfg.AuthType = newer + } + } + client, err := client.New(cfg) + if err != nil { + resp.Diagnostics.Append(diag.NewErrorDiagnostic(err.Error(), "")) + return nil + } + pc := &common.DatabricksClient{ + DatabricksClient: client, + } + pc.WithCommandExecutor(func(ctx context.Context, client *common.DatabricksClient) common.CommandExecutor { + return commands.NewCommandsAPI(ctx, client) + }) + return pc +} diff --git a/provider/provider_test.go b/provider/provider_test.go index bb52d36727..47638a7e6f 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -8,91 +8,14 @@ import ( "net/http/httptest" "os" "path/filepath" - "strings" "testing" "time" "github.com/databricks/terraform-provider-databricks/common" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -type providerFixture struct { - host string - token string - username string - password string - configFile string - profile string - azureClientID string - azureClientSecret string - azureTenantID string - azureResourceID string - authType string - env map[string]string - assertError string - assertAuth string - assertHost string - assertAzure bool -} - -func (tt providerFixture) rawConfig() map[string]any { - rawConfig := map[string]any{} - if tt.host != "" { - rawConfig["host"] = tt.host - } - if tt.token != "" { - rawConfig["token"] = tt.token - } - if tt.username != "" { - rawConfig["username"] = tt.username - } - if tt.password != "" { - rawConfig["password"] = tt.password - } - if tt.configFile != "" { - rawConfig["config_file"] = tt.configFile - } - if tt.profile != "" { - rawConfig["profile"] = tt.profile - } - if tt.azureClientID != "" { - rawConfig["azure_client_id"] = tt.azureClientID - } - if tt.azureClientSecret != "" { - rawConfig["azure_client_secret"] = tt.azureClientSecret - } - if tt.azureTenantID != "" { - rawConfig["azure_tenant_id"] = tt.azureTenantID - } - if tt.azureResourceID != "" { - rawConfig["azure_workspace_resource_id"] = tt.azureResourceID - } - if tt.authType != "" { - rawConfig["auth_type"] = tt.authType - } - return rawConfig -} - -func (tc providerFixture) apply(t *testing.T) *common.DatabricksClient { - c, err := configureProviderAndReturnClient(t, tc) - if tc.assertError != "" { - require.NotNilf(t, err, "Expected to have %s error", tc.assertError) - require.True(t, strings.HasPrefix(err.Error(), tc.assertError), - "Expected to have '%s' error, but got '%s'", tc.assertError, err) - return nil - } - if err != nil { - require.NoError(t, err) - return nil - } - assert.Equal(t, tc.assertAzure, c.IsAzure()) - assert.Equal(t, tc.assertAuth, c.Config.AuthType) - assert.Equal(t, tc.assertHost, c.Config.Host) - return c -} - func TestConfig_NoParams(t *testing.T) { if f, err := os.Stat("~/.databrickscfg"); err == nil && !f.IsDir() { // the provider should fail to configure if no configuration options are available, @@ -425,7 +348,7 @@ func TestConfig_OAuthFetchesToken(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(shortLivedOAuthHandler)) defer ts.Close() - client := providerFixture{ + testFixture := providerFixture{ env: map[string]string{ "DATABRICKS_HOST": ts.URL, "DATABRICKS_CLIENT_ID": "x", @@ -433,9 +356,17 @@ func TestConfig_OAuthFetchesToken(t *testing.T) { }, assertAuth: "oauth-m2m", assertHost: ts.URL, - }.apply(t) + } - ws, err := client.WorkspaceClient() + client := testFixture.applyWithSDKv2(t) + testOAuthFetchesToken(t, client) + + client = testFixture.applyWithPluginFramework(t) + testOAuthFetchesToken(t, client) +} + +func testOAuthFetchesToken(t *testing.T, c *common.DatabricksClient) { + ws, err := c.WorkspaceClient() require.NoError(t, err) bgCtx := context.Background() { @@ -452,32 +383,6 @@ func TestConfig_OAuthFetchesToken(t *testing.T) { } } -func configureProviderAndReturnClient(t *testing.T, tt providerFixture) (*common.DatabricksClient, error) { - for k, v := range tt.env { - t.Setenv(k, v) - } - p := DatabricksProvider() - ctx := context.Background() - diags := p.Configure(ctx, terraform.NewResourceConfigRaw(tt.rawConfig())) - if len(diags) > 0 { - issues := []string{} - for _, d := range diags { - issues = append(issues, d.Summary) - } - return nil, fmt.Errorf(strings.Join(issues, ", ")) - } - client := p.Meta().(*common.DatabricksClient) - r, err := http.NewRequest("GET", "", nil) - if err != nil { - return nil, err - } - err = client.Config.Authenticate(r) - if err != nil { - return nil, err - } - return client, nil -} - type parseUserAgentTestCase struct { name string env string diff --git a/provider/test_utils.go b/provider/test_utils.go new file mode 100644 index 0000000000..7f7b6b22a4 --- /dev/null +++ b/provider/test_utils.go @@ -0,0 +1,197 @@ +package provider + +import ( + "context" + "fmt" + "net/http" + "strings" + "testing" + + "github.com/databricks/terraform-provider-databricks/common" + "github.com/hashicorp/terraform-plugin-framework/provider" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-go/tftypes" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +type providerFixture struct { + host string + token string + username string + password string + configFile string + profile string + azureClientID string + azureClientSecret string + azureTenantID string + azureResourceID string + authType string + env map[string]string + assertError string + assertAuth string + assertHost string + assertAzure bool +} + +func (tt providerFixture) rawConfig() map[string]string { + rawConfig := map[string]string{} + if tt.host != "" { + rawConfig["host"] = tt.host + } + if tt.token != "" { + rawConfig["token"] = tt.token + } + if tt.username != "" { + rawConfig["username"] = tt.username + } + if tt.password != "" { + rawConfig["password"] = tt.password + } + if tt.configFile != "" { + rawConfig["config_file"] = tt.configFile + } + if tt.profile != "" { + rawConfig["profile"] = tt.profile + } + if tt.azureClientID != "" { + rawConfig["azure_client_id"] = tt.azureClientID + } + if tt.azureClientSecret != "" { + rawConfig["azure_client_secret"] = tt.azureClientSecret + } + if tt.azureTenantID != "" { + rawConfig["azure_tenant_id"] = tt.azureTenantID + } + if tt.azureResourceID != "" { + rawConfig["azure_workspace_resource_id"] = tt.azureResourceID + } + if tt.authType != "" { + rawConfig["auth_type"] = tt.authType + } + return rawConfig +} + +func (tt providerFixture) rawConfigSDKv2() map[string]any { + rawConfig := tt.rawConfig() + rawConfigSDKv2 := map[string]any{} + for k, v := range rawConfig { + rawConfigSDKv2[k] = v + } + return rawConfigSDKv2 +} + +func (tt providerFixture) rawConfigPluginFramework() tftypes.Value { + rawConfig := tt.rawConfig() + + rawConfigTypeMap := map[string]tftypes.Type{} + for k := range rawConfig { + rawConfigTypeMap[k] = tftypes.String + } + rawConfigType := tftypes.Object{ + AttributeTypes: rawConfigTypeMap, + } + + rawConfigValueMap := map[string]tftypes.Value{} + for k, v := range rawConfig { + rawConfigValueMap[k] = tftypes.NewValue(tftypes.String, v) + } + rawConfigValue := tftypes.NewValue(rawConfigType, rawConfigValueMap) + return rawConfigValue +} + +func (tc providerFixture) applyWithSDKv2(t *testing.T) *common.DatabricksClient { + c, err := configureProviderAndReturnClient_SDKv2(t, tc) + return tc.applyAssertions(c, t, err) +} + +func (tc providerFixture) applyWithPluginFramework(t *testing.T) *common.DatabricksClient { + c, err := configureProviderAndReturnClient_PluginFramework(t, tc) + return tc.applyAssertions(c, t, err) +} + +func (tc providerFixture) applyAssertions(c *common.DatabricksClient, t *testing.T, err error) *common.DatabricksClient { + if tc.assertError != "" { + require.NotNilf(t, err, "Expected to have %s error", tc.assertError) + require.True(t, strings.HasPrefix(err.Error(), tc.assertError), + "Expected to have '%s' error, but got '%s'", tc.assertError, err) + return nil + } + if err != nil { + require.NoError(t, err) + return nil + } + assert.Equal(t, tc.assertAzure, c.IsAzure()) + assert.Equal(t, tc.assertAuth, c.Config.AuthType) + assert.Equal(t, tc.assertHost, c.Config.Host) + return c +} + +func (tc providerFixture) apply(t *testing.T) { + _ = tc.applyWithSDKv2(t) + _ = tc.applyWithPluginFramework(t) +} + +func configureProviderAndReturnClient_SDKv2(t *testing.T, tt providerFixture) (*common.DatabricksClient, error) { + for k, v := range tt.env { + t.Setenv(k, v) + } + p := DatabricksProvider() + ctx := context.Background() + diags := p.Configure(ctx, terraform.NewResourceConfigRaw(tt.rawConfigSDKv2())) + if len(diags) > 0 { + issues := []string{} + for _, d := range diags { + issues = append(issues, d.Summary) + } + return nil, fmt.Errorf(strings.Join(issues, ", ")) + } + client := p.Meta().(*common.DatabricksClient) + r, err := http.NewRequest("GET", "", nil) + if err != nil { + return nil, err + } + err = client.Config.Authenticate(r) + if err != nil { + return nil, err + } + return client, nil +} + +func configureProviderAndReturnClient_PluginFramework(t *testing.T, tt providerFixture) (*common.DatabricksClient, error) { + for k, v := range tt.env { + t.Setenv(k, v) + } + p := GetDatabricksProviderPluginFramework() + ctx := context.Background() + rawConfig := tt.rawConfigPluginFramework() + var providerSchemaResponse provider.SchemaResponse + p.Schema(ctx, provider.SchemaRequest{}, &providerSchemaResponse) + configRequest := provider.ConfigureRequest{ + Config: tfsdk.Config{ + Raw: rawConfig, + Schema: providerSchemaResponse.Schema, + }, + } + configResponse := &provider.ConfigureResponse{} + p.Configure(ctx, configRequest, configResponse) + diags := configResponse.Diagnostics + if len(diags) > 0 { + issues := []string{} + for _, d := range diags { + issues = append(issues, d.Summary()) + } + return nil, fmt.Errorf(strings.Join(issues, ", ")) + } + client := configResponse.ResourceData.(*common.DatabricksClient) + r, err := http.NewRequest("GET", "", nil) + if err != nil { + return nil, err + } + err = client.Config.Authenticate(r) + if err != nil { + return nil, err + } + return client, nil +}