Skip to content

Commit 4b00d89

Browse files
Akshay MallMaxrovr
authored andcommitted
Bug fixed - To support TF import of KMS vault replica.
1 parent 396fd1c commit 4b00d89

File tree

1 file changed

+143
-111
lines changed

1 file changed

+143
-111
lines changed

internal/service/kms/kms_vault_replication_resource.go

Lines changed: 143 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package kms
33
import (
44
"context"
55
"fmt"
6+
"log"
67
"strings"
78

9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
810
"github.com/oracle/terraform-provider-oci/internal/client"
911
"github.com/oracle/terraform-provider-oci/internal/tfresource"
1012

11-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1213
oci_kms "github.com/oracle/oci-go-sdk/v65/keymanagement"
1314
)
1415

@@ -20,7 +21,6 @@ func KmsVaultReplicationResource() *schema.Resource {
2021
Timeouts: tfresource.DefaultTimeout,
2122
Create: createKmsVaultReplica,
2223
Read: readKmsVaultReplica,
23-
Update: updateKmsVaultReplica,
2424
Delete: deleteKmsVaultReplica,
2525
Schema: map[string]*schema.Schema{
2626
// Required
@@ -32,7 +32,10 @@ func KmsVaultReplicationResource() *schema.Resource {
3232
"replica_region": {
3333
Type: schema.TypeString,
3434
Required: true,
35+
ForceNew: true,
3536
},
37+
38+
// Optional
3639
"replica_vault_metadata": {
3740
Type: schema.TypeList,
3841
Optional: true,
@@ -67,6 +70,18 @@ func KmsVaultReplicationResource() *schema.Resource {
6770
},
6871

6972
// Computed
73+
"crypto_endpoint": {
74+
Type: schema.TypeString,
75+
Computed: true,
76+
},
77+
"management_endpoint": {
78+
Type: schema.TypeString,
79+
Computed: true,
80+
},
81+
"vault_replica_status": {
82+
Type: schema.TypeString,
83+
Computed: true,
84+
},
7085
},
7186
}
7287
}
@@ -87,14 +102,6 @@ func readKmsVaultReplica(d *schema.ResourceData, m interface{}) error {
87102
return tfresource.ReadResource(sync)
88103
}
89104

90-
func updateKmsVaultReplica(d *schema.ResourceData, m interface{}) error {
91-
sync := &KmsVaultReplicaResourceCrud{}
92-
sync.D = d
93-
sync.Client = m.(*client.OracleClients).KmsVaultClient()
94-
95-
return tfresource.UpdateResource(d, sync)
96-
}
97-
98105
func deleteKmsVaultReplica(d *schema.ResourceData, m interface{}) error {
99106
sync := &KmsVaultReplicaResourceCrud{}
100107
sync.D = d
@@ -106,134 +113,148 @@ func deleteKmsVaultReplica(d *schema.ResourceData, m interface{}) error {
106113
type KmsVaultReplicaResourceCrud struct {
107114
tfresource.BaseCrud
108115
Client *oci_kms.KmsVaultClient
109-
Res *oci_kms.ListVaultReplicasResponse
116+
Res *oci_kms.VaultReplicaSummary
110117
DisableNotFoundRetries bool
111118
}
112119

113120
func (s *KmsVaultReplicaResourceCrud) ID() string {
114-
return *s.Res.OpcRequestId
115-
}
116-
117-
func (s *KmsVaultReplicaResourceCrud) Create() error {
118-
replicaRegionStr := ""
119-
if replicaRegion, ok := s.D.GetOkExists("replica_region"); ok {
120-
tmp := replicaRegion.(string)
121-
replicaRegionStr = tmp
122-
}
121+
log.Printf("[INFO] ID()")
123122

124-
vaultIdStr := ""
123+
vaultIdStr := "vault_id"
125124
if vaultId, ok := s.D.GetOkExists("vault_id"); ok {
126125
tmp := vaultId.(string)
127126
vaultIdStr = tmp
128127
}
128+
replicaRegionStr := *s.Res.Region
129129

130-
return s.createVaultReplicaHelper(vaultIdStr, replicaRegionStr)
130+
log.Printf("[INFO] ID() Setting ID: %s", fmt.Sprintf("%s:%s", vaultIdStr, replicaRegionStr))
131+
return fmt.Sprintf("%s:%s", vaultIdStr, replicaRegionStr)
131132
}
132133

133-
func (s *KmsVaultReplicaResourceCrud) Get() error {
134-
request := oci_kms.ListVaultReplicasRequest{}
134+
func (s *KmsVaultReplicaResourceCrud) Create() error {
135+
log.Printf("[INFO] Create()")
136+
request := oci_kms.CreateVaultReplicaRequest{}
135137

136138
if vaultId, ok := s.D.GetOkExists("vault_id"); ok {
137139
tmp := vaultId.(string)
138140
request.VaultId = &tmp
139141
}
140142

141-
request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms")
142-
143-
response, err := s.Client.ListVaultReplicas(context.Background(), request)
144-
if err != nil {
145-
return err
143+
if replicaRegion, ok := s.D.GetOkExists("replica_region"); ok {
144+
tmp := replicaRegion.(string)
145+
request.ReplicaRegion = &tmp
146146
}
147147

148-
s.Res = &response
149-
return nil
150-
}
151-
152-
func (s *KmsVaultReplicaResourceCrud) Update() error {
148+
if replicaVaultMetadata, ok := s.D.GetOkExists("replica_vault_metadata"); ok {
149+
if tmpList := replicaVaultMetadata.([]interface{}); len(tmpList) > 0 {
150+
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "replica_vault_metadata", 0)
151+
replicaExternalVaultMetadata := oci_kms.ReplicaExternalVaultMetadata{}
153152

154-
// Update is only supported for the change in replica region. All others are a forceNew
155-
if s.D.HasChange("replica_region") {
153+
if privateEndpointId, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "private_endpoint_id")); ok {
154+
tmp := privateEndpointId.(string)
155+
replicaExternalVaultMetadata.PrivateEndpointId = &tmp
156+
}
156157

157-
oldRaw, newRaw := s.D.GetChange("replica_region")
158-
oldReplicaRegionName := oldRaw.(string)
159-
newReplicaRegionName := newRaw.(string)
158+
if idcsAccountNameUrl, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "idcs_account_name_url")); ok {
159+
tmp := idcsAccountNameUrl.(string)
160+
replicaExternalVaultMetadata.IdcsAccountNameUrl = &tmp
161+
}
160162

161-
vaultIdStr := ""
162-
if vaultId, ok := s.D.GetOkExists("vault_id"); ok {
163-
tmp := vaultId.(string)
164-
vaultIdStr = tmp
163+
request.ReplicaVaultMetadata = &replicaExternalVaultMetadata
165164
}
165+
}
166166

167-
// delete replica in the old region for the primary vault
168-
err := s.deleteVaultReplicaHelper(vaultIdStr, oldReplicaRegionName)
169-
if err != nil {
170-
return err
171-
}
167+
request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms")
168+
169+
log.Printf("[INFO] Create() Sending Create Replica Request")
170+
_, err := s.Client.CreateVaultReplica(context.Background(), request)
171+
if err != nil {
172+
return err
173+
}
172174

173-
// Create replica in the new region for the primary vault after deletion is completed
174-
return s.createVaultReplicaHelper(vaultIdStr, newReplicaRegionName)
175+
log.Printf("[INFO] Create() Waiting for Replica Creation")
176+
retentionPolicyFunc := func() bool { return s.Res.Status == oci_kms.VaultReplicaSummaryStatusCreated }
177+
waitErr := tfresource.WaitForResourceCondition(s, retentionPolicyFunc, s.D.Timeout(schema.TimeoutCreate))
178+
if waitErr != nil {
179+
return waitErr
175180
}
181+
log.Printf("[INFO] Create() Replica Creation Completed")
182+
176183
return nil
177184
}
178185

179-
func (s *KmsVaultReplicaResourceCrud) Delete() error {
180-
replicaRegionStr := ""
181-
if replicaRegion, ok := s.D.GetOkExists("replica_region"); ok {
182-
tmp := replicaRegion.(string)
183-
replicaRegionStr = tmp
184-
}
186+
func (s *KmsVaultReplicaResourceCrud) Get() error {
187+
log.Printf("[INFO] Get()")
188+
189+
request := oci_kms.ListVaultReplicasRequest{}
190+
191+
/*
192+
*The Vault ID is only present in the config and not in the Response so we need to check
193+
* if Vault ID is available in the state/config then use that else extract it from the ID
194+
* We can't always use the ID as it is only set after resource creation or provided during import
195+
*/
196+
vaultIdStr := "vault_id"
197+
replicaRegionStr := "replica_region"
185198

186-
vaultIdStr := ""
187199
if vaultId, ok := s.D.GetOkExists("vault_id"); ok {
188200
tmp := vaultId.(string)
189201
vaultIdStr = tmp
202+
request.VaultId = &tmp
190203
}
191-
192-
return s.deleteVaultReplicaHelper(vaultIdStr, replicaRegionStr)
193-
}
194-
195-
func (s *KmsVaultReplicaResourceCrud) createVaultReplicaHelper(vaultId string, replicaRegion string) error {
196-
request := oci_kms.CreateVaultReplicaRequest{}
197-
198-
if len(strings.TrimSpace(vaultId)) != 0 {
199-
request.VaultId = &vaultId
200-
}
201-
202-
if len(strings.TrimSpace(replicaRegion)) != 0 {
203-
request.ReplicaRegion = &replicaRegion
204+
if replicaRegion, ok := s.D.GetOkExists("replica_region"); ok {
205+
tmp := replicaRegion.(string)
206+
replicaRegionStr = tmp
204207
}
205-
206-
if replicaVaultMetadata, ok := s.D.GetOkExists("replica_vault_metadata"); ok {
207-
if tmpList := replicaVaultMetadata.([]interface{}); len(tmpList) > 0 {
208-
fieldKeyFormat := fmt.Sprintf("%s.%d.%%s", "replica_vault_metadata", 0)
209-
tmp, err := s.mapToReplicaVaultMetadata(fieldKeyFormat)
210-
if err != nil {
211-
return err
212-
}
213-
request.ReplicaVaultMetadata = &tmp
208+
// If the Vault ID or Replica Region String didn't get updated from state/config, use ID
209+
if vaultIdStr == "vault_id" || replicaRegionStr == "replica_region" {
210+
log.Printf("[INFO] Get() Vault ID or Replica Region String didn't get updated from state/config, using Resource ID")
211+
parts := strings.Split(s.D.Id(), ":")
212+
if len(parts) > 1 {
213+
vaultId := parts[0]
214+
request.VaultId = &vaultId
215+
replicaRegionStr = parts[1]
216+
} else {
217+
log.Fatalf("[ERROR] Get() unable to parse current ID: %s. The expected format of the ID is \"{vault_id}:{replica_region}\"", s.D.Id())
214218
}
215219
}
216220

217221
request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms")
218222

219-
_, err := s.Client.CreateVaultReplica(context.Background(), request)
223+
log.Printf("[INFO] Get() Calling List Vault Replicas")
224+
response, err := s.Client.ListVaultReplicas(context.Background(), request)
220225
if err != nil {
221226
return err
222227
}
223228

224-
retentionPolicyFunc := func() bool { return s.Res.Items[0].Status == oci_kms.VaultReplicaSummaryStatusCreated }
225-
return tfresource.WaitForResourceCondition(s, retentionPolicyFunc, s.D.Timeout(schema.TimeoutCreate))
229+
vaultReplicaSummaryRes := oci_kms.VaultReplicaSummary{Status: oci_kms.VaultReplicaSummaryStatusDeleted}
230+
for _, vaultReplicaSummary := range response.Items {
231+
vaultReplicaRegion := *(vaultReplicaSummary.Region)
232+
if vaultReplicaRegion == replicaRegionStr {
233+
vaultReplicaSummaryRes = vaultReplicaSummary
234+
}
235+
}
236+
s.Res = &vaultReplicaSummaryRes
237+
// Explicitly Call VoidState to Remove Deleted Vault Replica from State
238+
if s.Res.Status == oci_kms.VaultReplicaSummaryStatusDeleted {
239+
log.Printf("[INFO] VoidState() as no resource is found, removing from state")
240+
s.VoidState()
241+
}
242+
243+
return nil
226244
}
227245

228-
func (s *KmsVaultReplicaResourceCrud) deleteVaultReplicaHelper(vaultId string, replicaRegion string) error {
246+
func (s *KmsVaultReplicaResourceCrud) Delete() error {
247+
log.Printf("[INFO] Delete()")
229248
request := oci_kms.DeleteVaultReplicaRequest{}
230249

231-
if len(strings.TrimSpace(vaultId)) != 0 {
232-
request.VaultId = &vaultId
250+
if vaultId, ok := s.D.GetOkExists("vault_id"); ok {
251+
tmp := vaultId.(string)
252+
request.VaultId = &tmp
233253
}
234254

235-
if len(strings.TrimSpace(replicaRegion)) != 0 {
236-
request.ReplicaRegion = &replicaRegion
255+
if replicaRegion, ok := s.D.GetOkExists("replica_region"); ok {
256+
tmp := replicaRegion.(string)
257+
request.ReplicaRegion = &tmp
237258
}
238259

239260
request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms")
@@ -243,60 +264,71 @@ func (s *KmsVaultReplicaResourceCrud) deleteVaultReplicaHelper(vaultId string, r
243264
return err
244265
}
245266

246-
retentionPolicyFunc := func() bool {
247-
return (len(s.Res.Items) == 0 || s.Res.Items[0].Status == oci_kms.VaultReplicaSummaryStatusDeleted)
267+
retentionPolicyFunc := func() bool { return s.Res == nil || s.Res.Status == oci_kms.VaultReplicaSummaryStatusDeleted }
268+
waitErr := tfresource.WaitForResourceCondition(s, retentionPolicyFunc, s.D.Timeout(schema.TimeoutDelete))
269+
if waitErr != nil {
270+
return waitErr
248271
}
249-
return tfresource.WaitForResourceCondition(s, retentionPolicyFunc, s.D.Timeout(schema.TimeoutDelete))
272+
273+
return nil
250274
}
251275

252276
func (s *KmsVaultReplicaResourceCrud) SetData() error {
277+
log.Printf("[INFO] SetData()")
278+
279+
parts := strings.Split(s.D.Id(), ":")
280+
if len(parts) > 1 {
281+
vaultId := parts[0]
282+
s.D.Set("vault_id", &vaultId)
283+
}
284+
285+
if s.Res.CryptoEndpoint != nil {
286+
s.D.Set("crypto_endpoint", *s.Res.CryptoEndpoint)
287+
}
288+
289+
if s.Res.ManagementEndpoint != nil {
290+
s.D.Set("management_endpoint", *s.Res.ManagementEndpoint)
291+
}
292+
293+
if s.Res.Region != nil {
294+
s.D.Set("replica_region", *s.Res.Region)
295+
}
296+
297+
s.D.Set("vault_replica_status", s.Res.Status)
298+
253299
return nil
254300
}
255301

256-
// Necessary to have. Otherwise cause "Could not set resource state" error from setState() in crud helper
302+
// State Necessary to have. Otherwise, cause "Could not set resource state, sync did not have a valid .Res.State, .Resource.State, or .WorkRequest.State" error from setState() in crud_helper
257303
func (s *KmsVaultReplicaResourceCrud) State() oci_kms.VaultReplicaSummaryStatusEnum {
258-
if len(s.Res.Items) > 0 {
259-
return s.Res.Items[0].Status
260-
}
261-
return ""
304+
log.Printf("[INFO] State()")
305+
return s.Res.Status
262306
}
263307

264308
func (s *KmsVaultReplicaResourceCrud) CreatedPending() []string {
309+
log.Printf("[INFO] CreatedPending()")
265310
return []string{
266311
string(oci_kms.VaultReplicaSummaryStatusCreating),
267312
}
268313
}
269314

270315
func (s *KmsVaultReplicaResourceCrud) CreatedTarget() []string {
316+
log.Printf("[INFO] CreatedTarget()")
271317
return []string{
272318
string(oci_kms.VaultReplicaSummaryStatusCreated),
273319
}
274320
}
275321

276322
func (s *KmsVaultReplicaResourceCrud) DeletedPending() []string {
323+
log.Printf("[INFO] DeletedPending()")
277324
return []string{
278325
string(oci_kms.VaultReplicaSummaryStatusDeleting),
279326
}
280327
}
281328

282329
func (s *KmsVaultReplicaResourceCrud) DeletedTarget() []string {
330+
log.Printf("[INFO] DeletedTarget()")
283331
return []string{
284332
string(oci_kms.VaultReplicaSummaryStatusDeleted),
285333
}
286334
}
287-
288-
func (s *KmsVaultReplicaResourceCrud) mapToReplicaVaultMetadata(fieldKeyFormat string) (oci_kms.ReplicaExternalVaultMetadata, error) {
289-
result := oci_kms.ReplicaExternalVaultMetadata{}
290-
291-
if privateEndpointId, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "private_endpoint_id")); ok {
292-
tmp := privateEndpointId.(string)
293-
result.PrivateEndpointId = &tmp
294-
}
295-
296-
if idcsAccountNameUrl, ok := s.D.GetOkExists(fmt.Sprintf(fieldKeyFormat, "idcs_account_name_url")); ok {
297-
tmp := idcsAccountNameUrl.(string)
298-
result.IdcsAccountNameUrl = &tmp
299-
}
300-
301-
return result, nil
302-
}

0 commit comments

Comments
 (0)