diff --git a/LICENSE b/LICENSE index fe41e72..5e6d632 100644 --- a/LICENSE +++ b/LICENSE @@ -1,35 +1,27 @@ -Copyright (c) 2021 Oracle and/or its affiliates. +Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. The Universal Permissive License (UPL), Version 1.0 -Subject to the condition set forth below, permission is hereby granted to any -person obtaining a copy of this software, associated documentation and/or data -(collectively the "Software"), free of charge and under any and all copyright -rights in the Software, and any and all patent rights owned or freely -licensable by each licensor hereunder covering either (i) the unmodified -Software as contributed to or provided by such licensor, or (ii) the Larger -Works (as defined below), to deal in both +Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this +software, associated documentation and/or data (collectively the "Software"), free of charge and under any and +all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor +hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or +(ii) the Larger Works (as defined below), to deal in both (a) the Software, and -(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if -one is included with the Software (each a "Larger Work" to which the Software -is contributed by such licensors), +(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software +(each a “Larger Work” to which the Software is contributed by such licensors), -without restriction, including without limitation the rights to copy, create -derivative works of, display, perform, and distribute the Software and make, -use, sell, offer for sale, import, export, have made, and have sold the -Software and the Larger Work(s), and to sublicense the foregoing rights on -either these or other terms. +without restriction, including without limitation the rights to copy, create derivative works of, display, +perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have +sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms. This license is subject to the following condition: -The above copyright notice and either this complete permission notice or at -a minimum a reference to the UPL must be included in all copies or -substantial portions of the Software. +The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must +be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/README.md b/README.md index 9d08cb5..ba58bd3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,125 @@ -# oci-postgresql +# terraform-oci-arch-postgresql -[![License: UPL](https://img.shields.io/badge/license-UPL-green)](https://img.shields.io/badge/license-UPL-green) [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=oracle-devrel_terraform-oci-arch-postgresql)](https://sonarcloud.io/dashboard?id=oracle-devrel_terraform-oci-arch-postgresql) +PostgreSQL is an open source object-relational database management system. It’s highly extensible, highly scalable, and has many features. PostgreSQL supports data replication across multiple data centers. -## THIS IS A NEW, BLANK REPO THAT IS NOT READY FOR USE YET. PLEASE CHECK BACK SOON! +This reference architecture shows a typical three-node deployment of a PostgreSQL cluster on Oracle Cloud Infrastructure Compute instances. In this architecture, the servers are configured in master and standby configuration and use streaming replication. -## Introduction -MISSING +For details of the architecture, see [_Deploy a PostgreSQL database_](https://docs.oracle.com/en/solutions/deploy-postgresql-db/index.html) -## Getting Started -MISSING +## Prerequisites + +- Permission to `manage` the following types of resources in your Oracle Cloud Infrastructure tenancy: `vcns`, `internet-gateways`, `route-tables`, `security-lists`, `subnets`, and `instances`. + +- Quota to create the following resources: 1 VCN, 1 subnet, 1 Internet Gateway, 1 route rules, and 3 compute instances (1 primary master PostgreSQL instance and 2 Standby instances of PostgreSQL). + +If you don't have the required permissions and quota, contact your tenancy administrator. See [Policy Reference](https://docs.cloud.oracle.com/en-us/iaas/Content/Identity/Reference/policyreference.htm), [Service Limits](https://docs.cloud.oracle.com/en-us/iaas/Content/General/Concepts/servicelimits.htm), [Compartment Quotas](https://docs.cloud.oracle.com/iaas/Content/General/Concepts/resourcequotas.htm). + +## Deploy Using Oracle Resource Manager + +1. Click [![Deploy to Oracle Cloud](https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg)](https://cloud.oracle.com/resourcemanager/stacks/create?region=home&zipUrl=https://github.com/oracle-devrel/terraform-oci-arch-postgresql/releases/latest/download/terraform-oci-arch-postgresql-stack-latest.zip) + + If you aren't already signed in, when prompted, enter the tenancy and user credentials. + +2. Review and accept the terms and conditions. + +3. Select the region where you want to deploy the stack. + +4. Follow the on-screen prompts and instructions to create the stack. + +5. After creating the stack, click **Terraform Actions**, and select **Plan**. + +6. Wait for the job to be completed, and review the plan. + + To make any changes, return to the Stack Details page, click **Edit Stack**, and make the required changes. Then, run the **Plan** action again. + +7. If no further changes are necessary, return to the Stack Details page, click **Terraform Actions**, and select **Apply**. + +## Deploy Using the Terraform CLI + +### Clone the Repository +Now, you'll want a local copy of this repo. You can make that with the commands: + + git clone https://github.com/oracle-devrel/terraform-oci-arch-postgresql + cd terraform-oci-arch-postgresql + ls ### Prerequisites -MISSING +First off, you'll need to do some pre-deploy setup. That's all detailed [here](https://github.com/cloud-partners/oci-prerequisites). + +Secondly, create a `terraform.tfvars` file and populate with the following information: -## Notes/Issues -MISSING +``` +# Authentication +tenancy_ocid = "" +user_ocid = "" +fingerprint = "" +private_key_path = "" -## URLs -* Nothing at this time +# Region +region = "" + +# Availablity Domain +availablity_domain_name = "" # for example GrCH:US-ASHBURN-AD-1 + +# Compartment +compartment_ocid = "" + +# PostgreSQL Password +postgresql_password = "" + +# PostgreSQL Version (supported versions 9.6, 10, 11, 12, 13) +postgresql_version = "" + +# Optional first HotStandby +postgresql_deploy_hotstandby1 = true +postgresql_hotstandby1_ad = "" # for example GrCH:US-ASHBURN-AD-2 +postgresql_hotstandby1_fd = "" # for example FAULT-DOMAIN-2 + +# Optional second HotStandby +postgresql_deploy_hotstandby2 = true +postgresql_hotstandby2_ad = "" # for example GrCH:US-ASHBURN-AD-3 +postgresql_hotstandby2_fd = "" # for example FAULT-DOMAIN-3 + +```` + +### Create the Resources +Run the following commands: + + terraform init + terraform plan + terraform apply + +### Destroy the Deployment +When you no longer need the deployment, you can run this command to destroy the resources: + + terraform destroy + +## Deploy as a Module +It's possible to utilize this repository as remote module, providing the necessary inputs: + +``` +module "oci-postgresql" { + source = "github.com/oracle-devrel/terraform-oci-arch-postgresql" + tenancy_ocid = "" + user_ocid = "" + fingerprint = "" + private_key_path = "" + region = "" + availablity_domain_name = "" + compartment_ocid = "" + use_existing_vcn = true # You can inject your own VCN and subnet + create_in_private_subnet = true # Subnet should be associated with NATGW and proper Route Table. + postgresql_vcn = oci_core_virtual_network.my_vcn.id # Injected VCN + postgresql_subnet = oci_core_subnet.my_private_subnet.id # Injected Private Subnet + postgresql_password = "" + postgresql_deploy_hotstandby1 = true # if we want to setup hotstandby1 + postgresql_deploy_hotstandby2 = true # if we want to setup hotstandby2 +} +``` + +## Architecture Diagram + +![](./images/postgre-oci.png) ## Contributing This project is open source. Please submit your contributions by forking this repository and submitting a pull request! Oracle appreciates any contributions that are made by the open source community. @@ -28,3 +130,4 @@ Copyright (c) 2021 Oracle and/or its affiliates. Licensed under the Universal Permissive License (UPL), Version 1.0. See [LICENSE](LICENSE) for more details. + diff --git a/bastion.tf b/bastion.tf new file mode 100644 index 0000000..5e5f67e --- /dev/null +++ b/bastion.tf @@ -0,0 +1,94 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "oci_bastion_bastion" "bastion-service" { + count = var.create_in_private_subnet ? 1 : 0 + bastion_type = "STANDARD" + compartment_id = var.compartment_ocid + target_subnet_id = !var.use_existing_vcn ? oci_core_subnet.postgresql_subnet[0].id : var.postgresql_subnet + client_cidr_block_allow_list = ["0.0.0.0/0"] + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } + name = "BastionService${random_id.tag.hex}" + max_session_ttl_in_seconds = 10800 +} + +resource "oci_bastion_session" "ssh_postgresql_master_session" { + depends_on = [oci_core_instance.postgresql_master, + oci_core_nat_gateway.postgresql_nat, + # oci_core_route_table_attachment.vcn01_subnet_app01_route_table_attachment, + oci_core_route_table.postgresql_rt2 + ] + + count = var.create_in_private_subnet ? 1 : 0 + bastion_id = oci_bastion_bastion.bastion-service[0].id + + key_details { + public_key_content = tls_private_key.public_private_key_pair.public_key_openssh + } + target_resource_details { + session_type = "MANAGED_SSH" + target_resource_id = oci_core_instance.postgresql_master.id + + target_resource_operating_system_user_name = "opc" + target_resource_port = 22 + target_resource_private_ip_address = oci_core_instance.postgresql_master.private_ip + } + + display_name = "ssh_postgresql_master_session" + key_type = "PUB" + session_ttl_in_seconds = 10800 +} + +resource "oci_bastion_session" "ssh_postgresql_hotstandby1_session" { + depends_on = [oci_core_instance.postgresql_master, + oci_core_nat_gateway.postgresql_nat, + # oci_core_route_table_attachment.vcn01_subnet_app01_route_table_attachment, + oci_core_route_table.postgresql_rt2 + ] + + count = (var.create_in_private_subnet && var.postgresql_deploy_hotstandby1) ? 1 : 0 + bastion_id = oci_bastion_bastion.bastion-service[0].id + + key_details { + public_key_content = tls_private_key.public_private_key_pair.public_key_openssh + } + target_resource_details { + session_type = "MANAGED_SSH" + target_resource_id = oci_core_instance.postgresql_hotstandby1[count.index].id + + target_resource_operating_system_user_name = "opc" + target_resource_port = 22 + target_resource_private_ip_address = oci_core_instance.postgresql_hotstandby1[count.index].private_ip + } + + display_name = "ssh_postgresql_hotstandby1_session" + key_type = "PUB" + session_ttl_in_seconds = 10800 +} + +resource "oci_bastion_session" "ssh_postgresql_hotstandby2_session" { + depends_on = [oci_core_instance.postgresql_master, + oci_core_nat_gateway.postgresql_nat, + # oci_core_route_table_attachment.vcn01_subnet_app01_route_table_attachment, + oci_core_route_table.postgresql_rt2 + ] + + count = (var.create_in_private_subnet && var.postgresql_deploy_hotstandby2) ? 1 : 0 + bastion_id = oci_bastion_bastion.bastion-service[0].id + + key_details { + public_key_content = tls_private_key.public_private_key_pair.public_key_openssh + } + target_resource_details { + session_type = "MANAGED_SSH" + target_resource_id = oci_core_instance.postgresql_hotstandby2[count.index].id + + target_resource_operating_system_user_name = "opc" + target_resource_port = 22 + target_resource_private_ip_address = oci_core_instance.postgresql_hotstandby2[count.index].private_ip + } + + display_name = "ssh_postgresql_hotstandby2_session" + key_type = "PUB" + session_ttl_in_seconds = 10800 +} diff --git a/block_volume.tf b/block_volume.tf new file mode 100644 index 0000000..ffef847 --- /dev/null +++ b/block_volume.tf @@ -0,0 +1,90 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "oci_core_volume" "postgresql_master_volume" { + count = var.add_iscsi_volume ? 1 : 0 + availability_domain = var.availablity_domain_name + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_Master_Volume" + size_in_gbs = var.iscsi_volume_size_in_gbs + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_volume_attachment" "postgresql_master_volume_attachment" { + count = var.add_iscsi_volume ? 1 : 0 + attachment_type = "iscsi" + instance_id = oci_core_instance.postgresql_master.id + volume_id = oci_core_volume.postgresql_master_volume[0].id +} + +resource "oci_core_volume_backup" "postgresql_master_volume_backup" { + count = (var.add_iscsi_volume && var.boot_volume_initial_backup) ? 1 : 0 + volume_id = oci_core_volume.postgresql_master_volume[0].id + display_name = "PostgreSQL_Master_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_master_volume_backup_policy_assignment" { + count = (var.add_iscsi_volume && var.block_volume_backup_policy_enabled) ? 1 : 0 + asset_id = oci_core_volume.postgresql_master_volume[0].id + policy_id = data.oci_core_volume_backup_policies.block_volume_backup_policy[count.index].volume_backup_policies[0].id +} + +resource "oci_core_volume" "postgresql_hotstandby1_volume" { + count = (var.postgresql_deploy_hotstandby1 && var.add_iscsi_volume && var.boot_volume_initial_backup) ? 1 : 0 + availability_domain = var.postgresql_hotstandby1_ad == "" ? var.availablity_domain_name : var.postgresql_hotstandby1_ad + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_HotStandby1_Volume" + size_in_gbs = var.iscsi_volume_size_in_gbs + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_volume_attachment" "postgresql_hotstandby1_volume_attachment" { + count = (var.postgresql_deploy_hotstandby1 && var.add_iscsi_volume) ? 1 : 0 + attachment_type = "iscsi" + instance_id = oci_core_instance.postgresql_hotstandby1[0].id + volume_id = oci_core_volume.postgresql_hotstandby1_volume[0].id +} + +resource "oci_core_volume_backup" "postgresql_hotstandby1_volume_backup" { + count = (var.postgresql_deploy_hotstandby1 && var.add_iscsi_volume && var.boot_volume_initial_backup) ? 1 : 0 + volume_id = oci_core_volume.postgresql_hotstandby1_volume[0].id + display_name = "PostgreSQL_HotStandby1_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_hotstandby1_volume_backup_policy_assignment" { + count = (var.postgresql_deploy_hotstandby1 && var.add_iscsi_volume && var.block_volume_backup_policy_enabled) ? 1 : 0 + asset_id = oci_core_volume.postgresql_hotstandby1_volume[0].id + policy_id = data.oci_core_volume_backup_policies.block_volume_backup_policy[count.index].volume_backup_policies[0].id +} + +resource "oci_core_volume" "postgresql_hotstandby2_volume" { + count = (var.postgresql_deploy_hotstandby2 && var.add_iscsi_volume) ? 1 : 0 + availability_domain = var.postgresql_hotstandby2_ad == "" ? var.availablity_domain_name : var.postgresql_hotstandby2_ad + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_HotStandby2_Volume" + size_in_gbs = var.iscsi_volume_size_in_gbs + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_volume_attachment" "postgresql_hotstandby2_volume_attachment" { + count = (var.postgresql_deploy_hotstandby2 && var.add_iscsi_volume) ? 1 : 0 + attachment_type = "iscsi" + instance_id = oci_core_instance.postgresql_hotstandby2[0].id + volume_id = oci_core_volume.postgresql_hotstandby2_volume[0].id +} + +resource "oci_core_volume_backup" "postgresql_hotstandby2_volume_backup" { + count = (var.postgresql_deploy_hotstandby2 && var.add_iscsi_volume && var.boot_volume_initial_backup) ? 1 : 0 + volume_id = oci_core_volume.postgresql_hotstandby2_volume[0].id + display_name = "PostgreSQL_HotStandby2_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_hotstandby2_volume_backup_policy_assignment" { + count = (var.postgresql_deploy_hotstandby2 && var.add_iscsi_volume && var.block_volume_backup_policy_enabled) ? 1 : 0 + asset_id = oci_core_volume.postgresql_hotstandby2_volume[0].id + policy_id = data.oci_core_volume_backup_policies.block_volume_backup_policy[count.index].volume_backup_policies[0].id +} + diff --git a/compute.tf b/compute.tf new file mode 100644 index 0000000..ebd93de --- /dev/null +++ b/compute.tf @@ -0,0 +1,222 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +data "template_file" "key_script" { + template = file("${path.module}/scripts/sshkey.tpl") + vars = { + ssh_public_key = tls_private_key.public_private_key_pair.public_key_openssh + } +} + +data "template_cloudinit_config" "cloud_init" { + gzip = true + base64_encode = true + + part { + filename = "ainit.sh" + content_type = "text/x-shellscript" + content = data.template_file.key_script.rendered + } +} + +resource "oci_core_instance" "postgresql_master" { + availability_domain = var.availablity_domain_name + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_Master" + shape = var.postgresql_instance_shape + + dynamic "shape_config" { + for_each = local.is_flexible_postgresql_instance_shape ? [1] : [] + content { + memory_in_gbs = var.postgresql_instance_flex_shape_memory + ocpus = var.postgresql_instance_flex_shape_ocpus + } + } + + dynamic "agent_config" { + for_each = var.create_in_private_subnet ? [1] : [] + content { + are_all_plugins_disabled = false + is_management_disabled = false + is_monitoring_disabled = false + plugins_config { + desired_state = "ENABLED" + name = "Bastion" + } + } + } + + fault_domain = var.postgresql_master_fd + + create_vnic_details { + subnet_id = !var.use_existing_vcn ? oci_core_subnet.postgresql_subnet[0].id : var.postgresql_subnet + display_name = "primaryvnic" + assign_public_ip = var.create_in_private_subnet ? false : true + hostname_label = "pgmaster" + } + + source_details { + source_type = "image" + source_id = data.oci_core_images.InstanceImageOCID_postgresql_instance_shape.images[0].id + } + + metadata = { + ssh_authorized_keys = var.ssh_public_key + user_data = data.template_cloudinit_config.cloud_init.rendered + } + + provisioner "local-exec" { + command = "sleep 240" + } + + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_boot_volume_backup" "postgresql_master_boot_volume_backup" { + count = var.boot_volume_initial_backup ? 1 : 0 + boot_volume_id = oci_core_instance.postgresql_master.boot_volume_id + display_name = "PostgreSQL_Master_Boot_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_master_boot_volume_backup_policy_assignment" { + count = var.boot_volume_backup_policy_enabled ? 1 : 0 + asset_id = oci_core_instance.postgresql_master.boot_volume_id + policy_id = data.oci_core_volume_backup_policies.boot_volume_backup_policy.volume_backup_policies[0].id +} + +resource "oci_core_instance" "postgresql_hotstandby1" { + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + availability_domain = var.postgresql_hotstandby1_ad == "" ? var.availablity_domain_name : var.postgresql_hotstandby1_ad + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_HotStandby1" + shape = var.postgresql_hotstandby1_shape + + dynamic "shape_config" { + for_each = local.is_flexible_postgresql_hotstandby1_shape ? [1] : [] + content { + memory_in_gbs = var.postgresql_hotstandby1_flex_shape_memory + ocpus = var.postgresql_hotstandby1_flex_shape_ocpus + } + } + + dynamic "agent_config" { + for_each = var.create_in_private_subnet ? [1] : [] + content { + are_all_plugins_disabled = false + is_management_disabled = false + is_monitoring_disabled = false + plugins_config { + desired_state = "ENABLED" + name = "Bastion" + } + } + } + + + fault_domain = var.postgresql_hotstandby1_fd + + create_vnic_details { + subnet_id = !var.use_existing_vcn ? oci_core_subnet.postgresql_subnet[0].id : var.postgresql_subnet + display_name = "primaryvnic" + assign_public_ip = var.create_in_private_subnet ? false : true + hostname_label = "pgstandby1" + } + + source_details { + source_type = "image" + source_id = data.oci_core_images.InstanceImageOCID_postgresql_hotstandby1_shape.images[0].id + } + + metadata = { + ssh_authorized_keys = var.ssh_public_key + user_data = data.template_cloudinit_config.cloud_init.rendered + } + + provisioner "local-exec" { + command = "sleep 240" + } + + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_boot_volume_backup" "postgresql_hotstandby1_boot_volume_backup" { + count = (var.postgresql_deploy_hotstandby1 && var.boot_volume_initial_backup) ? 1 : 0 + boot_volume_id = oci_core_instance.postgresql_hotstandby1[0].boot_volume_id + display_name = "PostgreSQL_Hotstandby1_Boot_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_hotstandby1_boot_volume_backup_policy_assignment" { + count = (var.postgresql_deploy_hotstandby1 && var.boot_volume_backup_policy_enabled) ? 1 : 0 + asset_id = oci_core_instance.postgresql_hotstandby1[0].boot_volume_id + policy_id = data.oci_core_volume_backup_policies.boot_volume_backup_policy.volume_backup_policies[0].id +} + +resource "oci_core_instance" "postgresql_hotstandby2" { + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + availability_domain = var.postgresql_hotstandby2_ad == "" ? var.availablity_domain_name : var.postgresql_hotstandby2_ad + compartment_id = var.compartment_ocid + display_name = "PostgreSQL_HotStandby2" + shape = var.postgresql_hotstandby2_shape + + dynamic "shape_config" { + for_each = local.is_flexible_postgresql_hotstandby2_shape ? [1] : [] + content { + memory_in_gbs = var.postgresql_hotstandby2_flex_shape_memory + ocpus = var.postgresql_hotstandby2_flex_shape_ocpus + } + } + + + dynamic "agent_config" { + for_each = var.create_in_private_subnet ? [1] : [] + content { + are_all_plugins_disabled = false + is_management_disabled = false + is_monitoring_disabled = false + plugins_config { + desired_state = "ENABLED" + name = "Bastion" + } + } + } + + fault_domain = var.postgresql_hotstandby2_fd + + create_vnic_details { + subnet_id = !var.use_existing_vcn ? oci_core_subnet.postgresql_subnet[0].id : var.postgresql_subnet + display_name = "primaryvnic" + assign_public_ip = var.create_in_private_subnet ? false : true + hostname_label = "pgstandby2" + } + + source_details { + source_type = "image" + source_id = data.oci_core_images.InstanceImageOCID_postgresql_hotstandby2_shape.images[0].id + } + + metadata = { + ssh_authorized_keys = var.ssh_public_key + user_data = data.template_cloudinit_config.cloud_init.rendered + } + + provisioner "local-exec" { + command = "sleep 240" + } + + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_boot_volume_backup" "postgresql_hotstandby2_boot_volume_backup" { + count = (var.postgresql_deploy_hotstandby2 && var.boot_volume_initial_backup) ? 1 : 0 + boot_volume_id = oci_core_instance.postgresql_hotstandby2[0].boot_volume_id + display_name = "PostgreSQL_Hotstandby2_Boot_Volume_Backup_FULL" + type = "FULL" +} + +resource "oci_core_volume_backup_policy_assignment" "postgresql_hotstandby2_boot_volume_backup_policy_assignment" { + count = (var.postgresql_deploy_hotstandby2 && var.boot_volume_backup_policy_enabled) ? 1 : 0 + asset_id = oci_core_instance.postgresql_hotstandby2[0].boot_volume_id + policy_id = data.oci_core_volume_backup_policies.boot_volume_backup_policy.volume_backup_policies[0].id +} diff --git a/datasources.tf b/datasources.tf new file mode 100644 index 0000000..b57c99f --- /dev/null +++ b/datasources.tf @@ -0,0 +1,117 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +data "oci_core_vnic_attachments" "postgresql_master_vnics" { + compartment_id = var.compartment_ocid + availability_domain = var.availablity_domain_name + instance_id = oci_core_instance.postgresql_master.id +} + + +data "oci_core_vnic_attachments" "postgresql_master_primaryvnic_attach" { + availability_domain = var.availablity_domain_name + compartment_id = var.compartment_ocid + instance_id = oci_core_instance.postgresql_master.id +} + +data "oci_core_vnic" "postgresql_master_primaryvnic" { + vnic_id = data.oci_core_vnic_attachments.postgresql_master_primaryvnic_attach.vnic_attachments.0.vnic_id +} + +data "oci_core_vnic_attachments" "postgresql_hotstandby1_primaryvnic_attach" { + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + availability_domain = var.postgresql_hotstandby1_ad + compartment_id = var.compartment_ocid + instance_id = oci_core_instance.postgresql_hotstandby1[count.index].id +} + +data "oci_core_vnic" "postgresql_hotstandby1_primaryvnic" { + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + vnic_id = data.oci_core_vnic_attachments.postgresql_hotstandby1_primaryvnic_attach[count.index].vnic_attachments.0.vnic_id +} + +data "oci_core_vnic_attachments" "postgresql_hotstandby2_primaryvnic_attach" { + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + availability_domain = var.postgresql_hotstandby2_ad + compartment_id = var.compartment_ocid + instance_id = oci_core_instance.postgresql_hotstandby2[count.index].id +} + +data "oci_core_vnic" "postgresql_hotstandby2_primaryvnic" { + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + vnic_id = data.oci_core_vnic_attachments.postgresql_hotstandby2_primaryvnic_attach[count.index].vnic_attachments.0.vnic_id +} + + +# Get the latest Oracle Linux image +data "oci_core_images" "InstanceImageOCID_postgresql_instance_shape" { + compartment_id = var.compartment_ocid + operating_system = var.instance_os + operating_system_version = var.linux_os_version + shape = var.postgresql_instance_shape + + filter { + name = "display_name" + values = ["^.*Oracle[^G]*$"] + regex = true + } +} + +# Get the latest Oracle Linux image +data "oci_core_images" "InstanceImageOCID_postgresql_hotstandby1_shape" { + compartment_id = var.compartment_ocid + operating_system = var.instance_os + operating_system_version = var.linux_os_version + shape = var.postgresql_hotstandby1_shape + + filter { + name = "display_name" + values = ["^.*Oracle[^G]*$"] + regex = true + } +} + +# Get the latest Oracle Linux image +data "oci_core_images" "InstanceImageOCID_postgresql_hotstandby2_shape" { + compartment_id = var.compartment_ocid + operating_system = var.instance_os + operating_system_version = var.linux_os_version + shape = var.postgresql_hotstandby2_shape + + filter { + name = "display_name" + values = ["^.*Oracle[^G]*$"] + regex = true + } +} + +data "oci_identity_region_subscriptions" "home_region_subscriptions" { + tenancy_id = var.tenancy_ocid + + filter { + name = "is_home_region" + values = [true] + } +} + + +data "oci_core_volume_backup_policies" "boot_volume_backup_policy" { + # count = var.add_iscsi_volume ? 1 : 0 + + filter { + name = "display_name" + values = [var.boot_volume_backup_policy_level] + regex = true + } +} + + +data "oci_core_volume_backup_policies" "block_volume_backup_policy" { + count = var.add_iscsi_volume ? 1 : 0 + + filter { + name = "display_name" + values = [var.block_volume_backup_policy_level] + regex = true + } +} diff --git a/examples/remote-module-network-inside-module/main.tf b/examples/remote-module-network-inside-module/main.tf new file mode 100644 index 0000000..d5e834a --- /dev/null +++ b/examples/remote-module-network-inside-module/main.tf @@ -0,0 +1,32 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +variable "user_ocid" {} +variable "fingerprint" {} +variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} +variable "postgresql_password" {} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + +module "postgres" { + source = "github.com/oracle-devrel/terraform-oci-arch-postgresql" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + region = var.region + private_key_path = var.private_key_path + availablity_domain_name = var.availablity_domain_name + compartment_ocid = var.compartment_ocid + postgresql_password = var.postgresql_password +} + diff --git a/examples/remote-module-no-hotstandbys/main.tf b/examples/remote-module-no-hotstandbys/main.tf new file mode 100644 index 0000000..847e03d --- /dev/null +++ b/examples/remote-module-no-hotstandbys/main.tf @@ -0,0 +1,104 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +variable "user_ocid" {} +variable "fingerprint" {} +variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} +variable "postgresql_password" {} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + +resource "oci_core_virtual_network" "my_vcn" { + cidr_block = "192.168.0.0/16" + compartment_id = var.compartment_ocid + display_name = "myVCN" + dns_label = "myvcn" +} + +resource "oci_core_nat_gateway" "my_nat" { + compartment_id = var.compartment_ocid + display_name = "myNAT" + vcn_id = oci_core_virtual_network.my_vcn.id +} + +resource "oci_core_route_table" "my_rt" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "myRT" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_nat_gateway.my_nat.id + } +} + +resource "oci_core_security_list" "my_securitylist" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "mySecurityList" + + egress_security_rules { + protocol = "6" + destination = "0.0.0.0/0" + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "22" + min = "22" + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "5432" + min = "5432" + } + } +} + +resource "oci_core_subnet" "my_subnet" { + cidr_block = "192.168.1.0/24" + display_name = "mySubnet" + dns_label = "mysubnet" + security_list_ids = [oci_core_security_list.my_securitylist.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + route_table_id = oci_core_route_table.my_rt.id + dhcp_options_id = oci_core_virtual_network.my_vcn.default_dhcp_options_id + prohibit_public_ip_on_vnic = true +} + +module "postgres" { + source = "github.com/oracle-devrel/terraform-oci-arch-postgresql" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + region = var.region + private_key_path = var.private_key_path + availablity_domain_name = var.availablity_domain_name + compartment_ocid = var.compartment_ocid + use_existing_vcn = true # usage of the external existing VCN + create_in_private_subnet = true # usage of the private subnet + postgresql_vcn = oci_core_virtual_network.my_vcn.id # injecting myVCN + postgresql_subnet = oci_core_subnet.my_subnet.id # injecting private mySubnet + postgresql_password = var.postgresql_password +} + diff --git a/examples/remote-module-private-subnet/main.tf b/examples/remote-module-private-subnet/main.tf new file mode 100644 index 0000000..30bb29e --- /dev/null +++ b/examples/remote-module-private-subnet/main.tf @@ -0,0 +1,121 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +variable "user_ocid" {} +variable "fingerprint" {} +variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} +variable "postgresql_password" {} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + +resource "oci_core_virtual_network" "my_vcn" { + cidr_block = "192.168.0.0/16" + compartment_id = var.compartment_ocid + display_name = "myVCN" + dns_label = "myvcn" +} + +resource "oci_core_nat_gateway" "my_nat" { + compartment_id = var.compartment_ocid + display_name = "myNAT" + vcn_id = oci_core_virtual_network.my_vcn.id +} + +resource "oci_core_route_table" "my_rt" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "myRT" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_nat_gateway.my_nat.id + } +} + +resource "oci_core_security_list" "my_securitylist" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "mySecurityList" + + egress_security_rules { + protocol = "6" + destination = "0.0.0.0/0" + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "22" + min = "22" + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "5432" + min = "5432" + } + } +} + +resource "oci_core_subnet" "my_subnet" { + cidr_block = "192.168.1.0/24" + display_name = "mySubnet" + dns_label = "mysubnet" + security_list_ids = [oci_core_security_list.my_securitylist.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + route_table_id = oci_core_route_table.my_rt.id + dhcp_options_id = oci_core_virtual_network.my_vcn.default_dhcp_options_id + prohibit_public_ip_on_vnic = true +} + +module "postgres" { + source = "github.com/oracle-devrel/terraform-oci-arch-postgresql" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + region = var.region + private_key_path = var.private_key_path + availablity_domain_name = var.availablity_domain_name + compartment_ocid = var.compartment_ocid + use_existing_vcn = true # usage of the external existing VCN + create_in_private_subnet = true # usage of the private subnet + postgresql_vcn = oci_core_virtual_network.my_vcn.id # injecting myVCN + postgresql_subnet = oci_core_subnet.my_subnet.id # injecting private mySubnet + postgresql_password = var.postgresql_password + add_iscsi_volume = true # adding iSCSI volume... + iscsi_volume_size_in_gbs = 200 # ... with 200 GB of size + postgresql_version = "12" # non-default version of PostgreSQL12 + # OCPUs & memory for flex shape in master node. + postgresql_instance_shape = "VM.Standard.E3.Flex" + postgresql_instance_flex_shape_ocpus = 2 + postgresql_instance_flex_shape_memory = 20 + # OCPUs & memory for flex shape in hotstanby1 node. + postgresql_deploy_hotstandby1 = true + postgresql_hotstandby1_shape = "VM.Standard.E3.Flex" + postgresql_hotstandby1_flex_shape_ocpus = 1 + postgresql_hotstandby1_flex_shape_memory = 10 + # OCPUs & memory for flex shape in hotstanby2 node. + postgresql_deploy_hotstandby2 = true + postgresql_hotstandby2_shape = "VM.Standard.E3.Flex" + postgresql_hotstandby2_flex_shape_ocpus = 1 + postgresql_hotstandby2_flex_shape_memory = 5 +} + diff --git a/examples/remote-module-public-subnet/main.tf b/examples/remote-module-public-subnet/main.tf new file mode 100644 index 0000000..6a3496f --- /dev/null +++ b/examples/remote-module-public-subnet/main.tf @@ -0,0 +1,105 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +variable "user_ocid" {} +variable "fingerprint" {} +variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} +variable "postgresql_password" {} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + +resource "oci_core_virtual_network" "my_vcn" { + cidr_block = "192.168.0.0/16" + compartment_id = var.compartment_ocid + display_name = "myVCN" + dns_label = "myvcn" +} + +resource "oci_core_internet_gateway" "my_igw" { + compartment_id = var.compartment_ocid + display_name = "myIGW" + vcn_id = oci_core_virtual_network.my_vcn.id +} + +resource "oci_core_route_table" "my_rt" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "myRT" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.my_igw.id + } +} + +resource "oci_core_security_list" "my_securitylist" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + display_name = "mySecurityList" + + egress_security_rules { + protocol = "6" + destination = "0.0.0.0/0" + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "22" + min = "22" + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "5432" + min = "5432" + } + } +} + +resource "oci_core_subnet" "my_subnet" { + cidr_block = "192.168.1.0/24" + display_name = "mySubnet" + dns_label = "mysubnet" + security_list_ids = [oci_core_security_list.my_securitylist.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.my_vcn.id + route_table_id = oci_core_route_table.my_rt.id + dhcp_options_id = oci_core_virtual_network.my_vcn.default_dhcp_options_id +} + +module "postgres" { + source = "github.com/oracle-devrel/terraform-oci-arch-postgresql" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + region = var.region + private_key_path = var.private_key_path + availablity_domain_name = var.availablity_domain_name + compartment_ocid = var.compartment_ocid + use_existing_vcn = true # usage of the external existing VCN + create_in_private_subnet = false # usage of the public subnet + postgresql_vcn = oci_core_virtual_network.my_vcn.id # injecting myVCN + postgresql_subnet = oci_core_subnet.my_subnet.id # injecting public mySubnet + postgresql_password = var.postgresql_password + postgresql_deploy_hotstandby1 = true + postgresql_deploy_hotstandby2 = true +} + diff --git a/images/postgre-oci.png b/images/postgre-oci.png new file mode 100644 index 0000000..6ca67bf Binary files /dev/null and b/images/postgre-oci.png differ diff --git a/network.tf b/network.tf new file mode 100644 index 0000000..eaf6882 --- /dev/null +++ b/network.tf @@ -0,0 +1,84 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "oci_core_virtual_network" "postgresql_vcn" { + count = !var.use_existing_vcn ? 1 : 0 + cidr_block = var.postgresql_vcn_cidr + compartment_id = var.compartment_ocid + display_name = "PostgreSQLVCN" + dns_label = "postgresvcn" + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_drg" "postgresql_drg" { + count = (var.create_in_private_subnet && var.create_drg_for_private_subnet && !var.use_existing_vcn) ? 1 : 0 + compartment_id = var.compartment_ocid + display_name = "PostgreSQLDRG" + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_drg_attachment" "postgresql_drg_attachment" { + count = (var.create_in_private_subnet && var.create_drg_for_private_subnet && !var.use_existing_vcn) ? 1 : 0 + drg_id = oci_core_drg.postgresql_drg[0].id + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + display_name = "PostgreSQLDRG_Attachment" +} + +resource "oci_core_internet_gateway" "postgresql_igw" { + count = (!var.create_in_private_subnet && !var.use_existing_vcn) ? 1 : 0 + compartment_id = var.compartment_ocid + display_name = "PostgreSQLIGW" + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_route_table" "postgresql_rt" { + count = (!var.create_in_private_subnet && !var.use_existing_vcn) ? 1 : 0 + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + display_name = "PostgreSQLRouteTable" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.postgresql_igw[count.index].id + } + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_nat_gateway" "postgresql_nat" { + count = (var.create_in_private_subnet && !var.use_existing_vcn) ? 1 : 0 + compartment_id = var.compartment_ocid + display_name = "PostgreSQLNAT" + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_route_table" "postgresql_rt2" { + count = (var.create_in_private_subnet && !var.use_existing_vcn) ? 1 : 0 + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + display_name = "PostgreSQLRouteTable2" + + route_rules { + destination = "0.0.0.0/0" + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_nat_gateway.postgresql_nat[count.index].id + } + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + +resource "oci_core_subnet" "postgresql_subnet" { + count = !var.use_existing_vcn ? 1 : 0 + cidr_block = var.postgresql_subnet_cidr + display_name = "PostgreSQLSubnet" + dns_label = "postgressubnet" + security_list_ids = [oci_core_security_list.postgresql_securitylist[0].id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + route_table_id = var.create_in_private_subnet ? oci_core_route_table.postgresql_rt2[0].id : oci_core_route_table.postgresql_rt[0].id + dhcp_options_id = oci_core_virtual_network.postgresql_vcn[0].default_dhcp_options_id + prohibit_public_ip_on_vnic = var.create_in_private_subnet ? true : false + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} + diff --git a/orm/provider.tf b/orm/provider.tf new file mode 100644 index 0000000..57cc21a --- /dev/null +++ b/orm/provider.tf @@ -0,0 +1,30 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +terraform { + required_version = ">= 0.14" + required_providers { + oci = { + source = "hashicorp/oci" + version = "4.34.0" + } + } +} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + # user_ocid = var.user_ocid + # fingerprint = var.fingerprint + # private_key_path = var.private_key_path + region = var.region +} + +provider "oci" { + alias = "homeregion" + tenancy_ocid = var.tenancy_ocid + # user_ocid = var.user_ocid + # fingerprint = var.fingerprint + # private_key_path = var.private_key_path + region = data.oci_identity_region_subscriptions.home_region_subscriptions.region_subscriptions[0].region_name + disable_auto_retries = "true" +} diff --git a/orm/variables.tf b/orm/variables.tf new file mode 100644 index 0000000..d7e8d85 --- /dev/null +++ b/orm/variables.tf @@ -0,0 +1,184 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +#variable "user_ocid" {} +#variable "fingerprint" {} +#variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} + +variable "use_existing_vcn" { + default = false +} + +variable "postgresql_vcn" { + default = "" +} + +variable "postgresql_subnet" { + default = "" +} + +variable "show_advanced" { + default = false +} + +variable "create_in_private_subnet" { + default = true +} + +variable "create_drg_for_private_subnet" { + default = true +} + +variable "release" { + description = "Reference Architecture Release (OCI Architecture Center)" + default = "1.4" +} + +variable "ssh_public_key" { + default = "" +} + +variable "postgresql_vcn_cidr" { + default = "10.1.0.0/16" +} + +variable "postgresql_subnet_cidr" { + default = "10.1.20.0/24" +} + +variable "postgresql_instance_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_instance_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_instance_flex_shape_memory" { + default = 10 +} + +variable "instance_os" { + description = "Operating system for compute instances" + default = "Oracle Linux" +} + +variable "linux_os_version" { + description = "Operating system version for all Linux instances" + default = "7.9" +} + +variable "postgresql_master_fd" { + default = "FAULT-DOMAIN-1" +} + +variable "postgresql_replicat_username" { + default = "replicator" +} + +variable "postgresql_password" { + default = "" +} + +variable "postgresql_version" { + default = "13" +} + +variable "add_iscsi_volume" { + default = true +} + +variable "iscsi_volume_size_in_gbs" { + default = 100 +} + +variable "boot_volume_backup_policy_enabled" { + default = true +} + +variable "boot_volume_backup_policy_level" { + default = "gold" +} + +variable "boot_volume_initial_backup" { + default = true +} + +variable "block_volume_backup_policy_enabled" { + default = true +} + +variable "block_volume_backup_policy_level" { + default = "gold" +} + +variable "block_volume_initial_backup" { + default = true +} + +variable "postgresql_deploy_hotstandby1" { + default = false +} + +variable "postgresql_hotstandby1_fd" { + default = "FAULT-DOMAIN-2" +} + +variable "postgresql_hotstandby1_ad" { + default = "" +} + +variable "postgresql_hotstandby1_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_hotstandby1_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_hotstandby1_flex_shape_memory" { + default = 10 +} + +variable "postgresql_deploy_hotstandby2" { + default = false +} + +variable "postgresql_hotstandby2_fd" { + default = "FAULT-DOMAIN-3" +} + +variable "postgresql_hotstandby2_ad" { + default = "" +} + +variable "postgresql_hotstandby2_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_hotstandby2_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_hotstandby2_flex_shape_memory" { + default = 10 +} + +# Dictionary Locals +locals { + compute_flexible_shapes = [ + "VM.Standard.E3.Flex", + "VM.Standard.E4.Flex" + ] +} + +# Checks if is using Flexible Compute Shapes +locals { + is_flexible_postgresql_instance_shape = contains(local.compute_flexible_shapes, var.postgresql_instance_shape) + is_flexible_postgresql_hotstandby1_shape = contains(local.compute_flexible_shapes, var.postgresql_hotstandby1_shape) + is_flexible_postgresql_hotstandby2_shape = contains(local.compute_flexible_shapes, var.postgresql_hotstandby2_shape) +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..4703c4a --- /dev/null +++ b/outputs.tf @@ -0,0 +1,27 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +output "PostgreSQL_Master_VM_public_IP" { + value = data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address +} + +output "PostgreSQL_Username" { + value = "postgres" +} + +output "generated_ssh_private_key" { + value = tls_private_key.public_private_key_pair.private_key_pem + sensitive = true +} + +output "bastion_ssh_postgresql_master_session_metadata" { + value = oci_bastion_session.ssh_postgresql_master_session.*.ssh_metadata +} + +output "bastion_ssh_postgresql_hotstandby1_session_metadata" { + value = oci_bastion_session.ssh_postgresql_hotstandby1_session.*.ssh_metadata +} + +output "bastion_ssh_postgresql_hotstandby2_session_metadata" { + value = oci_bastion_session.ssh_postgresql_hotstandby2_session.*.ssh_metadata +} diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..7963153 --- /dev/null +++ b/provider.tf @@ -0,0 +1,30 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +terraform { + required_version = ">= 0.14" + required_providers { + oci = { + source = "hashicorp/oci" + version = "4.34.0" + } + } +} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = var.region +} + +provider "oci" { + alias = "homeregion" + tenancy_ocid = var.tenancy_ocid + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path + region = data.oci_identity_region_subscriptions.home_region_subscriptions.region_subscriptions[0].region_name + disable_auto_retries = "true" +} diff --git a/release_files.json b/release_files.json index 19a2bdd..a910046 100644 --- a/release_files.json +++ b/release_files.json @@ -1,3 +1,39 @@ // see https://github.com/oracle-devrel/action-release-zip-maker for docs [ -] + { + "action": "create_zip", + "file_name": "terraform-oci-arch-postgresql-stack-latest.zip", + "files": [ + { + "src_pattern": "*.tf", + "dst_path": ".", + "exclude": [ + "provider.tf", + "variables.tf" + ] + }, + { + "src": "LICENSE" + }, + { + "src": "schema.yaml", + "dst": "schema.yaml" + }, + { + "src": "orm/variables.tf", + "dst": "variables.tf" + }, + { + "src": "orm/provider.tf", + "dst": "provider.tf" + }, + { + "src_pattern": "scripts/*" + } + ] + }, + { + "action": "upload_file", + "file_name": "terraform-oci-arch-postgresql-stack-latest.zip" + } +] \ No newline at end of file diff --git a/remote.tf b/remote.tf new file mode 100644 index 0000000..7e5aaeb --- /dev/null +++ b/remote.tf @@ -0,0 +1,909 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +data "template_file" "postgresql_install_binaries_sh" { + template = file("${path.module}/scripts/postgresql_install_binaries.sh") + + vars = { + pg_password = var.postgresql_password + pg_version_no_dot = replace(var.postgresql_version, ".", "") + pg_version = var.postgresql_version + } +} + +data "template_file" "postgresql_master_initdb_sh" { + template = file("${path.module}/scripts/postgresql_master_initdb.sh") + + vars = { + pg_password = var.postgresql_password + pg_version_no_dot = replace(var.postgresql_version, ".", "") + pg_version = var.postgresql_version + add_iscsi_volume = var.add_iscsi_volume + } +} + +data "template_file" "postgresql_master_setup_sql" { + template = file("${path.module}/scripts/postgresql_master_setup.sql") + + vars = { + pg_replicat_username = var.postgresql_replicat_username + pg_replicat_password = var.postgresql_password + } +} + +data "template_file" "postgresql_master_setup_sh" { + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + template = file("${path.module}/scripts/postgresql_master_setup.sh") + + vars = { + pg_master_ip = data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address + pg_hotstandby_ip = element(data.oci_core_vnic.postgresql_hotstandby1_primaryvnic.*.private_ip_address, 0) + pg_password = var.postgresql_password + pg_version_no_dot = replace(var.postgresql_version, ".", "") + pg_version = var.postgresql_version + pg_replicat_username = var.postgresql_replicat_username + node_subnet_cidr = var.postgresql_subnet_cidr + add_iscsi_volume = var.add_iscsi_volume + } +} + +data "template_file" "postgresql_master_setup2_sh" { + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + template = file("${path.module}/scripts/postgresql_master_setup2.sh") + + vars = { + pg_master_ip = data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address + pg_hotstandby_ip = element(data.oci_core_vnic.postgresql_hotstandby2_primaryvnic.*.private_ip_address, 0) + pg_version = var.postgresql_version + pg_replicat_username = var.postgresql_replicat_username + add_iscsi_volume = var.add_iscsi_volume + } +} + +data "template_file" "postgresql_standby_setup_sh" { + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + template = file("${path.module}/scripts/postgresql_standby_setup.sh") + + vars = { + pg_master_ip = data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address + pg_hotstandby_ip = element(data.oci_core_vnic.postgresql_hotstandby1_primaryvnic.*.private_ip_address, 0) + pg_password = var.postgresql_password + pg_version_no_dot = replace(var.postgresql_version, ".", "") + pg_version = var.postgresql_version + pg_replicat_username = var.postgresql_replicat_username + pg_replicat_password = var.postgresql_password + add_iscsi_volume = var.add_iscsi_volume + } +} + +resource "null_resource" "postgresql_master_attach_volume" { + + triggers = { + postgresql_master_id = oci_core_instance.postgresql_master.id + } + + count = var.add_iscsi_volume ? 1 : 0 + depends_on = [oci_core_instance.postgresql_master, oci_core_volume.postgresql_master_volume, oci_core_volume_attachment.postgresql_master_volume_attachment] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"rm -rf /home/opc/iscsiattach.sh\""] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + source = "${path.module}/scripts/iscsiattach.sh" + destination = "/home/opc/iscsiattach.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"chown root /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"chmod u+x /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"/home/opc/iscsiattach.sh\""] + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo -u root parted /dev/sdb --script -- mklabel gpt", + "sudo -u root parted /dev/sdb --script -- mkpart primary ext4 0% 100%", + "sudo -u root mkfs.ext4 /dev/sdb1 -F", + "sudo -u root mkdir /data", + "sudo -u root mount /dev/sdb1 /data", + "sudo /bin/su -c \"echo '/dev/sdb1 /data ext4 defaults,noatime,_netdev 0 0' >> /etc/fstab\"", + "sudo -u root mount | grep sdb1", + ] + } + +} + +resource "null_resource" "postgresql_master_install_binaries" { + + triggers = { + postgresql_master_id = oci_core_instance.postgresql_master.id + } + + depends_on = [oci_core_instance.postgresql_master, null_resource.postgresql_master_attach_volume] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_install_binaries.sh" + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = data.template_file.postgresql_install_binaries_sh.rendered + destination = "~/postgresql_install_binaries.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_install_binaries.sh", + "sudo ~/postgresql_install_binaries.sh" + ] + } +} + +resource "null_resource" "postgresql_master_initdb" { + + triggers = { + postgresql_master_id = oci_core_instance.postgresql_master.id + } + + depends_on = [null_resource.postgresql_master_install_binaries] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_master_initdb.sh" + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = data.template_file.postgresql_master_initdb_sh.rendered + destination = "~/postgresql_master_initdb.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_master_initdb.sh", + "sudo ~/postgresql_master_initdb.sh" + ] + } +} + +resource "null_resource" "postgresql_hotstandby1_install_binaries" { + + triggers = { + postgresql_hotstandby1_id = oci_core_instance.postgresql_hotstandby1[0].id + } + + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + depends_on = [oci_core_instance.postgresql_master, oci_core_instance.postgresql_hotstandby1, null_resource.postgresql_hotstandby1_attach_volume] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_install_binaries.sh" + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = data.template_file.postgresql_install_binaries_sh.rendered + destination = "~/postgresql_install_binaries.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_install_binaries.sh", + "sudo ~/postgresql_install_binaries.sh" + ] + } +} + +resource "null_resource" "postgresql_hotstandby2_install_binaries" { + + triggers = { + postgresql_hotstandby2_id = oci_core_instance.postgresql_hotstandby2[0].id + } + + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + depends_on = [oci_core_instance.postgresql_master, oci_core_instance.postgresql_hotstandby2, null_resource.postgresql_hotstandby2_attach_volume] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_install_binaries.sh" + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = data.template_file.postgresql_install_binaries_sh.rendered + destination = "~/postgresql_install_binaries.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_install_binaries.sh", + "sudo ~/postgresql_install_binaries.sh" + ] + } +} + + +resource "null_resource" "postgresql_master_setup" { + + triggers = { + postgresql_master_id = oci_core_instance.postgresql_master.id + } + + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + depends_on = [null_resource.postgresql_master_initdb, null_resource.postgresql_hotstandby1_install_binaries] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_master_setup.sh", + "sudo rm -rf /tmp/postgresql_master_setup_sql", + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = element(data.template_file.postgresql_master_setup_sh.*.rendered, 0) + destination = "~/postgresql_master_setup.sh" + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = element(data.template_file.postgresql_master_setup_sql.*.rendered, 0) + destination = "/tmp/postgresql_master_setup.sql" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_master_setup.sh", + "sudo ~/postgresql_master_setup.sh" + ] + } +} + +resource "null_resource" "postgresql_master_setup2" { + + triggers = { + postgresql_master_id = oci_core_instance.postgresql_master.id + } + + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + depends_on = [null_resource.postgresql_master_initdb, null_resource.postgresql_hotstandby2_install_binaries, null_resource.postgresql_master_setup, null_resource.postgresql_hotstandby1_setup] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_master_setup2.sh", + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = element(data.template_file.postgresql_master_setup2_sh.*.rendered, 0) + destination = "~/postgresql_master_setup2.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_master_primaryvnic.private_ip_address : data.oci_core_vnic.postgresql_master_primaryvnic.public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_master_session[0].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_master_setup2.sh", + "sudo ~/postgresql_master_setup2.sh" + ] + } +} + + +resource "null_resource" "postgresql_hotstandby1_attach_volume" { + + triggers = { + postgresql_hotstandby1_id = oci_core_instance.postgresql_hotstandby1[0].id + } + + count = (var.postgresql_deploy_hotstandby1 && var.add_iscsi_volume) ? 1 : 0 + depends_on = [oci_core_instance.postgresql_hotstandby1, oci_core_volume.postgresql_hotstandby1_volume, oci_core_volume_attachment.postgresql_hotstandby1_volume_attachment] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"rm -rf /home/opc/iscsiattach.sh\""] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + source = "${path.module}/scripts/iscsiattach.sh" + destination = "/home/opc/iscsiattach.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"chown root /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"chmod u+x /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"/home/opc/iscsiattach.sh\""] + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo -u root parted /dev/sdb --script -- mklabel gpt", + "sudo -u root parted /dev/sdb --script -- mkpart primary ext4 0% 100%", + "sudo -u root mkfs.ext4 /dev/sdb1 -F", + "sudo -u root mkdir /data", + "sudo -u root mount /dev/sdb1 /data", + "sudo /bin/su -c \"echo '/dev/sdb1 /data ext4 defaults,noatime,_netdev 0 0' >> /etc/fstab\"", + "sudo -u root mount | grep sdb1", + ] + } +} + +resource "null_resource" "postgresql_hotstandby1_setup" { + + triggers = { + postgresql_hotstandby1_id = oci_core_instance.postgresql_hotstandby1[0].id + } + + count = var.postgresql_deploy_hotstandby1 ? 1 : 0 + depends_on = [null_resource.postgresql_master_setup, null_resource.postgresql_hotstandby1_install_binaries, null_resource.postgresql_hotstandby1_attach_volume] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_standby_setup.sh", + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = element(data.template_file.postgresql_standby_setup_sh.*.rendered, 0) + destination = "~/postgresql_standby_setup.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby1_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby1_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_standby_setup.sh", + "sudo ~/postgresql_standby_setup.sh" + ] + } +} + +resource "null_resource" "postgresql_hotstandby2_attach_volume" { + + triggers = { + postgresql_hotstandby2_id = oci_core_instance.postgresql_hotstandby2[0].id + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"rm -rf /home/opc/iscsiattach.sh\""] + } + + count = (var.postgresql_deploy_hotstandby2 && var.add_iscsi_volume) ? 1 : 0 + depends_on = [oci_core_instance.postgresql_hotstandby2, oci_core_volume.postgresql_hotstandby2_volume, oci_core_volume_attachment.postgresql_hotstandby2_volume_attachment] + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + source = "${path.module}/scripts/iscsiattach.sh" + destination = "/home/opc/iscsiattach.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = ["sudo /bin/su -c \"chown root /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"chmod u+x /home/opc/iscsiattach.sh\"", + "sudo /bin/su -c \"/home/opc/iscsiattach.sh\""] + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo -u root parted /dev/sdb --script -- mklabel gpt", + "sudo -u root parted /dev/sdb --script -- mkpart primary ext4 0% 100%", + "sudo -u root mkfs.ext4 /dev/sdb1 -F", + "sudo -u root mkdir /data", + "sudo -u root mount /dev/sdb1 /data", + "sudo /bin/su -c \"echo '/dev/sdb1 /data ext4 defaults,noatime,_netdev 0 0' >> /etc/fstab\"", + "sudo -u root mount | grep sdb1", + ] + } +} + +resource "null_resource" "postgresql_hotstandby2_setup" { + + triggers = { + postgresql_hotstandby2_id = oci_core_instance.postgresql_hotstandby2[0].id + } + + count = var.postgresql_deploy_hotstandby2 ? 1 : 0 + depends_on = [null_resource.postgresql_master_setup2, null_resource.postgresql_hotstandby1_setup, null_resource.postgresql_hotstandby2_install_binaries, null_resource.postgresql_hotstandby2_attach_volume] + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "sudo rm -rf ~/postgresql_standby_setup.sh", + ] + } + + provisioner "file" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + + content = element(data.template_file.postgresql_standby_setup_sh.*.rendered, 0) + destination = "~/postgresql_standby_setup.sh" + } + + provisioner "remote-exec" { + connection { + type = "ssh" + user = "opc" + host = var.create_in_private_subnet ? data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].private_ip_address : data.oci_core_vnic.postgresql_hotstandby2_primaryvnic[count.index].public_ip_address + private_key = tls_private_key.public_private_key_pair.private_key_pem + script_path = "/home/opc/myssh.sh" + agent = false + timeout = "10m" + bastion_host = var.create_in_private_subnet ? "host.bastion.${var.region}.oci.oraclecloud.com" : null + bastion_port = var.create_in_private_subnet ? "22" : null + bastion_user = var.create_in_private_subnet ? oci_bastion_session.ssh_postgresql_hotstandby2_session[count.index].id : null + bastion_private_key = var.create_in_private_subnet ? tls_private_key.public_private_key_pair.private_key_pem : null + } + inline = [ + "chmod +x ~/postgresql_standby_setup.sh", + "sudo ~/postgresql_standby_setup.sh" + ] + } +} diff --git a/schema.yaml b/schema.yaml new file mode 100644 index 0000000..d6f3082 --- /dev/null +++ b/schema.yaml @@ -0,0 +1,537 @@ +## Copyright © 2021, Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + + title: "Create three-node deployment of a High Available PostgreSQL database on Oracle Cloud Infrastructure Compute instances." + stackDescription: "Deploy typical three-node deployment of a High Available PostgreSQL database on Oracle Cloud Infrastructure Compute instances." + schemaVersion: 1.1.0 + version: "20190404" + locale: "en" + + variableGroups: + - title: General Configuration + visible: false + variables: + - tenancy_ocid + - region + - release + - use_existing_vcn + - postgresql_vcn + - postgresql_subnet + + - title: Required Configuration + variables: + - compartment_ocid + - availablity_domain_name + - postgresql_version + - postgresql_password + - postgresql_deploy_hotstandby1 + - postgresql_deploy_hotstandby2 + - create_in_private_subnet + - show_advanced + + - title: Network Optional Configuration + visible: + and: + - show_advanced + variables: + - postgresql_vcn_cidr + - postgresql_subnet_cidr + - create_drg_for_private_subnet + + - title: Compute, Storage & Backup Optional Configuration + visible: + and: + - show_advanced + variables: + - ssh_public_key + - instance_os + - linux_os_version + - add_iscsi_volume + - boot_volume_backup_policy_enabled + - boot_volume_backup_policy_level + - boot_volume_initial_backup + - iscsi_volume_size_in_gbs + - block_volume_backup_policy_enabled + - block_volume_backup_policy_level + - block_volume_initial_backup + + - title: PostgreSQL Master Optional Configuration + visible: + and: + - show_advanced + variables: + - postgresql_master_fd + - postgresql_instance_shape + - postgresql_instance_flex_shape_ocpus + - postgresql_instance_flex_shape_memory + - postgresql_replicat_username + + - title: PostgreSQL HotStandby1 Optional Configuration + visible: + and: + - show_advanced + - postgresql_deploy_hotstandby1 + variables: + - postgresql_hotstandby1_ad + - postgresql_hotstandby1_fd + - postgresql_hotstandby1_shape + - postgresql_hotstandby1_flex_shape_ocpus + - postgresql_hotstandby1_flex_shape_memory + + - title: PostgreSQL HotStandby2 Configuration + visible: + and: + - show_advanced + - postgresql_deploy_hotstandby2 + variables: + - postgresql_hotstandby2_ad + - postgresql_hotstandby2_fd + - postgresql_hotstandby2_shape + - postgresql_hotstandby2_flex_shape_ocpus + - postgresql_hotstandby2_flex_shape_memory + + variables: + + show_advanced: + type: boolean + title: "Show advanced options?" + description: "Shows advanced options." + visible: true + default: false + + postgresql_deploy_hotstandby1: + type: boolean + title: "Deploy first PostgreSQL HotStandby?" + description: "Check the box to deploy first PostgreSQL HotStandby." + visible: true + default: true + + postgresql_deploy_hotstandby2: + type: boolean + title: "Deploy second PostgreSQL HotStandby?" + description: "Check the box to deploy second PostgreSQL HotStandby." + visible: true + default: true + + compartment_ocid: + type: oci:identity:compartment:id + required: true + visible: true + title: Compartment + description: "Compartment where you want to create the solution resources" + + region: + type: oci:identity:region:name + required: true + visible: true + title: Region + description: "Region where you want to deploy the resources defined by this stack." + + availablity_domain_name: + type: oci:identity:availabilitydomain:name + required: true + visible: true + title: "Availability Domain for master PostgreSQL" + description: "Availability Domain to be chosen for master PostgreSQL." + dependsOn: + compartmentId: ${compartment_ocid} + + ssh_public_key: + type: oci:core:ssh:publickey + title: "Public SSH Key" + description: "Choose public SSH Key to be uploaded into compute instances." + required: false + + postgresql_password: + type: password + required: true + visible: true + title: "PostgreSQL Password" + description: "The password must start with a letter, and it can contain letters (uppercase, lowercase), numbers, and the symbols _ $ #" + minLength: 12 + maxLength: 30 + pattern: ^[A-Za-z][A-Za-z0-9_#\$]+$ + + postgresql_version: + type: enum + visible: true + required: true + title: "PostgreSQL Version" + description: "Choose PostgreSQL Version." + default: "13" + enum: + - "13" + - "12" + - "11" + - "10" + - "9.6" + + create_in_private_subnet: + type: boolean + visible: true + required: true + title: "Create in Private Subnet" + description: "Providing an option to create PostgreSQL VMs in private or public subnet (for private subnet OCI Bastion Service will be provisioned)." + default: true + + # Optional Configuration + + add_iscsi_volume: + type: boolean + title: "Add iSCSI Volume to compute?" + description: "Check the box to add iSCSI Volume to compute instance." + visible: true + default: true + + iscsi_volume_size_in_gbs: + type: number + title: "iSCSI Volume Size in GB" + description: "Choose the size of iSCSI volume attached to compute instance (default=100GB, min=50GB, max=32000GB)." + required: false + minimum: 50 + maximum: 32000 + multipleOf: 1 + default: 100 + visible: + and: + - add_iscsi_volume + + boot_volume_backup_policy_enabled: + type: boolean + title: "Enable Boot Volume Backup Policy" + description: "Check the box if you want to add Boot Volume Backup Policy." + visible: true + default: true + + boot_volume_backup_policy_level: + type: enum + required: false + title: "Boot Volume Backup Policy" + description: "Choose the value for Boot Volume Backup Policy." + default: "gold" + enum: + - "gold" + - "silver" + - "bronze" + visible: + and: + - boot_volume_backup_policy_enabled + + boot_volume_initial_backup: + type: boolean + title: "Initial FULL backup of the Boot Volume" + description: "Check the box if you want to take initial FULL backup of the Boot Volume." + visible: true + default: true + + block_volume_backup_policy_enabled: + type: boolean + title: "Enable iSCSI Block Volume Backup Policy" + description: "Check the box if you want to add iSCSI Block Volume Backup Policy." + visible: + and: + - add_iscsi_volume + default: true + + block_volume_backup_policy_level: + type: enum + required: false + title: "iSCSI Block Volume Backup Policy" + description: "Choose the value for iSCSI Block Volume Backup Policy." + default: "gold" + enum: + - "gold" + - "silver" + - "bronze" + visible: + and: + - add_iscsi_volume + - block_volume_backup_policy_enabled + + block_volume_initial_backup: + type: boolean + title: "Initial FULL backup of the iSCSI Block Volume" + description: "Check the box if you want to take initial FULL backup of the iSCSI Block Volume." + visible: + and: + - add_iscsi_volume + default: true + + + postgresql_vcn_cidr: + type: string + visible: true + required: false + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + title: "VCN CIDR" + description: "Choose VCN CIDR for your PostgreSQL deployments." + default: "10.1.0.0/16" + + postgresql_subnet_cidr: + type: string + visible: true + required: false + pattern: "^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])$" + title: "VCN CIDR" + description: "Choose Subnet CIDR for your PostgreSQL deployments." + default: "10.1.20.0/24" + + create_drg_for_private_subnet: + type: boolean + visible: + and: + - create_in_private_subnet + required: false + title: "Create DRG for Private Subnet scenario" + description: "Providing an option to create Dynamic Routing Gateway (DRG) for VCN and afterwards you can connect to your private subnet from on-premise." + default: true + + postgresql_instance_shape: + type: oci:core:instanceshape:name + required: false + title: "Shape for PostgreSQL Master node" + description: "Choose shape for PostgreSQL Master node." + default: "VM.Standard.E3.Flex" + dependsOn: + compartmentId: ${compartment_ocid} + + postgresql_instance_flex_shape_ocpus: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 1 + title: "Flex Shape OCPUs" + description: "Choose number of OCPUs for Flex Shape." + visible: + and: + - or: + - eq: + - postgresql_instance_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_instance_shape + - "VM.Standard.E4.Flex" + + postgresql_instance_flex_shape_memory: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 10 + title: "Flex Shape Memory (GB)" + description: "Choose number GB for Flex Shape Memory." + visible: + and: + - or: + - eq: + - postgresql_instance_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_instance_shape + - "VM.Standard.E4.Flex" + + + instance_os: + type: enum + required: false + title: "Instance OS" + description: "An Operating System that determines the operating system for the instance." + default: "Oracle Linux" + enum: + - "Oracle Linux" + + linux_os_version: + type: enum + required: false + title: "Instance OS version" + description: "An Operating System version that determines the operating system version for the instance." + default: "7.9" + enum: + - "7.8" + - "7.9" + + postgresql_master_fd: + type: enum + required: false + title: "PostgreSQL Master Fault Domain" + description: "Choose Fault Domain for PostgreSQL Master." + default: "FAULT-DOMAIN-1" + enum: + - "FAULT-DOMAIN-1" + - "FAULT-DOMAIN-2" + - "FAULT-DOMAIN-3" + + postgresql_replicat_username: + type: string + required: false + title: "PostgreSQL Replicat Username" + description: "Type PostgreSQL Replicat Username" + + postgresql_hotstandby1_ad: + type: oci:identity:availabilitydomain:name + required: false + title: "AD for the first PostgreSQL HotStandby" + description: "Availability Domain for the first PostgreSQL HotStandby." + dependsOn: + compartmentId: ${compartment_ocid} + + postgresql_hotstandby1_fd: + type: enum + required: false + title: "The first PostgreSQL HotStandby's Fault Domain" + description: "Choose Fault Domain for the first PostgreSQL HotStandby." + default: "FAULT-DOMAIN-2" + enum: + - "FAULT-DOMAIN-1" + - "FAULT-DOMAIN-2" + - "FAULT-DOMAIN-3" + + postgresql_hotstandby1_shape: + type: oci:core:instanceshape:name + required: false + title: "Shape for the first PostgreSQL HotStandby node" + description: "Choose shape for the first PostgreSQL HotStandby node." + default: "VM.Standard.E3.Flex" + dependsOn: + compartmentId: ${compartment_ocid} + + postgresql_hotstandby1_flex_shape_ocpus: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 1 + title: "Flex Shape OCPUs" + description: "Choose number of OCPUs for Flex Shape." + visible: + and: + - or: + - eq: + - postgresql_hotstandby1_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_hotstandby1_shape + - "VM.Standard.E4.Flex" + + postgresql_hotstandby1_flex_shape_memory: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 10 + title: "Flex Shape Memory (GB)" + description: "Choose number GB for Flex Shape Memory." + visible: + and: + - or: + - eq: + - postgresql_hotstandby1_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_hotstandby1_shape + - "VM.Standard.E4.Flex" + + postgresql_hotstandby2_ad: + type: oci:identity:availabilitydomain:name + required: false + title: "AD for the second PostgreSQL HotStandby" + description: "Availability Domain for the second PostgreSQL HotStandby." + dependsOn: + compartmentId: ${compartment_ocid} + + postgresql_hotstandby2_fd: + type: enum + required: false + title: "The second PostgreSQL HotStandby's Fault Domain" + description: "Choose Fault Domain for the second PostgreSQL HotStandby." + default: "FAULT-DOMAIN-3" + enum: + - "FAULT-DOMAIN-1" + - "FAULT-DOMAIN-2" + - "FAULT-DOMAIN-3" + + postgresql_hotstandby2_shape: + type: oci:core:instanceshape:name + required: false + title: "Shape for the second PostgreSQL HotStandby node" + description: "Choose shape for the second PostgreSQL HotStandby node." + default: "VM.Standard.E3.Flex" + dependsOn: + compartmentId: ${compartment_ocid} + + postgresql_hotstandby2_flex_shape_ocpus: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 1 + title: "Flex Shape OCPUs" + description: "Choose number of OCPUs for Flex Shape." + visible: + and: + - or: + - eq: + - postgresql_hotstandby2_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_hotstandby2_shape + - "VM.Standard.E4.Flex" + + postgresql_hotstandby2_flex_shape_memory: + type: number + required: false + minimum: 1 + maximum: 128 + multipleOf: 1 + default: 10 + title: "Flex Shape Memory (GB)" + description: "Choose number GB for Flex Shape Memory." + visible: + and: + - or: + - eq: + - postgresql_hotstandby2_shape + - "VM.Standard.E3.Flex" + - eq: + - postgresql_hotstandby2_shape + - "VM.Standard.E4.Flex" + + + outputs: + + generated_ssh_private_key: + title: "Generated SSH Private Key" + displayText: "Generated SSH Private Key" + type: copyableString + visible: true + + PostgreSQL_Master_VM_public_IP: + title: "PostgreSQL Master VM public IP" + displayText: "PostgreSQL Master VM public IP" + type: string + visible: true + + PostgreSQL_HotStandby1_VM_public_IP: + title: "PostgreSQL HotStandby1 VM public IP" + displayText: "PostgreSQL HotStandby1 VM public IP" + type: string + visible: true + + PostgreSQL_HotStandby2_VM_public_IP: + title: "PostgreSQL HotStandby2 VM public IP" + displayText: "PostgreSQL HotStandby2 VM public IP" + type: string + visible: true + + PostgreSQL_Username: + title: "PostgreSQL Username" + displayText: "PostgreSQL Username" + type: string + visible: true + diff --git a/scripts/iscsiattach.sh b/scripts/iscsiattach.sh new file mode 100644 index 0000000..f102cc9 --- /dev/null +++ b/scripts/iscsiattach.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# iscsiattach.sh - Scan and automatically attach new iSCSI targets +# +# Author: Steven B. Nelson, Sr. Solutions Architect +# Oracle Cloud Infrastructure +# +# 20 April 2017 +# Copyright Oracle, Inc. All rights reserved. + +BASEADDR="169.254.2.2" + +# Set a base address incrementor so we can loop through all the +# addresses. +addrCount=0 + +#while [ ${addrCount} -le 32 ] +while [ ${addrCount} -le 1 ] +do + + CURRADDR=`echo ${BASEADDR} | awk -F\. '{last=$4+'${addrCount}';print $1"."$2"."$3"."last}'` + + clear + echo "Attempting connection to ${CURRADDR}" + + mkfifo discpipe + # Find all the iSCSI Block Storage volumes attached to the instance but + # not configured for use on the instance. Basically, get a list of the + # volumes that the instance can see, the loop through the ones it has, + # and add volumes not already configured on the instance. + # + # First get the list of volumes visible (attached) to the instance + + iscsiadm -m discovery -t st -p ${CURRADDR}:3260 | grep -v uefi | awk '{print $2}' > discpipe 2> /dev/null & + + # If the result is non-zero, that generally means that there are no targets available or + # that the portal is reachable but not active. We make no distinction between the two + # and simply skip ahead. + result=$? + if [ ${result} -ne 0 ] + then + (( addrCount = addrCount + 1 )) + continue + fi + + # Loop through the list (via the named FIFO pipe below) + while read target + do + mkfifo sesspipe + # Get the list of the currently attached Block Storage volumes + iscsiadm -m session -P 0 | grep -v uefi | awk '{print $4}' > sesspipe 2> /dev/null & + + # Set a flag, and loop through the sessions (attached, but not configured) + # and see if the volumes match. If so, skip to the next until we get + # through the list. Session list is via the pipe. + found="false" + while read session + do + if [ ${target} = ${session} ] + then + found="true" + break + fi + done < sesspipe + + # If the volume is not found, configure it. Get the resulting device file. + if [ ${found} = "false" ] + then + iscsiadm -m node -o new -T ${target} -p ${CURRADDR}:3260 + iscsiadm -m node -o update -T ${target} -n node.startup -v automatic + iscsiadm -m node -T ${target} -p ${CURRADDR}:3260 -l + sleep 10 + fi + done < discpipe + + (( addrCount = addrCount + 1 )) + find . -maxdepth 1 -type p -exec rm {} \; +done +echo "Scan Complete." diff --git a/scripts/postgresql_install_binaries.sh b/scripts/postgresql_install_binaries.sh new file mode 100644 index 0000000..df4e69e --- /dev/null +++ b/scripts/postgresql_install_binaries.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +echo '#####################################' +echo 'Starting PostgreSQL Install Binaries.' +echo '#####################################' + +# Install the repository RPM: +sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm + +# Install PostgreSQL: +sudo yum install -y postgresql${pg_version_no_dot}-server + +# Install PostgreSQL pg_basebackup utility +sudo yum-config-manager --enable ol7_developer +sudo yum-config-manager --enable ol7_developer_EPEL + +sudo yum install -y llvm5.0-devel +sudo yum install -y postgresql${pg_version_no_dot}-devel + +echo '#####################################' +echo 'PostgreSQL Install Binaries finished.' +echo '#####################################' diff --git a/scripts/postgresql_master_initdb.sh b/scripts/postgresql_master_initdb.sh new file mode 100644 index 0000000..2a317c8 --- /dev/null +++ b/scripts/postgresql_master_initdb.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +echo '#####################################' +echo 'Starting PostgreSQL Master initdb.' +echo '#####################################' + +export pg_version='${pg_version}' +export add_iscsi_volume='${add_iscsi_volume}' + +# Optionally initialize the database and enable automatic start: +if [[ $pg_version == "9.6" ]]; then + sudo /usr/pgsql-${pg_version}/bin/postgresql${pg_version_no_dot}-setup initdb +else + sudo /usr/pgsql-${pg_version}/bin/postgresql-${pg_version_no_dot}-setup initdb +fi + +if [[ $add_iscsi_volume == "true" ]]; then + sudo mkdir /data/pgsql + sudo chown -R postgres:postgres /data/pgsql + sudo -u postgres bash -c "/usr/pgsql-${pg_version_no_dot}/bin/initdb --pgdata=/data/pgsql" + sudo sed -i 's/Environment=PGDATA=\/var\/lib\/pgsql\/${pg_version_no_dot}\/data\//Environment=PGDATA=\/data\/pgsql\//g' /usr/lib/systemd/system/postgresql-${pg_version_no_dot}.service +fi + +sudo systemctl enable postgresql-${pg_version} +sudo systemctl start postgresql-${pg_version} +sudo systemctl status postgresql-${pg_version} + +if [[ $pg_version == "9.6" ]]; then + if [[ $add_iscsi_volume == "true" ]]; then + sudo -u root bash -c "tail -5 /data/pgsql/log/postgresql-*.log" + else + sudo -u root bash -c "tail -5 /var/lib/pgsql/${pg_version}/data/pg_log/postgresql-*.log" + fi +else + if [[ $add_iscsi_volume == "true" ]]; then + sudo -u root bash -c "tail -5 /data/pgsql/log/postgresql-*.log" + else + sudo -u root bash -c "tail -5 /var/lib/pgsql/${pg_version}/data/log/postgresql-*.log" + fi +fi + +echo '#####################################' +echo 'PostgreSQL Master initdb finished.' +echo '#####################################' \ No newline at end of file diff --git a/scripts/postgresql_master_setup.sh b/scripts/postgresql_master_setup.sh new file mode 100644 index 0000000..89fc28d --- /dev/null +++ b/scripts/postgresql_master_setup.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +echo '#################################################' +echo 'Starting PostgreSQL Master setup for HotStandby1.' +echo '#################################################' + +export pg_version='${pg_version}' +export add_iscsi_volume='${add_iscsi_volume}' + +# Change password of postgres user +echo "postgres:${pg_password}" | chpasswd + +# Setting firewall rules +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-source=${pg_hotstandby_ip}/32" +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-port=5432/tcp" +sudo -u root bash -c "firewall-cmd --reload" + +# Create replication user +chown postgres /tmp/postgresql_master_setup.sql +sudo -u postgres bash -c "psql -d template1 -f /tmp/postgresql_master_setup.sql" + +if [[ $add_iscsi_volume == "true" ]]; then + # Update the content of postgresql.conf to support WAL + sudo -u root bash -c "echo 'wal_level = replica' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'archive_mode = on' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'wal_log_hints = on' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'max_wal_senders = 3' | sudo tee -a /data/pgsql/postgresql.conf" + if [[ $pg_version == "13" ]]; then + sudo -u root bash -c "echo 'wal_keep_size = 16MB' | sudo tee -a /data/pgsql/postgresql.conf" + else + sudo -u root bash -c "echo 'wal_keep_segments = 8' | sudo tee -a /data/pgsql/postgresql.conf" + fi + sudo -u root bash -c "echo 'hot_standby = on' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'listen_addresses = '\''0.0.0.0'\'' ' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "chown postgres /data/pgsql/postgresql.conf" + + # Update the content of pg_hba to include standby host for replication + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_hotstandby_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_master_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_hotstandby_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_master_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${node_subnet_cidr} md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "chown postgres /data/pgsql/pg_hba.conf" +else + # Update the content of postgresql.conf to support WAL + sudo -u root bash -c "echo 'wal_level = replica' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'archive_mode = on' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'wal_log_hints = on' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'max_wal_senders = 3' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + if [[ $pg_version == "13" ]]; then + sudo -u root bash -c "echo 'wal_keep_size = 16MB' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + else + sudo -u root bash -c "echo 'wal_keep_segments = 8' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + fi + sudo -u root bash -c "echo 'hot_standby = on' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'listen_addresses = '\''0.0.0.0'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/postgresql.conf" + + # Update the content of pg_hba to include standby host for replication + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_hotstandby_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_master_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_hotstandby_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_master_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${node_subnet_cidr} md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/pg_hba.conf" +fi + +# Restart of PostrgreSQL service +sudo systemctl stop postgresql-${pg_version} +sudo systemctl start postgresql-${pg_version} +sudo systemctl status postgresql-${pg_version} + +echo '#################################################' +echo 'PostgreSQL Master setup for HotStandby1 finished.' +echo '#################################################' + diff --git a/scripts/postgresql_master_setup.sql b/scripts/postgresql_master_setup.sql new file mode 100644 index 0000000..f4f9eb5 --- /dev/null +++ b/scripts/postgresql_master_setup.sql @@ -0,0 +1,3 @@ +ALTER SYSTEM SET listen_addresses TO '*'; +CREATE USER ${pg_replicat_username} REPLICATION LOGIN ENCRYPTED PASSWORD '${pg_replicat_password}'; + diff --git a/scripts/postgresql_master_setup2.sh b/scripts/postgresql_master_setup2.sh new file mode 100644 index 0000000..a0aee68 --- /dev/null +++ b/scripts/postgresql_master_setup2.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +echo '#################################################' +echo 'Starting PostgreSQL Master setup for HotStandby2.' +echo '#################################################' + +export pg_version='${pg_version}' +export add_iscsi_volume='${add_iscsi_volume}' + +# Setting firewall rules +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-source=${pg_hotstandby_ip}/32" +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-port=5432/tcp" +sudo -u root bash -c "firewall-cmd --reload" + +if [[ $add_iscsi_volume == "true" ]]; then + # Update the content of pg_hba to include standby host for replication + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_hotstandby_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_hotstandby_ip}/32 md5' | sudo tee -a /data/pgsql/pg_hba.conf" + sudo -u root bash -c "chown postgres /data/pgsql/pg_hba.conf" +else + # Update the content of pg_hba to include standby host for replication + sudo -u root bash -c "echo 'host replication ${pg_replicat_username} ${pg_hotstandby_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "echo 'host all all ${pg_hotstandby_ip}/32 md5' | sudo tee -a /var/lib/pgsql/${pg_version}/data/pg_hba.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/pg_hba.conf" +fi + +# Restart of PostrgreSQL service +sudo systemctl stop postgresql-${pg_version} +sudo systemctl start postgresql-${pg_version} +sudo systemctl status postgresql-${pg_version} + +echo '#################################################' +echo 'PostgreSQL Master setup for HotStandby2 finished.' +echo '#################################################' \ No newline at end of file diff --git a/scripts/postgresql_standby_setup.sh b/scripts/postgresql_standby_setup.sh new file mode 100644 index 0000000..c4c5036 --- /dev/null +++ b/scripts/postgresql_standby_setup.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +echo '#################################################' +echo 'Starting PostgreSQL Standby Setup for HotStandby.' +echo '#################################################' + +export pg_version='${pg_version}' +export add_iscsi_volume='${add_iscsi_volume}' + +# Change password of postgres user +echo "postgres:${pg_password}" | chpasswd + +# Setting firewall rules +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-source=${pg_master_ip}/32" +sudo -u root bash -c "firewall-cmd --permanent --zone=trusted --add-port=5432/tcp" +sudo -u root bash -c "firewall-cmd --reload" + +if [[ $add_iscsi_volume == "true" ]]; then + # Create database on the volume + sudo mkdir /data/pgsql + sudo chown -R postgres:postgres /data/pgsql + sudo -u postgres bash -c "/usr/pgsql-${pg_version_no_dot}/bin/initdb --pgdata=/data/pgsql" + sudo sed -i 's/Environment=PGDATA=\/var\/lib\/pgsql\/${pg_version_no_dot}\/data\//Environment=PGDATA=\/data\/pgsql\//g' /usr/lib/systemd/system/postgresql-${pg_version_no_dot}.service + + # Take initial backup of database + sudo -u root bash -c "rm -rf /data/pgsql/*" + sudo -u postgres bash -c "export PGPASSWORD=${pg_replicat_password}; pg_basebackup -D /data/pgsql/ -h ${pg_master_ip} -X stream -c fast -U ${pg_replicat_username}" + # Update the content of recovery.conf + if [[ $pg_version == "13" ]]; then + touch /data/pgsql/standby.signal + touch /data/pgsql/recovery.signal + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "chown postgres /data/pgsql/postgresql.conf" + elif [[ $pg_version == "12" ]]; then + touch /data/pgsql/standby.signal + touch /data/pgsql/recovery.signal + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /data/pgsql/postgresql.conf" + sudo -u root bash -c "chown postgres /data/pgsql/postgresql.conf" + else + sudo -u root bash -c "echo 'standby_mode = '\''on'\'' ' | sudo tee -a /data/pgsql/recovery.conf" + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /data/pgsql/recovery.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /data/pgsql/recovery.conf" + sudo -u root bash -c "chown postgres /data/pgsql/recovery.conf" + fi +else + # Take initial backup of database + sudo -u root bash -c "rm -rf /var/lib/pgsql/${pg_version}/data/*" + sudo -u postgres bash -c "export PGPASSWORD=${pg_replicat_password}; pg_basebackup -D /var/lib/pgsql/${pg_version}/data/ -h ${pg_master_ip} -X stream -c fast -U ${pg_replicat_username}" + # Update the content of recovery.conf + if [[ $pg_version == "13" ]]; then + touch /var/lib/pgsql/${pg_version}/data/standby.signal + touch /var/lib/pgsql/${pg_version}/data/recovery.signal + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/postgresql.conf" + elif [[ $pg_version == "12" ]]; then + touch /var/lib/pgsql/${pg_version}/data/standby.signal + touch /var/lib/pgsql/${pg_version}/data/recovery.signal + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/postgresql.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/postgresql.conf" + else + sudo -u root bash -c "echo 'standby_mode = '\''on'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/recovery.conf" + sudo -u root bash -c "echo 'primary_conninfo = '\''host=${pg_master_ip} port=5432 user=${pg_replicat_username} password=${pg_replicat_password}'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/recovery.conf" + sudo -u root bash -c "echo 'recovery_target_timeline = '\''latest'\'' ' | sudo tee -a /var/lib/pgsql/${pg_version}/data/recovery.conf" + sudo -u root bash -c "chown postgres /var/lib/pgsql/${pg_version}/data/recovery.conf" + fi +fi + +# Restart of PostrgreSQL service +sudo systemctl enable postgresql-${pg_version} +sudo systemctl stop postgresql-${pg_version} +sudo systemctl start postgresql-${pg_version} +sudo systemctl status postgresql-${pg_version} + +if [[ $pg_version == "9.6" ]]; then + if [[ $add_iscsi_volume == "true" ]]; then + sudo -u root bash -c "tail -5 /data/pgsql/log/postgresql-*.log" + else + sudo -u root bash -c "tail -5 /var/lib/pgsql/${pg_version}/data/pg_log/postgresql-*.log" + fi +else + if [[ $add_iscsi_volume == "true" ]]; then + sudo -u root bash -c "tail -5 /data/pgsql/log/postgresql-*.log" + else + sudo -u root bash -c "tail -5 /var/lib/pgsql/${pg_version}/data/log/postgresql-*.log" + fi +fi + +echo '#################################################' +echo 'PostgreSQL Standby Setup for HotStandby finished.' +echo '#################################################' diff --git a/scripts/sshkey.tpl b/scripts/sshkey.tpl new file mode 100644 index 0000000..2555a46 --- /dev/null +++ b/scripts/sshkey.tpl @@ -0,0 +1,5 @@ +#!/bin/bash + +cp /home/opc/.ssh/authorized_keys /home/opc/.ssh/authorized_keys.bak +echo "${ssh_public_key}" >> /home/opc/.ssh/authorized_keys +chown -R opc /home/opc/.ssh/authorized_keys diff --git a/security-lists.tf b/security-lists.tf new file mode 100644 index 0000000..1c0becb --- /dev/null +++ b/security-lists.tf @@ -0,0 +1,35 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "oci_core_security_list" "postgresql_securitylist" { + count = !var.use_existing_vcn ? 1 : 0 + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.postgresql_vcn[0].id + display_name = "PostgreSQLSecurityList" + + egress_security_rules { + protocol = "6" + destination = "0.0.0.0/0" + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "22" + min = "22" + } + } + + ingress_security_rules { + protocol = "6" + source = "0.0.0.0/0" + + tcp_options { + max = "5432" + min = "5432" + } + } + defined_tags = { "${oci_identity_tag_namespace.ArchitectureCenterTagNamespace.name}.${oci_identity_tag.ArchitectureCenterTag.name}" = var.release } +} diff --git a/tags.tf b/tags.tf new file mode 100644 index 0000000..0f95f0f --- /dev/null +++ b/tags.tf @@ -0,0 +1,34 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "random_id" "tag" { + byte_length = 2 +} + +resource "oci_identity_tag_namespace" "ArchitectureCenterTagNamespace" { + provider = oci.homeregion + compartment_id = var.compartment_ocid + description = "ArchitectureCenterTagNamespace" + name = "ArchitectureCenter\\deploy-postgresql-db-${random_id.tag.hex}" + + provisioner "local-exec" { + command = "sleep 10" + } + +} + +resource "oci_identity_tag" "ArchitectureCenterTag" { + provider = oci.homeregion + description = "ArchitectureCenterTag" + name = "release" + tag_namespace_id = oci_identity_tag_namespace.ArchitectureCenterTagNamespace.id + + validator { + validator_type = "ENUM" + values = ["release", "1.4"] + } + + provisioner "local-exec" { + command = "sleep 120" + } +} diff --git a/tls.tf b/tls.tf new file mode 100644 index 0000000..7e5fa6d --- /dev/null +++ b/tls.tf @@ -0,0 +1,6 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +resource "tls_private_key" "public_private_key_pair" { + algorithm = "RSA" +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..d06f8cb --- /dev/null +++ b/variables.tf @@ -0,0 +1,184 @@ +## Copyright (c) 2021 Oracle and/or its affiliates. +## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl + +variable "tenancy_ocid" {} +variable "user_ocid" {} +variable "fingerprint" {} +variable "private_key_path" {} +variable "region" {} +variable "compartment_ocid" {} +variable "availablity_domain_name" {} + +variable "use_existing_vcn" { + default = false +} + +variable "postgresql_vcn" { + default = "" +} + +variable "postgresql_subnet" { + default = "" +} + +variable "show_advanced" { + default = false +} + +variable "create_in_private_subnet" { + default = true +} + +variable "create_drg_for_private_subnet" { + default = true +} + +variable "release" { + description = "Reference Architecture Release (OCI Architecture Center)" + default = "1.4" +} + +variable "ssh_public_key" { + default = "" +} + +variable "postgresql_vcn_cidr" { + default = "10.1.0.0/16" +} + +variable "postgresql_subnet_cidr" { + default = "10.1.20.0/24" +} + +variable "postgresql_instance_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_instance_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_instance_flex_shape_memory" { + default = 10 +} + +variable "instance_os" { + description = "Operating system for compute instances" + default = "Oracle Linux" +} + +variable "linux_os_version" { + description = "Operating system version for all Linux instances" + default = "7.9" +} + +variable "postgresql_master_fd" { + default = "FAULT-DOMAIN-1" +} + +variable "postgresql_replicat_username" { + default = "replicator" +} + +variable "postgresql_password" { + default = "" +} + +variable "postgresql_version" { + default = "13" +} + +variable "add_iscsi_volume" { + default = true +} + +variable "iscsi_volume_size_in_gbs" { + default = 100 +} + +variable "boot_volume_backup_policy_enabled" { + default = true +} + +variable "boot_volume_backup_policy_level" { + default = "gold" +} + +variable "boot_volume_initial_backup" { + default = true +} + +variable "block_volume_backup_policy_enabled" { + default = true +} + +variable "block_volume_backup_policy_level" { + default = "gold" +} + +variable "block_volume_initial_backup" { + default = true +} + +variable "postgresql_deploy_hotstandby1" { + default = false +} + +variable "postgresql_hotstandby1_fd" { + default = "FAULT-DOMAIN-2" +} + +variable "postgresql_hotstandby1_ad" { + default = "" +} + +variable "postgresql_hotstandby1_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_hotstandby1_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_hotstandby1_flex_shape_memory" { + default = 10 +} + +variable "postgresql_deploy_hotstandby2" { + default = false +} + +variable "postgresql_hotstandby2_fd" { + default = "FAULT-DOMAIN-3" +} + +variable "postgresql_hotstandby2_ad" { + default = "" +} + +variable "postgresql_hotstandby2_shape" { + default = "VM.Standard.E3.Flex" +} + +variable "postgresql_hotstandby2_flex_shape_ocpus" { + default = 1 +} + +variable "postgresql_hotstandby2_flex_shape_memory" { + default = 10 +} + +# Dictionary Locals +locals { + compute_flexible_shapes = [ + "VM.Standard.E3.Flex", + "VM.Standard.E4.Flex" + ] +} + +# Checks if is using Flexible Compute Shapes +locals { + is_flexible_postgresql_instance_shape = contains(local.compute_flexible_shapes, var.postgresql_instance_shape) + is_flexible_postgresql_hotstandby1_shape = contains(local.compute_flexible_shapes, var.postgresql_hotstandby1_shape) + is_flexible_postgresql_hotstandby2_shape = contains(local.compute_flexible_shapes, var.postgresql_hotstandby2_shape) +}