├── terraform-registry-manifest.json ├── examples ├── simple-provision │ ├── versions.tf │ ├── variables.tf │ ├── main.tf │ ├── outputs.tf │ └── README.md ├── full_stack_deployment │ ├── README.md │ └── main.tf ├── database │ └── postgresql │ │ └── main.tf ├── vdb │ ├── main.tf │ ├── sybase │ │ ├── bookmark │ │ │ └── main.tf │ │ ├── snapshot │ │ │ └── main.tf │ │ └── timestamp │ │ │ └── main.tf │ ├── mysql │ │ └── snapshot │ │ │ └── main.tf │ ├── postgresql │ │ ├── snapshot │ │ │ └── main.tf │ │ ├── bookmark │ │ │ └── main.tf │ │ └── timestamp │ │ │ └── main.tf │ ├── mssql │ │ ├── bookmark │ │ │ └── main.tf │ │ ├── snapshot │ │ │ └── main.tf │ │ └── timestamp │ │ │ └── main.tf │ ├── hana │ │ ├── bookmark │ │ │ └── main.tf │ │ ├── snapshot │ │ │ └── main.tf │ │ └── timestamp │ │ │ └── main.tf │ └── oracle │ │ ├── bookmark │ │ └── main.tf │ │ ├── snapshot │ │ └── main.tf │ │ └── timestamp │ │ └── main.tf ├── jenkins_integration │ ├── Readme.md │ └── jenkinsfile ├── appdata_dsource │ ├── mysql │ │ └── main.tf │ └── postgresql │ │ └── main.tf ├── vdb_group │ └── main.tf ├── oracle_dsource │ └── main.tf └── environment │ └── main.tf ├── dev_copy.sh ├── SUPPORT.md ├── internal └── provider │ ├── logging.go │ ├── provider_test.go │ ├── provider.go │ ├── resource_database_postgresql_test.go │ ├── commons.go │ ├── resource_oracle_dsource_test.go │ ├── resource_environment_test.go │ ├── resource_appdata_dsource_test.go │ ├── resource_database_postgresql.go │ └── resource_vdb_group.go ├── docs ├── guides │ └── provider_guide.md ├── resources │ ├── vdb_group.md │ ├── database_postgresql.md │ ├── environment.md │ ├── appdata_dsource.md │ └── oracle_dsource.md └── index.md ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── release.yml │ └── codeql.yml ├── CONTRIBUTING.md ├── .whitesource ├── main.go ├── GNUmakefile ├── pull_request_template.md ├── .goreleaser.yml ├── README.md ├── go.mod └── CODE_OF_CONDUCT.md /terraform-registry-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "metadata": { 4 | "protocol_versions": ["5.0"] 5 | } 6 | } -------------------------------------------------------------------------------- /examples/simple-provision/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | delphix = { 4 | source = "delphix-integrations/delphix" 5 | version = ">=3.1.0" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dev_copy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Script to copy build binaries to terraform plugins location 4 | 5 | rm -rf ~/.terraform.d/plugins/delphix.com/dct/delphix/$CP_VERSION/$CP_TARGET/ 6 | mkdir -p ~/.terraform.d/plugins/delphix.com/dct/delphix/$CP_VERSION/$CP_TARGET/ 7 | cp $CP_PATH ~/.terraform.d/plugins/delphix.com/dct/delphix/$CP_VERSION/$CP_TARGET/ -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | ## Support 2 | This software is provided as-is, without warranty of any kind or commercial support through Delphix. See the associated license for additional details. Questions, issues, feature requests, and contributions should be directed to the community as outlined in the [Delphix Community Guidelines](https://delphix.github.io/community-guidelines.html). 3 | -------------------------------------------------------------------------------- /examples/simple-provision/variables.tf: -------------------------------------------------------------------------------- 1 | variable "dct_hostname" { 2 | type = string 3 | description = "dct hostname config file [default: workspace variable set]" 4 | } 5 | 6 | variable "dct_api_key" { 7 | type = string 8 | description = "dct api key config file [default: workspace variable set]" 9 | } 10 | 11 | variable "source_data_id_1" { 12 | description = "Name or ID of the VDB or Data Source to provision from. [User Defined]" 13 | } -------------------------------------------------------------------------------- /internal/provider/logging.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | var ( 9 | WarnLog *log.Logger 10 | InfoLog *log.Logger 11 | ErrorLog *log.Logger 12 | ) 13 | 14 | func init() { 15 | 16 | ErrorLog = log.New(os.Stderr, "[DELPHIX] [ERROR] ", log.LstdFlags) 17 | WarnLog = log.New(os.Stdout, "[DELPHIX] [WARN] ", log.LstdFlags) 18 | InfoLog = log.New(os.Stdout, "[DELPHIX] [INFO] ", log.LstdFlags) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /examples/full_stack_deployment/README.md: -------------------------------------------------------------------------------- 1 | This file show cases how to provision a full stack of deployment including an Azure VM, add the environment Delphix, ingest an Oracle dSource, and provision 1 VDB. 2 | 3 | This is a great example of disaster recovery scenarios or showcasing the full power of Delphix. 4 | 5 | Note: This example will not work out of the box, by default, as you might not have the same Oracle configuration and the Azure VM is half implementated. Consult the comments within the file for further direction. -------------------------------------------------------------------------------- /examples/database/postgresql/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when creating an source. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | key = "1.XXXX" 16 | host = "HOSTNAME" 17 | } 18 | 19 | resource "delphix_database_postgresql" "source" { 20 | name = "test" 21 | repository_value = "REPO-1" 22 | engine_value = "2" 23 | environment_value = "ENV-1" 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/simple-provision/main.tf: -------------------------------------------------------------------------------- 1 | # Configure the connection to Data Control Tower 2 | provider "delphix" { 3 | host = var.dct_hostname 4 | key = var.dct_api_key 5 | tls_insecure_skip = true 6 | } 7 | 8 | # Provision a VDB 1 9 | resource "delphix_vdb" "provision_vdb_1" { 10 | name = "tfmtest1" 11 | source_data_id = var.source_data_id_1 12 | auto_select_repository = true 13 | } 14 | 15 | # Create a VDB Group with VDB 1 16 | resource "delphix_vdb_group" "create_vdb_group" { 17 | name = "Terraform Demo Group" 18 | vdb_ids = [ 19 | delphix_vdb.provision_vdb_1.id 20 | ] 21 | } -------------------------------------------------------------------------------- /docs/guides/provider_guide.md: -------------------------------------------------------------------------------- 1 | # Guide: Delphix Provider Guide 2 | 3 | ## Delphix Provider Guide 4 | [We have provided a handful of examples in our GitHub repository to help you get a jump start with our Delphix Provider.](https://github.com/delphix-integrations/terraform-provider-delphix/tree/main/examples) These examples range from Terraform resource templates, quick Terraform examples, and full Jenkins pipelines. We update this repository based on our implementation experience, so be sure to check back for updates! 5 | 6 | If you have a suggested template, request, or modification, please submit it in our [GitHub Issues section.](https://github.com/delphix-integrations/terraform-provider-delphix) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe 3 | .DS_Store 4 | example.tf 5 | terraform.tfplan 6 | terraform.tfstate 7 | bin/ 8 | dist/ 9 | modules-dev/ 10 | /pkg/ 11 | website/.vagrant 12 | website/.bundle 13 | website/build 14 | website/node_modules 15 | .vagrant/ 16 | *.backup 17 | ./*.tfstate 18 | .terraform/ 19 | *.log 20 | *.bak 21 | *~ 22 | .*.swp 23 | .idea 24 | *.iml 25 | *.test 26 | *.iml 27 | *.terraform.lock.hcl 28 | website/vendor 29 | 30 | # Test exclusions 31 | !command/test-fixtures/**/*.tfstate 32 | !command/test-fixtures/**/.terraform/ 33 | 34 | # Keep windows files with windows line endings 35 | *.winfile eol=crlf 36 | 37 | # examples executions 38 | ./examples/environment/*.terraform* 39 | ./examples/vdb/*.terraform* 40 | -------------------------------------------------------------------------------- /examples/simple-provision/outputs.tf: -------------------------------------------------------------------------------- 1 | ### 2 | # VDB Group Information 3 | ### 4 | output "vdb_group_id" { 5 | value = delphix_vdb_group.create_vdb_group.id 6 | } 7 | 8 | output "vdb_group_name" { 9 | value = delphix_vdb_group.create_vdb_group.name 10 | } 11 | 12 | ### 13 | # VDB 1 Information 14 | ### 15 | output "vdb_id_1" { 16 | value = delphix_vdb.provision_vdb_1.id 17 | } 18 | 19 | output "vdb_name_1" { 20 | value = delphix_vdb.provision_vdb_1.name 21 | } 22 | 23 | output "vdb_ip_address_1" { 24 | value = delphix_vdb.provision_vdb_1.ip_address 25 | } 26 | 27 | output "vdb_database_type_1" { 28 | value = delphix_vdb.provision_vdb_1.database_type 29 | } 30 | 31 | output "vdb_database_version_1" { 32 | value = delphix_vdb.provision_vdb_1.database_version 33 | } 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '"[DATE]: [FEATURE NAME]"' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is and why it is important. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen / how you might solve this problem. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any existing workarounds, alternative solutions or features you've considered, and why you think your solution is preferable. 18 | 19 | 20 | **Additional context** 21 | Add any other context or screenshots about the feature request here. 22 | -------------------------------------------------------------------------------- /examples/simple-provision/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### Simple Getting Stated 3 | 4 | 1) Update the dct_hostname and dct_api_key variables in the `variables.tf` or in Terrafrom Cloud with the DCT Server and API Key. 5 | For example: 6 | - DCT: uv123abcfei59h6qajyy.vm.cld.sr 7 | - API Key: 2.ZAAgpjHxljW7A7g... 8 | 9 | 2) Update `Oracle_QA` with an applicable VDB name and run the following commands. 10 | ``` 11 | # Create all resources 12 | terraform apply -var="source_data_id_1=Oracle_QA" 13 | 14 | # Destroy resources 15 | terraform destroy" 16 | ``` 17 | 18 | 19 | ### Troubleshoot: Invalid Resource State 20 | 21 | If you find that you've lost the sync between DCT and Terraform, use the `terraform state rm` command to help reconfigure without starting over. 22 | ``` 23 | terraform state rm delphix_vdb.provision_vdb_1 24 | 25 | terraform state rm delphix_vdb_group.create_vdb_group 26 | ``` 27 | 28 | [Documentation](https://developer.hashicorp.com/terraform/cli/commands/state/rm) 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '"[DATE] [BUG]"' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | ** Expected Behavior** 11 | Describe what should have happened. 12 | 13 | ** Actual Behavior** 14 | Describe what actually happened. 15 | 16 | **Steps To Reproduce the Problem** 17 | Describe in as much detail as possible how to reproduce the problem. 18 | 19 | Steps to reproduce the behavior: 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Version** 29 | Indicate the relevant versions of components. This may include the package version, operating system version, or other components relevant to the project. 30 | 31 | **Additional Context** 32 | Add any other context about the problem here, including additional logs or debugging information if appropriate. 33 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 1. Fork the project. 3 | 1. Make your bug fix or new feature. 4 | 1. Add tests for your code. 5 | 1. Send a pull request. 6 | 7 | Contributions must be signed as `User Name `. Make sure to [set up Git with user name and email address](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup). Bug fixes should branch from the current stable branch. New features should be based on the release branch. 8 | 9 | ## Contributor Agreement 10 | All contributors are required to sign the Delphix Contributor agreement prior to contributing code to an open source repository. This process is handled automatically by [cla-assistant](https://cla-assistant.io/). Simply open a pull request and a bot will automatically check to see if you have signed the latest agreement. If not, you will be prompted to do so as part of the pull request process. 11 | 12 | ## Code of Conduct 13 | This project operates under the Delphix Code of Conduct. By participating in this project you agree to abide by its terms. 14 | -------------------------------------------------------------------------------- /internal/provider/provider_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 8 | ) 9 | 10 | var testAccProviders map[string]*schema.Provider 11 | var testAccProvider *schema.Provider 12 | 13 | func new_provider() *schema.Provider { 14 | return Provider("acc-test-version")() 15 | } 16 | 17 | func init() { 18 | testAccProvider = new_provider() 19 | testAccProviders = map[string]*schema.Provider{ 20 | "delphix": testAccProvider, 21 | } 22 | } 23 | 24 | func TestProvider(t *testing.T) { 25 | if err := new_provider().InternalValidate(); err != nil { 26 | t.Fatalf("err: %s", err) 27 | } 28 | } 29 | 30 | func TestProvider_impl(t *testing.T) { 31 | var _ *schema.Provider = new_provider() 32 | } 33 | 34 | func testAccPreCheck(t *testing.T) { 35 | if err := os.Getenv("DCT_KEY"); err == "" { 36 | t.Fatal("DCT_KEY must be set for acceptance tests") 37 | } 38 | if err := os.Getenv("DCT_HOST"); err == "" { 39 | t.Fatal("DCT_HOST must be set for acceptance tests") 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/vdb/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | delphix = { 4 | version = ">=3.3.2" 5 | source = "delphix.com/dct/delphix" 6 | } 7 | } 8 | } 9 | 10 | provider "delphix" { 11 | tls_insecure_skip = true 12 | key = "1.XXXX" 13 | host = "HOSTNAME" 14 | } 15 | 16 | resource "delphix_vdb" "vdb_name" { 17 | provision_type = "snapshot" 18 | auto_select_repository = true 19 | source_data_id = "dsource" 20 | 21 | pre_refresh { 22 | name = "n" 23 | command = "time" 24 | shell = "bash" 25 | } 26 | pre_refresh { 27 | name = "n2" 28 | command = "time" 29 | shell = "bash" 30 | } 31 | } 32 | 33 | resource "delphix_vdb" "vdb_name2" { 34 | provision_type = "timestamp" 35 | auto_select_repository = true 36 | source_data_id = "dsource2" 37 | timestamp = "2021-05-01T08:51:34.148000+00:00" 38 | 39 | post_refresh { 40 | name = "n" 41 | command = "time" 42 | shell = "bash" 43 | } 44 | post_refresh { 45 | name = "n2" 46 | command = "time" 47 | shell = "bash" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "configMode": "AUTO", 4 | "configExternalURL": "", 5 | "projectToken": "", 6 | "enableLicenseViolations": "true", 7 | "displayLicenseViolations": "true", 8 | "enableIaC": "true", 9 | "baseBranches": [] 10 | }, 11 | "scanSettingsSAST": { 12 | "enableScan": true, 13 | "scanPullRequests": true, 14 | "incrementalScan": true, 15 | "baseBranches": [], 16 | "snippetSize": 10 17 | }, 18 | "checkRunSettings": { 19 | "vulnerableCheckRunConclusionLevel": "failure", 20 | "displayMode": "diff", 21 | "useMendCheckNames": true 22 | }, 23 | "checkRunSettingsSAST": { 24 | "checkRunConclusionLevel": "failure", 25 | "severityThreshold": "high" 26 | }, 27 | "issueSettings": { 28 | "minSeverityLevel": "LOW", 29 | "issueType": "DEPENDENCY" 30 | }, 31 | "issueSettingsSAST": { 32 | "minSeverityLevel": "high", 33 | "issueType": "repo" 34 | }, 35 | "remediateSettings": { 36 | "workflowRules": { 37 | "enabled": true 38 | } 39 | }, 40 | "imageSettings":{ 41 | "imageTracing":{ 42 | "enableImageTracingPR": false, 43 | "addRepositoryCoordinate": false, 44 | "addDockerfilePath": false, 45 | "addMendIdentifier": false 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /examples/jenkins_integration/Readme.md: -------------------------------------------------------------------------------- 1 | ### Summary 2 | The Jenkinsfile presents a simple CI/CD scenario where it provisions a VDB, runs an automated test (like Selenium or JUnit) against that application & dataset, and then destroys the VDB. On testing failure, which will happen every time, a bookmark is created. This Jenksinfile leverages the DCT Terrafrom Provider and an API Curl command to show the full breadth of possibilites. All other steps are mocked out. 3 | 4 | ### Simple Getting Stated 5 | 1) Create a Jenkinsfile Pipeline Job 6 | 2) Insert or reference the associated `Jenkinsfile` file. 7 | - Note: This Jenkinsfile also references the Terraform files in the `../simple-provision` folder. Feel free to fork, update, and modify those. 8 | 3) Update the following values: 9 | - DCT_HOSTNAME - Example: `123.0.0.0` 10 | - DCT_API_KEY - Example: `2.abc...` 11 | - [Manage this value through the Jenkins' Credentials plugin](https://docs.cloudbees.com/docs/cloudbees-ci/latest/cloud-secure-guide/injecting-secrets) 12 | - In a pinch, update it directly. 13 | - SOURCE_VDB - Example: `Oracle_QA` 14 | 4) Run Jenkins Job 15 | 16 | Note: I suggest you reduce the sleep timers in early testing scenarios . 17 | 18 | 19 | ### Known Issues 20 | On VDB destroy, the underlying Bookmark's snapshot will be deleted and the Bookmark will become "dangling". 21 | Instead, I recommend using an "Enable/Disable" command instead of "Provision/Destroy" or skip the destroy VDB on failure. -------------------------------------------------------------------------------- /examples/appdata_dsource/mysql/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when creating an app data dsource. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | #dsource with replication 21 | 22 | resource "delphix_appdata_dsource" "test_app_data_dsource" { 23 | source_value = "1-APPDATA_STAGED_SOURCE_CONFIG-6" 24 | group_id = "1-GROUP-1" 25 | log_sync_enabled = false 26 | make_current_account_owner = true 27 | link_type = "AppDataStaged" 28 | name = "appdata_dsource" 29 | staging_mount_base = "" 30 | environment_user = "HOST_USER-2" 31 | staging_environment = "1-UNIX_HOST_ENVIRONMENT-2" 32 | parameters = jsonencode({ 33 | dSourceType : "Replication", 34 | mountPath : "/delphix/zfs3", 35 | stagingPort : 3310, 36 | serverId : 106 , 37 | sourceip : "10.110.203.176", 38 | sourceUse : "XXXX", 39 | sourcePass : "XXXX", 40 | logSync: true, 41 | replicationUser: "XXXX", 42 | replicationPass: "XXXX", 43 | databaseList: "ALL", 44 | backupPath: "", 45 | stagingBasedir: "/usr", 46 | stagingPass: "XXXX" 47 | }) 48 | sync_parameters = jsonencode({ 49 | resync = true 50 | }) 51 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # Terraform Provider release workflow. 2 | name: Release 3 | 4 | # This GitHub action creates a release when a tag that matches the pattern 5 | # "v*" (e.g. v0.1.0) is created. 6 | on: 7 | push: 8 | tags: 9 | - 'v*' 10 | 11 | # Releases need permissions to read and write the repository contents. 12 | # GitHub considers creating releases and uploading assets as writing contents. 13 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | goreleaser: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 21 | with: 22 | # Allow goreleaser to access older tag information. 23 | fetch-depth: 0 24 | - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 25 | with: 26 | go-version-file: 'go.mod' 27 | cache: true 28 | - name: Import GPG key 29 | uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0 30 | id: import_gpg 31 | with: 32 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 33 | passphrase: ${{ secrets.PASSPHRASE }} 34 | - name: Run GoReleaser 35 | uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0 36 | with: 37 | args: release --clean 38 | env: 39 | # GitHub sets the GITHUB_TOKEN secret automatically. 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "flag" 6 | "log" 7 | 8 | provider "terraform-provider-delphix/internal/provider" 9 | 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" 11 | ) 12 | 13 | // Run "go generate" to format example terraform files and generate the docs for the registry/website 14 | 15 | // If you do not have terraform installed, you can remove the formatting command, but its suggested to 16 | // ensure the documentation is formatted properly. 17 | //go:generate terraform fmt -recursive ./examples/ 18 | 19 | // Run the docs generation tool, check its repository for more information on how it works and how docs 20 | // can be customized. 21 | //go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs 22 | 23 | var ( 24 | // these will be set by the goreleaser configuration 25 | // to appropriate values for the compiled binary 26 | version string = "dev" 27 | 28 | // goreleaser can also pass the specific commit if you want 29 | // commit string = "" 30 | ) 31 | 32 | func main() { 33 | var debugMode bool 34 | 35 | flag.BoolVar(&debugMode, "debug", false, "set to true to run the provider with support for debuggers like delve") 36 | flag.Parse() 37 | 38 | opts := &plugin.ServeOpts{ProviderFunc: provider.Provider(version)} 39 | 40 | if debugMode { 41 | // TODO: update this string with the full name of your provider as used in your configs 42 | err := plugin.Debug(context.Background(), "dxi-terraform-provider", opts) 43 | if err != nil { 44 | log.Fatal(err.Error()) 45 | } 46 | return 47 | } 48 | 49 | plugin.Serve(opts) 50 | } 51 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | TEST?=$$(go list ./... | grep -v 'vendor') 2 | HOSTNAME=delphix.com 3 | NAMESPACE=dct 4 | NAME=delphix 5 | BINARY=terraform-provider-${NAME} 6 | VERSION=4.1.0 7 | OS_ARCH=darwin_arm64 8 | 9 | default: install 10 | 11 | build: 12 | go build -o ${BINARY} 13 | 14 | release: 15 | GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64 16 | GOOS=darwin GOARCH=arm64 go build -o ./bin/${BINARY}_${VERSION}_darwin_arm64 17 | GOOS=freebsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_freebsd_386 18 | GOOS=freebsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_freebsd_amd64 19 | GOOS=freebsd GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_freebsd_arm 20 | GOOS=linux GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_linux_386 21 | GOOS=linux GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_linux_amd64 22 | GOOS=linux GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_linux_arm 23 | GOOS=openbsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_openbsd_386 24 | GOOS=openbsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_openbsd_amd64 25 | GOOS=solaris GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_solaris_amd64 26 | GOOS=windows GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_windows_386 27 | GOOS=windows GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_windows_amd64 28 | 29 | install: build 30 | mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 31 | mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH} 32 | 33 | test: 34 | go test -i $(TEST) || exit 1 35 | echo $(TEST) | xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 36 | 37 | testacc: 38 | TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m 39 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | 7 | # Problem: 8 | 14 | # Solution: 15 | 22 | # Testing 23 | 28 | 32 | 38 | 44 | 49 | 54 | -------------------------------------------------------------------------------- /examples/vdb_group/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases a simple example to 3 | * 1) Set local VDB variables 4 | * 2) Provision 5 VDBs using a for_each loop 5 | * 3) Place the 5 VDBs into a single VDB Group using a for loop 6 | */ 7 | 8 | terraform { 9 | required_providers { 10 | delphix = { 11 | version = ">=3.3.2" 12 | source = "delphix-integrations/delphix" 13 | } 14 | } 15 | } 16 | 17 | // *** Requirement***: Update the key and host with valid credentials. 18 | provider "delphix" { 19 | tls_insecure_skip = true 20 | key = "1.XXXX" 21 | host = "HOSTNAME" 22 | } 23 | 24 | 25 | // Create variables for the VDBs. 26 | // *** Requirement***: Update the Snapshot ID with a valid Snapshot. The same snapshot can be reused. 27 | locals { 28 | vdbs = { 29 | "vdb1" = { snapshot_id = "6-ORACLE_DB_CONTAINER-7", name = "us1" }, 30 | "vdb2" = { snapshot_id = "6-ORACLE_DB_CONTAINER-1", name = "us2" }, 31 | "vdb3" = { snapshot_id = "6-ORACLE_DB_CONTAINER-5", name = "us3" }, 32 | "vdb4" = { snapshot_id = "6-ORACLE_DB_CONTAINER-21", name = "us4" }, 33 | "vdb5" = { snapshot_id = "6-ORACLE_DB_CONTAINER-23", name = "us5" } 34 | } 35 | } 36 | 37 | // Provision by Snapshot the 5 VDBs in a loop. 38 | // Instead of a for_each loop, you could optionally copy this resource 4 more times and replace the values directly. 39 | resource "delphix_vdb" "vdb_provision_loop" { 40 | for_each = try(local.vdbs, {}) 41 | name = each.value.name 42 | source_data_id = each.value.snapshot_id 43 | auto_select_repository = true 44 | 45 | } 46 | // Place the 5 VDBs in a single VDB Group. 47 | // The sort() function helps to maintain the order of the vdbs to avoid erroneous drift. 48 | resource "delphix_vdb_group" "this" { 49 | name = "random" 50 | vdb_ids = sort(flatten([for vdb in delphix_vdb.example : vdb.id])) 51 | tags { 52 | key = "environment" 53 | value = "production" 54 | } 55 | tags { 56 | key = "project" 57 | value = "terraform" 58 | } 59 | } -------------------------------------------------------------------------------- /examples/oracle_dsource/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when creating an app data dsource. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | 21 | 22 | resource "delphix_oracle_dsource" "test_oracle_dsource" { 23 | name = "test2" 24 | source_value = "DBOMSRB331B3" 25 | group_id = "4-GROUP-1" 26 | log_sync_enabled = false 27 | make_current_account_owner = true 28 | environment_user_id = "HOST_USER-1" 29 | rman_channels = 2 30 | files_per_set = 5 31 | check_logical = false 32 | encrypted_linking_enabled = false 33 | compressed_linking_enabled = true 34 | bandwidth_limit = 0 35 | number_of_connections = 1 36 | diagnose_no_logging_faults = true 37 | pre_provisioning_enabled = false 38 | link_now = true 39 | force_full_backup = false 40 | double_sync = false 41 | skip_space_check = false 42 | do_not_resume = false 43 | files_for_full_backup = [] 44 | log_sync_mode = "UNDEFINED" 45 | log_sync_interval = 5 46 | ops_pre_sync { 47 | name = "key-1" 48 | command = "echo \"hello world\"" 49 | shell = "shell" 50 | credentials_env_vars { 51 | base_var_name = "XXXX" 52 | password = "XXXX" 53 | } 54 | } 55 | ops_post_sync { 56 | name = "key-2" 57 | command = "echo \"hello world\"" 58 | shell = "shell" 59 | credentials_env_vars { 60 | base_var_name = "XXXX" 61 | password = "XXXX" 62 | } 63 | } 64 | ops_pre_log_sync { 65 | name = "key-2" 66 | command = "echo \"hello world\"" 67 | shell = "shell" 68 | credentials_env_vars { 69 | base_var_name = "XXXX" 70 | password = "XXXX" 71 | } 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # Visit https://goreleaser.com for documentation on how to customize this 2 | # behavior. 3 | version: 2 4 | env: 5 | - PROVIDER_VERSION=4.1.0 6 | before: 7 | hooks: 8 | # this is just an example and not a requirement for provider building/publishing 9 | - go mod tidy 10 | snapshot: 11 | version_template: '{{ .Env.PROVIDER_VERSION }}' 12 | builds: 13 | - env: 14 | # goreleaser does not work with CGO, it could also complicate 15 | # usage by users in CI/CD systems like HCP Terraform where 16 | # they are unable to install libraries. 17 | - CGO_ENABLED=0 18 | mod_timestamp: '{{ .CommitTimestamp }}' 19 | flags: 20 | - -trimpath 21 | ldflags: 22 | - '-s -w -X main.version={{.Env.PROVIDER_VERSION}} -X main.commit={{.Commit}}' 23 | goos: 24 | - freebsd 25 | - windows 26 | - linux 27 | - darwin 28 | goarch: 29 | - amd64 30 | - '386' 31 | - arm 32 | - arm64 33 | ignore: 34 | - goos: darwin 35 | goarch: '386' 36 | binary: terraform-provider-delphix 37 | hooks: 38 | post: 39 | - cmd: ./dev_copy.sh 40 | env: 41 | - CP_PATH={{ .Path }} 42 | - CP_TARGET={{ .Target }} 43 | - CP_VERSION={{ .Env.PROVIDER_VERSION }} 44 | archives: 45 | - formats: [ 'zip' ] 46 | name_template: '{{ .ProjectName }}_{{ .Env.PROVIDER_VERSION }}_{{ .Os }}_{{ .Arch }}' 47 | checksum: 48 | extra_files: 49 | - glob: 'terraform-registry-manifest.json' 50 | name_template: '{{ .ProjectName }}_{{ .Env.PROVIDER_VERSION }}_manifest.json' 51 | name_template: '{{ .ProjectName }}_{{ .Env.PROVIDER_VERSION }}_SHA256SUMS' 52 | algorithm: sha256 53 | signs: 54 | - artifacts: checksum 55 | args: 56 | # if you are using this in a GitHub action or some other automated pipeline, you 57 | # need to pass the batch flag to indicate its not interactive. 58 | - "--batch" 59 | - "--local-user" 60 | - "{{ .Env.GPG_FINGERPRINT }}" # set this environment variable for your signing key 61 | - "--output" 62 | - "${signature}" 63 | - "--detach-sign" 64 | - "${artifact}" 65 | release: 66 | extra_files: 67 | - glob: 'terraform-registry-manifest.json' 68 | name_template: '{{ .ProjectName }}_{{ .Env.PROVIDER_VERSION }}_manifest.json' 69 | # If you want to manually examine the release before its live, uncomment this line: 70 | # draft: true 71 | changelog: 72 | disable: true 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform Provider Delphix 2 | 3 | ![CodeQL](https://github.com/delphix-integrations/terraform-provider-delphix/actions/workflows/codeql.yml/badge.svg?branch=main) 4 | ![Release](https://github.com/delphix-integrations/terraform-provider-delphix/actions/workflows/release.yml/badge.svg?event=release) 5 | ![Version](https://img.shields.io/github/v/release/delphix-integrations/terraform-provider-delphix) 6 | 7 | Terraform Provider for Delphix enables Terraform to create and manage Delphix Continuous Data & 8 | Continuous Compliance infrastructure using the Delphix Control Tower (DCT) APIs. 9 | 10 | Full implementation directions can be found on the [Delphix Ecosystem Documentation](https://help.delphix.com/eh/current/Content/Ecoystem/Terraform.htm) and [Terraform Provider Registry](https://registry.terraform.io/providers/delphix-integrations/delphix/latest/docs). 11 | 12 | ## Prerequisites 13 | 14 | 1. Install Delphix Control Tower (DCT). For more information, visit the [DCT documentation](https://docs.delphix.com/dct). 15 | 2. Delphix Continuous Data and Continuous Compliance engines must be connected to DCT. 16 | 3. An API key must be created for authenticating with DCT APIs. Refer to the [DCT API keys documentation](https://dct.delphix.com/docs/api-keys-2) for more info. 17 | 4. Additional infrastructure required for testing the provider operations. [e.g Hosts to be added as environments, dSources to create VDBs from] 18 | 5. Development setup for Golang. 19 | 20 | 21 | ## Getting Started (Development) 22 | 23 | This guide covers the following 24 | 25 | 1. Install IDE [Visual Studio Code](https://code.visualstudio.com). 26 | 27 | 2. Install guide for [Golang](https://go.dev/dl/). 28 | 29 | 3. Install guide for [GoReleaser](https://goreleaser.com/install/). 30 | 31 | 4. Install Go Plugin for VS Code. 32 | 33 | 5. Install [Terraform](https://www.terraform.io/downloads). 34 | 35 | 6. Fork this repo and clone it locally. Switch to the `develop` branch which always heads to the latest development code. 36 | 37 | 7. Run following command to create binaries: 38 | 39 | ```goreleaser release --skip-publish --snapshot --rm-dist``` 40 | 41 | 8. Execute example main.tf file under /examples/ directory using the following commands: 42 | 43 | ``` 44 | terraform init 45 | terraform plan 46 | terraform apply 47 | ``` 48 | 49 | ## Contributing 50 | This project is currently not accepting external contributions. 51 | -------------------------------------------------------------------------------- /docs/resources/vdb_group.md: -------------------------------------------------------------------------------- 1 | # Resource: delphix_vdb_group 2 | 3 | 4 | 5 | A VDB Group is a collection of virtual databases. The VDB Group (delphix_vdb_group) resource allows creating such a collection in Data Control Tower (DCT). 6 | 7 | 8 | 9 | VDB Groups are valuable when you need to coordinate the provision, refreshes, and bookmark operations across multiple datasets, such as an application that requires datasets from an Oracle database, PostgreSQL database, and Unstructured Files (vFiles). 10 | 11 | 12 | 13 | VDB Groups must contain VDBs from different root dSources. Therefore, they are not intended for bulk actions, such as refreshing multiple datasets to the same point in time. 14 | 15 | 16 | 17 | ## Example Usage 18 | 19 | 20 | 21 | ```hcl 22 | 23 | Create a VDB Group, add existing VDBs to the group, and assign tags. 24 | 25 | 26 | 27 | resource "delphix_vdb_group" "vdb_group_name" { 28 | 29 | name = "my vdb group" 30 | 31 | vdb_ids = ["vdb_id_1”, “vdb_id_2”, “vdb_id_3"] 32 | 33 | tags { 34 | 35 | key = "environment" 36 | 37 | value = "production" 38 | 39 | } 40 | 41 | tags { 42 | 43 | key = "project" 44 | 45 | value = "terraform" 46 | 47 | } 48 | 49 | } 50 | 51 | ``` 52 | 53 | 54 | 55 | ## Argument Reference 56 | 57 | The following arguments apply to all configurations. 58 | 59 | 60 | 61 | * `id` - A unique identifier for the entity. (Output only) 62 | 63 | * `name` - (Required) The unique name for the VDB Group. [Updatable] 64 | 65 | * `vdb_ids` - (Required) The list of VDB IDs or Names for this VDB Group. [Updatable] 66 | 67 | * `tags` - The tags to be created for the VDB Group. [Updatable] 68 | 69 | This is a map of two required parameters: 70 | 71 | * `key` - Key of the tag. 72 | 73 | * `value` - Value of the tag. 74 | 75 | * `ignore_tag_changes` – This flag enables whether changes in the tags are identified by Terraform. By default, this is set to true, meaning changes to the resource's tags are ignored. 76 | 77 | 78 | 79 | ## Import 80 | Use the [`import` block](https://developer.hashicorp.com/terraform/language/import) to add VDB Groups created directly in DCT into a Terraform state file. 81 | 82 | For example: 83 | ```terraform 84 | import { 85 | to = delphix_vdb_group_import_demo 86 | id = "vdb_group_id" 87 | } 88 | ``` 89 | 90 | 91 | 92 | ## Limitations 93 | 94 | Please contact Delphix Support to make a feature request and/or create a GitHub Issue. 95 | 96 | -------------------------------------------------------------------------------- /docs/resources/database_postgresql.md: -------------------------------------------------------------------------------- 1 | # Resource: delphix_database_postgresql 2 | 3 | In the Delphix Platform, a Database (or Source Config) identifies the environment's location from which a specific source dataset can be ingested from. dSources are then created from these Databases. 4 | 5 | ## System Requirements 6 | 7 | * Data Control Tower v14.0.1+ is required for database management. Lower versions are not supported. 8 | * The Database PostgreSQL resource only supports the Delphix PostgreSQL database type (POSTGRES). This resource does not support Oracle, SQL Server, or SAP ASE. 9 | 10 | ## Example Usage 11 | 12 | ```hcl 13 | # Create a postgres database/source. 14 | 15 | resource "delphix_database_postgresql" "source" { 16 | name = "test" 17 | repository_value = "REPO-1" 18 | engine_value = "2" 19 | environment_value = "ENV-1" 20 | } 21 | 22 | ``` 23 | 24 | ## Argument Reference 25 | 26 | * `name` - (Required) The name of the new source. 27 | * `repository_value` - (Required) The Id or Name of the Repository onto which the source will be created.. 28 | * `environment_value` - The Id or Name of the environment to create the source on. 29 | * `engine_value` - The Id or Name of the engine to create the source on. 30 | * `id` - The Source object entity ID. 31 | * `database_type` - The type of this source database. 32 | * `namespace_id` - The namespace id of this source database. 33 | * `namespace_name` - The namespace name of this source database. 34 | * `is_replica` - Is this a replicated object. 35 | * `database_version` - The version of this source database. 36 | * `data_uuid` - A universal ID that uniquely identifies this source database. 37 | * `ip_address` - The IP address of the source's host. 38 | * `fqdn` - The FQDN of the source's host. 39 | * `size` - The total size of this source database, in bytes. 40 | * `jdbc_connection_string` - The JDBC connection URL for this source database. 41 | * `plugin_version` - The version of the plugin associated with this source database. 42 | * `toolkit_id` - The ID of the toolkit associated with this source database(AppData only). 43 | * `is_dsource` - Is this associated with dSource. 44 | * `repository` - The repository id for this source. 45 | * `appdata_source_type` - The type of this appdata source database (Appdata Only). 46 | * `tags` - The tags to be created for database. This is a map of 2 parameters: 47 | * `key` - Key of the tag 48 | * `value` - Value of the tag 49 | 50 | ## Import 51 | 52 | Use the [`import` block](https://developer.hashicorp.com/terraform/language/import) to add source configs created directly in Data Control Tower into a Terraform state file. 53 | 54 | For example: 55 | ```terraform 56 | import { 57 | to = delphix_database_postgresql.source_config_import 58 | id = "source_config_id" 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module terraform-provider-delphix 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.23.7 6 | 7 | require ( 8 | github.com/delphix/dct-sdk-go/v25 v25.2.0 9 | github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 10 | ) 11 | 12 | require ( 13 | github.com/ProtonMail/go-crypto v1.1.0-alpha.0 // indirect 14 | github.com/agext/levenshtein v1.2.2 // indirect 15 | github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect 16 | github.com/cloudflare/circl v1.6.1 // indirect 17 | github.com/fatih/color v1.16.0 // indirect 18 | github.com/google/go-cmp v0.6.0 // indirect 19 | github.com/hashicorp/errwrap v1.0.0 // indirect 20 | github.com/hashicorp/go-checkpoint v0.5.0 // indirect 21 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 22 | github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect 23 | github.com/hashicorp/go-hclog v1.5.0 // indirect 24 | github.com/hashicorp/go-multierror v1.1.1 // indirect 25 | github.com/hashicorp/go-plugin v1.6.0 // indirect 26 | github.com/hashicorp/go-uuid v1.0.3 // indirect 27 | github.com/hashicorp/go-version v1.6.0 // indirect 28 | github.com/hashicorp/hc-install v0.6.3 // indirect 29 | github.com/hashicorp/hcl/v2 v2.19.1 // indirect 30 | github.com/hashicorp/logutils v1.0.0 // indirect 31 | github.com/hashicorp/terraform-exec v0.20.0 // indirect 32 | github.com/hashicorp/terraform-json v0.21.0 // indirect 33 | github.com/hashicorp/terraform-plugin-go v0.22.0 // indirect 34 | github.com/hashicorp/terraform-plugin-log v0.9.0 35 | github.com/hashicorp/terraform-registry-address v0.2.3 // indirect 36 | github.com/hashicorp/terraform-svchost v0.1.1 // indirect 37 | github.com/hashicorp/yamux v0.1.2 // indirect 38 | github.com/mattn/go-colorable v0.1.13 // indirect 39 | github.com/mattn/go-isatty v0.0.20 // indirect 40 | github.com/mitchellh/copystructure v1.2.0 // indirect 41 | github.com/mitchellh/go-testing-interface v1.14.1 // indirect 42 | github.com/mitchellh/go-wordwrap v1.0.0 // indirect 43 | github.com/mitchellh/mapstructure v1.5.0 // indirect 44 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 45 | github.com/oklog/run v1.0.0 // indirect 46 | github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect 47 | github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect 48 | github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect 49 | github.com/zclconf/go-cty v1.14.2 // indirect 50 | golang.org/x/crypto v0.36.0 // indirect 51 | golang.org/x/mod v0.17.0 // indirect 52 | golang.org/x/sys v0.31.0 // indirect 53 | golang.org/x/text v0.23.0 // indirect 54 | google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect 55 | google.golang.org/grpc v1.61.1 // indirect 56 | ) 57 | 58 | require ( 59 | github.com/golang/protobuf v1.5.3 // indirect 60 | github.com/kr/pretty v0.2.1 // indirect 61 | github.com/kr/text v0.2.0 // indirect 62 | golang.org/x/net v0.38.0 // indirect 63 | google.golang.org/appengine v1.6.8 // indirect 64 | google.golang.org/protobuf v1.33.0 // indirect 65 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 66 | ) 67 | -------------------------------------------------------------------------------- /examples/vdb/sybase/bookmark/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a SYBASE database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | bookmark_id = "" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | database_name = "dbname_to_be_created" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | retention_policy_id = "test_retention_policy" 33 | custom_env_files = ["/export/home/env_file_1"] 34 | custom_env_vars = { 35 | MY_ENV_VAR1 = "$HOME" 36 | MY_ENV_VAR2 = "$CRS_HOME/after" 37 | } 38 | truncate_log_on_checkpoint = true 39 | repository_id = "" 40 | config_params jsonencode({ 41 | processes = 150 42 | }) 43 | pre_snapshot { 44 | name = "string", 45 | command = "string", 46 | shell = "bash", 47 | } 48 | pre_stop { 49 | name = "string", 50 | command = "string", 51 | shell = "bash", 52 | } 53 | pre_refresh { 54 | name = "string", 55 | command = "string", 56 | shell = "bash", 57 | } 58 | post_start { 59 | name = "string", 60 | command = "string", 61 | shell = "bash", 62 | } 63 | post_snapshot { 64 | name = "string", 65 | command = "string", 66 | shell = "bash", 67 | } 68 | post_refresh { 69 | name = "string", 70 | command = "string", 71 | shell = "bash", 72 | } 73 | post_stop { 74 | name = "string", 75 | command = "string", 76 | shell = "bash", 77 | } 78 | post_rollback { 79 | name = "string", 80 | command = "string", 81 | shell = "bash", 82 | } 83 | pre_rollback { 84 | name = "string", 85 | command = "string", 86 | shell = "bash", 87 | } 88 | pre_start { 89 | name = "string", 90 | command = "string", 91 | shell = "bash", 92 | } 93 | configure_clone { 94 | name = "string", 95 | command = "string", 96 | shell = "bash", 97 | } 98 | make_current_account_owner = true 99 | tags { 100 | key = "key-1" 101 | value = "value-1" 102 | } 103 | } -------------------------------------------------------------------------------- /examples/vdb/sybase/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a SYBASE database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "snapshot-id" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | database_name = "dbname_to_be_created" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | engine_id = "1" 33 | retention_policy_id = "test_retention_policy" 34 | custom_env_files = ["/export/home/env_file_1"] 35 | custom_env_vars = { 36 | MY_ENV_VAR1 = "$HOME" 37 | MY_ENV_VAR2 = "$CRS_HOME/after" 38 | } 39 | repository_id = "" 40 | truncate_log_on_checkpoint = true 41 | config_params jsonencode({ 42 | processes = 150 43 | }) 44 | pre_snapshot { 45 | name = "string" 46 | command = "string" 47 | shell = "bash" 48 | } 49 | pre_stop { 50 | name = "string" 51 | command = "string" 52 | shell = "bash" 53 | } 54 | pre_refresh { 55 | name = "string" 56 | command = "string" 57 | shell = "bash" 58 | } 59 | post_start { 60 | name = "string" 61 | command = "string" 62 | shell = "bash" 63 | } 64 | post_snapshot { 65 | name = "string" 66 | command = "string" 67 | shell = "bash" 68 | } 69 | post_refresh { 70 | name = "string" 71 | command = "string" 72 | shell = "bash" 73 | } 74 | post_stop { 75 | name = "string" 76 | command = "string" 77 | shell = "bash" 78 | } 79 | post_rollback { 80 | name = "string" 81 | command = "string" 82 | shell = "bash" 83 | } 84 | pre_rollback { 85 | name = "string" 86 | command = "string" 87 | shell = "bash" 88 | } 89 | pre_start { 90 | name = "string" 91 | command = "string" 92 | shell = "bash" 93 | } 94 | configure_clone { 95 | name = "string" 96 | command = "string" 97 | shell = "bash" 98 | } 99 | make_current_account_owner = true 100 | tags { 101 | key = "key-1" 102 | value = "value-1" 103 | } 104 | } -------------------------------------------------------------------------------- /examples/vdb/sybase/timestamp/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a SYBASE database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | timestamp = "" 22 | timestamp_in_database_timezone = "" 23 | name = "vdb_to_be_created" 24 | source_data_id = "dsource-name" 25 | engine_id = "1" 26 | vdb_restart = true 27 | environment_id = "env-name" 28 | environment_user_id = "environment_user_name" 29 | target_group_id = "group-123" 30 | snapshot_policy_id = "test_snapshot_policy" 31 | database_name = "dbname_to_be_created" 32 | mount_point = "/var/mnt" 33 | auto_select_repository = true 34 | retention_policy_id = "test_retention_policy" 35 | custom_env_files = ["/export/home/env_file_1"] 36 | custom_env_vars = { 37 | MY_ENV_VAR1 = "$HOME" 38 | MY_ENV_VAR2 = "$CRS_HOME/after" 39 | } 40 | truncate_log_on_checkpoint = true 41 | repository_id = "" 42 | config_params jsonencode({ 43 | processes = 150 44 | }) 45 | pre_snapshot { 46 | name = "string" 47 | command = "string" 48 | shell = "bash" 49 | } 50 | pre_stop { 51 | name = "string" 52 | command = "string" 53 | shell = "bash" 54 | } 55 | pre_refresh { 56 | name = "string" 57 | command = "string" 58 | shell = "bash" 59 | } 60 | post_start { 61 | name = "string" 62 | command = "string" 63 | shell = "bash" 64 | } 65 | post_snapshot { 66 | name = "string" 67 | command = "string" 68 | shell = "bash" 69 | } 70 | post_refresh { 71 | name = "string" 72 | command = "string" 73 | shell = "bash" 74 | } 75 | post_stop { 76 | name = "string" 77 | command = "string" 78 | shell = "bash" 79 | } 80 | post_rollback { 81 | name = "string" 82 | command = "string" 83 | shell = "bash" 84 | } 85 | pre_rollback { 86 | name = "string" 87 | command = "string" 88 | shell = "bash" 89 | } 90 | pre_start { 91 | name = "string" 92 | command = "string" 93 | shell = "bash" 94 | } 95 | configure_clone { 96 | name = "string" 97 | command = "string" 98 | shell = "bash" 99 | } 100 | make_current_account_owner = true 101 | tags { 102 | key = "key-1" 103 | value = "value-1" 104 | } 105 | } -------------------------------------------------------------------------------- /examples/vdb/mysql/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a PostgreSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "snapshot-id" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | engine_id = "1" 25 | vdb_restart = true 26 | environment_id = "env-name" 27 | environment_user_id = "environment_user_name" 28 | target_group_id = "group-123" 29 | snapshot_policy_id = "test_snapshot_policy" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | retention_policy_id = "test_retention_policy" 33 | custom_env_files = ["/export/home/env_file_1"] 34 | custom_env_vars = { 35 | MY_ENV_VAR1 = "$HOME" 36 | MY_ENV_VAR2 = "$CRS_HOME/after" 37 | } 38 | repository_id = "" 39 | appdata_source_params = jsonencode({ 40 | baseDir: "/usr", 41 | config_settings_prov: [], 42 | mPath: "/delphix/zfs5", 43 | port: 3890, 44 | serverId: 190, 45 | vdbPass: XXXX, 46 | vdbUser: XXXX 47 | }) 48 | 49 | additional_mount_points = [{ 50 | shared_path = "/", 51 | mount_path = "/work", 52 | environment_id = "environment-123" 53 | }] 54 | 55 | post_snapshot { 56 | name = "string" 57 | command = "string" 58 | shell = "bash" 59 | } 60 | pre_snapshot { 61 | name = "string" 62 | command = "string" 63 | shell = "bash" 64 | } 65 | pre_stop { 66 | name = "string" 67 | command = "string" 68 | shell = "bash" 69 | } 70 | configure_clone { 71 | name = "string" 72 | command = "string" 73 | shell = "bash" 74 | } 75 | post_refresh { 76 | name = "string" 77 | command = "string" 78 | shell = "bash" 79 | } 80 | post_stop { 81 | name = "string" 82 | command = "string" 83 | shell = "bash" 84 | } 85 | post_rollback { 86 | name = "string" 87 | command = "string" 88 | shell = "bash" 89 | } 90 | post_start { 91 | name = "string" 92 | command = "string" 93 | shell = "bash" 94 | } 95 | pre_rollback { 96 | name = "string" 97 | command = "string" 98 | shell = "bash" 99 | } 100 | pre_start { 101 | name = "string" 102 | command = "string" 103 | shell = "bash" 104 | } 105 | pre_refresh { 106 | name = "string" 107 | command = "string" 108 | shell = "bash" 109 | } 110 | make_current_account_owner = true 111 | tags { 112 | key = "key-1" 113 | value = "value-1" 114 | } 115 | } -------------------------------------------------------------------------------- /examples/vdb/postgresql/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a PostgreSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "snapshot-id" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | engine_id = "1" 25 | vdb_restart = true 26 | environment_id = "env-name" 27 | environment_user_id = "environment_user_name" 28 | target_group_id = "group-123" 29 | snapshot_policy_id = "test_snapshot_policy" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | retention_policy_id = "test_retention_policy" 33 | custom_env_files = ["/export/home/env_file_1"] 34 | custom_env_vars = { 35 | MY_ENV_VAR1 = "$HOME" 36 | MY_ENV_VAR2 = "$CRS_HOME/after" 37 | } 38 | repository_id = "" 39 | appdata_source_params = jsonencode({ 40 | mountLocation = "/mnt/GAT" 41 | postgresPort = 5434 42 | configSettingsStg = [{ propertyName: "timezone", value:"GMT", commentProperty:false}] 43 | }) 44 | 45 | post_snapshot { 46 | name = "string" 47 | command = "string" 48 | shell = "bash" 49 | } 50 | pre_snapshot { 51 | name = "string" 52 | command = "string" 53 | shell = "bash" 54 | } 55 | pre_stop { 56 | name = "string" 57 | command = "string" 58 | shell = "bash" 59 | } 60 | configure_clone { 61 | name = "string" 62 | command = "string" 63 | shell = "bash" 64 | } 65 | post_refresh { 66 | name = "string" 67 | command = "string" 68 | shell = "bash" 69 | } 70 | post_stop { 71 | name = "string" 72 | command = "string" 73 | shell = "bash" 74 | } 75 | post_rollback { 76 | name = "string" 77 | command = "string" 78 | shell = "bash" 79 | } 80 | post_start { 81 | name = "string" 82 | command = "string" 83 | shell = "bash" 84 | } 85 | pre_rollback { 86 | name = "string" 87 | command = "string" 88 | shell = "bash" 89 | } 90 | pre_start { 91 | name = "string" 92 | command = "string" 93 | shell = "bash" 94 | } 95 | pre_refresh { 96 | name = "string" 97 | command = "string" 98 | shell = "bash" 99 | } 100 | make_current_account_owner = true 101 | tags { 102 | key = "key-1" 103 | value = "value-1" 104 | } 105 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Delphix Code of Conduct 2 | ## Our Pledge 3 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 4 | 5 | ## Our Standards 6 | Examples of behavior that contributes to creating a positive environment include: 7 | 8 | * Using welcoming and inclusive language 9 | * Being respectful of differing viewpoints and experiences 10 | * Gracefully accepting constructive criticism 11 | * Focusing on what is best for the community 12 | * Showing empathy towards other community members 13 | 14 | Examples of unacceptable behavior by participants include: 15 | 16 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 17 | * Trolling, insulting/derogatory comments, and personal or political attacks 18 | * Public or private harassment 19 | * Publishing others’ private information, such as a physical or electronic address, without explicit permission 20 | * Other conduct which could reasonably be considered inappropriate in a professional setting 21 | 22 | ## Our Responsibilities 23 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 24 | 25 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 26 | 27 | ## Scope 28 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 29 | 30 | ## Enforcement 31 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting Delphix at open-source@delphix.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 32 | 33 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership. 34 | 35 | ## Attribution 36 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at contributor-convenant.org 37 | 38 | 39 | Copyright (c) 2019 by Delphix 40 | -------------------------------------------------------------------------------- /examples/vdb/postgresql/bookmark/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a PostgreSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | bookmark_id = "bookmark_name" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | mount_point = "/var/mnt" 30 | auto_select_repository = true 31 | retention_policy_id = "test_retention_policy" 32 | custom_env_files = ["/export/home/env_file_1"] 33 | custom_env_vars = { 34 | MY_ENV_VAR1 = "$HOME" 35 | MY_ENV_VAR2 = "$CRS_HOME/after" 36 | } 37 | repository_id = "" 38 | appdata_source_params = jsonencode({ 39 | mountLocation = "/mnt/GAT" 40 | postgresPort = 5434 41 | configSettingsStg = [{ propertyName: "timezone", value:"GMT", commentProperty:false}] 42 | }) 43 | additional_mount_points = [{ 44 | shared_path = "/", 45 | mount_path = "/work", 46 | environment_id = "environment-123" 47 | }] 48 | 49 | post_snapshot { 50 | name = "string" 51 | command = "string" 52 | shell = "bash" 53 | } 54 | pre_snapshot { 55 | name = "string" 56 | command = "string" 57 | shell = "bash" 58 | } 59 | pre_stop { 60 | name = "string" 61 | command = "string" 62 | shell = "bash" 63 | } 64 | configure_clone { 65 | name = "string" 66 | command = "string" 67 | shell = "bash" 68 | } 69 | post_refresh { 70 | name = "string" 71 | command = "string" 72 | shell = "bash" 73 | } 74 | post_stop { 75 | name = "string" 76 | command = "string" 77 | shell = "bash" 78 | } 79 | post_rollback { 80 | name = "string" 81 | command = "string" 82 | shell = "bash" 83 | } 84 | post_start { 85 | name = "string" 86 | command = "string" 87 | shell = "bash" 88 | } 89 | pre_rollback { 90 | name = "string" 91 | command = "string" 92 | shell = "bash" 93 | } 94 | pre_start { 95 | name = "string" 96 | command = "string" 97 | shell = "bash" 98 | } 99 | pre_refresh { 100 | name = "string" 101 | command = "string" 102 | shell = "bash" 103 | } 104 | make_current_account_owner = true 105 | tags { 106 | key = "key-1" 107 | value = "value-1" 108 | } 109 | } -------------------------------------------------------------------------------- /examples/vdb/mssql/bookmark/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a MSSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | bookmark_id = "" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | database_name = "dbname_to_be_created" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | retention_policy_id = "test_retention_policy" 33 | custom_env_files = ["/export/home/env_file_1"] 34 | custom_env_vars = { 35 | MY_ENV_VAR1 = "$HOME" 36 | MY_ENV_VAR2 = "$CRS_HOME/after" 37 | } 38 | cdc_on_provision = true 39 | repository_id = "" 40 | recovery_model = "" 41 | config_params jsonencode({ 42 | processes = 150 43 | }) 44 | post_snapshot { 45 | name = "string" 46 | command = "string" 47 | shell = "bash" 48 | } 49 | post_script { 50 | name = "string" 51 | command = "string" 52 | shell = "bash" 53 | } 54 | pre_snapshot { 55 | name = "string" 56 | command = "string" 57 | shell = "bash" 58 | } 59 | pre_stop { 60 | name = "string" 61 | command = "string" 62 | shell = "bash" 63 | } 64 | post_start { 65 | name = "string" 66 | command = "string" 67 | shell = "bash" 68 | } 69 | pre_rollback { 70 | name = "string" 71 | command = "string" 72 | shell = "bash" 73 | } 74 | pre_start { 75 | name = "string" 76 | command = "string" 77 | shell = "bash" 78 | } 79 | pre_refresh { 80 | name = "string" 81 | command = "string" 82 | shell = "bash" 83 | } 84 | pre_script { 85 | name = "string" 86 | command = "string" 87 | shell = "bash" 88 | } 89 | post_refresh { 90 | name = "string" 91 | command = "string" 92 | shell = "bash" 93 | } 94 | post_stop { 95 | name = "string" 96 | command = "string" 97 | shell = "bash" 98 | } 99 | configure_clone { 100 | name = "string" 101 | command = "string" 102 | shell = "bash" 103 | } 104 | post_rollback { 105 | name = "string" 106 | command = "string" 107 | shell = "bash" 108 | } 109 | make_current_account_owner = true 110 | tags { 111 | key = "key-1" 112 | value = "value-1" 113 | } 114 | } -------------------------------------------------------------------------------- /examples/vdb/mssql/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a MSSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "snapshot-id" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | database_name = "dbname_to_be_created" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | engine_id = "1" 33 | retention_policy_id = "test_retention_policy" 34 | custom_env_files = ["/export/home/env_file_1"] 35 | custom_env_vars = { 36 | MY_ENV_VAR1 = "$HOME" 37 | MY_ENV_VAR2 = "$CRS_HOME/after" 38 | } 39 | cdc_on_provision = true 40 | repository_id = "" 41 | recovery_model = "" 42 | config_params jsonencode({ 43 | processes = 150 44 | }) 45 | post_snapshot { 46 | name = "string" 47 | command = "string" 48 | shell = "bash" 49 | } 50 | post_script { 51 | name = "string" 52 | command = "string" 53 | shell = "bash" 54 | } 55 | pre_snapshot { 56 | name = "string" 57 | command = "string" 58 | shell = "bash" 59 | } 60 | pre_stop { 61 | name = "string" 62 | command = "string" 63 | shell = "bash" 64 | } 65 | post_start { 66 | name = "string" 67 | command = "string" 68 | shell = "bash" 69 | } 70 | pre_rollback { 71 | name = "string" 72 | command = "string" 73 | shell = "bash" 74 | } 75 | pre_start { 76 | name = "string" 77 | command = "string" 78 | shell = "bash" 79 | } 80 | pre_refresh { 81 | name = "string" 82 | command = "string" 83 | shell = "bash" 84 | } 85 | pre_script { 86 | name = "string" 87 | command = "string" 88 | shell = "bash" 89 | } 90 | post_refresh { 91 | name = "string" 92 | command = "string" 93 | shell = "bash" 94 | } 95 | post_stop { 96 | name = "string" 97 | command = "string" 98 | shell = "bash" 99 | } 100 | configure_clone { 101 | name = "string" 102 | command = "string" 103 | shell = "bash" 104 | } 105 | post_rollback { 106 | name = "string" 107 | command = "string" 108 | shell = "bash" 109 | } 110 | make_current_account_owner = true 111 | tags { 112 | key = "key-1" 113 | value = "value-1" 114 | } 115 | 116 | } -------------------------------------------------------------------------------- /examples/vdb/postgresql/timestamp/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a PostgreSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | timestamp = "" 22 | timestamp_in_database_timezone = "" 23 | name = "vdb_to_be_created" 24 | source_data_id = "dsource-name" 25 | engine_id = "1" 26 | vdb_restart = true 27 | environment_id = "env-name" 28 | environment_user_id = "environment_user_name" 29 | target_group_id = "group-123" 30 | snapshot_policy_id = "test_snapshot_policy" 31 | database_name = "dbname_to_be_created" 32 | mount_point = "/var/mnt" 33 | auto_select_repository = true 34 | retention_policy_id = "test_retention_policy" 35 | custom_env_files = ["/export/home/env_file_1"] 36 | custom_env_vars = { 37 | MY_ENV_VAR1 = "$HOME" 38 | MY_ENV_VAR2 = "$CRS_HOME/after" 39 | } 40 | repository_id = "" 41 | appdata_source_params = jsonencode({ 42 | mountLocation = "/mnt/GAT" 43 | postgresPort = 5434 44 | configSettingsStg = [{ propertyName: "timezone", value:"GMT", commentProperty:false}] 45 | }) 46 | additional_mount_points = [{ 47 | shared_path = "/", 48 | mount_path = "/work", 49 | environment_id = "environment-123" 50 | }] 51 | post_snapshot { 52 | name = "string" 53 | command = "string" 54 | shell = "bash" 55 | } 56 | pre_snapshot { 57 | name = "string" 58 | command = "string" 59 | shell = "bash" 60 | } 61 | pre_stop { 62 | name = "string" 63 | command = "string" 64 | shell = "bash" 65 | } 66 | configure_clone { 67 | name = "string" 68 | command = "string" 69 | shell = "bash" 70 | } 71 | post_refresh { 72 | name = "string" 73 | command = "string" 74 | shell = "bash" 75 | } 76 | post_stop { 77 | name = "string" 78 | command = "string" 79 | shell = "bash" 80 | } 81 | post_rollback { 82 | name = "string" 83 | command = "string" 84 | shell = "bash" 85 | } 86 | post_start { 87 | name = "string" 88 | command = "string" 89 | shell = "bash" 90 | } 91 | pre_rollback { 92 | name = "string" 93 | command = "string" 94 | shell = "bash" 95 | } 96 | pre_start { 97 | name = "string" 98 | command = "string" 99 | shell = "bash" 100 | } 101 | pre_refresh { 102 | name = "string" 103 | command = "string" 104 | shell = "bash" 105 | } 106 | make_current_account_owner = true 107 | tags { 108 | key = "key-1" 109 | value = "value-1" 110 | } 111 | } -------------------------------------------------------------------------------- /examples/vdb/hana/bookmark/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a SAP Hana database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | bookmark_id = "" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | vdb_restart = true 25 | environment_id = "env-name" 26 | environment_user_id = "environment_user_name" 27 | target_group_id = "group-123" 28 | snapshot_policy_id = "test_snapshot_policy" 29 | mount_point = "/var/mnt" 30 | auto_select_repository = true 31 | retention_policy_id = "test_retention_policy" 32 | custom_env_files = ["/export/home/env_file_1"] 33 | custom_env_vars = { 34 | MY_ENV_VAR1 = "$HOME" 35 | MY_ENV_VAR2 = "$CRS_HOME/after" 36 | } 37 | repository_id = "" 38 | appdata_source_params = jsonencode({ 39 | mountLocation = "/mnt/bkmrk" 40 | configServices = [{ 41 | "sTenantServicePort" = "indexserver:30049" 42 | }, 43 | { 44 | "sTenantServicePort" = "xsengine:30052" 45 | }] 46 | tDatabaseName = "tfbkmrk" 47 | tSystemUserName = "" 48 | tSystemUserPassword ="" 49 | }) 50 | additional_mount_points = [{ 51 | shared_path = "/", 52 | mount_path = "/work", 53 | environment_id = "environment-123" 54 | }] 55 | post_snapshot { 56 | name = "string" 57 | command = "string" 58 | shell = "bash" 59 | } 60 | pre_snapshot { 61 | name = "string" 62 | command = "string" 63 | shell = "bash" 64 | } 65 | pre_stop { 66 | name = "string" 67 | command = "string" 68 | shell = "bash" 69 | } 70 | configure_clone { 71 | name = "string" 72 | command = "string" 73 | shell = "bash" 74 | } 75 | post_refresh { 76 | name = "string" 77 | command = "string" 78 | shell = "bash" 79 | } 80 | post_stop { 81 | name = "string" 82 | command = "string" 83 | shell = "bash" 84 | } 85 | post_rollback { 86 | name = "string" 87 | command = "string" 88 | shell = "bash" 89 | } 90 | post_start { 91 | name = "string" 92 | command = "string" 93 | shell = "bash" 94 | } 95 | pre_rollback { 96 | name = "string" 97 | command = "string" 98 | shell = "bash" 99 | } 100 | pre_start { 101 | name = "string" 102 | command = "string" 103 | shell = "bash" 104 | } 105 | pre_refresh { 106 | name = "string" 107 | command = "string" 108 | shell = "bash" 109 | } 110 | make_current_account_owner = true 111 | tags { 112 | key = "key-1" 113 | value = "value-1" 114 | } 115 | } -------------------------------------------------------------------------------- /examples/vdb/mssql/timestamp/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a MSSQL database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | timestamp = "" 22 | timestamp_in_database_timezone = "" 23 | name = "vdb_to_be_created" 24 | source_data_id = "dsource-name" 25 | vdb_restart = true 26 | environment_id = "env-name" 27 | environment_user_id = "environment_user_name" 28 | target_group_id = "group-123" 29 | snapshot_policy_id = "test_snapshot_policy" 30 | database_name = "dbname_to_be_created" 31 | mount_point = "/var/mnt" 32 | auto_select_repository = true 33 | engine_id = "1" 34 | retention_policy_id = "test_retention_policy" 35 | custom_env_files = ["/export/home/env_file_1"] 36 | custom_env_vars = { 37 | MY_ENV_VAR1 = "$HOME" 38 | MY_ENV_VAR2 = "$CRS_HOME/after" 39 | } 40 | recovery_model = "" 41 | cdc_on_provision = true 42 | repository_id = "" 43 | 44 | config_params jsonencode({ 45 | processes = 150 46 | }) 47 | post_snapshot { 48 | name = "string" 49 | command = "string" 50 | shell = "bash" 51 | } 52 | post_script { 53 | name = "string" 54 | command = "string" 55 | shell = "bash" 56 | } 57 | pre_snapshot { 58 | name = "string" 59 | command = "string" 60 | shell = "bash" 61 | } 62 | pre_stop { 63 | name = "string" 64 | command = "string" 65 | shell = "bash" 66 | } 67 | post_start { 68 | name = "string" 69 | command = "string" 70 | shell = "bash" 71 | } 72 | pre_rollback { 73 | name = "string" 74 | command = "string" 75 | shell = "bash" 76 | } 77 | pre_start { 78 | name = "string" 79 | command = "string" 80 | shell = "bash" 81 | } 82 | pre_refresh { 83 | name = "string" 84 | command = "string" 85 | shell = "bash" 86 | } 87 | pre_script { 88 | name = "string" 89 | command = "string" 90 | shell = "bash" 91 | } 92 | post_refresh { 93 | name = "string" 94 | command = "string" 95 | shell = "bash" 96 | } 97 | post_stop { 98 | name = "string" 99 | command = "string" 100 | shell = "bash" 101 | } 102 | configure_clone { 103 | name = "string" 104 | command = "string" 105 | shell = "bash" 106 | } 107 | post_rollback { 108 | name = "string" 109 | command = "string" 110 | shell = "bash" 111 | } 112 | make_current_account_owner = true 113 | tags { 114 | key = "key-1" 115 | value = "value-1" 116 | } 117 | } -------------------------------------------------------------------------------- /examples/vdb/hana/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning a SAP Hana database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "snapshot-id" 22 | name = "vdb_to_be_created" 23 | engine_id = "1" 24 | source_data_id = "dsource-name" 25 | vdb_restart = true 26 | environment_id = "env-name" 27 | environment_user_id = "environment_user_name" 28 | target_group_id = "group-123" 29 | snapshot_policy_id = "test_snapshot_policy" 30 | mount_point = "/var/mnt" 31 | auto_select_repository = true 32 | retention_policy_id = "test_retention_policy" 33 | custom_env_files = ["/export/home/env_file_1"] 34 | custom_env_vars = { 35 | MY_ENV_VAR1 = "$HOME" 36 | MY_ENV_VAR2 = "$CRS_HOME/after" 37 | } 38 | repository_id = "" 39 | appdata_source_params = jsonencode({ 40 | mountLocation = "/mnt/bkmrk" 41 | configServices = [{ 42 | "sTenantServicePort" = "indexserver:30049" 43 | }, 44 | { 45 | "sTenantServicePort" = "xsengine:30052" 46 | }] 47 | tDatabaseName = "tfbkmrk" 48 | tSystemUserName = "" 49 | tSystemUserPassword ="" 50 | }) 51 | additional_mount_points = [{ 52 | shared_path = "/", 53 | mount_path = "/work", 54 | environment_id = "environment-123" 55 | }] 56 | post_snapshot { 57 | name = "string" 58 | command = "string" 59 | shell = "bash" 60 | } 61 | pre_snapshot { 62 | name = "string" 63 | command = "string" 64 | shell = "bash" 65 | } 66 | pre_stop { 67 | name = "string" 68 | command = "string" 69 | shell = "bash" 70 | } 71 | configure_clone { 72 | name = "string" 73 | command = "string" 74 | shell = "bash" 75 | } 76 | post_refresh { 77 | name = "string" 78 | command = "string" 79 | shell = "bash" 80 | } 81 | post_stop { 82 | name = "string" 83 | command = "string" 84 | shell = "bash" 85 | } 86 | post_rollback { 87 | name = "string" 88 | command = "string" 89 | shell = "bash" 90 | } 91 | post_start { 92 | name = "string" 93 | command = "string" 94 | shell = "bash" 95 | } 96 | pre_rollback { 97 | name = "string" 98 | command = "string" 99 | shell = "bash" 100 | } 101 | pre_start { 102 | name = "string" 103 | command = "string" 104 | shell = "bash" 105 | } 106 | pre_refresh { 107 | name = "string" 108 | command = "string" 109 | shell = "bash" 110 | } 111 | make_current_account_owner = true 112 | tags { 113 | key = "key-1" 114 | value = "value-1" 115 | } 116 | 117 | } -------------------------------------------------------------------------------- /examples/vdb/hana/timestamp/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning an SAP Hana database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | timestamp = "" 22 | timestamp_in_database_timezone = "" 23 | name = "vdb_to_be_created" 24 | source_data_id = "dsource-name" 25 | engine_id = "1" 26 | vdb_restart = true 27 | environment_id = "env-name" 28 | environment_user_id = "environment_user_name" 29 | target_group_id = "group-123" 30 | snapshot_policy_id = "test_snapshot_policy" 31 | mount_point = "/var/mnt" 32 | auto_select_repository = true 33 | retention_policy_id = "test_retention_policy" 34 | custom_env_files = ["/export/home/env_file_1"] 35 | custom_env_vars = { 36 | MY_ENV_VAR1 = "$HOME" 37 | MY_ENV_VAR2 = "$CRS_HOME/after" 38 | } 39 | repository_id = "" 40 | appdata_source_params = jsonencode({ 41 | mountLocation = "/mnt/bkmrk" 42 | configServices = [{ 43 | "sTenantServicePort" = "indexserver:30049" 44 | }, 45 | { 46 | "sTenantServicePort" = "xsengine:30052" 47 | }] 48 | tDatabaseName = "tfbkmrk" 49 | tSystemUserName = "" 50 | tSystemUserPassword ="" 51 | }) 52 | additional_mount_points = [{ 53 | shared_path = "/", 54 | mount_path = "/work", 55 | environment_id = "environment-123" 56 | }] 57 | post_snapshot { 58 | name = "string" 59 | command = "string" 60 | shell = "bash" 61 | } 62 | pre_snapshot { 63 | name = "string" 64 | command = "string" 65 | shell = "bash" 66 | } 67 | pre_stop { 68 | name = "string" 69 | command = "string" 70 | shell = "bash" 71 | } 72 | configure_clone { 73 | name = "string" 74 | command = "string" 75 | shell = "bash" 76 | } 77 | post_refresh { 78 | name = "string" 79 | command = "string" 80 | shell = "bash" 81 | } 82 | post_stop { 83 | name = "string" 84 | command = "string" 85 | shell = "bash" 86 | } 87 | post_rollback { 88 | name = "string" 89 | command = "string" 90 | shell = "bash" 91 | } 92 | post_start { 93 | name = "string" 94 | command = "string" 95 | shell = "bash" 96 | } 97 | pre_rollback { 98 | name = "string" 99 | command = "string" 100 | shell = "bash" 101 | } 102 | pre_start { 103 | name = "string" 104 | command = "string" 105 | shell = "bash" 106 | } 107 | pre_refresh { 108 | name = "string" 109 | command = "string" 110 | shell = "bash" 111 | } 112 | make_current_account_owner = true 113 | tags { 114 | key = "key-1" 115 | value = "value-1" 116 | } 117 | } -------------------------------------------------------------------------------- /internal/provider/provider.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "net/http" 7 | 8 | dctapi "github.com/delphix/dct-sdk-go/v25" 9 | 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 12 | ) 13 | 14 | func init() { 15 | // Set descriptions to support markdown syntax, this will be used in document generation 16 | // and the language server. 17 | schema.DescriptionKind = schema.StringMarkdown 18 | 19 | // Customize the content of descriptions when output. For example you can add defaults on 20 | // to the exported descriptions if present. 21 | // schema.SchemaDescriptionBuilder = func(s *schema.Schema) string { 22 | // desc := s.Description 23 | // if s.Default != nil { 24 | // desc += fmt.Sprintf(" Defaults to `%v`.", s.Default) 25 | // } 26 | // return strings.TrimSpace(desc) 27 | // } 28 | } 29 | 30 | func Provider(version string) func() *schema.Provider { 31 | return func() *schema.Provider { 32 | p := &schema.Provider{ 33 | Schema: map[string]*schema.Schema{ 34 | "key": { 35 | Type: schema.TypeString, 36 | Required: true, 37 | Sensitive: true, 38 | DefaultFunc: schema.EnvDefaultFunc("DCT_KEY", nil), 39 | }, 40 | "tls_insecure_skip": { 41 | Type: schema.TypeBool, 42 | Optional: true, 43 | DefaultFunc: schema.EnvDefaultFunc("DCT_TLS_INSECURE_SKIP", false), 44 | }, 45 | "host": { 46 | Type: schema.TypeString, 47 | Required: true, 48 | DefaultFunc: schema.EnvDefaultFunc("DCT_HOST", nil), 49 | }, 50 | "host_scheme": { 51 | Type: schema.TypeString, 52 | Optional: true, 53 | DefaultFunc: schema.EnvDefaultFunc("DCT_HOST_SCHEME", "https"), 54 | }, 55 | "debug": { 56 | Type: schema.TypeBool, 57 | Optional: true, 58 | Default: false, 59 | }, 60 | }, 61 | ResourcesMap: map[string]*schema.Resource{ 62 | "delphix_vdb": resourceVdb(), 63 | "delphix_vdb_group": resourceVdbGroup(), 64 | "delphix_environment": resourceEnvironment(), 65 | "delphix_appdata_dsource": resourceAppdataDsource(), 66 | "delphix_oracle_dsource": resourceOracleDsource(), 67 | "delphix_database_postgresql": resourceSource(), 68 | }, 69 | } 70 | 71 | p.ConfigureContextFunc = configure(version, p) 72 | 73 | return p 74 | } 75 | } 76 | 77 | type apiClient struct { 78 | client *dctapi.APIClient 79 | } 80 | 81 | func configure(version string, p *schema.Provider) func(context.Context, *schema.ResourceData) (interface{}, diag.Diagnostics) { 82 | return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) { 83 | // configure client 84 | cfg := dctapi.NewConfiguration() 85 | cfg.Host = d.Get("host").(string) 86 | cfg.UserAgent = p.UserAgent("terraform-provider-delphix", version) 87 | cfg.Scheme = d.Get("host_scheme").(string) 88 | cfg.HTTPClient = &http.Client{Transport: &http.Transport{ 89 | TLSClientConfig: &tls.Config{InsecureSkipVerify: d.Get("tls_insecure_skip").(bool)}, 90 | }} 91 | cfg.AddDefaultHeader("Authorization", "apk "+d.Get("key").(string)) 92 | cfg.AddDefaultHeader("x-dct-client-name", "Terraform") 93 | 94 | client := dctapi.NewAPIClient(cfg) 95 | 96 | if d.Get("debug").(bool) { 97 | // print out raw api request body for debug purposes 98 | client.GetConfig().Debug = true 99 | } 100 | // make a test call 101 | 102 | req := client.ManagementAPI.GetRegisteredEngines(ctx) 103 | _, _, err := client.ManagementAPI.GetRegisteredEnginesExecute(req) 104 | 105 | if err != nil { 106 | return nil, diag.FromErr(err) 107 | } 108 | 109 | return &apiClient{client}, nil 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /internal/provider/resource_database_postgresql_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "testing" 9 | 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 12 | ) 13 | 14 | func Test_source_create_positive(t *testing.T) { 15 | name := os.Getenv("SOURCE_NAME") 16 | repository_id := os.Getenv("REPOSITORY_VALUE") 17 | 18 | resource.Test(t, resource.TestCase{ 19 | PreCheck: func() { 20 | testsourcePreCheck(t, repository_id, name) 21 | }, 22 | Providers: testAccProviders, 23 | CheckDestroy: testSourceDestroy, 24 | Steps: []resource.TestStep{ 25 | { 26 | Config: testsourceBasic("", name), 27 | ExpectError: regexp.MustCompile(`.*`), 28 | }, 29 | { 30 | Config: testsourceBasic(repository_id, name), 31 | Check: resource.ComposeTestCheckFunc( 32 | testSourceExists("delphix_database_postgresql.new_dsource", name), 33 | resource.TestCheckResourceAttr("delphix_database_postgresql.new_dsource", "name", name)), 34 | }, 35 | { 36 | Config: testsourceUpdate(repository_id, "update_name"), 37 | Check: resource.ComposeTestCheckFunc( 38 | testSourceExists("delphix_database_postgresql.new_dsource", "update_name"), 39 | resource.TestCheckResourceAttr("delphix_database_postgresql.new_dsource", "name", "update_name")), 40 | }, 41 | }, 42 | }) 43 | } 44 | 45 | func testsourcePreCheck(t *testing.T, repo_value string, name string) { 46 | testAccPreCheck(t) 47 | if repo_value == "" { 48 | t.Fatal("REPOSITORY_VALUE must be set for env acceptance tests") 49 | } 50 | if name == "" { 51 | t.Fatal("SOURCE_NAME must be set for env acceptance tests") 52 | } 53 | } 54 | 55 | func testsourceBasic(repo_value string, name string) string { 56 | return fmt.Sprintf(` 57 | resource "delphix_database_postgresql" "new_dsource" { 58 | repository_value = "%s" 59 | name = "%s" 60 | tags { 61 | key = "dlpx" 62 | value = "acc-test" 63 | } 64 | } 65 | `, repo_value, name) 66 | } 67 | 68 | func testSourceDestroy(s *terraform.State) error { 69 | client := testAccProvider.Meta().(*apiClient).client 70 | 71 | for _, rs := range s.RootModule().Resources { 72 | if rs.Type != "delphix_database_postgresql" { 73 | continue 74 | } 75 | 76 | sourceId := rs.Primary.ID 77 | 78 | _, httpResp, _ := client.SourcesAPI.GetSourceById(context.Background(), sourceId).Execute() 79 | if httpResp == nil { 80 | return fmt.Errorf("Source has not been deleted") 81 | } 82 | 83 | if httpResp.StatusCode != 404 { 84 | return fmt.Errorf("Exepcted a 404 Not Found for a deleted Source but got %d", httpResp.StatusCode) 85 | } 86 | } 87 | 88 | return nil 89 | } 90 | 91 | func testsourceUpdate(repo_value string, name string) string { 92 | return fmt.Sprintf(` 93 | resource "delphix_database_postgresql" "new_dsource" { 94 | repository_value = "%s" 95 | name = "%s" 96 | tags { 97 | key = "dlpx" 98 | value = "acc-test" 99 | } 100 | } 101 | `, repo_value, name) 102 | } 103 | 104 | func testSourceExists(n string, name string) resource.TestCheckFunc { 105 | return func(s *terraform.State) error { 106 | rs, ok := s.RootModule().Resources[n] 107 | 108 | if !ok { 109 | return fmt.Errorf("Not found: %s", n) 110 | } 111 | 112 | sourceId := rs.Primary.ID 113 | if sourceId == "" { 114 | return fmt.Errorf("No sourceId set") 115 | } 116 | 117 | client := testAccProvider.Meta().(*apiClient).client 118 | res, _, err := client.SourcesAPI.GetSourceById(context.Background(), sourceId).Execute() 119 | if err != nil { 120 | return err 121 | } 122 | 123 | resSourceId := res.GetName() 124 | if resSourceId != name { 125 | return fmt.Errorf("SourceId mismatch") 126 | } 127 | 128 | return nil 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /examples/appdata_dsource/postgresql/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when creating an app data dsource. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | 21 | # resource "delphix_appdata_dsource" "test_app_data_dsource" { 22 | # source_value = "1-APPDATA_STAGED_SOURCE_CONFIG-6" 23 | # group_id = "1-GROUP-1" 24 | # log_sync_enabled = false 25 | # make_current_account_owner = true 26 | # link_type = "AppDataStaged" 27 | # name = "appdata_dsource" 28 | # staging_mount_base = "" 29 | # environment_user = "HOST_USER-2" 30 | # staging_environment = "1-UNIX_HOST_ENVIRONMENT-2" 31 | # parameters = jsonencode({ 32 | # externalBackup : [], 33 | # delphixInitiatedBackupFlag : true, 34 | # delphixInitiatedBackup : [ 35 | # { 36 | # userName : "XXXX", 37 | # postgresSourcePort : XXXX, 38 | # userPass : "XXXX", 39 | # sourceHostAddress : "HOSTNAME" 40 | # } 41 | # ], 42 | # singleDatabaseIngestionFlag : false, 43 | # singleDatabaseIngestion : [], 44 | # stagingPushFlag : false, 45 | # postgresPort : XXXX, 46 | # configSettingsStg : [], 47 | # mountLocation : "/tmp/delphix_mnt" 48 | # }) 49 | # sync_parameters = jsonencode({ 50 | # resync = true 51 | # }) 52 | # } 53 | 54 | resource "delphix_appdata_dsource" "test_app_data_dsource_second" { 55 | source_value = "1-APPDATA_STAGED_SOURCE_CONFIG-7" 56 | group_id = "1-GROUP-1" 57 | log_sync_enabled = false 58 | make_current_account_owner = true 59 | link_type = "AppDataStaged" 60 | name = "appdata_dsource_second" 61 | staging_mount_base = "" 62 | environment_user = "HOST_USER-2" 63 | staging_environment = "1-UNIX_HOST_ENVIRONMENT-2" 64 | parameters = jsonencode({ 65 | delphixInitiatedBackupFlag : true, 66 | delphixInitiatedBackup : [ 67 | { 68 | userName : "XXXX", 69 | postgresSourcePort : XXXX, 70 | userPass : "XXXX", 71 | sourceHostAddress : "HOSTNAME" 72 | } 73 | ], 74 | postgresPort : XXX, 75 | mountLocation : "/tmp/delphix_mnt_second" 76 | }) 77 | sync_parameters = jsonencode({ 78 | resync = true 79 | }) 80 | ops_pre_sync { 81 | name = "key-1" 82 | command = "echo \"hello world\"" 83 | shell = "shell" 84 | credentials_env_vars { 85 | base_var_name = "XXXX" 86 | password = "XXXX" 87 | } 88 | } 89 | ops_post_sync { 90 | name = "key-2" 91 | command = "echo \"hello world\"" 92 | shell = "shell" 93 | credentials_env_vars { 94 | base_var_name = "XXXX" 95 | password = "XXXX" 96 | } 97 | } 98 | } 99 | 100 | 101 | # Below are the 3 ways to link dsource with params , use any one of them 102 | # externalBackup: [ 103 | # { 104 | # keepStagingInSync: false, 105 | # backupPath: "/var/tmp/backup", 106 | # walLogPath: "/var/tmp/backup" 107 | # } 108 | # ] 109 | 110 | # singleDatabaseIngestion: [ 111 | # { 112 | # databaseUserName: "postgres", 113 | # sourcePort: 5432, 114 | # dumpJobs: 2, 115 | # restoreJobs: 2, 116 | # databaseName: "abcd", 117 | # databaseUserPassword: "xxxx", 118 | # dumpDir: "abcd", 119 | # sourceHost: "abcd", 120 | # postgresqlFile: "abcd" 121 | # } 122 | # ] 123 | 124 | # delphixInitiatedBackup : [ 125 | # { 126 | # userName : "XXXX", 127 | # postgresSourcePort : XXXX, 128 | # userPass : "XXXX", 129 | # sourceHostAddress : "HOSTNAME" 130 | # } 131 | # ] 132 | -------------------------------------------------------------------------------- /examples/vdb/oracle/bookmark/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning an Oracle database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | bookmark_id = "" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | os_username = "os-user-x" 25 | os_password = "os-password-x" 26 | vdb_restart = true 27 | environment_id = "oracle-env-name" 28 | environment_user_id = "environment_user_name" 29 | target_group_id = "group-123" 30 | open_reset_logs = true 31 | archive_log = true 32 | online_log_groups = 2 33 | snapshot_policy_id = "test_snapshot_policy" 34 | unique_name = "dbdhcp2" 35 | online_log_size = 4 36 | database_name = "dbname_to_be_created" 37 | mount_point = "/var/mnt" 38 | auto_select_repository = true 39 | custom_env_files = ["/export/home/env_file_1"] 40 | custom_env_vars = { 41 | MY_ENV_VAR1 = "$ORACLE_HOME" 42 | MY_ENV_VAR2 = "$CRS_HOME/after" 43 | } 44 | file_mapping_rules = "/datafile/dbdhcp3/oradata/dbdhcp3:/data\n/u03/app/ora11202/product/11.2.0/dbhome_1/dbs/dbv_R2V4.dbf:/data/dbv_R2V4.dbf" 45 | new_dbid = true 46 | cluster_node_ids = ["ORACLE_CLUSTER_NODE-ID"] 47 | auxiliary_template_id = "aux-template-1" 48 | instance_name = "dbdhcp2" 49 | retention_policy_id = "test_retention_policy" 50 | template_id = "template-1" 51 | repository_id = "" 52 | listener_ids = ["id1","id2"] 53 | cdb_id = "" 54 | vcdb_name = "" //(MT) 55 | vcdb_database_name = "" //(MT) 56 | target_vcdb_tde_keystore_path = "" //(MT) 57 | parent_tde_keystore_password = "" //(MT) 58 | cdb_tde_keystore_password = "" //(MT) 59 | tde_key_identifier = "" //(MT) 60 | vcdb_tde_key_identifier = "" //(MT) 61 | parent_tde_keystore_path = "" //(MT) 62 | tde_exported_key_file_secret = "" //(MT) 63 | oracle_rac_custom_env_vars = [{ 64 | node_id = "ORACLE_CLUSTER_NODE-1", 65 | name = "MY_ENV_VAR1", 66 | value = "$CRS_HOME/after" 67 | }] //(RAC) 68 | oracle_rac_custom_env_files = [ 69 | { 70 | node_id = "ORACLE_CLUSTER_NODE-1", 71 | path_parameters = "/export/home/env_file_1" 72 | }] //(RAC) 73 | config_params jsonencode({ 74 | processes = 150 75 | }) 76 | pre_start { 77 | name = "string" 78 | command = "string" 79 | shell = "bash" 80 | } 81 | pre_rollback { 82 | name = "string" 83 | command = "string" 84 | shell = "bash" 85 | } 86 | post_start { 87 | name = "string" 88 | command = "string" 89 | shell = "bash" 90 | } 91 | post_rollback { 92 | name = "string" 93 | command = "string" 94 | shell = "bash" 95 | } 96 | pre_stop { 97 | name = "string" 98 | command = "string" 99 | shell = "bash" 100 | } 101 | configure_clone { 102 | name = "string" 103 | command = "string" 104 | shell = "bash" 105 | } 106 | post_snapshot { 107 | name = "string" 108 | command = "string" 109 | shell = "bash" 110 | } 111 | pre_refresh { 112 | name = "string" 113 | command = "string" 114 | shell = "bash" 115 | } 116 | post_refresh { 117 | name = "string" 118 | command = "string" 119 | shell = "bash" 120 | } 121 | post_stop { 122 | name = "string" 123 | command = "string" 124 | shell = "bash" 125 | } 126 | pre_snapshot { 127 | name = "string" 128 | command = "string" 129 | shell = "bash" 130 | } 131 | tags { 132 | key = "key-1" 133 | value = "value-1" 134 | } 135 | make_current_account_owner = true 136 | } -------------------------------------------------------------------------------- /examples/vdb/oracle/snapshot/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning an Oracle database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | snapshot_id = "1-oracle-snapshot-id" 22 | name = "vdb_to_be_created" 23 | source_data_id = "dsource-name" 24 | engine_id = "1" 25 | os_username = "os-user-x" 26 | os_password = "os-password-x" 27 | vdb_restart = true 28 | environment_id = "oracle-env-name" 29 | environment_user_id = "environment_user_name" 30 | target_group_id = "group-123" 31 | auto_select_repository = true 32 | open_reset_logs = true 33 | archive_log = true 34 | online_log_groups = 2 35 | snapshot_policy_id = "test_snapshot_policy" 36 | unique_name = "dbdhcp2" 37 | online_log_size = 4 38 | custom_env_files = ["/export/home/env_file_1"] 39 | custom_env_vars = { 40 | MY_ENV_VAR1 = "$ORACLE_HOME" 41 | MY_ENV_VAR2 = "$CRS_HOME/after" 42 | } 43 | file_mapping_rules = "/datafile/dbdhcp3/oradata/dbdhcp3:/data\n/u03/app/ora11202/product/11.2.0/dbhome_1/dbs/dbv_R2V4.dbf:/data/dbv_R2V4.dbf" 44 | new_dbid = true 45 | cluster_node_ids = ["ORACLE_CLUSTER_NODE-ID"] 46 | auxiliary_template_id = "aux-template-1" 47 | database_name = "dbname_to_be_created" 48 | mount_point = "/var/mnt" 49 | instance_name = "dbdhcp2" 50 | retention_policy_id = "test_retention_policy" 51 | template_id = "template-1" 52 | cdb_id = "" 53 | listener_ids = ["id"] 54 | repository_id = " " 55 | vcdb_name = "" //(MT) 56 | vcdb_database_name = "" //(MT) 57 | target_vcdb_tde_keystore_path = "" //(MT) 58 | parent_tde_keystore_password = "" //(MT) 59 | cdb_tde_keystore_password = "" //(MT) 60 | tde_key_identifier = "" //(MT) 61 | vcdb_tde_key_identifier = "" //(MT) 62 | parentTdeKeystorePath = "" //(MT) 63 | tde_exported_key_file_secret = "" //(MT) 64 | oracle_rac_custom_env_vars = [{ 65 | node_id = "ORACLE_CLUSTER_NODE-1", 66 | name = "MY_ENV_VAR1", 67 | value = "$CRS_HOME/after" 68 | }] //(RAC) 69 | oracle_rac_custom_env_files = [ 70 | { 71 | node_id = "ORACLE_CLUSTER_NODE-1", 72 | path_parameters = "/export/home/env_file_1" 73 | }] //(RAC) 74 | 75 | config_params jsonencode({ 76 | processes = 150 77 | }) 78 | pre_start { 79 | name = "string" 80 | command = "string" 81 | shell = "bash" 82 | } 83 | pre_rollback { 84 | name = "string" 85 | command = "string" 86 | shell = "bash" 87 | } 88 | post_start { 89 | name = "string" 90 | command = "string" 91 | shell = "bash" 92 | } 93 | post_rollback { 94 | name = "string" 95 | command = "string" 96 | shell = "bash" 97 | } 98 | pre_stop { 99 | name = "string" 100 | command = "string" 101 | shell = "bash" 102 | } 103 | configure_clone { 104 | name = "string" 105 | command = "string" 106 | shell = "bash" 107 | } 108 | post_snapshot { 109 | name = "string" 110 | command = "string" 111 | shell = "bash" 112 | } 113 | pre_refresh { 114 | name = "string" 115 | command = "string" 116 | shell = "bash" 117 | } 118 | post_refresh { 119 | name = "string" 120 | command = "string" 121 | shell = "bash" 122 | } 123 | post_stop { 124 | name = "string" 125 | command = "string" 126 | shell = "bash" 127 | } 128 | pre_snapshot { 129 | name = "string" 130 | command = "string" 131 | shell = "bash" 132 | } 133 | tags { 134 | key = "key-1" 135 | value = "value-1" 136 | } 137 | make_current_account_owner = true 138 | } -------------------------------------------------------------------------------- /examples/vdb/oracle/timestamp/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases the properties available when provisioning an Oracle database from a DCT bookmark. 3 | */ 4 | 5 | terraform { 6 | required_providers { 7 | delphix = { 8 | version = "VERSION" 9 | source = "delphix-integrations/delphix" 10 | } 11 | } 12 | } 13 | 14 | provider "delphix" { 15 | tls_insecure_skip = true 16 | key = "1.XXXX" 17 | host = "HOSTNAME" 18 | } 19 | 20 | resource "delphix_vdb" "example" { 21 | timestamp = "" 22 | timestamp_in_database_timezone = "" 23 | name = "vdb_to_be_created" 24 | source_data_id = "dsource-name" 25 | engine_id = "1" 26 | os_username = "os-user-x" 27 | os_password = "os-password-x" 28 | vdb_restart = true 29 | environment_id = "oracle-env-name" 30 | environment_user_id = "environment_user_name" 31 | database_name = "dbname_to_be_created" 32 | mount_point = "/var/mnt" 33 | auto_select_repository = true 34 | target_group_id = "group-123" 35 | open_reset_logs = true 36 | archive_log = true 37 | online_log_groups = 2 38 | snapshot_policy_id = "test_snapshot_policy" 39 | unique_name = "dbdhcp2" 40 | online_log_size = 4 41 | custom_env_files = ["/export/home/env_file_1"] 42 | custom_env_vars = { 43 | MY_ENV_VAR1 = "$ORACLE_HOME" 44 | MY_ENV_VAR2 = "$CRS_HOME/after" 45 | } 46 | file_mapping_rules = "/datafile/dbdhcp3/oradata/dbdhcp3:/data\n/u03/app/ora11202/product/11.2.0/dbhome_1/dbs/dbv_R2V4.dbf:/data/dbv_R2V4.dbf" 47 | new_dbid = true 48 | auxiliary_template_id = "aux-template-1" 49 | instance_name = "dbdhcp2" 50 | retention_policy_id = "test_retention_policy" 51 | template_id = "template-1" 52 | listener_ids = ["id"] 53 | repository_id = "" 54 | cdb_id = "" 55 | vcdb_name = "" //(MT) 56 | vcdb_database_name = "" //(MT) 57 | target_vcdb_tde_keystore_path = "" //(MT) 58 | parent_tde_keystore_password = "" //(MT) 59 | cdb_tde_keystore_password = "" //(MT) 60 | tde_key_identifier = "" //(MT) 61 | vcdb_tde_key_identifier = "" //(MT) 62 | parentTdeKeystorePath = "" //(MT) 63 | tde_exported_key_file_secret = "" //(MT) 64 | oracle_rac_custom_env_vars = [{ 65 | node_id = "ORACLE_CLUSTER_NODE-1", 66 | name = "MY_ENV_VAR1", 67 | value = "$CRS_HOME/after" 68 | }] //(RAC) 69 | oracle_rac_custom_env_files = [ 70 | { 71 | node_id = "ORACLE_CLUSTER_NODE-1", 72 | path_parameters = "/export/home/env_file_1" 73 | }] //(RAC) 74 | config_params jsonencode({ 75 | processes = 150 76 | }) 77 | pre_start { 78 | name = "string" 79 | command = "string" 80 | shell = "bash" 81 | } 82 | pre_rollback { 83 | name = "string" 84 | command = "string" 85 | shell = "bash" 86 | } 87 | post_start { 88 | name = "string" 89 | command = "string" 90 | shell = "bash" 91 | } 92 | post_rollback { 93 | name = "string" 94 | command = "string" 95 | shell = "bash" 96 | } 97 | pre_stop { 98 | name = "string" 99 | command = "string" 100 | shell = "bash" 101 | } 102 | configure_clone { 103 | name = "string" 104 | command = "string" 105 | shell = "bash" 106 | } 107 | post_snapshot { 108 | name = "string" 109 | command = "string" 110 | shell = "bash" 111 | } 112 | pre_refresh { 113 | name = "string" 114 | command = "string" 115 | shell = "bash" 116 | } 117 | post_refresh { 118 | name = "string" 119 | command = "string" 120 | shell = "bash" 121 | } 122 | post_stop { 123 | name = "string" 124 | command = "string" 125 | shell = "bash" 126 | } 127 | pre_snapshot { 128 | name = "string" 129 | command = "string" 130 | shell = "bash" 131 | } 132 | tags { 133 | key = "key-1" 134 | value = "value-1" 135 | } 136 | make_current_account_owner = true 137 | } -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Delphix Provider 2 | 3 | The [Terraform Provider for Delphix](https://help.delphix.com/eh/current/content/terraform.htm) enables you to natively manage data-as-code along with your infrastructure. 4 | 5 | With Terraform and Delphix, you can now automatically provision, manage, and teardown any number of ephemeral data environments to drive enterprise DevOps workflows, such as test data management. 6 | 7 | The Delphix provider communicates directly with Data Control Tower (DCT) to generated virtual database and other objects. Therefore, DCT must be registered with one or more Delphix Continuous Data Engines. 8 | 9 | To learn more about Delphix and DCT APIs, refer to [Delphix Documentation](https://documentation.delphix.com/docs/) and [DCT Documentation](https://dct.delphix.com/docs/latest/). Please [submit a GitHub issue](https://github.com/delphix-integrations/terraform-provider-delphix/issues) if you have any questions. 10 | 11 | If you are a DCT customer, you can also request support from the [Delphix Support Portal](https://support.delphix.com/). 12 | 13 | ## System Requirements 14 | 15 | | Product | Version | 16 | |--------------------------------|----------| 17 | | Data Control Tower (DCT) | v2025.2.0+ | 18 | | Delphix Continuous Data Engine | v29.0.0.0+ | 19 | 20 | Note: The DCT and Continuous Data versions above guarantees full provider support. However, each resource might support older versions. Refer to the specific resource documentation page for more information. 21 | 22 | ## Release Notes 23 | 24 | The Delphix Provider's release notes can be found in the [Delphix Ecosystem Documentation](https://help.delphix.com/eh/current/Content/Ecoystem/Release_notes__Terraform_.htm). 25 | 26 | ## Connectivity and Authentication 27 | 28 | All communication is performed through HTTPS. The Delphix Provider uses DCT APIs to communicate with Delphix Continuous Data Engines. 29 | 30 | Authentication with DCT APIs is managed using API Keys. For generation of an API key, please refer to [DCT API Keys](https://dct.delphix.com/docs/latest/api-keys). For example: `apk 2.12345...` 31 | 32 | ## Example Usage 33 | 34 | The following script demonstrates how to configure the Delphix Provider to connect with Data Control Tower and then provision a VDB. Additional resource guides and documentation can be found on the left-hand side. 35 | 36 | ```hcl 37 | 38 | # Install the Delphix Provider 39 | terraform { 40 | required_providers { 41 | delphix = { 42 | source = "delphix-integrations/delphix" 43 | version = "4.1.0" 44 | } 45 | } 46 | } 47 | 48 | # Connect the Delphix Provider to DCT 49 | provider "delphix" { 50 | host = "" 51 | key = "" 52 | tls_insecure_skip = false 53 | } 54 | 55 | # Provision a VDB with the latest snapshot of data source 56 | resource "delphix_vdb" "vdb_name" { 57 | auto_select_repository = true 58 | source_data_id = "" 59 | } 60 | ``` 61 | 62 | ### Example Global Parameter Reference 63 | 64 | * __host__: The hostname for DCT. 65 | * __key__: The API Key which is used to authenticate with DCT. (Example `apk 2.abc123...`). 66 | * __tls_insecure_skip__: (Optional) A boolean value which determines whether to skip the SSL/TLS check. The default value is `false`. Skipping any SSL/TLS check is not recommended for production environments. 67 | * __host_scheme__: (Optional) Determines the configured host URL's scheme. The default value is `https`. 68 | 69 | Consult the Resources section for details on individual resources, such as VDB, dSource, and Environment. 70 | 71 | ## Support Matrix 72 | 73 | | Feature | Provider Version | DCT Version | 74 | |---------------------------------------------|------------------|-------------| 75 | | delphix_vdb | v 1.0.0 | v 2.0.0 | 76 | | delphix_vdb_group | v 1.0.0 | v 2.0.0 | 77 | | delphix_environment | v 1.0.0 | v 2.0.0 | 78 | | delphix_appdata_dsource | v 2.1.0 | v 10.0.0 | 79 | | delphix_oracle_dsource | v 3.1.0 | v 10.0.0 | 80 | | delphix_database_postgresql | v 3.2.0 | v 14.0.0 | 81 | | delphix_vdb update
delphix_database_postgresql import | v 3.3.0 | v 22.0.0 | 82 | | delphix_oracle_dsource update
delphix_oracle_dsource import | v 3.4.1 | v 2025.1.2 | 83 | | delphix_appdata_dsource update
delphix_appdata_dsource import | v 4.0.0 | v 2025.2.0 | 84 | | delphix_environment update
delphix_environment import | v 4.0.0 | v 2025.2.0 | 85 | | delphix_vdb_group tag management
delphix_vdb_group import | v 4.1.0 | v 2025.3.0 | -------------------------------------------------------------------------------- /examples/full_stack_deployment/main.tf: -------------------------------------------------------------------------------- 1 | /** 2 | * Summary: This template showcases a mock example to 3 | * 1) Provision an Azure VM. 4 | * 2) Create a Target environment from that VM. 5 | * 3) Link and Sync a dSource. Create a new snapshot. 6 | * 4) Provision a new VDB from that Oracle dSource's snapshot. 7 | * *** Warning: This is only an example. It will not work out of the box.*** 8 | */ 9 | 10 | terraform { 11 | required_providers { 12 | delphix = { 13 | version = ">=3.3.2" 14 | source = "delphix-integrations/delphix" 15 | } 16 | azurerm = { 17 | source = "hashicorp/azurerm" 18 | version = "~>3.0" 19 | } 20 | } 21 | } 22 | 23 | # *** Requirement***: Various variables used throughout the example. 24 | locals { 25 | dct-key = "<1.XXXX>" 26 | dct-host = "" 27 | vm-hostname = "oracle-linux-host" 28 | vm-username = "" 29 | vm-password = "" 30 | source-db-name = "" // Name of Database dynamically identified on the source environment 31 | dsource-name = "full_deploy_dsource" 32 | vdb-name = "full_deploy_vdb" 33 | } 34 | 35 | provider "delphix" { 36 | tls_insecure_skip = true 37 | key = local.dct-key 38 | host = loca.dct-host 39 | } 40 | 41 | 42 | # *** Requirement ***: This is an example only and will not work without significant modification and additional files. 43 | # See the official documentation here for a full VM deployment: https://learn.microsoft.com/en-us/azure/virtual-machines/linux/quick-create-terraform 44 | # The VM creation terraform resource can be replaced with an equivalent resource GCP, AWS, VMWare, etc that's compatible with Delphix Continuous Data. 45 | # Consult your organization's DevOps expert for guidance on how to provision a VM that's approved for your company. 46 | resource "azurerm_linux_virtual_machine" "azure_vm" { 47 | name = "Delphix Oracle Target" 48 | location = azurerm_resource_group.rg.location // Not provided 49 | resource_group_name = azurerm_resource_group.rg.name // Not provided 50 | network_interface_ids = [azurerm_network_interface.my_terraform_nic.id] // Not provided 51 | size = "Standard_DS1_v2" 52 | 53 | os_disk { 54 | name = "myOsDisk" 55 | caching = "ReadWrite" 56 | storage_account_type = "Premium_LRS" 57 | } 58 | 59 | source_image_reference { 60 | publisher = "Canonical" 61 | offer = "0001-com-ubuntu-server-jammy" 62 | sku = "22_04-lts-gen2" 63 | version = "latest" 64 | } 65 | 66 | computer_name = local.vm-hostname 67 | admin_username = local.vm-username 68 | admin_password = local.vm-password // Not secure. Example only 69 | 70 | boot_diagnostics { 71 | storage_account_uri = azurerm_storage_account.my_storage_account.primary_blob_endpoint // Not provided 72 | } 73 | } 74 | 75 | # Add the Azure VM as a Delphix environment. 76 | # Docs: https://registry.terraform.io/providers/delphix-integrations/delphix/latest/docs/resources/environment 77 | resource "delphix_environment" "linux-oracle-target" { 78 | name = local.vm-hostname 79 | os_name = "UNIX" 80 | hostname = local.vm-hostname 81 | username = local.vm-username 82 | password = local.vm-password 83 | engine_id = 1 84 | toolkit_path = "/home/delphix_os/toolkit" 85 | description = "This is a unix target for the Oracle VDB." 86 | } 87 | 88 | 89 | # If we were ingesting a PostgreSQL (or AppData) database, we would need to configure a Source Config (Source) 90 | # resource "delphix_database_postgresql" "postgresql_source_config" { 91 | # name = local.source-db-name + "source config" 92 | # repository_value = "PostgreSQL Repo" 93 | # engine_value = "1" 94 | # environment_value = local.vm-hostname 95 | # } 96 | 97 | # Link and Sync the dSource and take a new snapshot 98 | # *** Requirement *** This is an Oracle dSource. Updates are likely required. 99 | # Docs: https://registry.terraform.io/providers/delphix-integrations/delphix/latest/docs/resources/oracle_dsource 100 | resource "delphix_oracle_dsource" "full_oracle_dsource" { 101 | name = local.dsource-name 102 | source_value = local.source-db-name 103 | group_id = "full_deployment_group" 104 | environment_user_id = local.vm-username 105 | log_sync_enabled = false 106 | link_now = true 107 | make_current_account_owner = true 108 | } 109 | 110 | 111 | # Provision by Snapshot the 1 Oracle VDB on the newly created environment 112 | # Docs: https://registry.terraform.io/providers/delphix-integrations/delphix/latest/docs/resources/vdb 113 | resource "delphix_vdb" "vdb_provision_loop" { 114 | name = local.vdb-name 115 | source_data_id = local.dsource-name 116 | environment_id = local.vm-hostname 117 | auto_select_repository = true 118 | } 119 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023, 2024 by Delphix. All rights reserved. 3 | # 4 | # 5 | # 6 | # Copyright (c) 2023, 2024 by Delphix. All rights reserved. 7 | # 8 | # 9 | # For most projects, this workflow file will not need changing; you simply need 10 | # to commit it to your repository. 11 | # 12 | # You may wish to alter this file to override the set of languages analyzed, 13 | # or to provide custom queries or build logic. 14 | # 15 | # ******** NOTE ******** 16 | # We have attempted to detect the languages in your repository. Please check 17 | # the `language` matrix defined below to confirm you have the correct set of 18 | # supported CodeQL languages. 19 | # 20 | name: "CodeQL" 21 | 22 | on: 23 | push: 24 | branches: [ "main", "**/*", "dependabot/**/*", "dlpx/**/*", "gh-readonly-queue/**/*", "projects/**/*" ] 25 | pull_request: 26 | branches: [ "main", "**/*", "dependabot/**/*", "dlpx/**/*", "gh-readonly-queue/**/*", "projects/**/*" ] 27 | schedule: 28 | - cron: '30 11 * * 1' 29 | 30 | jobs: 31 | analyze: 32 | name: Analyze (${{ matrix.language }}) 33 | # Runner size impacts CodeQL analysis time. To learn more, please see: 34 | # - https://gh.io/recommended-hardware-resources-for-running-codeql 35 | # - https://gh.io/supported-runners-and-hardware-resources 36 | # - https://gh.io/using-larger-runners (GitHub.com only) 37 | # Consider using larger runners or machines with greater resources for possible analysis time improvements. 38 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} 39 | timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} 40 | permissions: 41 | # required for all workflows 42 | security-events: write 43 | 44 | # required to fetch internal or private CodeQL packs 45 | packages: read 46 | 47 | # only required for workflows in private repositories 48 | actions: read 49 | contents: read 50 | 51 | strategy: 52 | fail-fast: false 53 | matrix: 54 | include: 55 | - language: go 56 | build-mode: autobuild 57 | # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' 58 | # Use `c-cpp` to analyze code written in C, C++ or both 59 | # Use 'java-kotlin' to analyze code written in Java, Kotlin or both 60 | # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both 61 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, 62 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. 63 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how 64 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages 65 | steps: 66 | - name: Checkout repository 67 | uses: actions/checkout@v4 68 | 69 | # Initializes the CodeQL tools for scanning. 70 | - name: Initialize CodeQL 71 | uses: github/codeql-action/init@v3 72 | with: 73 | languages: ${{ matrix.language }} 74 | build-mode: ${{ matrix.build-mode }} 75 | # If you wish to specify custom queries, you can do so here or in a config file. 76 | # By default, queries listed here will override any specified in a config file. 77 | # Prefix the list here with "+" to use these queries and those in the config file. 78 | 79 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 80 | queries: security-extended,security-and-quality 81 | 82 | # If the analyze step fails for one of the languages you are analyzing with 83 | # "We were unable to automatically build your code", modify the matrix above 84 | # to set the build mode to "manual" for that language. Then modify this step 85 | # to build your code. 86 | # ℹ️ Command-line programs to run using the OS shell. 87 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 88 | - if: matrix.build-mode == 'manual' 89 | shell: bash 90 | run: | 91 | echo 'If you are using a "manual" build mode for one or more of the' \ 92 | 'languages you are analyzing, replace this with the commands to build' \ 93 | 'your code, for example:' 94 | echo ' make bootstrap' 95 | echo ' make release' 96 | exit 1 97 | - name: Perform CodeQL Analysis 98 | uses: github/codeql-action/analyze@v3 99 | with: 100 | category: "/language:${{matrix.language}}" 101 | -------------------------------------------------------------------------------- /examples/environment/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | delphix = { 4 | version = "1.0.0-beta" 5 | source = "delphix.com/dct/delphix" 6 | } 7 | } 8 | } 9 | 10 | provider "delphix" { 11 | tls_insecure_skip = true 12 | key = "xxx" 13 | host = "localhost" 14 | } 15 | 16 | /* Unix Standalone */ 17 | resource "delphix_environment" "unixtgt" { 18 | engine_id = 1 19 | os_type = "UNIX" 20 | username = "xxx" 21 | password = "xxx" 22 | hosts { 23 | hostname = "xxx" 24 | toolkit_path = "/home/delphix_os/toolkit" 25 | } 26 | name = "unixtgt" 27 | description = "This is a unix target." 28 | } 29 | 30 | /* Unix Standalone using Hashicorp vault 31 | resource "delphix_environment" "unixtgt" { 32 | engine_id = 1 33 | os_type = "UNIX" 34 | hosts { 35 | hostname = "xxx" 36 | } 37 | vault = "xxx" 38 | hashicorp_vault_engine = "xxx" 39 | hashicorp_vault_secret_path = "xxx" 40 | hashicorp_vault_username_key = "xxx" 41 | hashicorp_vault_secret_key = "xxx" 42 | toolkit_path = "/home/delphix_os/toolkit" 43 | name = "unixtgt" 44 | description = "This is a unix target." 45 | } */ 46 | 47 | /* Unix Standalone using CyberArk vault 48 | resource "delphix_environment" "unixtgt" { 49 | engine_id = 1 50 | os_type = "UNIX" 51 | hosts { 52 | hostname = "xxx" 53 | } 54 | vault = "xxx" 55 | cyberark_vault_query_string = "xxx" 56 | toolkit_path = "/home/delphix_os/toolkit" 57 | name = "unixtgt" 58 | description = "This is a unix target." 59 | } */ 60 | 61 | /* Win Standalone - Target*/ 62 | /* resource "delphix_environment" "wintgt" { 63 | engine_id = 2 64 | os_type = "WINDOWS" 65 | username = "xxx" 66 | password = "xxx" 67 | hosts { 68 | hostname = "xxx" 69 | ssh_port = 22 70 | } 71 | name = "wintgt" 72 | connector_port = 9100 73 | description = "This is a windows target." 74 | } */ 75 | 76 | /* Win Standalone - Source*/ 77 | /* resource "delphix_environment" "WindowsSrc" { 78 | engine_id = 2 79 | os_type = "WINDOWS" 80 | username = "xxx" 81 | password = "xxx" 82 | hosts { 83 | hostname = "xxx" 84 | } 85 | name = "WindowsSrc" 86 | staging_environment = delphix_environment.wintgt.id 87 | } */ 88 | 89 | 90 | /* Unix Standalone - All Params */ 91 | /* resource "delphix_environment" "env_name" { 92 | engine_id = 2 93 | os_type = "UNIX" 94 | username = "xxx" 95 | password = "xxx" 96 | hosts { 97 | hostname = "xxx" 98 | ssh_port = 22 99 | java_home = "/j/h" 100 | } 101 | toolkit_path = "/home/delphix" 102 | name = "Test" 103 | is_cluster = false 104 | cluster_home = "/home/ghrid" 105 | staging_environment = "stage" 106 | connector_port = 5312 107 | ase_db_password = "pass" 108 | ase_db_username = "user" 109 | dsp_keystore_alias = "alias" 110 | dsp_keystore_password = "pass" 111 | dsp_keystore_path = "path" 112 | dsp_truststore_password = "pass" 113 | dsp_truststore_path = "path" 114 | description = "desc" 115 | is_target = false 116 | } */ 117 | 118 | 119 | /* Win Cluster - Source*/ 120 | /* resource "delphix_environment" "winsrc-cluster" { 121 | engine_id = 2 122 | is_target = false 123 | os_type = "WINDOWS" 124 | username = "xxx" 125 | password = "xxx" 126 | hosts { 127 | hostname = "xxx" 128 | } 129 | name = "winsrc-cluster" 130 | staging_environment = delphix_environment.wintgt.id 131 | is_cluster = true 132 | } */ 133 | 134 | /* Unix Cluster */ 135 | /* resource "delphix_environment" "unixcluster" { 136 | engine_id = 2 137 | os_type = "UNIX" 138 | username = "xxx" 139 | password = "xxx" 140 | hosts { 141 | hostname = "xxx" 142 | } 143 | toolkit_path = "/work" 144 | name = "unixcluster" 145 | description = "This is a unix target." 146 | is_cluster = true 147 | cluster_home = "/u01/app/19.0.0.0/grid" 148 | } */ 149 | 150 | 151 | /* Windows Failover Cluster - Used as target */ 152 | /* resource "delphix_environment" "fc-cluster-0" { 153 | engine_id = 2 154 | os_type = "WINDOWS" 155 | username = "xxx" 156 | password = "xxx" 157 | hosts { 158 | hostname = "xxx" 159 | } 160 | name = "fc-cluster-0" 161 | connector_port = 9100 162 | description = "This is an FC cluster" 163 | } 164 | resource "delphix_environment" "fc-cluster-1" { 165 | engine_id = 2 166 | os_type = "WINDOWS" 167 | username = "xxx" 168 | password = "xxx" 169 | hosts { 170 | hostname = "xxx" 171 | } 172 | name = "fc-cluster-1" 173 | connector_port = 9100 174 | description = "This is an FC cluster." 175 | } 176 | 177 | resource "delphix_environment" "fc-tgt-cluster" { 178 | engine_id = 2 179 | is_target = true 180 | os_type = "WINDOWS" 181 | username = "xxx" 182 | password = "xxx" 183 | hosts { 184 | hostname = "xxx" 185 | } 186 | name = "fc-tgt-cluster" 187 | staging_environment = "2-WINDOWS_HOST_ENVIRONMENT-35" 188 | is_cluster = true 189 | } */ -------------------------------------------------------------------------------- /internal/provider/commons.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | const ( 4 | Pending string = "PENDING" 5 | Started string = "STARTED" 6 | Timedout string = "TIMEDOUT" 7 | Failed string = "FAILED" 8 | Completed string = "COMPLETED" 9 | Canceled string = "CANCELED" 10 | Abandoned string = "ABANDONED" 11 | JOB_STATUS_SLEEP_TIME int = 5 12 | STATUS_POLL_SLEEP_TIME int = 20 13 | DLPX string = "[DELPHIX] " 14 | INFO string = "[INFO] " 15 | WARN string = "[WARN] " 16 | ERROR string = "[ERROR] " 17 | ) 18 | 19 | var updatableVdbKeys = map[string]bool{ 20 | "name": true, 21 | "db_username": true, 22 | "db_password": true, 23 | "pre_refresh": true, 24 | "post_refresh": true, 25 | "configure_clone": true, 26 | "pre_snapshot": true, 27 | "post_snapshot": true, 28 | "pre_rollback": true, 29 | "post_rollback": true, 30 | "pre_start": true, 31 | "post_start": true, 32 | "pre_stop": true, 33 | "post_stop": true, 34 | "template_id": true, 35 | "pre_script": true, 36 | "post_script": true, 37 | "custom_env_vars": true, 38 | "custom_env_files": true, 39 | "appdata_source_params": true, 40 | "config_params": true, 41 | "cdb_tde_keystore_password": true, 42 | "target_vcdb_tde_keystore_path": true, 43 | "tde_key_identifier": true, 44 | "parent_tde_keystore_password": true, 45 | "parent_tde_keystore_path": true, 46 | "additional_mount_points": true, 47 | "cdc_on_provision": true, 48 | "environment_user_id": true, 49 | "listener_ids": true, 50 | "vdb_restart": true, 51 | "new_dbid": true, 52 | "mount_point": true, 53 | "tags": true, 54 | "database_name": true, 55 | "ignore_tag_changes": true, 56 | } 57 | 58 | var isDestructiveVdbUpdate = map[string]bool{ 59 | "name": false, 60 | "db_username": false, 61 | "db_password": false, 62 | "pre_refresh": false, 63 | "post_refresh": false, 64 | "configure_clone": false, 65 | "pre_snapshot": false, 66 | "post_snapshot": false, 67 | "pre_rollback": false, 68 | "post_rollback": false, 69 | "pre_start": false, 70 | "post_start": false, 71 | "pre_stop": false, 72 | "post_stop": false, 73 | "template_id": true, 74 | "pre_script": false, 75 | "post_script": false, 76 | "custom_env_vars": false, 77 | "custom_env_files": false, 78 | "appdata_source_params": true, 79 | "config_params": true, 80 | "cdb_tde_keystore_password": true, 81 | "target_vcdb_tde_keystore_path": true, 82 | "tde_key_identifier": true, 83 | "parent_tde_keystore_password": true, 84 | "parent_tde_keystore_path": true, 85 | "additional_mount_points": false, 86 | "cdc_on_provision": true, 87 | "environment_user_id": true, 88 | "listener_ids": false, 89 | "vdb_restart": false, 90 | "new_dbid": false, 91 | "mount_point": true, 92 | "tags": false, 93 | "ignore_tag_changes": false, 94 | } 95 | 96 | var updatableOracleDsourceKeys = map[string]bool{ 97 | "name": true, 98 | "environment_user_id": true, 99 | "backup_level_enabled": true, 100 | "rman_channels": true, 101 | "files_per_set": true, 102 | "check_logical": true, 103 | "encrypted_linking_enabled": true, 104 | "compressed_linking_enabled": true, 105 | "bandwidth_limit": true, 106 | "number_of_connections": true, 107 | "pre_provisioning_enabled": true, 108 | "diagnose_no_logging_faults": true, 109 | "external_file_path": true, 110 | "tags": true, 111 | "ops_pre_sync": true, 112 | "ops_pre_log_sync": true, 113 | "ops_post_sync": true, 114 | "ignore_tag_changes": true, 115 | "rollback_on_failure": true, 116 | } 117 | 118 | var updatableEnvKeys = map[string]bool{ 119 | "name": true, 120 | "cluster_home": true, 121 | "connector_port": true, 122 | "username": true, 123 | "password": true, 124 | "description": true, 125 | "tags": true, 126 | "hosts": true, 127 | "ignore_tag_changes": true, 128 | } 129 | 130 | var isDestructiveEnvUpdate = map[string]bool{ 131 | "name": false, 132 | "cluster_home": true, 133 | "connector_port": true, 134 | "username": true, 135 | "password": true, 136 | "description": false, 137 | "tags": false, 138 | "hosts": true, 139 | "ignore_tag_changes": false, 140 | } 141 | 142 | var updatableAppdataDsourceKeys = map[string]bool{ 143 | "name": true, 144 | "description": true, 145 | "staging_environment": true, 146 | "staging_environment_user": true, 147 | "environment_user": true, 148 | "parameters": true, 149 | "sync_policy_id": true, 150 | "retention_policy_id": true, 151 | "ops_pre_sync": true, 152 | "ops_post_sync": true, 153 | "tags": true, 154 | "ignore_tag_changes": true, 155 | "rollback_on_failure": true, 156 | } 157 | -------------------------------------------------------------------------------- /internal/provider/resource_oracle_dsource_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "testing" 9 | 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 12 | ) 13 | 14 | func TestOracleDsource_create_positive(t *testing.T) { 15 | sourcevalue := os.Getenv("ORACLE_DSOURCE_SOURCE_VALUE") 16 | groupId := os.Getenv("ORACLE_DSOURCE_GROUP_ID") 17 | name := os.Getenv("ORACLE_DSOURCE_NAME") 18 | 19 | resource.Test(t, resource.TestCase{ 20 | PreCheck: func() { 21 | testOracleDsourcePreCheck(t, sourcevalue, groupId, name) 22 | }, 23 | Providers: testAccProviders, 24 | CheckDestroy: testOracleDsourceDestroy, 25 | Steps: []resource.TestStep{ 26 | { 27 | Config: testOracleDsourceBasic(name, sourcevalue, groupId), 28 | Check: resource.ComposeTestCheckFunc( 29 | testOracleDsourceExists("delphix_oracle_dsource.test_oracle_dsource", sourcevalue), 30 | resource.TestCheckResourceAttr("delphix_oracle_dsource.test_oracle_dsource", "source_id", sourcevalue)), 31 | }, 32 | { 33 | // positive update test case 34 | Config: testOracleDsourceBasic("update_name", sourcevalue, groupId), // changing the name to update-name 35 | Check: resource.ComposeTestCheckFunc( 36 | testOracleDsourceExists("delphix_oracle_dsource.test_oracle_dsource", sourcevalue), 37 | resource.TestCheckResourceAttr("delphix_oracle_dsource.test_oracle_dsource", "name", "update_name"), // asserting the updated name 38 | resource.TestCheckResourceAttr("delphix_oracle_dsource.test_oracle_dsource", "group_id", groupId)), 39 | }, 40 | { 41 | // negative update test case 42 | Config: testOracleDsourceUpdateNegative(name, sourcevalue, "non-existent"), 43 | ExpectError: regexp.MustCompile("Error running apply: exit status 1"), 44 | }, 45 | { 46 | Config: testOracleDsourceBasic(name, "", groupId), 47 | ExpectError: regexp.MustCompile(`.*`), 48 | }, 49 | }, 50 | }) 51 | } 52 | 53 | func testOracleDsourcePreCheck(t *testing.T, sourceId string, groupId string, name string) { 54 | testAccPreCheck(t) 55 | if sourceId == "" { 56 | t.Fatal("ORACLE_DSOURCE_SOURCE_VALUE must be set for env acceptance tests") 57 | } 58 | if groupId == "" { 59 | t.Fatal("ORACLE_DSOURCE_GROUP_ID must be set for env acceptance tests") 60 | } 61 | if name == "" { 62 | t.Fatal("ORACLE_DSOURCE_NAME must be set for env acceptance tests") 63 | } 64 | } 65 | 66 | func testOracleDsourceBasic(name string, sourceValue string, groupId string) string { 67 | return fmt.Sprintf(` 68 | resource "delphix_oracle_dsource" "test_oracle_dsource" { 69 | name = "%s" 70 | source_value = "%s" 71 | group_id = "%s" 72 | tags { 73 | key = "dlpx" 74 | value = "acc-test" 75 | } 76 | ops_pre_sync { 77 | name = "string-change-opspresync22" 78 | command = "ls -lr" 79 | shell = "bash" 80 | credentials_env_vars { 81 | base_var_name = "mypass2t" 82 | password = "password_test" 83 | } 84 | credentials_env_vars { 85 | base_var_name = "mypass3t" 86 | password = "password_test" 87 | } 88 | } 89 | 90 | ops_post_sync { 91 | name = "string-change-opspostsync22" 92 | command = "ls -lrta" 93 | shell = "bash" 94 | credentials_env_vars { 95 | base_var_name = "mypassopspostsynct" 96 | password = "password_test" 97 | } 98 | } 99 | 100 | ops_pre_log_sync { 101 | name = "string-change-opsprelogsync22" 102 | command = "ls -lrt" 103 | shell = "shell" 104 | credentials_env_vars { 105 | base_var_name = "mypassopsprelogsynct" 106 | password = "password_test" 107 | } 108 | } 109 | } 110 | 111 | `, name, sourceValue, groupId) 112 | } 113 | 114 | func testOracleDsourceUpdateNegative(name string, sourceValue string, description string) string { 115 | return fmt.Sprintf(` 116 | resource "delphix_oracle_dsource" "test_oracle_dsource" { 117 | name = "%s" 118 | source_value = "%s" 119 | description = "%s" 120 | tags { 121 | key = "dlpx" 122 | value = "acc-test" 123 | } 124 | ops_pre_sync { 125 | name = "string-change-opspresync22" 126 | command = "ls -lr" 127 | shell = "bash" 128 | credentials_env_vars { 129 | base_var_name = "mypass2t" 130 | password = "password_test" 131 | } 132 | credentials_env_vars { 133 | base_var_name = "mypass3t" 134 | password = "password_test" 135 | } 136 | } 137 | 138 | ops_post_sync { 139 | name = "string-change-opspostsync22" 140 | command = "ls -lrta" 141 | shell = "bash" 142 | credentials_env_vars { 143 | base_var_name = "mypassopspostsynct" 144 | password = "password_test" 145 | } 146 | } 147 | 148 | ops_pre_log_sync { 149 | name = "string-change-opsprelogsync22" 150 | command = "ls -lrt" 151 | shell = "shell" 152 | credentials_env_vars { 153 | base_var_name = "mypassopsprelogsynct" 154 | password = "password_test" 155 | } 156 | } 157 | } 158 | `, name, sourceValue, description) 159 | } 160 | 161 | func testOracleDsourceExists(n string, sourceValue string) resource.TestCheckFunc { 162 | return func(s *terraform.State) error { 163 | rs, ok := s.RootModule().Resources[n] 164 | 165 | if !ok { 166 | return fmt.Errorf("Not found: %s", n) 167 | } 168 | 169 | dsourceId := rs.Primary.ID 170 | if dsourceId == "" { 171 | return fmt.Errorf("No dsourceId set") 172 | } 173 | 174 | client := testAccProvider.Meta().(*apiClient).client 175 | res, _, err := client.DSourcesAPI.GetDsourceById(context.Background(), dsourceId).Execute() 176 | if err != nil { 177 | return err 178 | } 179 | 180 | resSourceId := res.GetSourceId() 181 | if resSourceId != sourceValue { 182 | return fmt.Errorf("SourceId mismatch") 183 | } 184 | 185 | return nil 186 | } 187 | } 188 | 189 | func testOracleDsourceDestroy(s *terraform.State) error { 190 | client := testAccProvider.Meta().(*apiClient).client 191 | 192 | for _, rs := range s.RootModule().Resources { 193 | if rs.Type != "delphix_oracle_dsource" { 194 | continue 195 | } 196 | 197 | dsourceId := rs.Primary.ID 198 | 199 | _, httpResp, _ := client.DSourcesAPI.GetDsourceById(context.Background(), dsourceId).Execute() 200 | if httpResp == nil { 201 | return fmt.Errorf("Dsource has not been deleted") 202 | } 203 | 204 | if httpResp.StatusCode != 404 { 205 | return fmt.Errorf("Exepcted a 404 Not Found for a deleted Dsource but got %d", httpResp.StatusCode) 206 | } 207 | } 208 | 209 | return nil 210 | } 211 | -------------------------------------------------------------------------------- /examples/jenkins_integration/jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | environment { 5 | def provision_successful = false 6 | def vdb_id = "" 7 | def vdb_name = "" 8 | def DCT_HOSTNAME = "" 9 | def SOURCE_VDB = "" 10 | test_error = 'false' 11 | } 12 | 13 | stages { 14 | 15 | stage ('Build Application') { 16 | steps { 17 | echo ('Building...') 18 | sleep (50) 19 | } 20 | } 21 | 22 | stage ('Stand Up Full Application') { 23 | parallel { 24 | stage ('Apply Application Install') { 25 | steps{ 26 | echo ('Provisioning Test App...') 27 | sleep (30) 28 | } 29 | } 30 | stage ('Create Database w/ Terraform') { 31 | steps { 32 | script { 33 | echo ('Provisioning VDB...') 34 | git branch: 'main', changelog: false, poll: false, url: 'https://github.com/delphix-integrations/terraform-provider-delphix.git' 35 | // sh ('ls -R') 36 | sh ('terraform -chdir=examples/simple-provision init -upgrade') 37 | withCredentials([string(credentialsId: 'DCT_API_KEY', variable: 'KEY')]) { 38 | sh ('terraform -chdir=examples/simple-provision apply -var="source_data_id_1=$SOURCE_VDB" -var="dct_hostname=$DCT_HOSTNAME" -var="dct_api_key=$KEY" -auto-approve') 39 | } 40 | vdb_id = sh(script: 'terraform -chdir=examples/simple-provision output vdb_id_1', returnStdout: true) 41 | vdb_id = vdb_id.replaceAll('\\"', "").trim() 42 | vdb_name = sh(script: 'terraform -chdir=examples/simple-provision output vdb_name_1', returnStdout: true) 43 | echo ("vdb_id:" + vdb_id) 44 | echo ("vdb_name:" + vdb_name) 45 | provision_successful = true 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | stage ('Combine') { 53 | steps { 54 | echo ('Combining...') 55 | sleep (10) 56 | } 57 | } 58 | 59 | stage ('Run Tests') { 60 | parallel { 61 | stage ('UI') { 62 | stages { 63 | stage ('Run UI Tests') { 64 | steps{ 65 | echo ('UI Tests...') 66 | sleep (150) 67 | } 68 | } 69 | stage ('Send UI Test Results') { 70 | steps{ 71 | echo ('Send UI Test Results...') 72 | sleep (5) 73 | } 74 | } 75 | } 76 | } 77 | stage ('Unit') { 78 | stages { 79 | stage ('Run Unit Tests') { 80 | steps { 81 | script { 82 | echo ('Unit Tests...') 83 | sleep (70) 84 | catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { 85 | echo ('Identified 7 failing Unit Tests!') 86 | test_error = 'true'; 87 | sh "exit 1" 88 | } 89 | } 90 | } 91 | } 92 | stage ('Send Unit Test Results') { 93 | steps{ 94 | echo ('Send Unit Test Results...') 95 | sleep (6) 96 | } 97 | } 98 | } 99 | } 100 | stage ('Integ.') { 101 | stages { 102 | stage ('Run Integration Tests') { 103 | steps{ 104 | echo ('UI Tests...') 105 | sleep (130) 106 | } 107 | } 108 | stage ('Send Integration Test Results') { 109 | steps{ 110 | echo ('Send Integration Test Results...') 111 | sleep (4) 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | 119 | stage ('Bookmark Database') { 120 | when { 121 | equals expected: 'true', actual: test_error 122 | } 123 | steps{ 124 | script { 125 | echo ('Bookmark VDB... ') 126 | withCredentials([string(credentialsId: 'DCT_API_KEY', variable: 'KEY')]) { 127 | sh """ 128 | curl -X 'POST' -k \ 129 | 'https://$DCT_HOSTNAME/v3/bookmarks' \ 130 | -H 'accept: application/json' \ 131 | -H 'Authorization: apk ${KEY}' \ 132 | -H 'Content-Type: application/json' \ 133 | -d '{ 134 | "name": "JKNS-BOOKMARK-$BUILD_NUMBER", 135 | "vdb_ids": [ 136 | "${vdb_id}" 137 | ], 138 | "retain_forever": true, 139 | "make_current_account_owner": true 140 | }' 141 | """ 142 | } 143 | } 144 | } 145 | } 146 | 147 | stage ('Destroy Full Application') { 148 | parallel { 149 | stage ('Destroy Application') { 150 | steps { 151 | script { 152 | echo ('Destroying Application...') 153 | sleep (30) 154 | } 155 | } 156 | } 157 | stage ('Destroy Database w/ Terraform') { 158 | steps { 159 | script { 160 | if (provision_successful) { 161 | sleep (60) 162 | echo ('Destroying Test App and VDB...') 163 | withCredentials([string(credentialsId: 'DCT_API_KEY', variable: 'KEY')]) { 164 | sh ('terraform -chdir=examples/simple-provision destroy -var="source_data_id_1=$SOURCE_VDB" -var="dct_hostname=$DCT_HOSTNAME" -var="dct_api_key=$KEY" -auto-approve') 165 | } 166 | } else { 167 | echo ('No App or VDB to destroy...') 168 | } 169 | } 170 | } 171 | } 172 | } 173 | } 174 | } 175 | } -------------------------------------------------------------------------------- /internal/provider/resource_environment_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 13 | ) 14 | 15 | var env_name = "test-acc-name" 16 | 17 | func TestAccEnvironment_positive(t *testing.T) { 18 | engineId := os.Getenv("ACC_ENV_ENGINE_ID") 19 | username := os.Getenv("ACC_ENV_USERNAME") 20 | password := os.Getenv("ACC_ENV_PASSWORD") 21 | hostname := os.Getenv("ACC_ENV_HOSTNAME") 22 | toolkitPath := os.Getenv("ACC_ENV_TOOLKIT_PATH") 23 | 24 | resource.Test(t, resource.TestCase{ 25 | PreCheck: func() { testAccEnvPreCheck(t, engineId, username, password, hostname, toolkitPath) }, 26 | Providers: testAccProviders, 27 | CheckDestroy: testAccCheckEnvDestroy, 28 | Steps: []resource.TestStep{ 29 | { 30 | Config: testAccCheckDctEnvConfigBasic(engineId, username, password, hostname, toolkitPath), 31 | Check: resource.ComposeTestCheckFunc( 32 | testAccCheckDctEnvResourceExists("delphix_environment.new_env", engineId), 33 | resource.TestCheckResourceAttr("delphix_environment.new_env", "name", env_name)), 34 | }, 35 | }, 36 | }) 37 | } 38 | 39 | func TestAccEnvironment_update_positive(t *testing.T) { 40 | engineId := os.Getenv("ACC_ENV_ENGINE_ID") 41 | username := os.Getenv("ACC_ENV_USERNAME") 42 | password := os.Getenv("ACC_ENV_PASSWORD") 43 | hostname := os.Getenv("ACC_ENV_HOSTNAME") 44 | toolkitPath := os.Getenv("ACC_ENV_TOOLKIT_PATH") 45 | 46 | resource.Test(t, resource.TestCase{ 47 | PreCheck: func() { testAccEnvPreCheck(t, engineId, username, password, hostname, toolkitPath) }, 48 | Providers: testAccProviders, 49 | CheckDestroy: testAccCheckEnvDestroy, 50 | Steps: []resource.TestStep{ 51 | { 52 | Config: testAccCheckDctEnvConfigBasic(engineId, username, password, hostname, toolkitPath), 53 | Check: resource.ComposeTestCheckFunc( 54 | testAccCheckDctEnvResourceExists("delphix_environment.new_env", engineId), 55 | resource.TestCheckResourceAttr("delphix_environment.new_env", "name", env_name)), 56 | }, 57 | { 58 | // positive env update case 59 | Config: testAccEnvUpdatePositive(engineId, username, password, hostname, toolkitPath), 60 | Check: resource.ComposeTestCheckFunc( 61 | resource.TestCheckResourceAttr("delphix_environment.new_env", "name", "updated-name")), 62 | }, 63 | }, 64 | }) 65 | } 66 | 67 | func TestAccEnvironment_update_negative(t *testing.T) { 68 | engineId := os.Getenv("ACC_ENV_ENGINE_ID") 69 | username := os.Getenv("ACC_ENV_USERNAME") 70 | password := os.Getenv("ACC_ENV_PASSWORD") 71 | hostname := os.Getenv("ACC_ENV_HOSTNAME") 72 | toolkitPath := os.Getenv("ACC_ENV_TOOLKIT_PATH") 73 | 74 | resource.Test(t, resource.TestCase{ 75 | PreCheck: func() { testAccEnvPreCheck(t, engineId, username, password, hostname, toolkitPath) }, 76 | Providers: testAccProviders, 77 | CheckDestroy: testAccCheckEnvDestroy, 78 | Steps: []resource.TestStep{ 79 | { 80 | Config: testAccCheckDctEnvConfigBasic(engineId, username, password, hostname, toolkitPath), 81 | Check: resource.ComposeTestCheckFunc( 82 | testAccCheckDctEnvResourceExists("delphix_environment.new_env", engineId), 83 | resource.TestCheckResourceAttr("delphix_environment.new_env", "name", env_name)), 84 | }, 85 | { 86 | // negative update test case 87 | Config: testAccEnvUpdateNegative(engineId, username, password, "updated-hostname", toolkitPath), 88 | ExpectError: regexp.MustCompile("Error running apply: exit status 1"), 89 | }, 90 | }, 91 | }) 92 | } 93 | 94 | func testAccEnvPreCheck(t *testing.T, engineId string, username string, password string, hostname string, toolkitPath string) { 95 | testAccPreCheck(t) 96 | if engineId == "" { 97 | t.Fatal("ACC_ENV_ENGINE_ID must be set for env acceptance tests") 98 | } 99 | if username == "" { 100 | t.Fatal("ACC_ENV_USERNAME must be set for env acceptance tests") 101 | } 102 | if password == "" { 103 | t.Fatal("ACC_ENV_PASSWORD must be set for env acceptance tests") 104 | } 105 | if hostname == "" { 106 | t.Fatal("ACC_ENV_HOSTNAME must be set for env acceptance tests") 107 | } 108 | if toolkitPath == "" { 109 | t.Fatal("ACC_ENV_TOOLKIT_PATH must be set for env acceptance tests") 110 | } 111 | } 112 | 113 | func escape(s string) string { 114 | // Escape backslash or terraform interprets it as a special character 115 | return strings.ReplaceAll(s, "\\", "\\\\") 116 | } 117 | 118 | func testAccCheckDctEnvConfigBasic(engineId string, username string, password string, hostname string, toolkitPath string) string { 119 | return fmt.Sprintf(` 120 | resource "delphix_environment" "new_env" { 121 | engine_id = %s 122 | os_type = "UNIX" 123 | username = "%s" 124 | password = "%s" 125 | name = "%s" 126 | hosts { 127 | hostname = "%s" 128 | toolkit_path = "%s" 129 | } 130 | tags { 131 | key = "dlpx" 132 | value = "acc-test" 133 | } 134 | } 135 | `, engineId, escape(username), escape(password), env_name, escape(hostname), escape(toolkitPath)) 136 | } 137 | 138 | func testAccCheckDctEnvResourceExists(n string, engineId string) resource.TestCheckFunc { 139 | return func(s *terraform.State) error { 140 | rs, ok := s.RootModule().Resources[n] 141 | 142 | if !ok { 143 | return fmt.Errorf("Not found: %s", n) 144 | } 145 | 146 | EnvId := rs.Primary.ID 147 | if EnvId == "" { 148 | return fmt.Errorf("No EnvID set") 149 | } 150 | 151 | client := testAccProvider.Meta().(*apiClient).client 152 | res, _, err := client.EnvironmentsAPI.GetEnvironmentById(context.Background(), EnvId).Execute() 153 | if err != nil { 154 | return err 155 | } 156 | 157 | dctEngineId := res.GetEngineId() 158 | if dctEngineId != engineId { 159 | return fmt.Errorf("dctEngineId %s does not match provided engineID %s", dctEngineId, engineId) 160 | } 161 | 162 | return nil 163 | } 164 | } 165 | 166 | func testAccCheckEnvDestroy(s *terraform.State) error { 167 | client := testAccProvider.Meta().(*apiClient).client 168 | 169 | for _, rs := range s.RootModule().Resources { 170 | if rs.Type != "delphix_environment" { 171 | continue 172 | } 173 | 174 | EnvId := rs.Primary.ID 175 | 176 | _, httpResp, _ := client.EnvironmentsAPI.GetEnvironmentById(context.Background(), EnvId).Execute() 177 | if httpResp == nil { 178 | return fmt.Errorf("Environment has not been deleted") 179 | } 180 | 181 | if httpResp.StatusCode != 404 { 182 | return fmt.Errorf("Exepcted a 404 Not Found for a deleted Environment but got %d", httpResp.StatusCode) 183 | } 184 | } 185 | 186 | return nil 187 | } 188 | 189 | func testAccEnvUpdatePositive(engineId string, username string, password string, hostname string, toolkitPath string) string { 190 | return fmt.Sprintf(` 191 | resource "delphix_environment" "new_env" { 192 | engine_id = %s 193 | os_type = "UNIX" 194 | username = "%s" 195 | password = "%s" 196 | name = "updated-name" 197 | hosts { 198 | hostname = "%s" 199 | toolkit_path = "%s" 200 | } 201 | tags { 202 | key = "dlpx-changed" 203 | value = "acc-test-changed" 204 | } 205 | } 206 | `, engineId, escape(username), escape(password), escape(hostname), escape(toolkitPath)) 207 | } 208 | 209 | func testAccEnvUpdateNegative(engineId string, username string, password string, hostname string, toolkitPath string) string { 210 | return fmt.Sprintf(` 211 | resource "delphix_environment" "new_env" { 212 | engine_id = %s 213 | os_type = "UNIX" 214 | username = "%s" 215 | password = "%s" 216 | name = "%s" 217 | hosts { 218 | hostname = "%s" 219 | toolkit_path = "%s" 220 | } 221 | tags { 222 | key = "dlpx" 223 | value = "acc-test" 224 | } 225 | } 226 | `, engineId, escape(username), escape(password), env_name, escape(hostname), escape(toolkitPath)) 227 | } 228 | -------------------------------------------------------------------------------- /internal/provider/resource_appdata_dsource_test.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "regexp" 8 | "testing" 9 | 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" 12 | ) 13 | 14 | func Test_Acc_Appdata_Dsource(t *testing.T) { 15 | sourceId := os.Getenv("DSOURCE_SOURCE_ID") 16 | groupId := os.Getenv("DSOURCE_GROUP_ID") 17 | name := os.Getenv("DSOURCE_NAME") 18 | environmentUser := os.Getenv("DSOURCE_ENV_USER") 19 | stagingEnvironment := os.Getenv("DSOURCE_STAGE_ENV") 20 | parameters := os.Getenv("DSOURCE_PARAMETERS") 21 | 22 | resource.Test(t, resource.TestCase{ 23 | PreCheck: func() { 24 | testDsourcePreCheck(t, sourceId, groupId, name, environmentUser, stagingEnvironment, parameters) 25 | }, 26 | Providers: testAccProviders, 27 | CheckDestroy: testDsourceDestroy, 28 | Steps: []resource.TestStep{ 29 | { 30 | Config: testDsourceBasic(sourceId, groupId, false, false, name, environmentUser, stagingEnvironment, "", "dlpx", "acc-test"), 31 | ExpectError: regexp.MustCompile(`.*`), 32 | }, 33 | { 34 | Config: testDsourceBasic(sourceId, groupId, false, false, name, environmentUser, stagingEnvironment, parameters, "dlpx", "acc-test"), 35 | Check: resource.ComposeTestCheckFunc( 36 | testDsourceExists("delphix_appdata_dsource.new_data_dsource", sourceId), 37 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "source_id", sourceId)), 38 | }, 39 | { 40 | // positive update test case 41 | Config: testDsourceBasic(sourceId, groupId, false, false, "update_name", environmentUser, stagingEnvironment, parameters, "dlpx", "acc-test"), 42 | Check: resource.ComposeTestCheckFunc( 43 | testDsourceExists("delphix_appdata_dsource.new_data_dsource", sourceId), 44 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "name", "update_name"), 45 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "source_id", sourceId)), 46 | }, 47 | { 48 | // updating a tag and expecting no plan changes 49 | Config: testDsourceBasic(sourceId, groupId, false, false, "update_name", environmentUser, stagingEnvironment, parameters, "key1", "value1"), 50 | Check: resource.ComposeTestCheckFunc( 51 | testDsourceExists("delphix_appdata_dsource.new_data_dsource", sourceId), 52 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "source_id", sourceId), 53 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "tags.0.key", "key1"), 54 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "tags.0.value", "value1"), 55 | ), 56 | }, 57 | { 58 | // updating a tag and expecting plan changes 59 | Config: testDsourceBasic(sourceId, groupId, false, true, "update_name", environmentUser, stagingEnvironment, parameters, "key-upd", "value-upd"), 60 | Check: resource.ComposeTestCheckFunc( 61 | testDsourceExists("delphix_appdata_dsource.new_data_dsource", sourceId), 62 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "source_id", sourceId), 63 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "tags.0.key", "key1"), // since ignore_tag_changes is true, the key should not change 64 | resource.TestCheckResourceAttr("delphix_appdata_dsource.new_data_dsource", "tags.0.value", "value1"), // since ignore_tag_changes is true, the value should not change 65 | ), 66 | // PreConfig: func() { 67 | // fmt.Printf("[DEBUG] Applying configuration: %s", testDsourceBasic(sourceId, groupId, true, "update_name", environmentUser, stagingEnvironment, parameters, "key-upd", "value-upd")) 68 | // }, 69 | }, 70 | { 71 | // negative update test case, we are updating make_account_owner to true 72 | Config: testDsourceBasic(sourceId, groupId, true, false, name, environmentUser, stagingEnvironment, parameters, "dlpx", "acc-test"), 73 | ExpectError: regexp.MustCompile(`.*`), 74 | }, 75 | }, 76 | }) 77 | } 78 | 79 | // DEBUG: use this in check to see the resource state during test 80 | func checkState(n string) resource.TestCheckFunc { 81 | return func(s *terraform.State) error { 82 | rs, ok := s.RootModule().Resources[n] 83 | if !ok { 84 | return fmt.Errorf("Resource not found: %s", n) 85 | } 86 | 87 | fmt.Printf("[DEBUG] Current state for %s: %v\n", n, rs.Primary.Attributes) 88 | return nil 89 | } 90 | } 91 | 92 | func testDsourcePreCheck(t *testing.T, sourceId string, groupId string, name string, environmentUser string, stagingEnvironment string, parameters string) { 93 | testAccPreCheck(t) 94 | if sourceId == "" { 95 | t.Fatal("DSOURCE_SOURCE_ID must be set for env acceptance tests") 96 | } 97 | if groupId == "" { 98 | t.Fatal("DSOURCE_GROUP_ID must be set for env acceptance tests") 99 | } 100 | if name == "" { 101 | t.Fatal("DSOURCE_NAME must be set for env acceptance tests") 102 | } 103 | if environmentUser == "" { 104 | t.Fatal("DSOURCE_ENV_USER must be set for env acceptance tests") 105 | } 106 | if stagingEnvironment == "" { 107 | t.Fatal("DSOURCE_STAGE_ENV must be set for env acceptance tests") 108 | } 109 | if parameters == "" { 110 | t.Fatal("DSOURCE_PARAMETERS must be set for env acceptance tests") 111 | } 112 | } 113 | 114 | func testDsourceBasic(sourceId string, groupId string, make_current_account_owner bool, ignore_tag_changes bool, name string, environmentUser string, stagingEnvironment string, parameters string, key string, value string) string { 115 | return fmt.Sprintf(` 116 | resource "delphix_appdata_dsource" "new_data_dsource" { 117 | source_value = "%s" 118 | group_id = "%s" 119 | log_sync_enabled = false 120 | make_current_account_owner = "%v" 121 | link_type = "AppDataStaged" 122 | ignore_tag_changes = %v 123 | name = "%s" 124 | rollback_on_failure = true 125 | staging_mount_base = "" 126 | environment_user = "%s" 127 | staging_environment = "%s" 128 | parameters = jsonencode(%s) 129 | sync_parameters = jsonencode({ 130 | resync = true 131 | }) 132 | tags { 133 | key = "%s" 134 | value = "%s" 135 | } 136 | ops_pre_sync { 137 | name = "string-change-opspresync22" 138 | command = "ls -lr" 139 | shell = "bash" 140 | credentials_env_vars { 141 | base_var_name = "mypass2t" 142 | password = "password_test" 143 | } 144 | credentials_env_vars { 145 | base_var_name = "mypass3t" 146 | password = "password_test" 147 | } 148 | } 149 | 150 | ops_post_sync { 151 | name = "string-change-opspostsync22" 152 | command = "ls -lrta" 153 | shell = "bash" 154 | credentials_env_vars { 155 | base_var_name = "mypassopspostsynct" 156 | password = "password_test" 157 | } 158 | } 159 | } 160 | `, sourceId, groupId, make_current_account_owner, ignore_tag_changes, name, environmentUser, stagingEnvironment, parameters, key, value) 161 | } 162 | 163 | func testDsourceExists(n string, sourceId string) resource.TestCheckFunc { 164 | return func(s *terraform.State) error { 165 | rs, ok := s.RootModule().Resources[n] 166 | 167 | if !ok { 168 | return fmt.Errorf("Not found: %s", n) 169 | } 170 | 171 | dsourceId := rs.Primary.ID 172 | if dsourceId == "" { 173 | return fmt.Errorf("No dsourceId set") 174 | } 175 | 176 | client := testAccProvider.Meta().(*apiClient).client 177 | res, _, err := client.DSourcesAPI.GetDsourceById(context.Background(), dsourceId).Execute() 178 | if err != nil { 179 | return err 180 | } 181 | 182 | resSourceId := res.GetSourceId() 183 | if resSourceId != sourceId { 184 | return fmt.Errorf("SourceId mismatch") 185 | } 186 | 187 | return nil 188 | } 189 | } 190 | 191 | func testDsourceDestroy(s *terraform.State) error { 192 | client := testAccProvider.Meta().(*apiClient).client 193 | 194 | for _, rs := range s.RootModule().Resources { 195 | if rs.Type != "delphix_appdata_dsource" { 196 | continue 197 | } 198 | 199 | dsourceId := rs.Primary.ID 200 | 201 | _, httpResp, _ := client.DSourcesAPI.GetDsourceById(context.Background(), dsourceId).Execute() 202 | if httpResp == nil { 203 | return fmt.Errorf("Dsource has not been deleted") 204 | } 205 | 206 | if httpResp.StatusCode != 404 { 207 | return fmt.Errorf("Exepcted a 404 Not Found for a deleted Dsource but got %d", httpResp.StatusCode) 208 | } 209 | } 210 | 211 | return nil 212 | } 213 | -------------------------------------------------------------------------------- /docs/resources/environment.md: -------------------------------------------------------------------------------- 1 | # Resource: delphix_environment 2 | 3 | In Delphix, an environment is either a single instance host or a cluster of hosts that runs your databases. Environments can either be: 4 | - Source: where data originates. 5 | - Staging: where data is prepared for ingestion. . 6 | - Target: where data is delivered and used by developers and testers. 7 | - Note: Sometimes “Staging” is considered an intermediary environment which temporarily hosts a database for masking, subsetting, or synthetic data purposes. In virtualization, this is considered a Target environment. 8 | 9 | Each environment has unique properties and information depending on the operating system, installation, purpose, etc. 10 | The Delphix Environment resource (delphix_environment) in Terraform allows you to create, update, and delete Environments by enabling the apply, import, and destroy Terraform commands. Updating existing Delphix Environment resource parameters via the apply command is supported for the parameters specified below. 11 | 12 | Note: In DCT, environment are frequently referred to as Infrastructure Connections. 13 | 14 | ## Example Usage 15 | 16 | ### Create UNIX standalone environment 17 | ```hcl 18 | resource "delphix_environment" "unix_env_name" { 19 | engine_id = 2 20 | os_type = "UNIX" 21 | name = "my-env" 22 | username = "xxx" 23 | password = "xxx" 24 | hosts { 25 | hostname = "db.host.com" 26 | toolkit_path = "/home/delphix" 27 | ssh_port = 22 28 | java_home = "/java/home" 29 | } 30 | is_cluster = false 31 | cluster_home = "/home/ghrid" 32 | staging_environment = "stage" 33 | connector_port = 5312 34 | ase_db_password = "test" 35 | ase_db_username = "user-123" 36 | dsp_keystore_alias = "alias" 37 | dsp_keystore_password = "pass" 38 | dsp_keystore_path = "path" 39 | dsp_truststore_password = "pass" 40 | dsp_truststore_path = "/work" 41 | description = "desc" 42 | is_target = false 43 | } 44 | ``` 45 | 46 | ### Creating a WINDOWS standalone target environment 47 | ```hcl 48 | resource "delphix_environment" "win_tgt" { 49 | engine_id = 2 50 | os_type = "WINDOWS" 51 | name = "wintgt" 52 | description = "This is a windows target." 53 | username = "xxx" 54 | password = "xxx" 55 | hosts { 56 | hostname = "xxx" 57 | ssh_port = 22 58 | } 59 | connector_port = 9100 60 | } 61 | ``` 62 | ### Creating a WINDOWS standalone source environment 63 | ```hcl 64 | resource "delphix_environment" "win_standalone" { 65 | engine_id = 2 66 | os_type = "WINDOWS" 67 | name = "WindowsSrc" 68 | username = "xxx" 69 | password = "xxx" 70 | hosts { 71 | hostname = "db.host.com" 72 | } 73 | staging_environment = delphix_environment.wintgt.id 74 | } 75 | ``` 76 | 77 | ## Argument Reference 78 | 79 | ### General Linking Requirements 80 | * `name` - The name of the environment. [Updatable] 81 | * `description` - The environment description. [Updatable] 82 | * `os_type` - (Required) Operating system type of the environment. Valid values are [UNIX, WINDOWS] 83 | * `engine_id` - (Required) The ID of the Engine on which to create the environment. The ID can be obtained by querying the DCT Engines API. A Delphix Engine must be registered with DCT first for it to create an Engine ID. 84 | * `is_cluster` - Whether the environment to be created is a cluster. 85 | * `cluster_home` - Absolute path to cluster home directory. This parameter is (Required) for UNIX cluster environments. [Updatable] 86 | * `staging_environment` - ID of the environment where Delphix (Windows) Connector is installed. This is a required parameter when creating Windows source environments. 87 | * `connector_port` - The port on which Delphix connector will run. This is a (Required) parameter when creating Windows target environments. [Updatable] 88 | * `is_target` - Indicates whether the environment to be created is a target cluster environment. This property is used only when creating Windows cluster environments. 89 | 90 | ### Host Arguments 91 | * `hostname` - (Required) Host Name or IP Address of the host that being added to Delphix. [Updatable] 92 | * `ssh_port` - ssh port of the environment. [Updatable] 93 | * `toolkit_path` - The path where the Delphix Toolkit can be placed. [Updatable] 94 | * `oracle_tde_keystores_root_path` - The path to the root of the Oracle TDE keystores artifact directories. [Updatable] 95 | * `java_home` - The path to the user managed Java Development Kit (JDK). If not specified, then the OpenJDK will be used. [Updatable] 96 | * `nfs_addresses` - Array of IP address or hostnames. Valid values are a list of addresses. For eg: ["192.168.10.2"] [Updatable] 97 | 98 | ### General Authentication Arguments 99 | * `dsp_keystore_path` - DSP keystore path. 100 | * `dsp_keystore_password` - DSP keystore password. 101 | * `dsp_keystore_alias` - DSP keystore alias. 102 | * `dsp_truststore_path` - DSP truststore path. 103 | * `dsp_truststore_password` - DSP truststore password. 104 | * `use_engine_public_key` - Indicates whether to use public key authentication. 105 | 106 | ### SQL Server Authentication Arguments 107 | * `username` - OS username to enable a connection from the engine. [Updatable] 108 | * `password` - OS user's password. [Updatable] 109 | * `vault` - The name or reference of the vault from which to read the host credentials. 110 | * `hashicorp_vault_engine` – The Hashicorp Vault engine name where the credential is stored. 111 | * `hashicorp_vault_secret_path` - Path in the Hashicorp Vault engine where the credential is stored. 112 | * `hashicorp_vault_username_key` - Key for the username in the key-value store. 113 | * `hashicorp_vault_secret_key` - Key for the password in the key-value store. 114 | * `cyberark_vault_query_string` - Query to find a credential in the CyberArk vault. 115 | * `use_kerberos_authentication` - Indicates whether to use Kerberos authentication. 116 | 117 | ### SAP ASE (Sybase) Authentication Arguments 118 | * `ase_db_username` - Username for the SAP ASE database. 119 | * `ase_db_password` - Password for the SAP ASE database. 120 | * `ase_db_vault` - The name or reference of the vault from which to read the SAP ASE database credentials. 121 | * `ase_db_hashicorp_vault_engine` – The Hashicorp Vault engine name where the credential is stored. 122 | * `ase_db_hashicorp_vault_secret_path` - Path in the Hashicorp Vault engine where the credential is stored. 123 | * `ase_db_hashicorp_vault_username_key` - Key for the username in the key-value store. 124 | * `ase_db_hashicorp_vault_secret_key` - Key for the password in the key-value store. 125 | * `ase_db_cyberark_vault_query_string` - Query to find a credential in the CyberArk vault. 126 | * `ase_db_use_kerberos_authentication` - Whether to use Kerberos authentication for SAP ASE DB discovery. 127 | 128 | ### Advanced Arguments 129 | * `tags` - The tags to be created for this environment. This is a map of two parameters: [Updatable] 130 | * `key` - (Required) Key of the tag 131 | * `value` - (Required) Value of the tag 132 | * `ignore_tag_changes` – This flag enables whether changes in the tags are identified by Terraform. By default, this is set to true, meaning changes to the resource's tags are ignored. 133 | 134 | ## Import 135 | Use the import block to add Environments created directly in DCT into a Terraform state file. 136 | 137 | For example: 138 | ```hcl 139 | import { 140 | to = delphix_environment.env_import_demo 141 | id = "env_id" 142 | } 143 | ``` 144 | 145 | ## Limitations 146 | Not all properties are supported through the update command. Properties that are not supported by the update command are presented via an error message at runtime. 147 | 148 | ## Appendix 149 | Here are some additional examples: 150 | 151 | ### Create UNIX cluster 152 | ```hcl 153 | resource "delphix_environment" "unix_cluster" { 154 | engine_id = 2 155 | os_type = "UNIX" 156 | name = "unixcluster" 157 | description = "This is a unix target." 158 | username = "xxx" 159 | password = "xxx" 160 | hosts { 161 | hostname = "db.host.com" 162 | toolkit_path = "/home/delphix" 163 | } 164 | is_cluster = true 165 | cluster_home = "/u01/app/19.0.0.0/grid" 166 | } 167 | ``` 168 | 169 | ### Creating UNIX standalone target environment using HashiCorp Vault 170 | ```hcl 171 | resource "delphix_environment" "unix_with_hashi_vault" { 172 | engine_id = 2 173 | os_type = "UNIX" 174 | name = "unixtgt" 175 | hosts { 176 | hostname = "xxx" 177 | toolkit_path = "/home/delphix" 178 | } 179 | vault = "vault-name" 180 | hashicorp_vault_engine = "xxx" 181 | hashicorp_vault_secret_path = "xxx" 182 | hashicorp_vault_username_key = "xxx" 183 | hashicorp_vault_secret_key = "xxx" 184 | 185 | description = "This is unix target." 186 | } 187 | ``` 188 | 189 | ### Creating UNIX standalone target environment using CyberArk Vault 190 | ```hcl 191 | resource "delphix_environment" "unix_with_ca_vault" { 192 | engine_id = 2 193 | os_type = "UNIX" 194 | name = "unixtgt" 195 | description = "This is unix target." 196 | hosts { 197 | hostname = "xxx" 198 | toolkit_path = "/home/delphix" 199 | } 200 | vault = "vault-name" 201 | cyberark_query_string = "xxx" 202 | } 203 | ``` 204 | 205 | ### Creating a WINDOWS cluster source environment 206 | ```hcl 207 | resource "delphix_environment" "winsrc_cluster" { 208 | engine_id = 2 209 | is_target = false 210 | os_type = "WINDOWS" 211 | name = "winsrc-cluster" 212 | username = "xxx" 213 | password = "xxx" 214 | hosts { 215 | hostname = "xxx" 216 | } 217 | staging_environment = delphix_environment.wintgt.id 218 | is_cluster = true 219 | } 220 | ``` 221 | 222 | ### Creating a WINDOWS failover cluster that can be used as target 223 | ```hcl 224 | resource "delphix_environment" "win_fc_cluster_0" { 225 | engine_id = 2 226 | os_type = "WINDOWS" 227 | name = "fc-cluster-0" 228 | description = "This is an FC cluster" 229 | username = "xxx" 230 | password = "xxx" 231 | hosts { 232 | hostname = "xxx" 233 | } 234 | connector_port = 9100 235 | } 236 | resource "delphix_environment" "win_fc_cluster_1" { 237 | engine_id = 2 238 | os_type = "WINDOWS" 239 | name = "fc-cluster-1" 240 | description = "This is an FC cluster." 241 | username = "xxx" 242 | password = "xxx" 243 | hosts { 244 | hostname = "xxx" 245 | } 246 | connector_port = 9100 247 | } 248 | resource "delphix_environment" "win_fc_tgt_cluster" { 249 | engine_id = 2 250 | is_target = true 251 | os_type = "WINDOWS" 252 | name = "fc-tgt-cluster" 253 | username = "xxx" 254 | password = "xxx" 255 | hosts { 256 | hostname = "db.host.com" 257 | } 258 | staging_environment = delphix_environment.fc-cluster-1.id 259 | is_cluster = true 260 | } 261 | ``` 262 | -------------------------------------------------------------------------------- /internal/provider/resource_database_postgresql.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "strings" 7 | 8 | dctapi "github.com/delphix/dct-sdk-go/v25" 9 | "github.com/hashicorp/terraform-plugin-log/tflog" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 12 | ) 13 | 14 | func resourceSource() *schema.Resource { 15 | return &schema.Resource{ 16 | // This description is used by the documentation generator and the language server. 17 | Description: "Resource for Source creation.", 18 | 19 | CreateContext: resourceDatabasePostgressqlCreate, 20 | ReadContext: resourceDatabasePostgressqlRead, 21 | UpdateContext: resourceDatabasePostgressqlUpdate, 22 | DeleteContext: resourceDatabasePostgressqlDelete, 23 | 24 | Schema: map[string]*schema.Schema{ 25 | "name": { 26 | Type: schema.TypeString, 27 | Required: true, 28 | }, 29 | "repository_value": { 30 | Type: schema.TypeString, 31 | Required: true, 32 | }, 33 | "environment_value": { 34 | Type: schema.TypeString, 35 | Optional: true, 36 | }, 37 | "engine_value": { 38 | Type: schema.TypeString, 39 | Optional: true, 40 | }, 41 | 42 | // Output 43 | "id": { 44 | Type: schema.TypeString, 45 | Computed: true, 46 | }, 47 | "environment_id": { 48 | Type: schema.TypeString, 49 | Computed: true, 50 | }, 51 | "database_type": { 52 | Type: schema.TypeString, 53 | Computed: true, 54 | }, 55 | "namespace_id": { 56 | Type: schema.TypeString, 57 | Computed: true, 58 | }, 59 | "namespace_name": { 60 | Type: schema.TypeString, 61 | Computed: true, 62 | }, 63 | "is_replica": { 64 | Type: schema.TypeBool, 65 | Computed: true, 66 | }, 67 | "database_version": { 68 | Type: schema.TypeString, 69 | Computed: true, 70 | }, 71 | "ip_address": { 72 | Type: schema.TypeString, 73 | Computed: true, 74 | }, 75 | "data_uuid": { 76 | Type: schema.TypeString, 77 | Computed: true, 78 | }, 79 | "fqdn": { 80 | Type: schema.TypeString, 81 | Computed: true, 82 | }, 83 | "size": { 84 | Type: schema.TypeInt, 85 | Computed: true, 86 | }, 87 | "jdbc_connection_string": { 88 | Type: schema.TypeString, 89 | Computed: true, 90 | }, 91 | "plugin_version": { 92 | Type: schema.TypeString, 93 | Computed: true, 94 | }, 95 | "toolkit_id": { 96 | Type: schema.TypeString, 97 | Computed: true, 98 | }, 99 | "is_dsource": { 100 | Type: schema.TypeBool, 101 | Computed: true, 102 | }, 103 | "repository": { 104 | Type: schema.TypeString, 105 | Computed: true, 106 | }, 107 | "appdata_source_type": { 108 | Type: schema.TypeString, 109 | Computed: true, 110 | }, 111 | "tags": { 112 | Type: schema.TypeList, 113 | Optional: true, 114 | Computed: true, 115 | Elem: &schema.Resource{ 116 | Schema: map[string]*schema.Schema{ 117 | "key": { 118 | Type: schema.TypeString, 119 | Optional: true, 120 | }, 121 | "value": { 122 | Type: schema.TypeString, 123 | Optional: true, 124 | }, 125 | }, 126 | }, 127 | }, 128 | }, 129 | Importer: &schema.ResourceImporter{ 130 | StateContext: schema.ImportStatePassthroughContext, 131 | }, 132 | } 133 | } 134 | 135 | func resourceDatabasePostgressqlCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 136 | var diags diag.Diagnostics 137 | client := meta.(*apiClient).client 138 | 139 | sourceCreateParameters := dctapi.NewPostgresSourceCreateParametersWithDefaults() 140 | 141 | if v, has_v := d.GetOk("name"); has_v { 142 | sourceCreateParameters.SetName(v.(string)) 143 | } 144 | if v, has_v := d.GetOk("repository_value"); has_v { 145 | sourceCreateParameters.SetRepositoryId(v.(string)) 146 | } 147 | if v, has_v := d.GetOk("environment_value"); has_v { 148 | sourceCreateParameters.SetEnvironmentId(v.(string)) 149 | } 150 | if v, has_v := d.GetOk("engine_value"); has_v { 151 | sourceCreateParameters.SetEngineId(v.(string)) 152 | } 153 | 154 | req := client.SourcesAPI.CreatePostgresSource(ctx) 155 | 156 | apiRes, httpRes, err := req.PostgresSourceCreateParameters(*sourceCreateParameters).Execute() 157 | if diags := apiErrorResponseHelper(ctx, apiRes, httpRes, err); diags != nil { 158 | return diags 159 | } 160 | 161 | d.SetId(apiRes.GetSourceId()) 162 | 163 | job_res, job_err := PollJobStatus(apiRes.Job.GetId(), ctx, client) 164 | if job_err != "" { 165 | tflog.Error(ctx, DLPX+ERROR+"Job Polling failed but continuing with Source creation. Error: "+job_err) 166 | } 167 | 168 | tflog.Info(ctx, DLPX+INFO+"Job result is "+job_res) 169 | 170 | if job_res == Failed || job_res == Canceled || job_res == Abandoned { 171 | d.SetId("") 172 | tflog.Error(ctx, DLPX+ERROR+"Job "+job_res+" "+apiRes.Job.GetId()) 173 | return diag.Errorf("[NOT OK] Job %s %s with error %s", apiRes.Job.GetId(), job_res, job_err) 174 | } 175 | 176 | readDiags := resourceDatabasePostgressqlRead(ctx, d, meta) 177 | 178 | if readDiags.HasError() { 179 | return readDiags 180 | } 181 | 182 | return diags 183 | } 184 | 185 | func resourceDatabasePostgressqlRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 186 | client := meta.(*apiClient).client 187 | 188 | source_id := d.Id() 189 | 190 | res, diags := PollForObjectExistence(ctx, func() (interface{}, *http.Response, error) { 191 | return client.SourcesAPI.GetSourceById(ctx, source_id).Execute() 192 | }) 193 | 194 | if res == nil { 195 | tflog.Error(ctx, DLPX+ERROR+"PostgreSQL source not found: "+source_id+", removing from state. ") 196 | d.SetId("") 197 | return nil 198 | } 199 | 200 | if diags != nil { 201 | _, diags := PollForObjectDeletion(ctx, func() (interface{}, *http.Response, error) { 202 | return client.SourcesAPI.GetSourceById(ctx, source_id).Execute() 203 | }) 204 | // This would imply error in poll for deletion so we just log and exit. 205 | if diags != nil { 206 | tflog.Error(ctx, DLPX+ERROR+"Error in polling of source for deletion.") 207 | } else { 208 | // diags will be nill in case of successful poll for deletion logic aka 404 209 | tflog.Error(ctx, DLPX+ERROR+"Error reading the source "+source_id+", removing from state.") 210 | d.SetId("") 211 | } 212 | 213 | return nil 214 | } 215 | 216 | result, ok := res.(*dctapi.Source) 217 | if !ok { 218 | return diag.Errorf("Error occured in type casting.") 219 | } 220 | 221 | repository_value := d.Get("repository_value").(string) 222 | 223 | if repository_value == "" { 224 | resEnv, httpRes, err := client.EnvironmentsAPI.GetEnvironmentById(ctx, result.GetEnvironmentId()).Execute() 225 | 226 | if diags := apiErrorResponseHelper(ctx, resEnv, httpRes, err); diags != nil { 227 | return diags 228 | } 229 | if result.GetRepository() != "" { 230 | for _, repo := range resEnv.Repositories { 231 | if strings.EqualFold(repo.GetId(), result.GetRepository()) { 232 | repository_value = repo.GetName() 233 | } 234 | } 235 | } 236 | } 237 | 238 | d.Set("id", result.GetId()) 239 | d.Set("repository_value", repository_value) 240 | d.Set("environment_id", result.GetEnvironmentId()) 241 | d.Set("database_type", result.GetDatabaseType()) 242 | d.Set("name", result.GetName()) 243 | d.Set("is_replica", result.GetIsReplica()) 244 | d.Set("namespace_id", result.GetNamespaceId()) 245 | d.Set("namespace_name", result.GetNamespaceName()) 246 | d.Set("database_version", result.GetDatabaseVersion()) 247 | d.Set("ip_address", result.GetIpAddress()) 248 | d.Set("data_uuid", result.GetDataUuid()) 249 | d.Set("fqdn", result.GetFqdn()) 250 | d.Set("size", result.GetSize()) 251 | d.Set("jdbc_connection_string", result.GetJdbcConnectionString()) 252 | d.Set("plugin_version", result.GetPluginVersion()) 253 | d.Set("toolkit_id", result.GetToolkitId()) 254 | d.Set("is_dsource", result.GetIsDsource()) 255 | d.Set("repository", result.GetRepository()) 256 | d.Set("appdata_source_type", result.GetAppdataSourceType()) 257 | 258 | return diags 259 | } 260 | 261 | func resourceDatabasePostgressqlUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 262 | 263 | var diags diag.Diagnostics 264 | client := meta.(*apiClient).client 265 | updateSourceParam := dctapi.NewPostgresSourceUpdateParameters() 266 | 267 | // get the changed keys 268 | changedKeys := make([]string, 0, len(d.State().Attributes)) 269 | for k := range d.State().Attributes { 270 | if d.HasChange(k) { 271 | changedKeys = append(changedKeys, k) 272 | } 273 | } 274 | 275 | if d.HasChanges( 276 | "repository_value", 277 | "environment_value", 278 | "engine_value") { 279 | 280 | // revert and set the old value to the changed keys 281 | for _, key := range changedKeys { 282 | old, _ := d.GetChange(key) 283 | d.Set(key, old) 284 | } 285 | 286 | return diag.Errorf("cannot update one (or more) of the options changed. Please refer to provider documentation for updatable params.") 287 | } 288 | 289 | if d.HasChange("name") { 290 | updateSourceParam.SetName(d.Get("name").(string)) 291 | } 292 | 293 | res, httpRes, err := client.SourcesAPI.UpdatePostgresSourceById(ctx, d.Get("id").(string)).PostgresSourceUpdateParameters(*updateSourceParam).Execute() 294 | 295 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 296 | // revert and set the old value to the changed keys 297 | for _, key := range changedKeys { 298 | old, _ := d.GetChange(key) 299 | d.Set(key, old) 300 | } 301 | return diags 302 | } 303 | 304 | job_status, job_err := PollJobStatus(res.Job.GetId(), ctx, client) 305 | if job_err != "" { 306 | tflog.Warn(ctx, DLPX+WARN+"Source Update Job Polling failed but continuing with update. Error :"+job_err) 307 | } 308 | tflog.Info(ctx, DLPX+INFO+"Job result is "+job_status) 309 | if isJobTerminalFailure(job_status) { 310 | return diag.Errorf("[NOT OK] Source-Update %s. JobId: %s / Error: %s", job_status, res.Job.GetId(), job_err) 311 | } 312 | 313 | return diags 314 | } 315 | 316 | func resourceDatabasePostgressqlDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 317 | client := meta.(*apiClient).client 318 | 319 | source_id := d.Id() 320 | 321 | res, httpRes, err := client.SourcesAPI.DeleteSource(ctx, source_id).Execute() 322 | 323 | if diags := apiErrorResponseHelper(ctx, res, httpRes, err); diags != nil { 324 | return diags 325 | } 326 | 327 | job_status, job_err := PollJobStatus(res.Job.GetId(), ctx, client) 328 | if job_err != "" { 329 | tflog.Warn(ctx, DLPX+WARN+"Job Polling failed but continuing with deletion. Error :"+job_err) 330 | } 331 | tflog.Info(ctx, DLPX+INFO+" Job result is "+job_status) 332 | if isJobTerminalFailure(job_status) { 333 | return diag.Errorf("[NOT OK] Source-Delete %s. JobId: %s / Error: %s", job_status, res.Job.GetId(), job_err) 334 | } 335 | 336 | _, diags := PollForObjectDeletion(ctx, func() (interface{}, *http.Response, error) { 337 | return client.SourcesAPI.GetSourceById(ctx, source_id).Execute() 338 | }) 339 | 340 | return diags 341 | } 342 | -------------------------------------------------------------------------------- /internal/provider/resource_vdb_group.go: -------------------------------------------------------------------------------- 1 | package provider 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/hashicorp/terraform-plugin-log/tflog" 8 | 9 | dctapi "github.com/delphix/dct-sdk-go/v25" 10 | "github.com/hashicorp/terraform-plugin-sdk/v2/diag" 11 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 12 | ) 13 | 14 | func resourceVdbGroup() *schema.Resource { 15 | return &schema.Resource{ 16 | Description: "Resource for managing VDB Groups.", 17 | 18 | CreateContext: resourceVdbGroupCreate, 19 | ReadContext: resourceVdbGroupRead, 20 | UpdateContext: resourceVdbGroupUpdate, 21 | DeleteContext: resourceVdbGroupDelete, 22 | Importer: &schema.ResourceImporter{ 23 | StateContext: schema.ImportStatePassthroughContext, 24 | }, 25 | CustomizeDiff: CustomizeDiffTags, 26 | 27 | Schema: map[string]*schema.Schema{ 28 | "id": { 29 | Type: schema.TypeString, 30 | Computed: true, 31 | }, 32 | "name": { 33 | Type: schema.TypeString, 34 | Required: true, 35 | }, 36 | "vdb_ids": { 37 | Type: schema.TypeList, 38 | Optional: true, 39 | Elem: &schema.Schema{ 40 | Type: schema.TypeString, 41 | }, 42 | }, 43 | "ignore_tag_changes": { 44 | Type: schema.TypeBool, 45 | Default: true, 46 | Optional: true, 47 | }, 48 | "tags": { 49 | Type: schema.TypeList, 50 | Optional: true, 51 | Computed: true, 52 | Elem: &schema.Resource{ 53 | Schema: map[string]*schema.Schema{ 54 | "key": { 55 | Type: schema.TypeString, 56 | Required: true, 57 | }, 58 | "value": { 59 | Type: schema.TypeString, 60 | Required: true, 61 | }, 62 | }, 63 | }, 64 | DiffSuppressFunc: func(_, old, new string, d *schema.ResourceData) bool { 65 | if ignore, ok := d.GetOk("ignore_tag_changes"); ok && ignore.(bool) { 66 | return true 67 | } 68 | return false 69 | }, 70 | }, 71 | }, 72 | } 73 | } 74 | 75 | func resourceVdbGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 76 | var diags diag.Diagnostics 77 | 78 | client := meta.(*apiClient).client 79 | 80 | vdbGroupCreateReq := *dctapi.NewCreateVDBGroupRequest(d.Get("name").(string)) 81 | vdbGroupCreateReq.SetVdbIds(toStringArray(d.Get("vdb_ids"))) 82 | 83 | if v, has_v := d.GetOk("tags"); has_v { 84 | vdbGroupCreateReq.SetTags(toTagArray(v)) 85 | } 86 | 87 | apiRes, httpRes, err := client.VDBGroupsAPI.CreateVdbGroup(ctx).CreateVDBGroupRequest(vdbGroupCreateReq).Execute() 88 | 89 | if diags := apiErrorResponseHelper(ctx, apiRes, httpRes, err); diags != nil { 90 | return diags 91 | } 92 | 93 | d.SetId(apiRes.VdbGroup.GetId()) 94 | 95 | readDiags := resourceVdbGroupRead(ctx, d, meta) 96 | 97 | if readDiags.HasError() { 98 | return readDiags 99 | } 100 | return diags 101 | } 102 | 103 | func resourceVdbGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 104 | client := meta.(*apiClient).client 105 | 106 | var diags diag.Diagnostics 107 | 108 | vdbGroupId := d.Id() 109 | tflog.Info(ctx, DLPX+INFO+"VdbGroupId: "+vdbGroupId) 110 | apiRes, httpRes, err := client.VDBGroupsAPI.GetVdbGroup(ctx, vdbGroupId).Execute() 111 | 112 | if diags := apiErrorResponseHelper(ctx, apiRes, httpRes, err); diags != nil { 113 | d.SetId("") 114 | return diags 115 | } 116 | 117 | d.Set("name", apiRes.GetName()) 118 | d.Set("vdb_ids", apiRes.GetVdbIds()) 119 | tflog.Debug(ctx, "Getting Raw Config") 120 | errors := HandleRawConfigReadContext(ctx, d, apiRes) 121 | if errors != nil { 122 | return diag.FromErr(errors) 123 | } 124 | 125 | return diags 126 | } 127 | 128 | func resourceVdbGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 129 | tflog.Info(ctx, DLPX+INFO+"Updating VDB Group") 130 | client := meta.(*apiClient).client 131 | var name_or_vdb_ids_changed bool = false 132 | vdbGroupId := d.Id() 133 | 134 | // Existing update logic 135 | updateVdbGroupReq := *dctapi.NewUpdateVDBGroupParameters() 136 | if d.HasChange("name") { 137 | updateVdbGroupReq.SetName(d.Get("name").(string)) 138 | name_or_vdb_ids_changed = true 139 | } 140 | if d.HasChange("vdb_ids") { 141 | updateVdbGroupReq.SetVdbIds(toStringArray(d.Get("vdb_ids"))) 142 | name_or_vdb_ids_changed = true 143 | } 144 | 145 | _, httpRes, err := client.VDBGroupsAPI.UpdateVdbGroupById(ctx, vdbGroupId).UpdateVDBGroupParameters(updateVdbGroupReq).Execute() 146 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 147 | return diags 148 | } 149 | 150 | // Polling logic for name/vdb_ids update 151 | if name_or_vdb_ids_changed { 152 | maxAttempts := 10 153 | for attempt := 1; attempt <= maxAttempts; attempt++ { 154 | status, err := PollVdbGroupStatus(ctx, client, vdbGroupId) 155 | if err != nil { 156 | return diag.FromErr(err) 157 | } 158 | if status == "RUNNING" { 159 | break 160 | } 161 | if status == "FAILED" || status == "CANCELED" { 162 | return diag.Errorf("VDB group update failed with status: %s", status) 163 | } 164 | time.Sleep(time.Duration(STATUS_POLL_SLEEP_TIME) * time.Second) 165 | } 166 | } 167 | 168 | // Tag update logic 169 | tflog.Info(ctx, DLPX+INFO+"Updating tags for VDB Group: ") 170 | if !d.Get("ignore_tag_changes").(bool) { 171 | tflog.Info(ctx, DLPX+INFO+"Reading from Api to get existing tags") 172 | apiRes, httpRes, err := client.VDBGroupsAPI.GetVdbGroup(ctx, vdbGroupId).Execute() 173 | if diags := apiErrorResponseHelper(ctx, apiRes, httpRes, err); diags != nil { 174 | d.SetId("") 175 | return diags 176 | } 177 | tags := flattenTags(apiRes.GetTags()) 178 | tflog.Debug(ctx, "Existing tags", map[string]interface{}{ 179 | "tags": tags, 180 | }) 181 | newRaw := d.GetRawConfig() 182 | if newRaw.IsKnown() || !newRaw.IsNull() { 183 | attr := newRaw.GetAttr("tags") 184 | tflog.Debug(ctx, "New tags raw config value", map[string]interface{}{ 185 | "tags": attr.GoString(), 186 | }) 187 | d.Set("tags", flattenTags(apiRes.GetTags())) 188 | if attr.IsNull() || !attr.IsKnown() || attr.LengthInt() == 0 { 189 | // This now correctly gives [] if the user set tags = [] 190 | if len(tags) != 0 { 191 | tflog.Info(ctx, DLPX+INFO+"Tags field is not set, deleting all existing tags") 192 | httpRes, err := client.VDBGroupsAPI.DeleteVdbGroupTags(ctx, vdbGroupId).Execute() 193 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 194 | return diags 195 | } 196 | } 197 | return resourceVdbGroupRead(ctx, d, meta) 198 | } 199 | } 200 | 201 | if d.HasChange("tags") { 202 | oldTags, newTags := d.GetChange("tags") 203 | oldTagList := oldTags.([]interface{}) 204 | newTagList := newTags.([]interface{}) 205 | 206 | // Create a map of old tags for easy lookup 207 | oldTagMap := make(map[string]map[string]bool) 208 | for _, tag := range oldTagList { 209 | tagMap := tag.(map[string]interface{}) 210 | key := tagMap["key"].(string) 211 | value := tagMap["value"].(string) 212 | if _, exists := oldTagMap[key]; !exists { 213 | oldTagMap[key] = make(map[string]bool) 214 | } 215 | oldTagMap[key][value] = true 216 | } 217 | 218 | // Create a map of new tags for easy lookup 219 | newTagMap := make(map[string]map[string]bool) 220 | for _, tag := range newTagList { 221 | tagMap := tag.(map[string]interface{}) 222 | key := tagMap["key"].(string) 223 | value := tagMap["value"].(string) 224 | if _, exists := newTagMap[key]; !exists { 225 | newTagMap[key] = make(map[string]bool) 226 | } 227 | newTagMap[key][value] = true 228 | } 229 | 230 | // If newTagList is empty, delete all existing tags 231 | if len(newTagList) == 0 { 232 | for key := range oldTagMap { 233 | deleteTag := *dctapi.NewDeleteTag() 234 | deleteTag.SetKey(key) 235 | httpRes, err := client.VDBGroupsAPI.DeleteVdbGroupTags(ctx, vdbGroupId).DeleteTag(deleteTag).Execute() 236 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 237 | return diags 238 | } 239 | } 240 | } else { 241 | // Delete removed tags 242 | for key, oldValues := range oldTagMap { 243 | newValues, exists := newTagMap[key] 244 | if !exists { 245 | // Key doesn't exist in new tags, delete all values for this key 246 | deleteTag := *dctapi.NewDeleteTag() 247 | deleteTag.SetKey(key) 248 | httpRes, err := client.VDBGroupsAPI.DeleteVdbGroupTags(ctx, vdbGroupId).DeleteTag(deleteTag).Execute() 249 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 250 | return diags 251 | } 252 | } else { 253 | // Key exists, delete only values that are not in new tags 254 | for oldValue := range oldValues { 255 | if !newValues[oldValue] { 256 | deleteTag := *dctapi.NewDeleteTag() 257 | deleteTag.SetKey(key) 258 | deleteTag.SetValue(oldValue) 259 | httpRes, err := client.VDBGroupsAPI.DeleteVdbGroupTags(ctx, vdbGroupId).DeleteTag(deleteTag).Execute() 260 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 261 | return diags 262 | } 263 | } 264 | } 265 | } 266 | } 267 | 268 | // Create new tags 269 | var tags []dctapi.Tag 270 | for key, newValues := range newTagMap { 271 | oldValues, exists := oldTagMap[key] 272 | if !exists { 273 | // Key doesn't exist in old tags, create all values 274 | for value := range newValues { 275 | tag := *dctapi.NewTag(key, value) 276 | tags = append(tags, tag) 277 | } 278 | } else { 279 | // Key exists, create only new values 280 | for value := range newValues { 281 | if !oldValues[value] { 282 | tag := *dctapi.NewTag(key, value) 283 | tags = append(tags, tag) 284 | } 285 | } 286 | } 287 | } 288 | if len(tags) > 0 { 289 | tagsRequest := *dctapi.NewTagsRequest(tags) 290 | _, httpRes, err := client.VDBGroupsAPI.CreateVdbGroupsTags(ctx, vdbGroupId).TagsRequest(tagsRequest).Execute() 291 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 292 | return diags 293 | } 294 | } 295 | } 296 | } 297 | } 298 | 299 | return resourceVdbGroupRead(ctx, d, meta) 300 | } 301 | 302 | func PollVdbGroupStatus(ctx context.Context, client *dctapi.APIClient, vdbGroupId string) (string, error) { 303 | res, _, err := client.VDBGroupsAPI.GetVdbGroup(ctx, vdbGroupId).Execute() 304 | if err != nil { 305 | return "", err 306 | } 307 | return res.GetStatus(), nil 308 | } 309 | 310 | func resourceVdbGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { 311 | client := meta.(*apiClient).client 312 | 313 | var diags diag.Diagnostics 314 | 315 | vdbGroupId := d.Id() 316 | 317 | deleteVdbParams := dctapi.NewDeleteVDBParametersWithDefaults() 318 | deleteVdbParams.SetForce(false) 319 | 320 | httpRes, err := client.VDBGroupsAPI.DeleteVdbGroup(ctx, vdbGroupId).Execute() 321 | 322 | if diags := apiErrorResponseHelper(ctx, nil, httpRes, err); diags != nil { 323 | return diags 324 | } 325 | if err != nil { 326 | resBody, err := ResponseBodyToString(ctx, httpRes.Body) 327 | if err != nil { 328 | return diag.FromErr(err) 329 | } 330 | return diag.Errorf(resBody) 331 | } 332 | 333 | return diags 334 | } 335 | -------------------------------------------------------------------------------- /docs/resources/appdata_dsource.md: -------------------------------------------------------------------------------- 1 | # Resource: delphix_appdata_dsource 2 | 3 | In Delphix terminology, a dSource is an internal, read-only database copy that the Delphix Continuous Data Engine uses to create and update virtual copies of your database. 4 | A dSource is created and managed by the Delphix Continuous Data Engine and syncs with your chosen source database. The AppData dSource resource in Terraform allows you to create, update, delete and import AppData dSources. Updating existing dSource resource parameters via the apply command is supported for the parameters listed below. 5 | For Oracle, refer to the Oracle dSource resource. The Delphix Provider does not currently support SQL Server or SAP ASE. 6 | 7 | ## Note 8 | * `status` and `enabled` are computed values and are subject to change in the tfstate file based on the dSource state. 9 | * Parameters `credentials_env_vars` within `ops_pre_sync` and `ops_post_sync` object blocks are not updatable. Therefore, any changes made on a Terraform state file do not reflect the actual value of the actual infrastructure 10 | * Sensitive values in `credentials_env_vars` are stored as plain text in the state file. We recommend following Terraform’s sensitive input variables documentation. 11 | * `source_value` and `group_id` parameters cannot be updated after the initial resource creation. However, any differences detected in these parameters are suppressed from the Terraform plan to prevent unnecessary drift detection. 12 | * Only valid for DCT versions 2025.1 and earlier: 13 | * `Make_current_account_owner`,`wait_time` and `skip_wait_for_snapshot_creation` are applicable only during the creation of dsource. Note, these parameters are single-use and not applicable to updates. 14 | * Any new dSource created post Version>=3.2.1 can set wait_time to wait for snapshot creation, dSources created prior to this version will not support this capability. 15 | 16 | ## Example Usage 17 | 18 | The linking of a dSource can be configured through various ingestion approaches. Each configuration is customized to the connector and its supported options. The three PostgreSQL parameter sets below show different ingestion configuration examples. 19 | 20 | # Link dSource using external backup 21 | 22 | ```hcl 23 | resource "delphix_appdata_dsource" "pg_using_external_backup" { 24 | name = DSOURCE_NAME 25 | source_value = SOURCE_VALUE 26 | group_id = DATASET_GROUP_ID 27 | log_sync_enabled = false 28 | link_type = "AppDataStaged" 29 | staging_mount_base = MOUNT_PATH 30 | environment_user = ENV_USER 31 | staging_environment = STAGING_ENV 32 | parameters = jsonencode({ 33 | externalBackup: [ 34 | { 35 | keepStagingInSync: false, 36 | backupPath: BKP_PATH, 37 | walLogPath: LOG_PATH 38 | } 39 | ], 40 | postgresPort : PORT, 41 | mountLocation : MOUNT_PATH 42 | }) 43 | sync_parameters = jsonencode({ 44 | resync = true 45 | }) 46 | make_current_account_owner = true 47 | } 48 | ``` 49 | 50 | # Link dSource using Delphix Initiated Backup 51 | 52 | ```hcl 53 | resource "delphix_appdata_dsource" "pg_using_delphix_initiated_backup" { 54 | name = DSOURCE_NAME 55 | source_value = SOURCE_VALUE 56 | group_id = DATASET_GROUP_ID 57 | log_sync_enabled = false 58 | link_type = "AppDataStaged" 59 | staging_mount_base = MOUNT_PATH 60 | environment_user = ENV_USER 61 | staging_environment = STAGING_ENV 62 | parameters = jsonencode({ 63 | delphixInitiatedBackupFlag : true, 64 | delphixInitiatedBackup : [ 65 | { 66 | userName : USERNAME, 67 | postgresSourcePort : SOURCE_PORT, 68 | userPass : PASSWORD, 69 | sourceHostAddress : SOURCE_ADDRESS 70 | } 71 | ], 72 | postgresPort : PORT, 73 | mountLocation : MOUNT_PATH 74 | }) 75 | sync_parameters = jsonencode({ 76 | resync = true 77 | }) 78 | make_current_account_owner = true 79 | } 80 | ``` 81 | 82 | # Link dSource using Single Database Ingestion 83 | 84 | ```hcl 85 | resource "delphix_appdata_dsource" "pg_using_single_db_ingestion" { 86 | name = DSOURCE_NAME 87 | source_value = SOURCE_VALUE 88 | group_id = DATASET_GROUP_ID 89 | log_sync_enabled = false 90 | link_type = "AppDataStaged" 91 | staging_mount_base = MOUNT_PATH 92 | environment_user = ENV_USER 93 | staging_environment = STAGING_ENV 94 | parameters = jsonencode({ 95 | singleDatabaseIngestionFlag : true, 96 | singleDatabaseIngestion : [ 97 | { 98 | databaseUserName: DBUSER_NAME, 99 | sourcePort: SOURCE_PORT, 100 | dumpJobs: 2, 101 | restoreJobs: 2, 102 | databaseName: DB_NAME, 103 | databaseUserPassword: DB_PASS, 104 | dumpDir: DIR, 105 | sourceHost: SOURCE_HOST 106 | postgresqlFile: FILE 107 | } 108 | ], 109 | postgresPort : PORT, 110 | mountLocation : MOUNT_PATH 111 | }) 112 | sync_parameters = jsonencode({ 113 | resync = true 114 | }) 115 | make_current_account_owner = true 116 | } 117 | ``` 118 | 119 | ## Argument Reference 120 | 121 | ### General Linking Requirements 122 | * `name` - The unique name of the dSource. If unset, a name is randomly generated. [Updatable] 123 | * `source_value` - (Required) ID or Name of the Source to link. 124 | * `description` - The notes/description for the dSource. [Updatable] 125 | * `group_id` - (Required) ID of the dataset group where this dSource should belong to. 126 | * `rollback_on_failure` - When a dSource linking operation fails during SnapSync, it results in a tainted dsource on the engine. By setting this flag to true, the tainted dSource will be removed from both the Terraform state and the engine. By default, the flag is to false, meaning the tainted dSource is maintained on the Terraform state. 127 | 128 | ### Full Backup and Transactional Log requirements 129 | * `log_sync_enabled` - (Required) True if LogSync should run for this database. 130 | * `link_type` - (Required) The type of link to create. Default is AppDataDirect. 131 | * `AppDataDirect` - Represents the AppData specific parameters of a link request for a source directly replicated into the Delphix Continuous Data Engine. 132 | * `AppDataStaged` - Represents the AppData specific parameters of a link request for a source with a staging source. 133 | 134 | #### AppDataDirect properties 135 | * `excludes` - List of subdirectories in the source to exclude when syncing data.These paths are relative to the root of the source directory. 136 | * `follow_symlinks` - List of symlinks in the source to follow when syncing data. These paths are relative to the root of the source directory. All other symlinks are preserved. 137 | 138 | #### AppDataStaged properties 139 | * `staging_mount_base` - The base mount point for the NFS mount on the staging environment. 140 | * `environment_user` - (Required) The OS user to use for linking. [Updatable] 141 | * `staging_environment` - (Required) The environment used as an intermediate stage to pull data into Delphix. [Updatable] 142 | * `staging_environment_user` - Specifies the environment user that accesses the staging environment. [Updatable] 143 | * `parameters` - The JSON payload is based on the type of dSource being created. Different data sources require different parameters. Available parameters can be found within the data connector’s schema.json. [Updatable] 144 | * `sync_parameters` - The JSON payload conforming to the snapshot parameters definition in a Continuous Data plugin. 145 | * `sync_policy_id` - The ID of the SnapSync policy for the dSource. [Updatable] 146 | * `retention_policy_id` - The ID of the Retention policy for the dSource. [Updatable] 147 | 148 | ### Hooks 149 | Any combination of the following hooks can be provided on the AppData dSource resource. The available arguments are identical for each hook and are consolidated in a single list to save space. 150 | 151 | #### Names 152 | * `ops_pre_sync`: Operations to perform before syncing the created dSource. These operations can quiesce any data prior to syncing. See argument list below. 153 | * `ops_post_sync`: Operations to perform after syncing a created dSource. See argument list below. 154 | 155 | #### Arguments 156 | * `name` - Name of the hook [Updatable] 157 | * `command` - Command to be executed [Updatable] 158 | * `shell` - Type of shell. Valid values are [bash, shell, expect, ps, psd] [Updatable] 159 | * `credentials_env_vars` - List of environment variables that contain credentials for this operation 160 | * `base_var_name` - Base name of the environment variables. Variables are named by appending '_USER', '_PASSWORD', '_PUBKEY' and '_PRIVKEY' to this base name, respectively. Variables whose values are not entered or present in the type of credential or vault selected will not be set. 161 | * `password` - Password to assign to the environment variables. 162 | * `vault` - The name or reference of the vault to assign to the environment variables. 163 | * `hashicorp_vault_engine` - Vault engine name where the credential is stored. 164 | * `hashicorp_vault_secret_path` - Path in the vault engine where the credential is stored. 165 | * `hashicorp_vault_username_key` - Hashicorp vault key for the username in the key-value store. 166 | * `hashicorp_vault_secret_key` - Hashicorp vault key for the password in the key-value store. 167 | * `azure_vault_name` - Azure key vault name. 168 | * `azure_vault_username_key` - Azure vault key in the key-value store. 169 | * `azure_vault_secret_key` - Azure vault key in the key-value store. 170 | * `cyberark_vault_query_string` - Query to find a credential in the CyberArk vault. 171 | 172 | ### Initial Ingestion and Snapshot [Deprecated] 173 | The following arguments enable the user to control how the first ingestion and snapshot (SnapSync) should be taken. 174 | * `skip_wait_for_snapshot_creation` - In DCT v2025.1, waiting for Ingestion and Snapshotting (aka SnapSync) to complete is default functionality. Therefore, these the arguments skip_wait_for_snapshot_creation and wait_time are ignored. In future versions of the provider, we will look at re-implementing the skip SnapSync behavior 175 | * `wait_time` - In DCT v2025.1, waiting for Ingestion and Snapshotting (aka SnapSync) to complete is default functionality. Therefore, these the arguments skip_wait_for_snapshot_creation and wait_time are ignored. In future versions of the provider, we will look at re-implementing the skip SnapSync behavior. 176 | 177 | ### Advanced 178 | The following arguments apply to all dSources but they are not often necessary for simple sources. 179 | * `make_current_account_owner` - (Required) True/False. Indicates whether the account creating this reporting schedule must be configured as owner of the reporting schedule. 180 | * `tags` - The tags to be created for dSource. This is a map of two parameters: 181 | * `key` - (Required) Key of the tag 182 | * `value` - (Required) Value of the tag 183 | * `ignore_tag_changes` – This flag enables whether changes in the tags are identified by Terraform. By default, this is set to true, meaning changes to the resource's tags are ignored. 184 | 185 | ## Import 186 | Use the import block to add Appdata dSources created directly in DCT into a Terraform state file. 187 | 188 | For example: 189 | ```hcl 190 | import { 191 | to = delphix_appdata_dsource.dsrc_import_demo 192 | id = "dsource_id" 193 | } 194 | ``` 195 | 196 | ## Limitations 197 | Not all properties can be updated using the update command. Attempts to update an unsupported property will return a runtime error message. -------------------------------------------------------------------------------- /docs/resources/oracle_dsource.md: -------------------------------------------------------------------------------- 1 | # Resource: delphix_oracle_dsource 2 | 3 | In Delphix terminology, a dSource is an internal, read-only database copy that the Delphix Continuous Data Engine uses to create and update virtual copies of your database. 4 | 5 | A dSource is created and managed by the Delphix Continuous Data Engine and syncs with your chosen source database. 6 | 7 | The Oracle dSource resource allows Terraform to create and delete Oracle dSources via Terraform automation. This specifically enables the `apply`, `import`, and `destroy` Terraform commands. 8 | 9 | Updating existing dSource resource parameters via the `apply` command is supported for the parameters listed below. 10 | 11 | This Oracle dSource resource only supports Oracle. 12 | 13 | For other connectors, such as PostgreSQL and SAP HANA, refer to the AppData dSource resource. The Delphix Provider does not currently support SQL Server or SAP ASE. 14 | 15 | 16 | ## Note 17 | 18 | * `status` and `enabled` are computed values and are subject to change in the tfstate file based on the dSource state. 19 | * Parameters `credentials_env_vars` within `ops_pre_sync`, `ops_post_sync` and `ops_pre_log_sync` object blocks are not updatable. Any changes reflected on the state file do not reflect the actual value of the actual infrastructure. 20 | * Sensitive values in `credentials_env_vars` are stored as plain text in the state file. 21 | * `Make_current_account_owner `,`wait_time` and `skip_wait_for_snapshot_creation` are relevant only during the creation of dsource. Note, they can only be used once and are not applicable to updates. 22 | * `source_value` and `group_id` parameters cannot be updated after the initial resource creation. However, any differences detected in these parameters are suppressed from the Terraform plan to prevent unnecessary drift detection 23 | 24 | 25 | 26 | ## Example Usage 27 | 28 | * The linking of a dSource can be performed via direct ingestion as shown in the example below: 29 | 30 | 31 | ```hcl 32 | 33 | # Link Oracle dSource 34 | 35 | resource "delphix_oracle_dsource" "test_oracle_dsource" { 36 | name = "test2" 37 | source_value = "DBOMSRB331B3" 38 | } 39 | 40 | ``` 41 | 42 | ## Argument References 43 | 44 | ### General Linking Requirements 45 | 46 | * `name` - The unique name of the dSource. If empty, a name is randomly generated. [Updatable] 47 | * `source_value` - (Required) ID or name of the source to link. 48 | * `description` - The notes (or description) for the dSource. 49 | * `group_id` - ID of the Delphix Continuous Data dataset group where this dSource should belong to. This value is not reflected in DCT. Tags are recommended. 50 | * `rollback_on_failure` - Dsource linking operation when fails during snapsync creates a tainted dsource on the engine. Setting this flag to true will remove the tainted dsource from state as well as engine. By default, it is set to false, where the tainted dsource is maintained on the terraform state. 51 | 52 | ### Full Backup and Transaction Log Requirements 53 | 54 | * `external_file_path` - External file path. [Updatable] 55 | * `encrypted_linking_enabled` - True if SnapSync data from the source should be retrieved through an encrypted connection. Enabling this feature can decrease the performance of SnapSync from the source but has no impact on the performance of VDBs created from the retrieved data. [Updatable] 56 | * `compressed_linking_enabled` - True if SnapSync data from the source should be compressed over the network. Enabling this feature will reduce network bandwidth consumption and may significantly improve throughput, especially over slow network. [Updatable] 57 | * `check_logical` - True if extended block checking should be used for this linked database. [Updatable] 58 | * `files_for_full_backup` - List of datafiles to take a full backup of. This is useful if certain datafiles could not be backed up during previous SnapSync due to corruption or because they went offline. 59 | * `files_per_set` - The number of data files to include in each RMAN backup set. [Updatable] 60 | * `rman_channels` - The number of parallel channels to use. [Updatable] 61 | * `bandwidth_limit` - Bandwidth limit (MB/s) for SnapSync and LogSync network traffic. A value of 0 means no limit. [Updatable] 62 | * `number_of_connections` - Total number of transport connections to use during SnapSync. [Updatable] 63 | * `backup_level_enabled` - Boolean value indicates whether LEVEL-based incremental backups can be used on the source database. [Updatable] 64 | * `diagnose_no_logging_faults` - If true, NOLOGGING operations on this container are treated as faults and cannot be resolved manually. [Updatable] 65 | * `pre_provisioning_enabled` - If true, pre-provisioning will be performed after every sync. [Updatable] 66 | * `log_sync_enabled` - (Required) True if LogSync should run for this database. 67 | * `log_sync_mode` - LogSync operation mode for this database [`ARCHIVE_ONLY_MODE`, `ARCHIVE_REDO_MODE`, `UNDEFINED`]. 68 | * `log_sync_interval` - Interval between LogSync requests, in seconds. 69 | * `link_now` - True if initial load should be done immediately. 70 | 71 | 72 | ### Snapshot 73 | 74 | The following arguments enable the user to control how the first snapshot should be taken. 75 | 76 | * `force_full_backup` - Whether to take another full backup of the source database. 77 | * `double_sync` - True if two SnapSyncs should be performed in immediate succession to reduce the number of logs required to provision the snapshot. This may significantly reduce the time necessary to provision from a snapshot. 78 | * `do_not_resume` - Indicates if a fresh SnapSync must be started regardless of whether it was possible to resume the current SnapSync. If true, we will not resume; instead, we will ignore previous progress and back up all datafiles even if they have already been completed from the last failed SnapSync. This does not force a full backup; if an incremental was in progress this will start a new incremental snapshot. 79 | * `skip_wait_for_snapshot_creation` - In DCT v2025.1, waiting for Ingestion and Snapshotting (aka SnapSync) to complete is default functionality. Therefore, these the arguments skip_wait_for_snapshot_creation and wait_time are ignored. In future versions of the provider, we will look at re-implementing the skip SnapSync behavior 80 | * `wait_time` - In DCT v2025.1, waiting for Ingestion and Snapshotting (aka SnapSync) to complete is default functionality. Therefore, these the arguments skip_wait_for_snapshot_creation and wait_time are ignored. In future versions of the provider, we will look at re-implementing the skip SnapSync behavior. 81 | 82 | ### Password and Password Vault Management 83 | 84 | The following arguments define how the Delphix Continuous Data will authenticate with the source environment and database. 85 | 86 | * `environment_user_id` - ID of the environment user to use for linking. [Updatable] 87 | * `non_sys_username` - non-SYS database user to access this database. Only required for username-password auth (single tenant only). 88 | * `non_sys_password` - Password for non sys user authentication (single tenant only). 89 | * `fallback_username` - The database fallback username. Optional if bequeath connections are enabled (to be used in case of bequeath connection failures). Only required for username-password auth. 90 | * `fallback_password` - Password for fallback username. 91 | * `non_sys_vault` - The name or reference of the vault from which to read the database credentials (single tenant only). 92 | * `non_sys_hashicorp_vault_engine` - Vault engine name where the credential is stored (single tenant only). 93 | * `non_sys_hashicorp_vault_secret_path` - Path in the vault engine where the credential is stored (single tenant only). 94 | * `non_sys_hashicorp_vault_username_key` - Hashicorp vault key for the username in the key-value store (single tenant only). 95 | * `non_sys_hashicorp_vault_secret_key` - Hashicorp vault key for the password in the key-value store (single tenant only). 96 | * `non_sys_azure_vault_name` - Azure key vault name (single tenant only). 97 | * `non_sys_azure_vault_username_key` - Azure vault key for the username in the key-value store (single tenant only). 98 | * `non_sys_azure_vault_secret_key` - Azure vault key for the password in the key-value store (single tenant only). 99 | * `non_sys_cyberark_vault_query_string` - Query to find a credential in the CyberArk vault (single tenant only). 100 | * `fallback_vault` - The name or reference of the vault from which to read the database credentials. 101 | * `fallback_hashicorp_vault_engine` - Vault engine name where the credential is stored. 102 | * `fallback_hashicorp_vault_secret_path` - Path in the vault engine where the credential is stored. 103 | * `fallback_hashicorp_vault_username_key` - Hashicorp vault key for the username in the key-value store. 104 | * `fallback_hashicorp_vault_secret_key` - Hashicorp vault key for the password in the key-value store. 105 | * `fallback_azure_vault_name` - Azure key vault name. 106 | * `fallback_azure_vault_username_key` - Azure vault key for the username in the key-value store. 107 | * `fallback_azure_vault_secret_key` - Azure vault key for the password in the key-value store. 108 | * `fallback_cyberark_vault_query_string` - Query to find a credential in the CyberArk vault. 109 | 110 | 111 | ### Advanced 112 | 113 | The following arguments apply to all dSources but they are not often necessary for simple sources. 114 | 115 | * `make_current_account_owner` - Whether the account creating this reporting schedule must be configured as owner of the reporting schedule. Default: true. 116 | * `tags` - The tags to be created for dSource. This is a map of 2 parameters: [Updatable] 117 | * `key` - (Required) Key of the tag 118 | * `value` - (Required) Value of the tag 119 | * `ignore_tag_changes` – This flag enables whether changes in the tags are identified by Terraform. By default, this is set to true, meaning changes to the resource's tags are ignored. 120 | 121 | ### Hooks 122 | Any combination of the following hooks can be provided on the Oracle dSource resource. The available arguments are identical for each hook and are consolidated in a single list to save space. 123 | 124 | #### Names 125 | * `ops_pre_log_sync`: Operations to perform after syncing a created dSource and before running the LogSync. See argument list below. 126 | * `ops_pre_sync`: Operations to perform before syncing the created dSource. These operations can quiesce any data prior to syncing. See argument list below. 127 | * `ops_post_sync`: Operations to perform after syncing a created dSource. See argument list below. 128 | 129 | #### Arguments 130 | * `name` - Name of the hook [Updatable] 131 | * `command` - Command to be executed [Updatable] 132 | * `shell` - Type of shell. Valid values are [bash, shell, expect, ps, psd] [Updatable] 133 | * `credentials_env_vars` - List of environment variables that contain credentials for this operation 134 | * `base_var_name` - Base name of the environment variables. Variables are named by appending '_USER', '_PASSWORD', '_PUBKEY' and '_PRIVKEY' to this base name, respectively. Variables whose values are not entered or present in the type of credential or vault selected will not be set. 135 | * `password` - Password to assign to the environment variables. 136 | * `vault` - The name or reference of the vault to assign to the environment variables. 137 | * `hashicorp_vault_engine` - Vault engine name where the credential is stored. 138 | * `hashicorp_vault_secret_path` - Path in the vault engine where the credential is stored. 139 | * `hashicorp_vault_username_key` - Hashicorp vault key for the username in the key-value store. 140 | * `hashicorp_vault_secret_key` - Hashicorp vault key for the password in the key-value store. 141 | * `azure_vault_name` - Azure key vault name. 142 | * `azure_vault_username_key` - Azure vault key in the key-value store. 143 | * `azure_vault_secret_key` - Azure vault key in the key-value store. 144 | * `cyberark_vault_query_string` - Query to find a credential in the CyberArk vault. 145 | 146 | ## Import 147 | Use the [`import` block](https://developer.hashicorp.com/terraform/language/import) to add Oracle Dsources created directly in DCT into a Terraform state file. 148 | 149 | For example: 150 | ```terraform 151 | import { 152 | to = delphix_oracle_dsource.dsrc_import_demo 153 | id = "dsource_id" 154 | } 155 | ``` 156 | 157 | ## Limitations 158 | 159 | Not all properties are supported through the `update` command. Properties that are not supported by the `update` command are presented via an error message at runtime. --------------------------------------------------------------------------------