diff --git a/.gitignore b/.gitignore index 799c756..2a78f07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Local .terraform directories **/.terraform/* +**/.terrafor* # .tfstate files *.tfstate @@ -12,7 +13,6 @@ crash.log # .tfvars files are managed as part of configuration and so should be included in # version control. # -*.zip* *.tfvars # Ignore override files as they are usually used to override resources locally and so @@ -24,6 +24,9 @@ override.tf.json # General .DS_Store +**/.DS_Store +*.tgz +*.zip .AppleDouble .LSOverride diff --git a/README.md b/README.md index 27e22c7..15cc8ac 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,71 @@ # oci-dotnet -QuickStart on ASP.Net with simple Terraform scripts and ORM Stack + +QuickStart ASP.Net on OCI with Terraform scripts (Includes ORM Stack) + +## Deploy Using Oracle Resource Manager + +1. Click [![Deploy to Oracle Cloud][magic_button]][magic_dotnet_stack] + + If you aren't already signed in, when prompted, enter the tenancy and user credentials. + +1. Review and accept the terms and conditions. + +1. Select the region where you want to deploy the stack. + +1. Follow the on-screen prompts and instructions to create the stack. + +1. After creating the stack, click **Terraform Actions**, and select **Plan**. + +1. 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. + +1. 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 Module + +Now, you'll want a local copy of this repo. You can make that with the commands: + + git clone https://github.com/oracle-quickstart/oci-dotnet.git + cd oci-dotnet + ls + +### Set Up and Configure Terraform + +1. Complete the prerequisites described [here](https://github.com/cloud-partners/oci-prerequisites). + +1. Create a `terraform.tfvars` file, and specify the following variables: + +``` +# Authentication +tenancy_ocid = "" +user_ocid = "" +fingerprint = "" +private_key_path = "" + +# Region +region = "" + +# Compartment +compartment_ocid = "" + +```` + +### 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 + +[magic_button]: https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg +[magic_dotnet_stack]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/oracle-quickstart/oci-dotnet/releases/latest/download/oci-dotnet-stack-latest.zip diff --git a/compute.tf b/compute.tf new file mode 100755 index 0000000..a91d9be --- /dev/null +++ b/compute.tf @@ -0,0 +1,41 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +resource "oci_core_instance" "app_instance" { + availability_domain = random_shuffle.compute_ad.result[count.index % length(random_shuffle.compute_ad.result)] + compartment_id = var.compartment_ocid + display_name = "DotNet-${random_string.deploy_id.result}-${count.index}" + shape = var.instance_shape + freeform_tags = local.common_tags + + create_vnic_details { + subnet_id = oci_core_subnet.dotnet_main_subnet.id + display_name = "primaryvnic" + assign_public_ip = (var.instance_visibility == "Private") ? false : true + hostname_label = "dotnet-${random_string.deploy_id.result}-${count.index}" + } + + source_details { + source_type = "image" + source_id = lookup(data.oci_core_images.compute_images.images[0], "id") + } + + metadata = { + ssh_authorized_keys = var.generate_public_ssh_key ? tls_private_key.compute_ssh_key.public_key_openssh : var.public_ssh_key + user_data = data.template_cloudinit_config.instances.rendered + } + + count = var.num_instances +} + +### Important Security Notice ### +# The private key generated by this resource will be stored unencrypted in your Terraform state file. +# Use of this resource for production deployments is not recommended. +# Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run. + +# Generate ssh keys to access Compute Nodes, if generate_public_ssh_key=true, applies to the Compute +resource "tls_private_key" "compute_ssh_key" { + algorithm = "RSA" + rsa_bits = 2048 +} \ No newline at end of file diff --git a/datasources.tf b/datasources.tf new file mode 100644 index 0000000..21e8635 --- /dev/null +++ b/datasources.tf @@ -0,0 +1,127 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +# Gets a list of Availability Domains +data "oci_identity_availability_domains" "ADs" { + compartment_id = var.tenancy_ocid +} + +# Randoms +resource "random_string" "deploy_id" { + length = 4 + special = false +} + +# Check for resource limits +## Check available compute shape +data "oci_limits_services" "compute_services" { + compartment_id = var.tenancy_ocid + + filter { + name = "name" + values = ["compute"] + } +} +data "oci_limits_limit_definitions" "compute_limit_definitions" { + compartment_id = var.tenancy_ocid + service_name = data.oci_limits_services.compute_services.services.0.name + + filter { + name = "description" + values = [var.instance_shape] + } +} +data "oci_limits_resource_availability" "compute_resource_availability" { + compartment_id = var.tenancy_ocid + limit_name = data.oci_limits_limit_definitions.compute_limit_definitions.limit_definitions[0].name + service_name = data.oci_limits_services.compute_services.services.0.name + availability_domain = data.oci_identity_availability_domains.ADs.availability_domains[count.index].name + + count = length(data.oci_identity_availability_domains.ADs.availability_domains) +} +resource "random_shuffle" "compute_ad" { + input = local.compute_available_limit_ad_list + result_count = length(local.compute_available_limit_ad_list) +} +locals { + compute_available_limit_ad_list = [for limit in data.oci_limits_resource_availability.compute_resource_availability : limit.availability_domain if(limit.available - var.num_instances) >= 0] + compute_available_limit_error = length(local.compute_available_limit_ad_list) == 0 ? ( + file("ERROR: No limits available for the chosen compute shape and number of nodes")) : 0 +} + +# Gets a list of supported images based on the shape, operating_system and operating_system_version provided +data "oci_core_images" "compute_images" { + compartment_id = var.compartment_ocid + operating_system = var.image_operating_system + operating_system_version = var.image_operating_system_version + shape = var.instance_shape + sort_by = "TIMECREATED" + sort_order = "DESC" +} + +data "oci_identity_tenancy" "tenant_details" { + tenancy_id = var.tenancy_ocid + + provider = oci.current_region +} + +data "oci_identity_regions" "home_region" { + filter { + name = "key" + values = [data.oci_identity_tenancy.tenant_details.home_region_key] + } + + provider = oci.current_region +} + +# Available Services +data "oci_core_services" "all_services" { + filter { + name = "name" + values = ["All .* Services In Oracle Services Network"] + regex = true + } +} + +locals { + common_tags = { + Reference = "Created by OCI QuickStart for DotNet sample" + } +} + +# Cloud Init +data "template_cloudinit_config" "instances" { + gzip = true + base64_encode = true + + part { + filename = "cloud-config.yaml" + content_type = "text/cloud-config" + content = data.template_file.cloud_init.rendered + } +} +data "template_file" "cloud_init" { + template = file("${path.module}/scripts/cloud-config.template.yaml") + + vars = { + setup_preflight_sh_content = base64gzip(data.template_file.setup_preflight.rendered) + setup_template_sh_content = base64gzip(data.template_file.setup_template.rendered) + deploy_template_content = base64gzip(data.template_file.deploy_template.rendered) + } +} +data "template_file" "setup_preflight" { + template = file("${path.module}/scripts/setup.preflight.sh") +} +data "template_file" "setup_template" { + template = file("${path.module}/scripts/setup.template.sh") +} +data "template_file" "deploy_template" { + template = file("${path.module}/scripts/deploy.template.sh") + + vars = { + dotnet_standard_type = var.dotnet_standard_type + dotnet_custom_text_for_standard_webapp = var.dotnet_custom_text_for_standard_webapp + dotnet_git_custom_webapp = var.dotnet_git_custom_webapp + } +} \ No newline at end of file diff --git a/loadbalancer.tf b/loadbalancer.tf new file mode 100644 index 0000000..894cd7c --- /dev/null +++ b/loadbalancer.tf @@ -0,0 +1,66 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +resource "oci_load_balancer_load_balancer" "dotnet_lb" { + compartment_id = var.compartment_ocid + display_name = "DotNet-${random_string.deploy_id.result}" + shape = var.lb_shape + subnet_ids = [oci_core_subnet.dotnet_lb_subnet.id] + is_private = "false" + freeform_tags = local.common_tags +} + +resource "oci_load_balancer_backend_set" "dotnet_bes" { + name = "dotnet-${random_string.deploy_id.result}" + load_balancer_id = oci_load_balancer_load_balancer.dotnet_lb.id + policy = "IP_HASH" + + health_checker { + port = local.app_port_number + protocol = "HTTP" + response_body_regex = ".*" + url_path = "/" + return_code = 200 + interval_ms = 5000 + timeout_in_millis = 2000 + retries = 10 + } +} + +resource "oci_load_balancer_backend" "dotnet-be" { + load_balancer_id = oci_load_balancer_load_balancer.dotnet_lb.id + backendset_name = oci_load_balancer_backend_set.dotnet_bes.name + ip_address = element(oci_core_instance.app_instance.*.private_ip, count.index) + port = local.app_port_number + backup = false + drain = false + offline = false + weight = 1 + + count = var.num_instances +} + +resource "oci_load_balancer_listener" "dotnet_listener_80" { + load_balancer_id = oci_load_balancer_load_balancer.dotnet_lb.id + default_backend_set_name = oci_load_balancer_backend_set.dotnet_bes.name + name = "dotnet-${random_string.deploy_id.result}-80" + port = local.http_port_number + protocol = "HTTP" + + connection_configuration { + idle_timeout_in_seconds = "30" + } +} + +resource "oci_load_balancer_listener" "dotnet_listener_443" { + load_balancer_id = oci_load_balancer_load_balancer.dotnet_lb.id + default_backend_set_name = oci_load_balancer_backend_set.dotnet_bes.name + name = "dotnet-${random_string.deploy_id.result}-443" + port = local.https_port_number + protocol = "HTTP" + + connection_configuration { + idle_timeout_in_seconds = "30" + } +} \ No newline at end of file diff --git a/network.tf b/network.tf new file mode 100755 index 0000000..e3d48f6 --- /dev/null +++ b/network.tf @@ -0,0 +1,111 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +resource "oci_core_virtual_network" "dotnet_main_vcn" { + cidr_block = lookup(var.network_cidrs, "MAIN-VCN-CIDR") + compartment_id = var.compartment_ocid + display_name = "dotnet-main-${random_string.deploy_id.result}" + dns_label = "dotnetmain${random_string.deploy_id.result}" + freeform_tags = local.common_tags +} + +resource "oci_core_subnet" "dotnet_main_subnet" { + cidr_block = lookup(var.network_cidrs, "MAIN-SUBNET-REGIONAL-CIDR") + display_name = "dotnet-main-${random_string.deploy_id.result}" + dns_label = "dotnetmain${random_string.deploy_id.result}" + security_list_ids = [oci_core_security_list.dotnet_security_list.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + route_table_id = oci_core_route_table.dotnet_main_route_table.id + dhcp_options_id = oci_core_virtual_network.dotnet_main_vcn.default_dhcp_options_id + prohibit_public_ip_on_vnic = (var.instance_visibility == "Private") ? true : false + freeform_tags = local.common_tags +} + +resource "oci_core_subnet" "dotnet_lb_subnet" { + cidr_block = lookup(var.network_cidrs, ("MAIN-LB-SUBNET-REGIONAL-CIDR")) + display_name = "dotnet-lb-${random_string.deploy_id.result}" + dns_label = "dotnetlb${random_string.deploy_id.result}" + security_list_ids = [oci_core_security_list.dotnet_lb_security_list.id] + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + route_table_id = oci_core_route_table.dotnet_lb_route_table.id + dhcp_options_id = oci_core_virtual_network.dotnet_main_vcn.default_dhcp_options_id + prohibit_public_ip_on_vnic = false + freeform_tags = local.common_tags +} + +resource "oci_core_route_table" "dotnet_main_route_table" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + display_name = "dotnet-main-${random_string.deploy_id.result}" + freeform_tags = local.common_tags + + dynamic "route_rules" { + for_each = (var.instance_visibility == "Private") ? [1] : [] + content { + destination = lookup(data.oci_core_services.all_services.services[0], "cidr_block") + destination_type = "SERVICE_CIDR_BLOCK" + network_entity_id = oci_core_service_gateway.dotnet_service_gateway.id + } + } + + dynamic "route_rules" { + for_each = (var.instance_visibility == "Private") ? [] : [1] + content { + destination = lookup(var.network_cidrs, "ALL-CIDR") + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.dotnet_internet_gateway.id + } + } + +} + +resource "oci_core_route_table" "dotnet_lb_route_table" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + display_name = "dotnet-lb-${random_string.deploy_id.result}" + freeform_tags = local.common_tags + + route_rules { + destination = lookup(var.network_cidrs, "ALL-CIDR") + destination_type = "CIDR_BLOCK" + network_entity_id = oci_core_internet_gateway.dotnet_internet_gateway.id + } +} + +resource "oci_core_nat_gateway" "dotnet_nat_gateway" { + block_traffic = "false" + compartment_id = var.compartment_ocid + display_name = "dotnet-nat-gateway-${random_string.deploy_id.result}" + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + freeform_tags = local.common_tags + + count = var.use_only_always_free_elegible_resources ? 0 : ((var.instance_visibility == "Private") ? 0 : 0) +} + +resource "oci_core_internet_gateway" "dotnet_internet_gateway" { + compartment_id = var.compartment_ocid + display_name = "dotnet-internet-gateway-${random_string.deploy_id.result}" + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + freeform_tags = local.common_tags +} + +resource "oci_core_service_gateway" "dotnet_service_gateway" { + compartment_id = var.compartment_ocid + display_name = "dotnet-service-gateway-${random_string.deploy_id.result}" + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + services { + service_id = lookup(data.oci_core_services.all_services.services[0], "id") + } + + count = var.use_only_always_free_elegible_resources ? 0 : 1 +} + + + + + + + diff --git a/outputs.tf b/outputs.tf new file mode 100755 index 0000000..8e0bc5c --- /dev/null +++ b/outputs.tf @@ -0,0 +1,34 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +output "lb_public_url" { + value = format("http://%s", lookup(oci_load_balancer_load_balancer.dotnet_lb.ip_address_details[0], "ip_address")) +} + +### Important Security Notice ### +# The private key generated by this resource will be stored unencrypted in your Terraform state file. +# Use of this resource for production deployments is not recommended. +# Instead, generate a private key file outside of Terraform and distribute it securely to the system where Terraform will be run. +output "generated_private_key_pem" { + value = var.generate_public_ssh_key ? tls_private_key.compute_ssh_key.private_key_pem : "No Keys Auto Generated" +} + +output "dev" { + value = "Made with \u2764 by Oracle Developers" +} + +output "comments" { + value = "The application URL will be unavailable for a few minutes after provisioning, while the application is configured" +} + +output "deploy_id" { + value = random_string.deploy_id.result +} + +output "deployed_to_region" { + value = local.region_to_deploy +} +output "dotnet_template_used" { + value = var.dotnet_standard_type +} diff --git a/providers.tf b/providers.tf new file mode 100755 index 0000000..4f0d76f --- /dev/null +++ b/providers.tf @@ -0,0 +1,47 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +terraform { + required_version = ">= 0.13" + required_providers { + local = { source = "hashicorp/local" } + oci = { source = "hashicorp/oci" } + random = { source = "hashicorp/random" } + tls = { source = "hashicorp/tls" } + template = { source = "hashicorp/template" } + } +} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid + region = local.region_to_deploy + + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path +} + +provider "oci" { + alias = "home_region" + tenancy_ocid = var.tenancy_ocid + region = lookup(data.oci_identity_regions.home_region.regions[0], "name") + + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path +} + +provider "oci" { + alias = "current_region" + tenancy_ocid = var.tenancy_ocid + region = var.region + + user_ocid = var.user_ocid + fingerprint = var.fingerprint + private_key_path = var.private_key_path +} + +locals { + region_to_deploy = var.use_only_always_free_elegible_resources ? lookup(data.oci_identity_regions.home_region.regions[0], "name") : var.region +} \ No newline at end of file diff --git a/schema.yaml b/schema.yaml new file mode 100644 index 0000000..16a73f9 --- /dev/null +++ b/schema.yaml @@ -0,0 +1,254 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +title: "ASP.Net WebApp Sample" +description: "QuickStart on ASP.Net on Oracle Cloud Infrastructure" +schemaVersion: 1.1.0 +version: "20190304" + +source: + type: quickstart +logoUrl: data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiM1YzJkOTE7fS5jbHMtMiwuY2xzLTN7ZmlsbDojZmZmO30uY2xzLTJ7b3BhY2l0eTowLjE7fS5jbHMtNHtmaWxsOiNmMmYyZjI7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5sb2dvX05FVGNvcmU8L3RpdGxlPjxjaXJjbGUgY2xhc3M9ImNscy0xIiBjeD0iMzIiIGN5PSIzMiIgcj0iMzIiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik05LjgyLDlBMzIsMzIsMCwxLDAsNTUsNTQuMThaIi8+PHBhdGggY2xhc3M9ImNscy0zIiBkPSJNNy40LDM3LjI1YTEuMzUsMS4zNSwwLDAsMS0xLS40MiwxLjM4LDEuMzgsMCwwLDEtLjQxLTEsMS40LDEuNCwwLDAsMSwuNDEtMSwxLjM0LDEuMzQsMCwwLDEsMS0uNDMsMS4zNywxLjM3LDAsMCwxLDEsLjQzLDEuMzksMS4zOSwwLDAsMSwuNDIsMSwxLjM3LDEuMzcsMCwwLDEtLjQyLDFBMS4zOCwxLjM4LDAsMCwxLDcuNCwzNy4yNVoiLz48cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yNy4yNywzN0gyNC42NUwxNS4yOCwyMi40NmE2LDYsMCwwLDEtLjU4LTEuMTRoLS4wOGExOC43MiwxOC43MiwwLDAsMSwuMSwyLjVWMzdIMTIuNTlWMTguNzdoMi43N2w5LjEyLDE0LjI4cS41Ny44OS43NCwxLjIyaC4wNWExOS4yOCwxOS4yOCwwLDAsMS0uMTMtMi42OFYxOC43N2gyLjEzWiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTQxLjY5LDM3SDMyVjE4Ljc3aDkuMjRWMjAuN0gzNC4xOHY2LjA2aDYuNTh2MS45MkgzNC4xOFYzNWg3LjUyWiIvPjxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTU2LDIwLjdINTAuN1YzN0g0OC41N1YyMC43SDQzLjMzVjE4Ljc3SDU2WiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTI2LjEyLDQ5LjRhNC45Myw0LjkzLDAsMCwxLTIuMzIuNDksMy43NCwzLjc0LDAsMCwxLTIuODctMS4xNSw0LjI2LDQuMjYsMCwwLDEtMS4wOC0zLDQuNDYsNC40NiwwLDAsMSwxLjIxLTMuMjYsNC4xMiw0LjEyLDAsMCwxLDMuMDgtMS4yNCw0LjkzLDQuOTMsMCwwLDEsMiwuMzV2MWE0LDQsMCwwLDAtMi0uNSwzLjA2LDMuMDYsMCwwLDAtMi4zNSwxLDMuNjQsMy42NCwwLDAsMC0uOSwyLjU4LDMuNDcsMy40NywwLDAsMCwuODQsMi40NSwyLjg2LDIuODYsMCwwLDAsMi4yMS45MSw0LjE0LDQuMTQsMCwwLDAsMi4xOS0uNTZaIi8+PHBhdGggY2xhc3M9ImNscy00IiBkPSJNMzAuMjEsNDkuODlBMi43OCwyLjc4LDAsMCwxLDI4LjA4LDQ5YTMuMTEsMy4xMSwwLDAsMS0uNzktMi4yMywzLjI0LDMuMjQsMCwwLDEsLjgzLTIuMzYsMywzLDAsMCwxLDIuMjMtLjg1LDIuNjksMi42OSwwLDAsMSwyLjA5LjgzLDMuMjgsMy4yOCwwLDAsMSwuNzUsMi4yOSwzLjIyLDMuMjIsMCwwLDEtLjgxLDIuM0EyLjg0LDIuODQsMCwwLDEsMzAuMjEsNDkuODlabS4wNy01LjQ3YTEuODMsMS44MywwLDAsMC0xLjQ2LjYzLDIuNTksMi41OSwwLDAsMC0uNTQsMS43NCwyLjQ1LDIuNDUsMCwwLDAsLjU0LDEuNjgsMS44NSwxLjg1LDAsMCwwLDEuNDYuNjIsMS43NiwxLjc2LDAsMCwwLDEuNDMtLjYsMi42MiwyLjYyLDAsMCwwLC41LTEuNzIsMi42NiwyLjY2LDAsMCwwLS41LTEuNzNBMS43NSwxLjc1LDAsMCwwLDMwLjI4LDQ0LjQyWiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTM3Ljg2LDQ0LjcyYTEuMTgsMS4xOCwwLDAsMC0uNzMtLjE5LDEuMjMsMS4yMywwLDAsMC0xLC41OCwyLjY4LDIuNjgsMCwwLDAtLjQxLDEuNTh2My4wNmgtMXYtNmgxVjQ1aDBhMi4xLDIuMSwwLDAsMSwuNjMtMSwxLjQzLDEuNDMsMCwwLDEsLjk0LS4zNSwxLjU3LDEuNTcsMCwwLDEsLjU3LjA4WiIvPjxwYXRoIGNsYXNzPSJjbHMtNCIgZD0iTTQzLjcyLDQ3SDM5LjQ5QTIuMjQsMi4yNCwwLDAsMCw0MCw0OC41NGExLjg2LDEuODYsMCwwLDAsMS40Mi41NCwzLDMsMCwwLDAsMS44Ni0uNjd2LjlhMy40OCwzLjQ4LDAsMCwxLTIuMDkuNTcsMi41NCwyLjU0LDAsMCwxLTItLjgyLDMuMzUsMy4zNSwwLDAsMS0uNzMtMi4zLDMuMjgsMy4yOCwwLDAsMSwuNzktMi4yOCwyLjU1LDIuNTUsMCwwLDEsMi0uODgsMi4yNiwyLjI2LDAsMCwxLDEuODIuNzYsMy4xOCwzLjE4LDAsMCwxLC42NCwyLjEyWm0tMS0uODFhMiwyLDAsMCwwLS40LTEuMjksMS4zNywxLjM3LDAsMCwwLTEuMS0uNDYsMS41NSwxLjU1LDAsMCwwLTEuMTUuNDksMi4yMSwyLjIxLDAsMCwwLS41OSwxLjI3WiIvPjwvc3ZnPg== + +locale: "en" +groupings: + - title: "Basic Hidden" + visible: false + variables: + - compartment_ocid + - tenancy_ocid + - region + + - title: "General Configuration" + variables: + - num_instances + + - title: "Optional Configuration" + variables: + - show_advanced + - generate_public_ssh_key + - public_ssh_key + + - title: "Advanced Resource Options" + variables: + - use_only_always_free_elegible_resources + + - title: "Advanced Resource Options - DotNet App Customization" + variables: + - dotnet_standard_type + - dotnet_custom_text_for_standard_webapp + + - title: "Advanced Resource Options - Load Balancer" + variables: + - lb_shape + + - title: "Advanced Resource Options - Compute" + variables: + - instance_shape + - image_operating_system + - image_operating_system_version + - instance_visibility + + - title: "Extras Hidden" + variables: + - user_ocid + - fingerprint + - private_key_path + - network_cidrs + - dotnet_create_standard_webapp + - dotnet_git_custom_webapp + visible: false + +variables: + compartment_ocid: + type: oci:identity:compartment:id + required: true + title: "Compartment" + description: "The compartment in which to create compute instance(s) and ATP." + + num_instances: + type: enum + enum: + - "1" + - "2" + title: "Number of Instances" + description: "Choose the number of compute instances to deploy." + default: "2" + required: true + + show_advanced: + type: boolean + title: "Show advanced options?" + description: "Shows advanced options, select your ssh key, and other advanced options." + visible: true + + generate_public_ssh_key: + type: boolean + title: "Auto-generate public ssh key?" + description: "Auto-generate a public key and assign to the compute instances. Uncheck to provide your own public key or leave blank not to use any attach any key to the compute instance." + visible: + and: + - show_advanced + + public_ssh_key: + type: oci:core:ssh:publickey + title: "SSH Public Key" + description: "The public SSH key for the key-pair that you want to use, if you wish to login to the instances over SSH." + additionalProps: + allowMultiple: true + pattern: "((^(ssh-rsa AAAAB3NzaC1yc2|ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT|ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzOD|ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1Mj|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|ssh-dss AAAAB3NzaC1kc3)[0-9A-Za-z+\/]+[=]{0,3})( [^,]*)?)(,((ssh-rsa AAAAB3NzaC1yc2|ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT|ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzOD|ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1Mj|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|ssh-dss AAAAB3NzaC1kc3)[0-9A-Za-z+\/]+[=]{0,3})( [^,]*)?)*$" + visible: + and: + - and: + - show_advanced + - not: + - generate_public_ssh_key + + use_only_always_free_elegible_resources: + type: boolean + title: "Use only always free eligible resources?" + description: "*** Unchecking this may use options that are not included or supported by Always Free eligible resources." + visible: + and: + - show_advanced + + dotnet_standard_type: + type: enum + enum: + - "webApp" + - "blazorserver" + title: "Select the DotNet type to be created" + description: "WebApp creates the standard ASP.Net Core app. BlazorServer, creates sample with blazor pages." + required: true + visible: + and: + - show_advanced + + dotnet_custom_text_for_standard_webapp: + type: string + title: "Custom Text to show on the Home Page" + description: "Changes the standard Welcome message on the ASP.Net WebApp page." + required: true + visible: + and: + - show_advanced + + lb_shape: + type: enum + enum: + - "10Mbps-Micro" + - "100Mbps" + - "400Mbps" + - "8000Mbps" + title: "Select a shape for the load balancer" + description: "A load balancer provides automated traffic distribution from one entry point to multiple servers in a backend set. The load balancer ensures that your services remain available by directing traffic only to healthy servers in the backend set." + visible: + and: + - and: + - show_advanced + - not: + - use_only_always_free_elegible_resources + + instance_shape: + type: oci:core:instanceshape:name + title: "Select a shape for the compute instances" + description: "A shape is a template that determines the number of CPUs, amount of memory, and other resources allocated to a newly created instance." + dependsOn: + compartmentId: compartment_ocid + required: true + visible: + and: + - and: + - show_advanced + - not: + - use_only_always_free_elegible_resources + + image_operating_system: + type: string + title: "Compute Image OS" + description: "The OS/image installed on all compute instances." + required: true + visible: + and: + - and: + - show_advanced + - not: + - use_only_always_free_elegible_resources + + image_operating_system_version: + type: string + title: "Compute Image OS Version" + description: "The OS/image version installed on all compute instances." + required: true + visible: + and: + - and: + - show_advanced + - not: + - use_only_always_free_elegible_resources + + instance_visibility: + type: enum + enum: + - "Public" + - "Private" + title: "Choose instance visibility type" + description: "The instance visibility will define if assign a public ip address to the compute instance and if the subnet is public or private." + visible: + and: + - and: + - show_advanced + - not: + - use_only_always_free_elegible_resources + +outputGroups: + - title: "ASP.Net App details" + outputs: + - lb_public_url + - generated_private_key_pem + - deploy_id + - deployed_to_region + - dotnet_template_used + - dev + - comments + +outputs: + lb_public_url: + type: link + title: Open + visible: true + + generated_private_key_pem: + type: string + title: "Generated Private Key for SSH Access" + displayText: "Generated Private Key for ssh access to compute nodes" + visible: true + + dev: + type: string + title: "Message" + visible: true + + dotnet_template_used: + type: string + title: "Message" + visible: true + + deploy_id: + type: string + title: "Deployment Id" + visible: true + + deployed_to_region: + type: string + title: "Deployed using Region" + visible: true + + comments: + type: string + title: "Comments" + displayText: "The application URL will be unavailable for a few minutes after provisioning, while the application is configured" + visible: true + +primaryOutputButton: ${lb_public_url} \ No newline at end of file diff --git a/scripts/cloud-config.template.yaml b/scripts/cloud-config.template.yaml new file mode 100644 index 0000000..fba2011 --- /dev/null +++ b/scripts/cloud-config.template.yaml @@ -0,0 +1,51 @@ +#cloud-config + +write_files: +# setup script + - path: "/root/setup.preflight.sh" + permissions: "0777" + encoding: "gzip+base64" + content: | + ${setup_preflight_sh_content} + - path: "/root/setup.sh" + permissions: "0777" + encoding: "gzip+base64" + content: | + ${setup_template_sh_content} + - path: "/root/deploy.sh" + permissions: "0777" + encoding: "gzip+base64" + content: | + ${deploy_template_content} + - path: "/etc/systemd/system/dotnet-app.service" + permissions: "0644" + content: | + [Unit] + Description=Demo ASP.Net service + After=network.target + + [Service] + Type=simple + WorkingDirectory=/app/myOracleQuickstartWebApp/bin/Release/net5.0/linux-x64/publish/ + ExecStart=/usr/bin/dotnet /app/myOracleQuickstartWebApp/bin/Release/net5.0/linux-x64/publish/myOracleQuickstartWebApp.dll --urls "http://*:5000" + Restart=always + RestartSec=10 + KillSignal=SIGINT + SyslogIdentifier=dotnet-app-demo + User=www-data + Environment=ASPNETCORE_ENVIRONMENT=Production + Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false + + [Install] + WantedBy=multi-user.target + +runcmd: + - echo "Running prep scripts..." + - /root/setup.preflight.sh + - echo "Finished prep scripts." + - echo "Starting DotNet App..." + - systemctl enable dotnet-app + - systemctl start dotnet-app + +final_message: "The system is finally up, after $UPTIME seconds" +output: {all: '| tee -a /root/cloud-init-output.log'} \ No newline at end of file diff --git a/scripts/deploy.template.sh b/scripts/deploy.template.sh new file mode 100644 index 0000000..1df7008 --- /dev/null +++ b/scripts/deploy.template.sh @@ -0,0 +1,44 @@ +#!/bin/bash -x +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +# +# Description: Sets up Basic Asp.Net App. +# Return codes: 0 = +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# + +# Stop script on NZEC +set -e +# Stop script if unbound variable found +set -u +# This is causing it to fail +set -o pipefail + +# Set Variables for DotNet CLI +export HOME=/root +export DOTNET_CLI_HOME=/root +export DOTNET_CLI_TELEMETRY_OPTOUT=true + +# Prepare App folder +mkdir /app && cd /app +dotnet nuget list client-cert + +# Create base webApp +dotnet new ${dotnet_standard_type} -o myOracleQuickstartWebApp --no-https --no-restore + +## Customize standard WebApp +cd myOracleQuickstartWebApp +filenametocustomize="Pages/Index.cshtml" +if [[ -e $filenametocustomize ]] +then + sed -i 's/Welcome/${dotnet_custom_text_for_standard_webapp}/g' $filenametocustomize +fi + +# Optional git repo (Alternative Deployment) +# git clone ${dotnet_git_custom_webapp} myOracleQuickstartWebApp +# cd myOracleQuickstartWebApp + +# Publish app to be ready to run as a service - Linux X86, Linux X64, Linux ARM32, Linux ARM64 +dotnet restore +dotnet publish --configuration Release --runtime linux-x64 --self-contained true -p:PublishReadyToRun=true diff --git a/scripts/setup.preflight.sh b/scripts/setup.preflight.sh new file mode 100644 index 0000000..786b40e --- /dev/null +++ b/scripts/setup.preflight.sh @@ -0,0 +1,13 @@ +#!/bin/bash -x +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +# +# Description: Sets up Basic Asp.Net App. +# Return codes: 0 = +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# + +bash -x /root/setup.sh 2>&1 | tee -a /root/setup.log +bash -x /root/deploy.sh 2>&1 | tee -a /root/deploy.log +echo "Finished preflight" \ No newline at end of file diff --git a/scripts/setup.template.sh b/scripts/setup.template.sh new file mode 100644 index 0000000..c57efec --- /dev/null +++ b/scripts/setup.template.sh @@ -0,0 +1,32 @@ +#!/bin/bash -x +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +# +# Description: Sets up Basic Asp.Net App. +# Return codes: 0 = +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# + +# Configure firewall +iptables -I INPUT 6 -m state --state NEW -p tcp --dport 5000 -j ACCEPT +netfilter-persistent save + +# Install DotNet +wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +dpkg -i packages-microsoft-prod.deb + +# Install the DotNet SDK +apt-get update; \ + apt-get install -y apt-transport-https && \ + apt-get update && \ + apt-get install -y dotnet-sdk-5.0 + +# Install the DotNet runtime +apt-get update; \ + apt-get install -y apt-transport-https && \ + apt-get update && \ + apt-get install -y aspnetcore-runtime-5.0 + +###################################### +echo "Finished running setup.sh" diff --git a/security-lists.tf b/security-lists.tf new file mode 100755 index 0000000..96f8695 --- /dev/null +++ b/security-lists.tf @@ -0,0 +1,112 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +resource "oci_core_security_list" "dotnet_security_list" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + display_name = "dotnet-main-${random_string.deploy_id.result}" + freeform_tags = local.common_tags + + ingress_security_rules { + protocol = local.all_protocols + source = lookup(var.network_cidrs, "MAIN-SUBNET-REGIONAL-CIDR") + stateless = true + } + + + ingress_security_rules { + protocol = local.tcp_protocol_number + source = lookup(var.network_cidrs, "MAIN-LB-SUBNET-REGIONAL-CIDR") + + tcp_options { + max = local.app_port_number + min = local.app_port_number + } + } + + ingress_security_rules { + protocol = local.tcp_protocol_number + source = lookup(var.network_cidrs, (var.instance_visibility == "Private") ? "MAIN-VCN-CIDR" : "ALL-CIDR") + + tcp_options { + max = local.ssh_port_number + min = local.ssh_port_number + } + } + + egress_security_rules { + protocol = local.all_protocols + destination = lookup(var.network_cidrs, "MAIN-SUBNET-REGIONAL-CIDR") + stateless = true + } + + egress_security_rules { + protocol = local.all_protocols + destination = lookup(var.network_cidrs, (var.instance_visibility == "Private") ? "MAIN-VCN-CIDR" : "ALL-CIDR") + } + + egress_security_rules { + protocol = local.all_protocols + destination = lookup(data.oci_core_services.all_services.services[0], "cidr_block") + destination_type = "SERVICE_CIDR_BLOCK" + } +} + +resource "oci_core_security_list" "dotnet_lb_security_list" { + compartment_id = var.compartment_ocid + vcn_id = oci_core_virtual_network.dotnet_main_vcn.id + display_name = "dotnet-lb-${random_string.deploy_id.result}" + freeform_tags = local.common_tags + + ingress_security_rules { + protocol = local.all_protocols + source = lookup(var.network_cidrs, "ALL-CIDR") + stateless = true + } + + ingress_security_rules { + protocol = local.tcp_protocol_number + source = lookup(var.network_cidrs, "ALL-CIDR") + + tcp_options { + max = local.http_port_number + min = local.http_port_number + } + } + + ingress_security_rules { + protocol = local.tcp_protocol_number + source = lookup(var.network_cidrs, "ALL-CIDR") + + tcp_options { + max = local.https_port_number + min = local.https_port_number + } + } + + egress_security_rules { + protocol = local.all_protocols + destination = lookup(var.network_cidrs, "ALL-CIDR") + stateless = true + } + + egress_security_rules { + protocol = local.tcp_protocol_number + destination = lookup(var.network_cidrs, "MAIN-SUBNET-REGIONAL-CIDR") + + tcp_options { + max = local.app_port_number + min = local.app_port_number + } + } +} + +locals { + http_port_number = "80" + https_port_number = "443" + app_port_number = "5000" + ssh_port_number = "22" + tcp_protocol_number = "6" + all_protocols = "all" +} \ No newline at end of file diff --git a/terraform.tfvars.example b/terraform.tfvars.example new file mode 100644 index 0000000..44d6e12 --- /dev/null +++ b/terraform.tfvars.example @@ -0,0 +1,28 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +# OCI authentication +tenancy_ocid = "ocid1.tenancy....." +fingerprint = "" # e.g.: "5f:53:..." or leave blank if using CloudShell +user_ocid = "" # e.g.: "ocid1.user..." or leave blank if using CloudShell +private_key_path = "" # e.g.: "/users/user/.oci/oci_api_key.pem" or leave blank if using CloudShell + +# Deployment compartment +compartment_ocid = "ocid1.compartment...." + +# region +region = "us-ashburn-1" + +# Compute +num_instances = 2 +instance_shape = "VM.Standard.E2.1.Micro" +instance_visibility = "Public" +generate_public_ssh_key = true +public_ssh_key = "" + +# Network Details +lb_shape = "10Mbps-Micro" + +# Always Free only or support other shapes +use_only_always_free_elegible_resources = true \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..f4c3be5 --- /dev/null +++ b/variables.tf @@ -0,0 +1,80 @@ +# Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# + +variable "tenancy_ocid" {} +variable "region" {} +variable "compartment_ocid" {} + +variable "user_ocid" { + default = "" +} +variable "fingerprint" { + default = "" +} +variable "private_key_path" { + default = "" +} + +# Compute +variable "num_instances" { + default = 2 +} +variable "generate_public_ssh_key" { + default = true +} +variable "public_ssh_key" { + default = "" +} +variable "instance_shape" { + default = "VM.Standard.E2.1.Micro" +} +variable "image_operating_system" { + default = "Canonical Ubuntu" +} +variable "image_operating_system_version" { + default = "20.04" +} +variable "instance_visibility" { + default = "Public" +} + +# Network Details +variable "lb_shape" { + default = "10Mbps-Micro" +} + +variable "network_cidrs" { + type = map(string) + + default = { + MAIN-VCN-CIDR = "10.1.0.0/16" + MAIN-SUBNET-REGIONAL-CIDR = "10.1.21.0/24" + MAIN-LB-SUBNET-REGIONAL-CIDR = "10.1.22.0/24" + ALL-CIDR = "0.0.0.0/0" + } +} + +# Always Free only or support other shapes +variable "use_only_always_free_elegible_resources" { + default = true +} + +# ORM Schema visual control variables +variable "show_advanced" { + default = false +} + +# Customizing App +variable "dotnet_create_standard_webapp" { + default = true +} +variable "dotnet_standard_type" { + default = "webApp" # E.g.: blazorserver +} +variable "dotnet_custom_text_for_standard_webapp" { + default = "Welcome to the Oracle QuickStart" +} +variable "dotnet_git_custom_webapp" { + default = "https://github.com/aspnet/samples.git" +} \ No newline at end of file