11package access
22
33import (
4+ "context"
45 "fmt"
5- "log"
66 "net/http"
77
88 "github.com/databrickslabs/databricks-terraform/common"
9+ "github.com/databrickslabs/databricks-terraform/internal"
10+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
911 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1012)
1113
1214// NewSecretScopesAPI creates SecretScopesAPI instance from provider meta
1315func NewSecretScopesAPI (m interface {}) SecretScopesAPI {
14- return SecretScopesAPI {C : m .(* common.DatabricksClient )}
16+ return SecretScopesAPI {client : m .(* common.DatabricksClient )}
1517}
1618
1719// SecretScopesAPI exposes the Secret Scopes API
1820type SecretScopesAPI struct {
19- C * common.DatabricksClient
21+ client * common.DatabricksClient
22+ }
23+
24+ // SecretScopeList holds list of secret scopes
25+ type SecretScopeList struct {
26+ Scopes []SecretScope `json:"scopes,omitempty"`
27+ }
28+
29+ // SecretScope is a struct that encapsulates the secret scope
30+ type SecretScope struct {
31+ Name string `json:"name"`
32+ BackendType string `json:"backend_type,omitempty" tf:"computed"`
33+ InitialManagePrincipal string `json:"initial_manage_principal,omitempty"`
34+ KeyvaultMetadata * KeyvaultMetadata `json:"keyvault_metadata,omitempty"`
35+ }
36+
37+ // KeyvaultMetadata Azure Key Vault metadata wrapper
38+ type KeyvaultMetadata struct {
39+ // /subscriptions/.../resourceGroups/.../providers/Microsoft.KeyVault/vaults/my-azure-kv
40+ ResourceID string `json:"resource_id"`
41+ // https://my-azure-kv.vault.azure.net/
42+ DNSName string `json:"dns_name"`
43+ }
44+
45+ type secretScopeRequest struct {
46+ Scope string `json:"scope,omitempty"`
47+ BackendType string `json:"scope_backend_type,omitempty"`
48+ InitialManagePrincipal string `json:"initial_manage_principal,omitempty"`
49+ BackendAzureKeyvault * KeyvaultMetadata `json:"backend_azure_keyvault,omitempty"`
2050}
2151
2252// Create creates a new secret scope
23- func (a SecretScopesAPI ) Create (scope string , initialManagePrincipal string ) error {
24- req := map [string ]string {"scope" : scope }
25- if initialManagePrincipal != "" {
26- req ["initial_manage_principal" ] = initialManagePrincipal
53+ func (a SecretScopesAPI ) Create (s SecretScope ) error {
54+ req := secretScopeRequest {
55+ Scope : s .Name ,
56+ InitialManagePrincipal : s .InitialManagePrincipal ,
57+ BackendType : "DATABRICKS" ,
2758 }
28- return a .C .Post ("/secrets/scopes/create" , req , nil )
59+ if s .KeyvaultMetadata != nil {
60+ if ! a .client .IsAzure () {
61+ return fmt .Errorf ("Azure KeyVault is not available" )
62+ }
63+ if a .client .AzureAuth .IsClientSecretSet () {
64+ return fmt .Errorf ("Azure KeyVault cannot yet be configured for Service Principal authorization" )
65+ }
66+ req .BackendType = "AZURE_KEYVAULT"
67+ req .BackendAzureKeyvault = s .KeyvaultMetadata
68+ }
69+ return a .client .Post ("/secrets/scopes/create" , req , nil )
2970}
3071
3172// Delete deletes a secret scope
3273func (a SecretScopesAPI ) Delete (scope string ) error {
33- return a .C .Post ("/secrets/scopes/delete" , map [string ]string {
74+ return a .client .Post ("/secrets/scopes/delete" , map [string ]string {
3475 "scope" : scope ,
3576 }, nil )
3677}
3778
3879// List lists all secret scopes available in the workspace
3980func (a SecretScopesAPI ) List () ([]SecretScope , error ) {
4081 var listSecretScopesResponse SecretScopeList
41- err := a .C .Get ("/secrets/scopes/list" , nil , & listSecretScopesResponse )
82+ err := a .client .Get ("/secrets/scopes/list" , nil , & listSecretScopesResponse )
4283 return listSecretScopesResponse .Scopes , err
4384}
4485
@@ -62,69 +103,56 @@ func (a SecretScopesAPI) Read(scopeName string) (SecretScope, error) {
62103 }
63104}
64105
106+ // ResourceSecretScope manages secret scopes
65107func ResourceSecretScope () * schema.Resource {
108+ s := internal .StructToSchema (SecretScope {}, func (s map [string ]* schema.Schema ) map [string ]* schema.Schema {
109+ // TODO: CustomDiffFunc for initial_manage_principal & importing
110+ s ["name" ].ForceNew = true
111+ s ["initial_manage_principal" ].ForceNew = true
112+ s ["keyvault_metadata" ].ForceNew = true
113+ return s
114+ })
115+ readContext := func (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
116+ scope , err := NewSecretScopesAPI (m ).Read (d .Id ())
117+ if e , ok := err .(common.APIError ); ok && e .IsMissing () {
118+ d .SetId ("" )
119+ return nil
120+ }
121+ if err != nil {
122+ return diag .FromErr (err )
123+ }
124+ err = internal .StructToData (scope , s , d )
125+ if err != nil {
126+ return diag .FromErr (err )
127+ }
128+ return nil
129+ }
66130 return & schema.Resource {
67- Create : resourceSecretScopeCreate ,
68- Read : resourceSecretScopeRead ,
69- Delete : resourceSecretScopeDelete ,
70131 Importer : & schema.ResourceImporter {
71132 StateContext : schema .ImportStatePassthroughContext ,
72133 },
73- Schema : map [string ]* schema.Schema {
74- "name" : {
75- Type : schema .TypeString ,
76- Required : true ,
77- ForceNew : true ,
78- },
79- "initial_manage_principal" : {
80- Type : schema .TypeString ,
81- Optional : true ,
82- ForceNew : true ,
83- },
84- "backend_type" : {
85- Type : schema .TypeString ,
86- Computed : true ,
87- },
134+ CreateContext : func (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
135+ var scope SecretScope
136+ err := internal .DataToStructPointer (d , s , & scope )
137+ if err != nil {
138+ return diag .FromErr (err )
139+ }
140+ err = NewSecretScopesAPI (m ).Create (scope )
141+ if err != nil {
142+ return diag .FromErr (err )
143+ }
144+ d .SetId (scope .Name )
145+ return readContext (ctx , d , m )
88146 },
89- }
90- }
91-
92- func resourceSecretScopeCreate (d * schema.ResourceData , m interface {}) error {
93- client := m .(* common.DatabricksClient )
94- scopeName := d .Get ("name" ).(string )
95- initialManagePrincipal := d .Get ("initial_manage_principal" ).(string )
96- err := NewSecretScopesAPI (client ).Create (scopeName , initialManagePrincipal )
97- if err != nil {
98- return err
99- }
100- d .SetId (scopeName )
101- return resourceSecretScopeRead (d , m )
102- }
103-
104- func resourceSecretScopeRead (d * schema.ResourceData , m interface {}) error {
105- client := m .(* common.DatabricksClient )
106- id := d .Id ()
107- scope , err := NewSecretScopesAPI (client ).Read (id )
108- if err != nil {
109- if e , ok := err .(common.APIError ); ok && e .IsMissing () {
110- log .Printf ("[INFO] missing resource due to error: %v\n " , e )
111- d .SetId ("" )
147+ DeleteContext : func (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
148+ err := NewSecretScopesAPI (m ).Delete (d .Id ())
149+ if err != nil {
150+ return diag .FromErr (err )
151+ }
112152 return nil
113- }
114- return err
115- }
116- d .SetId (scope .Name )
117- err = d .Set ("name" , scope .Name )
118- if err != nil {
119- return err
153+ },
154+ ReadContext : readContext ,
155+ SchemaVersion : 2 ,
156+ Schema : s ,
120157 }
121- err = d .Set ("backend_type" , scope .BackendType )
122- return err
123- }
124-
125- func resourceSecretScopeDelete (d * schema.ResourceData , m interface {}) error {
126- client := m .(* common.DatabricksClient )
127- id := d .Id ()
128- err := NewSecretScopesAPI (client ).Delete (id )
129- return err
130158}
0 commit comments