diff --git a/docs/index.md b/docs/index.md index 29cff71..9de5095 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,7 @@ # Delphix Provider !> **NOTE** -The Terraform Provider for Delphix is currently beta and requires Delphix Control Tower (DCT) APIs to work. +The Terraform Provider for Delphix is currently beta and requires the Delphix Continuous Data Platform and Data Control Tower (DCT). The Terraform Provider for Delphix enables customers to natively manage data-as-code along with their infrastructure. diff --git a/docs/resources/vdb.md b/docs/resources/vdb.md index 05d6bb4..8c83d3d 100644 --- a/docs/resources/vdb.md +++ b/docs/resources/vdb.md @@ -32,6 +32,15 @@ resource "delphix_vdb" "vdb_name2" { } } +# Provision a VDB from a bookmark with a single VDB + +resource "delphix_vdb" "test_vdb" { + provision_type = "bookmark" + auto_select_repository = true + bookmark_id = "BOOKMARK_ID" + environment_id = "ENV_ID" +} + # Provision a VDB using snapshot and pre refresh hooks resource "delphix_vdb" "vdb_name" { @@ -48,9 +57,9 @@ resource "delphix_vdb" "vdb_name" { ## Argument Reference -* `source_data_id` - (Required) The ID of the source object (dSource or VDB) to provision from. All other objects referenced by the parameters must live on the same engine as the source. +* `source_data_id` - (Optional) The ID or name of the source object (dSource or VDB) to provision from. All other objects referenced by the parameters must live on the same engine as the source. -* `engine_id` - (Optional) The ID of the Engine onto which to provision. If the source ID unambiguously identifies a source object, this parameter is unnecessary and ignored. +* `engine_id` - (Optional) The ID or name of the Engine onto which to provision. If the source ID unambiguously identifies a source object, this parameter is unnecessary and ignored. * `target_group_id` - (Optional) The ID of the group into which the VDB will be provisioned. If unset, a group is selected randomly on the Engine. @@ -68,7 +77,7 @@ resource "delphix_vdb" "vdb_name" { * `db_password` - (Optional) [Updatable] The password of the database user (Oracle, ASE Only). Only for update. -* `environment_id` - (Optional) The ID of the target environment where to provision the VDB. If repository_id unambigously identifies a repository, this is unnecessary and ignored. Otherwise, a compatible repository is randomly selected on the environment. +* `environment_id` - (Optional) The ID or name of the target environment where to provision the VDB. If repository_id unambigously identifies a repository, this is unnecessary and ignored. Otherwise, a compatible repository is randomly selected on the environment. * `environment_user_id` - (Optional)[Updatable] The environment user ID to use to connect to the target environment. @@ -176,7 +185,9 @@ Environment variable to be set when the engine creates a VDB. See the Engine doc * `timestamp_in_database_timezone` - (Optional) The point in time from which to execute the operation, expressed as a date-time in the timezone of the source database. Mutually exclusive with timestamp. -* `snapshot_id` - (Optional) The ID of the snapshot from which to execute the operation. If the snapshot_id is not, selects the latest snapshot. +* `snapshot_id` - (Optional) The ID or name of the snapshot from which to execute the operation. If the snapshot_id is not, selects the latest snapshot. + +* `bookmark_id` - (Optional) The ID or name of the bookmark from which to execute the operation. The bookmark must contain only one VDB. ## Attribute Reference diff --git a/internal/provider/resource_vdb.go b/internal/provider/resource_vdb.go index 6550ce1..25ee585 100644 --- a/internal/provider/resource_vdb.go +++ b/internal/provider/resource_vdb.go @@ -33,7 +33,7 @@ func resourceVdb() *schema.Resource { }, "source_data_id": { Type: schema.TypeString, - Required: true, + Optional: true, }, "id": { Type: schema.TypeString, @@ -82,7 +82,7 @@ func resourceVdb() *schema.Resource { Type: schema.TypeString, Optional: true, }, - "vdb_name": { + "name": { Type: schema.TypeString, Computed: true, Optional: true, @@ -451,6 +451,10 @@ func resourceVdb() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "bookmark_id": { + Type: schema.TypeString, + Optional: true, + }, }, } } @@ -497,7 +501,7 @@ func helper_provision_by_snapshot(ctx context.Context, d *schema.ResourceData, m provisionVDBBySnapshotParameters.SetTargetGroupId(v.(string)) } - if v, has_v := d.GetOk("vdb_name"); has_v { + if v, has_v := d.GetOk("name"); has_v { provisionVDBBySnapshotParameters.SetName(v.(string)) } @@ -675,7 +679,7 @@ func helper_provision_by_timestamp(ctx context.Context, d *schema.ResourceData, provisionVDBByTimestampParameters.SetTargetGroupId(v.(string)) } - if v, has_v := d.GetOk("vdb_name"); has_v { + if v, has_v := d.GetOk("name"); has_v { provisionVDBByTimestampParameters.SetName(v.(string)) } @@ -881,6 +885,219 @@ func helper_provision_by_timestamp(ctx context.Context, d *schema.ResourceData, return diags } +func helper_provision_by_bookmark(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + client := meta.(*apiClient).client + + provisionVDBFromBookmarkParameters := dctapi.NewProvisionVDBFromBookmarkParameters(d.Get("bookmark_id").(string)) + + // Setters for provisionVDBFromBookmarkParameters + if v, has_v := d.GetOk("source_data_id"); has_v { + provisionVDBFromBookmarkParameters.SetSourceDataId(v.(string)) + } + + if v, has_v := d.GetOk("engine_id"); has_v { + eng_id, _ := strconv.Atoi(v.(string)) + provisionVDBFromBookmarkParameters.SetEngineId(int64(eng_id)) + } + + if v, has_v := d.GetOk("target_group_id"); has_v { + provisionVDBFromBookmarkParameters.SetTargetGroupId(v.(string)) + } + + if v, has_v := d.GetOk("name"); has_v { + provisionVDBFromBookmarkParameters.SetName(v.(string)) + } + + if v, has_v := d.GetOk("database_name"); has_v { + provisionVDBFromBookmarkParameters.SetDatabaseName(v.(string)) + } + + if v, has_v := d.GetOkExists("truncate_log_on_checkpoint"); has_v { + provisionVDBFromBookmarkParameters.SetTruncateLogOnCheckpoint(v.(bool)) + } + + if v, has_v := d.GetOk("os_username"); has_v { + provisionVDBFromBookmarkParameters.SetOsUsername(v.(string)) + } + + if v, has_v := d.GetOk("os_password"); has_v { + provisionVDBFromBookmarkParameters.SetOsPassword(v.(string)) + } + + if v, has_v := d.GetOk("environment_id"); has_v { + provisionVDBFromBookmarkParameters.SetEnvironmentId(v.(string)) + } + + if v, has_v := d.GetOk("environment_user_id"); has_v { + provisionVDBFromBookmarkParameters.SetEnvironmentUserId(v.(string)) + } + + if v, has_v := d.GetOk("repository_id"); has_v { + provisionVDBFromBookmarkParameters.SetRepositoryId(v.(string)) + } + + if v, has_v := d.GetOkExists("auto_select_repository"); has_v { + provisionVDBFromBookmarkParameters.SetAutoSelectRepository(v.(bool)) + } + + if v, has_v := d.GetOkExists("vdb_restart"); has_v { + provisionVDBFromBookmarkParameters.SetVdbRestart(v.(bool)) + } + + if v, has_v := d.GetOk("template_id"); has_v { + provisionVDBFromBookmarkParameters.SetTemplateId(v.(string)) + } + + if v, has_v := d.GetOk("file_mapping_rules"); has_v { + provisionVDBFromBookmarkParameters.SetFileMappingRules(v.(string)) + } + + if v, has_v := d.GetOk("oracle_instance_name"); has_v { + provisionVDBFromBookmarkParameters.SetOracleInstanceName(v.(string)) + } + + if v, has_v := d.GetOk("unique_name"); has_v { + provisionVDBFromBookmarkParameters.SetUniqueName(v.(string)) + } + + if v, has_v := d.GetOk("mount_point"); has_v { + provisionVDBFromBookmarkParameters.SetMountPoint(v.(string)) + } + + if v, has_v := d.GetOkExists("open_reset_logs"); has_v { + provisionVDBFromBookmarkParameters.SetOpenResetLogs(v.(bool)) + } + + if v, has_v := d.GetOk("snapshot_policy_id"); has_v { + provisionVDBFromBookmarkParameters.SetSnapshotPolicyId(v.(string)) + } + + if v, has_v := d.GetOk("retention_policy_id"); has_v { + provisionVDBFromBookmarkParameters.SetRetentionPolicyId(v.(string)) + } + + if v, has_v := d.GetOk("recovery_model"); has_v { + provisionVDBFromBookmarkParameters.SetRecoveryModel(v.(string)) + } + + if v, has_v := d.GetOk("pre_script"); has_v { + provisionVDBFromBookmarkParameters.SetPreScript(v.(string)) + } + + if v, has_v := d.GetOk("post_script"); has_v { + provisionVDBFromBookmarkParameters.SetPostScript(v.(string)) + } + + if v, has_v := d.GetOkExists("cdc_on_provision"); has_v { + provisionVDBFromBookmarkParameters.SetCdcOnProvision(v.(bool)) + } + + if v, has_v := d.GetOk("online_log_size"); has_v { + provisionVDBFromBookmarkParameters.SetOnlineLogSize(int32(v.(int))) + } + + if v, has_v := d.GetOk("online_log_groups"); has_v { + provisionVDBFromBookmarkParameters.SetOnlineLogGroups(int32(v.(int))) + } + + if v, has_v := d.GetOkExists("archive_log"); has_v { + provisionVDBFromBookmarkParameters.SetArchiveLog(v.(bool)) + } + + if v, has_v := d.GetOkExists("new_dbid"); has_v { + provisionVDBFromBookmarkParameters.SetNewDbid(v.(bool)) + } + + if v, has_v := d.GetOk("listener_ids"); has_v { + provisionVDBFromBookmarkParameters.SetListenerIds(toStringArray(v)) + } + + if v, has_v := d.GetOk("custom_env_vars"); has_v { + custom_env_vars := make(map[string]string) + + for k, v := range v.(map[string]interface{}) { + custom_env_vars[k] = v.(string) + } + provisionVDBFromBookmarkParameters.SetCustomEnvVars(custom_env_vars) + } + + if v, has_v := d.GetOk("custom_env_files"); has_v { + provisionVDBFromBookmarkParameters.SetCustomEnvFiles(toStringArray(v)) + } + + if v, has_v := d.GetOk("pre_refresh"); has_v { + provisionVDBFromBookmarkParameters.SetPreRefresh(toHookArray(v)) + } + + if v, has_v := d.GetOk("post_refresh"); has_v { + provisionVDBFromBookmarkParameters.SetPostRefresh(toHookArray(v)) + } + + if v, has_v := d.GetOk("pre_rollback"); has_v { + provisionVDBFromBookmarkParameters.SetPreRollback(toHookArray(v)) + } + + if v, has_v := d.GetOk("post_rollback"); has_v { + provisionVDBFromBookmarkParameters.SetPostRollback(toHookArray(v)) + } + + if v, has_v := d.GetOk("configure_clone"); has_v { + provisionVDBFromBookmarkParameters.SetConfigureClone(toHookArray(v)) + } + + if v, has_v := d.GetOk("pre_snapshot"); has_v { + provisionVDBFromBookmarkParameters.SetPreSnapshot(toHookArray(v)) + } + + if v, has_v := d.GetOk("post_snapshot"); has_v { + provisionVDBFromBookmarkParameters.SetPostSnapshot(toHookArray(v)) + } + + if v, has_v := d.GetOk("pre_start"); has_v { + provisionVDBFromBookmarkParameters.SetPreStart(toHookArray(v)) + } + + if v, has_v := d.GetOk("post_start"); has_v { + provisionVDBFromBookmarkParameters.SetPostStart(toHookArray(v)) + } + + if v, has_v := d.GetOk("pre_stop"); has_v { + provisionVDBFromBookmarkParameters.SetPreStop(toHookArray(v)) + } + + if v, has_v := d.GetOk("post_stop"); has_v { + provisionVDBFromBookmarkParameters.SetPostStop(toHookArray(v)) + } + + req := client.VDBsApi.ProvisionVdbFromBookmark(ctx) + + apiRes, httpRes, err := req.ProvisionVDBFromBookmarkParameters(*provisionVDBFromBookmarkParameters).Execute() + if diags := apiErrorResponseHelper(apiRes, httpRes, err); diags != nil { + return diags + } + + d.SetId(*apiRes.Vdb.Id) + + job_res, job_err := PollJobStatus(*apiRes.Job.Id, ctx, client) + if job_err != "" { + ErrorLog.Printf("Job Polling failed but continuing with provisioning. Error: %s", job_err) + } + InfoLog.Printf("Job result is %s", job_res) + if job_res == Failed || job_res == Canceled || job_res == Abandoned { + ErrorLog.Printf("Job %s %s!", job_res, *apiRes.Job.Id) + return diag.Errorf("[NOT OK] Job %s %s with error %s", *apiRes.Job.Id, job_res, job_err) + } + + readDiags := resourceVdbRead(ctx, d, meta) + + if readDiags.HasError() { + return readDiags + } + + return diags +} + func resourceVdbCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { if _, has_v := d.GetOk("db_username"); has_v { return diag.Errorf("db_username can not be set when creating a VDB.") @@ -893,18 +1110,24 @@ func resourceVdbCreate(ctx context.Context, d *schema.ResourceData, meta interfa if provision_type == "timestamp" { if _, has_v := d.GetOk("snapshot_id"); has_v { - return diag.Errorf("snapshot_id is not supported for provision_type is 'timestamp'") + return diag.Errorf("snapshot_id is not supported for provision_type = 'timestamp'") } else { return helper_provision_by_timestamp(ctx, d, meta) } } else if provision_type == "snapshot" { if _, has_v := d.GetOk("timestamp"); has_v { - return diag.Errorf("timestamp is not supported for provision_type is 'snapshot'") + return diag.Errorf("timestamp is not supported for provision_type = 'snapshot'") } else { return helper_provision_by_snapshot(ctx, d, meta) } + } else if provision_type == "bookmark" { + if _, has_v := d.GetOk("bookmark_id"); has_v { + return helper_provision_by_bookmark(ctx, d, meta) + } else { + return diag.Errorf("bookmark_id is required for provision_type = 'bookmark'") + } } else { - return diag.Errorf("provision_type must be 'timestamp' or 'snapshot'") + return diag.Errorf("provision_type must be 'timestamp', 'snapshot' or 'bookmark'") } } @@ -930,7 +1153,7 @@ func resourceVdbRead(ctx context.Context, d *schema.ResourceData, meta interface } d.Set("database_type", result.GetDatabaseType()) - d.Set("vdb_name", result.GetName()) + d.Set("name", result.GetName()) d.Set("database_version", result.GetDatabaseVersion()) d.Set("engine_id", result.GetEngineId()) d.Set("environment_id", result.GetEnvironmentId()) @@ -1016,8 +1239,8 @@ func resourceVdbUpdate(ctx context.Context, d *schema.ResourceData, meta interfa if d.HasChange("template_id") { updateVDBParam.SetTemplateId(d.Get("template_id").(string)) } - if d.HasChange("vdb_name") { - updateVDBParam.SetName(d.Get("vdb_name").(string)) + if d.HasChange("name") { + updateVDBParam.SetName(d.Get("name").(string)) } if d.HasChange("db_username") { updateVDBParam.SetDbUsername(d.Get("db_username").(string))