Skip to content

Commit 4e223ee

Browse files
committed
Adding the wait_for_sync support for OCI ECR
1 parent 2a91274 commit 4e223ee

File tree

1 file changed

+154
-1
lines changed

1 file changed

+154
-1
lines changed

spectrocloud/resource_registry_oci_ecr.go

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,30 @@ func resourceRegistryEcrCreate(ctx context.Context, d *schema.ResourceData, m in
221221
return diag.FromErr(err)
222222
}
223223
d.SetId(uid)
224+
225+
// Wait for sync if requested and provider_type is helm (ECR supports helm only for wait_for_sync)
226+
if providerType == "helm" && d.Get("wait_for_sync") != nil && d.Get("wait_for_sync").(bool) {
227+
diagnostics, isError := waitForOciEcrRegistrySync(ctx, d, uid, diags, c, schema.TimeoutCreate)
228+
if len(diagnostics) > 0 {
229+
diags = append(diags, diagnostics...)
230+
}
231+
// Fetch final sync status and set wait_for_status_message
232+
registry, statusErr := c.GetOciEcrRegistry(uid)
233+
if statusErr == nil && registry != nil && registry.Status != nil && registry.Status.SyncStatus != nil {
234+
statusMessage := ""
235+
if registry.Status.SyncStatus.Message != "" {
236+
statusMessage = registry.Status.SyncStatus.Message
237+
} else if registry.Status.SyncStatus.Status != "" {
238+
statusMessage = fmt.Sprintf("Status: %s", registry.Status.SyncStatus.Status)
239+
}
240+
if err := d.Set("wait_for_status_message", statusMessage); err != nil {
241+
diags = append(diags, diag.FromErr(err)...)
242+
}
243+
}
244+
if isError {
245+
return diagnostics
246+
}
247+
}
224248
case "basic":
225249
registry := toRegistryBasic(d)
226250
if err := validateRegistryCred(c, registryType, providerType, isSync, registry.Spec, nil); err != nil {
@@ -325,7 +349,7 @@ func resourceRegistryEcrRead(ctx context.Context, d *schema.ResourceData, m inte
325349
}
326350
// tls configuration handling
327351
tlsConfig := make([]interface{}, 0, 1)
328-
if registry.Spec.TLS != nil && (registry.Spec.TLS.Certificate != "" || registry.Spec.TLS.InsecureSkipVerify) {
352+
if registry.Spec.TLS != nil {
329353
tls := make(map[string]interface{})
330354
tls["certificate"] = registry.Spec.TLS.Certificate
331355
tls["insecure_skip_verify"] = registry.Spec.TLS.InsecureSkipVerify
@@ -451,6 +475,30 @@ func resourceRegistryEcrUpdate(ctx context.Context, d *schema.ResourceData, m in
451475
if err != nil {
452476
return diag.FromErr(err)
453477
}
478+
479+
// Wait for sync if requested and provider_type is helm
480+
if providerType == "helm" && d.Get("wait_for_sync") != nil && d.Get("wait_for_sync").(bool) {
481+
diagnostics, isError := waitForOciEcrRegistrySync(ctx, d, d.Id(), diags, c, schema.TimeoutUpdate)
482+
if len(diagnostics) > 0 {
483+
diags = append(diags, diagnostics...)
484+
}
485+
// Fetch final sync status and set wait_for_status_message
486+
registry, statusErr := c.GetOciEcrRegistry(d.Id())
487+
if statusErr == nil && registry != nil && registry.Status != nil && registry.Status.SyncStatus != nil {
488+
statusMessage := ""
489+
if registry.Status.SyncStatus.Message != "" {
490+
statusMessage = registry.Status.SyncStatus.Message
491+
} else if registry.Status.SyncStatus.Status != "" {
492+
statusMessage = fmt.Sprintf("Status: %s", registry.Status.SyncStatus.Status)
493+
}
494+
if err := d.Set("wait_for_status_message", statusMessage); err != nil {
495+
diags = append(diags, diag.FromErr(err)...)
496+
}
497+
}
498+
if isError {
499+
return diagnostics
500+
}
501+
}
454502
case "basic":
455503
registry := toRegistryBasic(d)
456504
if err := validateRegistryCred(c, registryType, providerType, isSync, registry.Spec, nil); err != nil {
@@ -733,3 +781,108 @@ func resourceOciRegistrySyncRefreshFunc(c *client.V1Client, uid string) retry.St
733781
}
734782
}
735783
}
784+
785+
// waitForOciEcrRegistrySync waits for an OCI ECR registry to complete its synchronization by polling GetOciEcrRegistry.
786+
func waitForOciEcrRegistrySync(ctx context.Context, d *schema.ResourceData, uid string, diags diag.Diagnostics, c *client.V1Client, timeoutType string) (diag.Diagnostics, bool) {
787+
stateConf := &retry.StateChangeConf{
788+
Pending: []string{
789+
"InProgress",
790+
"Pending",
791+
"Unknown",
792+
"",
793+
},
794+
Target: []string{
795+
"Success",
796+
"Completed",
797+
},
798+
Refresh: resourceOciEcrRegistrySyncRefreshFunc(c, uid),
799+
Timeout: d.Timeout(timeoutType) - 1*time.Minute,
800+
MinTimeout: 10 * time.Second,
801+
Delay: 30 * time.Second,
802+
}
803+
804+
_, err := stateConf.WaitForStateContext(ctx)
805+
if err != nil {
806+
var timeoutErr *retry.TimeoutError
807+
if errors.As(err, &timeoutErr) {
808+
currentStatus := timeoutErr.LastState
809+
statusMessage := ""
810+
registry, statusErr := c.GetOciEcrRegistry(uid)
811+
if statusErr == nil && registry != nil && registry.Status != nil && registry.Status.SyncStatus != nil {
812+
if registry.Status.SyncStatus.Status != "" {
813+
currentStatus = registry.Status.SyncStatus.Status
814+
}
815+
if registry.Status.SyncStatus.Message != "" {
816+
statusMessage = fmt.Sprintf(" Message: %s", registry.Status.SyncStatus.Message)
817+
}
818+
}
819+
if currentStatus == "" {
820+
currentStatus = "Unknown"
821+
}
822+
diags = append(diags, diag.Diagnostic{
823+
Severity: diag.Warning,
824+
Summary: "OCI ECR registry sync timeout",
825+
Detail: fmt.Sprintf(
826+
"OCI ECR registry synchronization timed out after waiting for %v. Current sync status is '%s'.%s "+
827+
"The registry sync may still be in progress. You may need to increase the timeout or wait for the sync to complete manually.",
828+
d.Timeout(timeoutType)-1*time.Minute, currentStatus, statusMessage),
829+
})
830+
return diags, false
831+
}
832+
833+
registry, statusErr := c.GetOciEcrRegistry(uid)
834+
if statusErr == nil && registry != nil && registry.Status != nil && registry.Status.SyncStatus != nil {
835+
status := registry.Status.SyncStatus.Status
836+
if status == "Failed" || status == "Error" || status == "failed" || status == "error" {
837+
errorDetail := fmt.Sprintf("OCI ECR registry synchronization failed with status '%s'.", status)
838+
if registry.Status.SyncStatus.Message != "" {
839+
errorDetail += fmt.Sprintf("\n\nError details: %s", registry.Status.SyncStatus.Message)
840+
}
841+
errorDetail += "\n\nPlease check the registry configuration (endpoint, credentials) and try again."
842+
diags = append(diags, diag.Diagnostic{
843+
Severity: diag.Warning,
844+
Summary: "OCI ECR registry sync failed",
845+
Detail: errorDetail,
846+
})
847+
return diags, false
848+
}
849+
}
850+
851+
return diag.FromErr(err), true
852+
}
853+
return nil, false
854+
}
855+
856+
// resourceOciEcrRegistrySyncRefreshFunc returns a retry.StateRefreshFunc that checks the sync status of an OCI ECR registry via GetOciEcrRegistry.
857+
func resourceOciEcrRegistrySyncRefreshFunc(c *client.V1Client, uid string) retry.StateRefreshFunc {
858+
return func() (interface{}, string, error) {
859+
registry, err := c.GetOciEcrRegistry(uid)
860+
if err != nil {
861+
return nil, "", err
862+
}
863+
if registry == nil || registry.Status == nil || registry.Status.SyncStatus == nil {
864+
return nil, "", nil
865+
}
866+
syncStatus := registry.Status.SyncStatus
867+
if !syncStatus.IsSyncSupported {
868+
return syncStatus, "Success", nil
869+
}
870+
status := syncStatus.Status
871+
if status == "" {
872+
return syncStatus, "", nil
873+
}
874+
switch status {
875+
case "Success", "Completed", "success", "completed":
876+
return syncStatus, "Success", nil
877+
case "Failed", "Error", "failed", "error":
878+
if syncStatus.Message != "" {
879+
return syncStatus, status, fmt.Errorf("registry sync failed: %s", syncStatus.Message)
880+
}
881+
return syncStatus, status, fmt.Errorf("registry sync failed")
882+
case "InProgress", "Running", "Syncing", "inprogress", "running", "syncing":
883+
return syncStatus, "InProgress", nil
884+
default:
885+
return syncStatus, status, nil
886+
}
887+
}
888+
}

0 commit comments

Comments
 (0)