diff --git a/.gitignore b/.gitignore index 241c253..3d735d3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,11 @@ **/.terraform/* # .tfstate files -*.tfstate -*.tfstate.* +**/*.tfstate +**/*.tfstate.* # Crash log files -crash.log +**/crash.log # Ignore any .tfvars files that are generated automatically for each Terraform run. Most # .tfvars files are managed as part of configuration and so should be included in @@ -14,22 +14,23 @@ crash.log # # example.tfvars *.tfvars -*.json +*/*.tfvars +**/*.json # Ignore data files **/data # Ignore override files as they are usually used to override resources locally and so # are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json +**/override.tf +**/override.tf.json +**/*_override.tf +**/*_override.tf.json # Include override files you do wish to add to version control using negated pattern # # !example_override.tf -.terraform.*.hcl +**/.terraform.*.hcl # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan # example: *tfplan* diff --git a/README.md b/README.md index f3128ac..69a7816 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,161 @@ -# Deploy HPCC Systems Platform with Terraform - -This set of Terraform examples deploys all the available features that come with the HPCC Systems OSS Terraform modules. - -## Order of deployment -| Order | Name | Required | -| ----- | --------- | :------: | -| 1 | `VNet` | yes | -| 2 | `AKS` | yes | -| 3 | `Storage` | no | -| 4 | `Logging` | no | -| 5 | `AKS` | no | -| 6 | `HPCC` | yes | - -## Modules -| Name | Source | Used in | -| :---------------------------------: | :----: | :-----: | -| `terraform-azurerm-virtual-network` | | `VNet` | \ No newline at end of file +# Deploy HPCC Systems on Azure under Kubernetes + +NOTE: Documentation of this Terraform for the developer, or others who are interested, can be found [here](documentation/hpcc-tf-for-developers.md). + +This is a slightly-opinionated Terraform module for deploying an HPCC Systems cluster on Azure's Kubernetes service (aks). The goal is to provide a simple method for deploying a cluster from scratch, with only the most important options to consider. + +The HPCC Systems cluster created by this module uses ephemeral storage, which is the default. This means the storage will be deleted when the cluster is deleted) But, you can also have Persistent Storage. See the section titled [Persistent Storage](#persistent-storage), below. + +## Requirements + +* **terraform** This is a Terraform module, so you need to have terraform installed on your system. Instructions for downloading and installing terraform can be found at [https://www.terraform.io/downloads.html](https://www.terraform.io/downloads.html). Do make sure you install a 64-bit version of terraform, as that is needed to accommodate some of the large random numbers used for IDs in the Terraform modules. + +* **helm** Helm is used to deploy the HPCC Systems processes under Kubernetes. Instructions for downloading and installing Helm are at [https://helm.sh/docs/intro/install](https://helm.sh/docs/intro/install/). + +* **kubectl** The Kubernetes client (kubectl) is also required so you can inspect and manage the Azure Kubernetes cluster. Instructions for download and installing that can be found at [https://kubernetes.io/releases/download/](https://kubernetes.io/releases/download/). Make sure you have version 1.22.0 or later. + +* **Azure CLI** To work with Azure, you will need to install the Azure Command Line tools. Instructions can be found at [https://docs.microsoft.com/en-us/cli/azure/install-azure-cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli). Even if you think you won't be working with Azure, this module does leverage the command line tools to manipulate network security groups within Kubernetes clusters. TL;DR: Make sure you have the command line tools installed. + +* To successfully create everything you will need to have Azure's `Contributor` role plus access to `Microsoft.Authorization/*/Write` and `Microsoft.Authorization/*/Delete` permissions on your subscription. You may have to create a custom role for this. Of course, Azure's `Owner` role includes everything so if you're the subscription's owner then you're good to go. +* You need a minimum of 28 vCPUs available on `azure` and `aks_serv_node_size` must be at least `xlarge`. The following `az` command will tell you the maximum number of vCPUs you can use. And, the 2nd `az` command, below, gives you the number of vCPUs you have already used in region `eastus` (replace `eastus` with the name of the region you are using). Furthermore, you can get the number of vCPUs available for you to use by subtracting the result of the 2nd `az` command, below, from the result of the first `az` command. + * `az vm list-usage --location "eastus" -o table|grep "Total Regional vCPUs"|sed "s/ */\t/g"|cut -f5` + * `az vm list-usage --location "eastus" -o table|grep "Total Regional vCPUs"|sed "s/ */\t/g"|cut -f4` +* You need to make sure `jq` and `kubelogin` are installed on your linux machine. You can determine if they are by using the `which` command, e.g. `which jq` returns `jq`s path if it is installed. The following commands can be used to install '`jq` and `kubelogin`, respectively: + * `sudo apt-get install jq` + * `sudo az aks install-cli` +* If you run the terraform code on an azure VM, then the azure VM must have EncryptionAtHost enabled. You can do this by: 1) Stopping your azure VM; 2) click on `Disk` in the Overview of the azure VM; 3) click on the tab, `Additional Settings`; 4) selecting `yes` radio button under `Encryption at host`. + +## Installing/Using This Module + +1. If necessary, login to Azure. + * From the command line, this is usually accomplished with the `az login` command. +1. Clone this repo to your local system and change current directory. + * `git clone https://github.com/hpccsystems-solutions-lab/terraform-azurerm-hpcc-lite.git` + * `cd terraform-azurerm-hpcc-lite` +1. Issue `terraform init` to initialize the Terraform modules. +2. Issue `terraform apply` + This command will do a `terraform init`, `terraform plan` and `terraform apply` for each of the subsystems needed, i.e. `vnet`, `aks`, `storage`, and `hpcc` (the `storage` subsystem is deployed only if you set `external_storage_desired=true`). The order that these subsystems are deploy is: `vnet`, `aks`, `storage`, and `hpcc`. + For each subsystem, `terraform` creates a `plan` file which is stored in the directory: `~/tflogs` (note: if this directory doesn't exist, it is created automatically). +1. Decide how you want to supply option values to the module during invocation. There are three possibilities: + 1. Invoke the `terraform apply` command and enter values for each option as terraform prompts for it, then enter `yes` at the final prompt to begin building the cluster. + 1. **Recommended:** Create a `lite.auto.tfvars` file containing the values for each option, invoke `terraform apply`, then enter `yes` at the final prompt to begin building the cluster. The easiest way to create `lite.auto.tfvars` is to copy the example file, `lite.auto.tfvars.example`, and then edit the copy: + * `cp -v lite.auto.tfvars.example lite.auto.tfvars` + 1. Use -var arguments on the command line when executing the terraform tool to set each of the values found in the .tfvars file. This method is useful if you are driving the creation of the cluster from a script. +1. After the Kubernetes cluster is deployed, your local `kubectl` tool can be used to interact with it. At some point during the deployment `kubectl` will acquire the login credentials for the cluster and it will be the current context (so any `kubectl` commands you enter will be directed to that cluster by default). + +At the end of a successful deployment these items are output for aks, hpcc, and vnet: +* aks + * Advisor recommendations or 'none', `advisor_recommendations`. + * Location of the aks credentials, `aks_login`. + * Name of the Azure Kubernetes Service, `cluster_name`. + * Resource group where the cluster is deployed, `cluster_resource_group_name`. +* hpcc + * The URL used to access ECL Watch, `eclwatch_url`. + * The deployment azure resource group, `deployment_resource_group`. + * Whether there is external storage or not, `external_storage_config_exists`. +* vnet + * Advisor recommendations or 'none', `advisor_recommendations`. + * ID of private subnet, `private_subnet_id`. + * ID of public subnet, `public_subnet_id`. + * ID of route table, `route_table_id`. + * Route table name, `route_table_name`. + * Virtual network resource group name, `resource_group_name`. + * Virtual network name, `vnet_name`. + +## Available Options + +Options have data types. The ones used in this module are: +* string + * Typical string enclosed by quotes + * Example + * `"value"` +* number + * Integer number; do not quote + * Example + * `1234` +* boolean + * true or false (not quoted) +* map of string + * List of key/value pairs, delimited by commas + * Both key and value should be a quoted string + * Entire map is enclosed by braces + * Example with two key/value pairs + * `{"key1" = "value1", "key2" = "value2"}` + * Empty value is `{}` +* list of string + * List of values, delimited by commas + * A value is a quoted string + * Entire list is enclosed in brackets + * Example with two values + * `["value1", "value2"]` + * Empty value is `[]` + +The following options should be set in your `lite.auto.tfvars` file (or entered interactively, if you choose to not create a file). Only a few of them have default values. The rest are required. The 'Updateable' column indicates whether, for any given option, it is possible to successfully apply the update against an already-running HPCC k8s cluster. + +|Option|Type|Description|Updatable| +|:-----|:---|:----------|:--------| +| `a_record_name` | string | Name of the A record, of following dns zone, where the ecl watch ip is placed This A record will be created and therefore should not exist in the following dns zone. Example entry: "my-product". This should be something project specific rather than something generic. | Y | +| `admin_username` | string | Username of the administrator of this HPCC Systems cluster. Example entry: "jdoe" | N | +| `aks_admin_email` | string | Email address of the administrator of this HPCC Systems cluster. Example entry: "jane.doe@hpccsystems.com" | Y | +| `aks_admin_ip_cidr_map` | map of string | Map of name => CIDR IP addresses that can administrate this AKS. Format is '{"name"="cidr" [, "name"="cidr"]*}'. The 'name' portion must be unique. To add no CIDR addresses, use '{}'. The corporate network and your current IP address will be added automatically, and these addresses will have access to the HPCC cluster as a user. | Y | +| `aks_admin_name` | string | Name of the administrator of this HPCC Systems cluster. Example entry: "Jane Doe" | Y | +| `aks_azure_region` | string | The Azure region abbreviation in which to create these resources. Example entry: "eastus" | N | +| `aks_dns_zone_name` | string | Name of an existing dns zone. Example entry: "hpcczone.us-hpccsystems-dev.azure.lnrsg.io" | N | +| `aks_dns_zone_resource_group_name` | string | Name of the resource group of the above dns zone. Example entry: "app-dns-prod-eastus2" | N | +| `aks_enable_roxie` | boolean | Enable ROXIE? This will also expose port 8002 on the cluster. Example entry: false | Y | +| `aks_logging_monitoring_enabled` | boolean | This variable enable you to ask for logging and monitoring of the Kubernetes and hpcc cluster (true means enable logging and monitoring, false means don't. | N | +| `aks_4nodepools ` | boolean | Determines whether 1 or 4 nodepools are use -- 4 used if true otherwise 2 used. (default is false). | N | +| `aks_nodepools_max_capacity` | string | The maximum number of nodes of every hpcc nodepool.| N | +| `aks_roxie_node_size ` | string | The VM size for each roxie node in the HPCC Systems. Example format `aks_roxie_node-size`="xlarge".| N | +| `aks_serv_node_size ` | string | The VM size for each serv node in the HPCC Systems. Example format `aks_serv_node-size`="2xlarge".| N | +| `aks_spray_node_size ` | string | The VM size for each spray node in the HPCC Systems. Example format `aks_spray_node-size`="2xlarge".| N | +| `aks_thor_node_size ` | string | The VM size for each thor node in the HPCC Systems. Example format `aks_thor_node-size`="2xlarge".| N | +| `aks_capacity ` | map of number | The min and max number of nodes of each node pool in the HPCC Systems. Example format is '{ roxie_min = 1, roxie_max = 3, serv_min = 1, serv_max = 3, spray_min = 1, spray_max = 3, thor_min = 1, thor_max = 3}'. | N | +| `authn_htpasswd_filename` | string | If you would like to use htpasswd to authenticate users to the cluster, enter the filename of the htpasswd file. This file should be uploaded to the Azure 'dllsshare' file share in order for the HPCC processes to find it. A corollary is that persistent storage is enabled. An empty string indicates that htpasswd is not to be used for authentication. Example entry: "htpasswd.txt" | Y | +| `enable_code_security` | boolean | Enable code security? If true, only signed ECL code will be allowed to create embedded language functions, use PIPE(), etc. Example entry: false | Y | +| `enable_thor` | boolean | If you want a thor cluster then 'enable_thor' must be set to true Otherwise it is set to false | Y | +| `external_storage_desired` | boolean | If you want external storage instead of ephemeral storage then set this variable to true otherwise set it to false. | Y | +| `extra_tags` | map of string | Map of name => value tags that can will be associated with the cluster. Format is '{"name"="value" [, "name"="value"]*}'. The 'name' portion must be unique. To add no tags, use '{}'. | Y | +| `hpcc_user_ip_cidr_list` | list of string | List of explicit CIDR addresses that can access this HPCC Systems cluster. To allow public access, set value to ["0.0.0.0/0"] or []. | Y | +| `hpcc_version` | string | The version of HPCC Systems to install. Only versions in nn.nn.nn format are supported. | Y | +| `my_azure_id` | string | Your azure account object id. Find this on azure portal, by going to 'users' then search for your name and click on it. The account object id is called 'Object ID'. There is a link next to it that lets you copy it. | N | +| `storage_data_gb` | number | The amount of storage reserved for data in gigabytes. Must be 1 or more. If a storage account is defined (see below) then this value is ignored. | Y | +| `storage_lz_gb` | number | The amount of storage reserved for the landing zone in gigabytes. Must be 1 or more. If a storage account is defined (see below) then this value is ignored. | Y | +| `thor_max_jobs` | number | The maximum number of simultaneous Thor jobs allowed. Must be 1 or more. | Y | +| `thor_num_workers` | number | The number of Thor workers to allocate. Must be 1 or more. | Y | + +## Persistent Storage + +To get persistent storage, i.e. storage that is not deleted when the HPCC cluster is deleted, set the variable, `external_storage_desired`, to true. + +## Useful Things + +* Useful `az cli` commands: + * `az account list --output table` + * Shows your current subscriptions, and determine which is the default + * `az account set --subscription "My_Subscription"` + * Sets the default subscription +* Useful `kubectl` commands once the cluster is deployed: + * `kubectl get pods` + * Shows Kubernetes pods for the current cluster. + * `kubectl get services` + * Show the current services running on the pods on the current cluster. + * `kubectl config get-contexts` + * Show the saved kubectl contexts. A context contains login and reference information for a remote Kubernetes cluster. A kubectl command typically relays information about the current context. + * `kubectl config use-context ` + * Make \ context the current context for future kubectl commands. + * `kubectl config unset contexts.` + * Delete context named \. + * Note that when you delete the current context, kubectl does not select another context as the current context. Instead, no context will be current. You must use `kubectl config use-context ` to make another context current. +* Note that `terraform destroy` does not delete the kubectl context. You need to use `kubectl config unset contexts.` to get rid of the context from your local system. +* If a deployment fails and you want to start over, you have two options: + * Immediately issue a `terraform destroy` command and let terraform clean up. + * Clean up the resources by hand: + * Delete the Azure resource group manually, such as through the Azure Portal. + * Note that there are two resource groups, if the deployment got far enough. Examples: + * `app-thhpccplatform-sandbox-eastus-68255` + * `mc_tf-zrms-default-aks-1` + * The first one contains the Kubernetes service that created the second one (services that support Kubernetes). So, if you delete only the first resource group, the second resource group will be deleted automatically. + * Delete all terraform state files using `rm *.tfstate*` + * Then, of course, fix whatever caused the deployment to fail. +* If you want to completely reset terraform, issue `rm -rf .terraform* *.tfstate*` and then `terraform init`. diff --git a/aks/aks.auto.tfvars.example b/aks/aks.auto.tfvars.example deleted file mode 100644 index ab557cf..0000000 --- a/aks/aks.auto.tfvars.example +++ /dev/null @@ -1,127 +0,0 @@ -cluster_version = "1.25" -cluster_ordinal = 1 //cluster name suffix -sku_tier = "free" -dns_resource_group = "app-dns-prod-eastus2" -internal_domain = "my-dns-zone.io" -hpcc_log_analytics_enabled = false - -rbac_bindings = { - cluster_admin_users = { - # "service_principal1" = "", - # "user1" = "" - # "user2" = "" - - } - - cluster_view_users = {} - cluster_view_groups = [] -} - -core_services_config = { - alertmanager = { - smtp_host = "smtp-hostname.ds:25" - smtp_from = "demo@lexisnexisrisk.com" - routes = [] - receivers = [] - } - - # coredns = { - # forward_zones = { - # "" = "" - # } - # } - - external_dns = { - public_domain_filters = ["my-dns-zone.io"] - } - - # cert_manager = { - # acme_dns_zones = ["my-dns-zone.io"] - # default_issuer_name = "zerossl" - # } - - ingress_internal_core = { - domain = "my-dns-zone.io" - subdomain_suffix = "hpcc" // dns record suffix //must be unique accross subscription - public_dns = true - } -} - -cluster_endpoint_access_cidrs = ["0.0.0.0/0"] - -availability_zones = [1,2] - -node_groups = { - thorpool = { - ultra_ssd = false - node_os = "ubuntu" - node_type = "gp" # gp, gpd, mem, memd, stor - node_type_version = "v2" # v1, v2 - node_size = "2xlarge" # large, xlarge, 2xlarge, 4xlarge, 8xlarge, 12xlarge, 16xlarge, 18xlarge, 20xlarge, 24xlarge, 26xlarge - single_group = false - min_capacity = 1 - max_capacity = 3 - # placement_group_key = null - labels = { - "lnrs.io/tier" = "standard" - "workload" = "thorpool" - } - taints = [] - tags = {} - }, - - roxiepool = { - ultra_ssd = false - node_os = "ubuntu" - node_type = "gp" - node_type_version = "v2" - node_size = "2xlarge" - single_group = false - min_capacity = 1 - max_capacity = 3 - # placement_group_key = null - labels = { - "lnrs.io/tier" = "standard" - "workload" = "roxiepool" - } - taints = [] - tags = {} - }, - - servpool = { - ultra_ssd = false - node_os = "ubuntu" - node_type = "gpd" - node_type_version = "v1" - node_size = "4xlarge" - single_group = false - min_capacity = 1 - max_capacity = 3 - # placement_group_key = null - labels = { - "lnrs.io/tier" = "standard" - "workload" = "servpool" - } - taints = [] - tags = {} - }, - - spraypool = { - ultra_ssd = false - node_os = "ubuntu" - node_type = "gp" - node_type_version = "v1" - node_size = "2xlarge" - single_group = false - min_capacity = 1 - max_capacity = 3 - # placement_group_key = null - labels = { - "lnrs.io/tier" = "standard" - "workload" = "spraypool" - "spray-service" = "spraypool" - } - taints = [] - tags = {} - } -} diff --git a/aks/aks.tf b/aks/aks.tf index 3c317a0..f609661 100644 --- a/aks/aks.tf +++ b/aks/aks.tf @@ -1,27 +1,8 @@ -# resource "kubernetes_secret" "private_docker_registry" { -# count = can(var.registry.server) && can(var.registry.username) && can(var.registry.password) ? 1 : 0 -# metadata { -# name = "docker-cfg" -# } -# type = "kubernetes.io/dockerconfigjson" -# data = { -# ".dockerconfigjson" = jsonencode({ -# auths = { -# "${var.registry.server}" = { -# "username" = var.registry.username -# "password" = var.registry.password -# "email" = var.admin.email -# "auth" = base64encode("${var.registry.username}:${var.registry.password}") -# } -# } -# }) -# } -# } - module "aks" { depends_on = [random_string.string] - source = "github.com/gfortil/terraform-azurerm-aks.git?ref=HPCC-27615" - # source = "../../../terraform-azurerm-aks" + #source = "git@github.com:hpccsystems-solutions-lab/tlh-oss-terraform-azurerm-aks.git" + source = "github.com/hpccsystems-solutions-lab/tlh-oss-terraform-azurerm-aks.git" + #source = "/home/azureuser/temp/OSS/terraform-azurerm-aks" providers = { kubernetes = kubernetes.default @@ -29,7 +10,7 @@ module "aks" { kubectl = kubectl.default } - location = var.metadata.location + location = local.metadata.location resource_group_name = module.resource_groups["azure_kubernetes_service"].name cluster_name = local.cluster_name @@ -38,6 +19,8 @@ module "aks" { # for v1.6.2 aks: sku_tier_paid = false sku_tier = var.sku_tier + logging_monitoring_enabled = var.aks_logging_monitoring_enabled + cluster_endpoint_access_cidrs = var.cluster_endpoint_access_cidrs virtual_network_resource_group_name = try(var.use_existing_vnet.resource_group_name, local.get_vnet_config.resource_group_name) @@ -45,25 +28,25 @@ module "aks" { subnet_name = try(var.use_existing_vnet.subnets.aks.name, "aks-hpcc-private") route_table_name = try(var.use_existing_vnet.route_table_name, local.get_vnet_config.route_table_name) - dns_resource_group_lookup = { "${var.internal_domain}" = var.dns_resource_group } + dns_resource_group_lookup = { "${local.internal_domain}" = local.dns_resource_group } - admin_group_object_ids = [data.azuread_group.subscription_owner.object_id] + admin_group_object_ids = null rbac_bindings = var.rbac_bindings availability_zones = var.availability_zones - node_groups = var.node_groups + node_groups = local.node_groups core_services_config = { - alertmanager = var.core_services_config.alertmanager - coredns = var.core_services_config.coredns - external_dns = var.core_services_config.external_dns - cert_manager = var.core_services_config.cert_manager + alertmanager = local.core_services_config.alertmanager + coredns = local.core_services_config.coredns + external_dns = local.core_services_config.external_dns + cert_manager = local.core_services_config.cert_manager ingress_internal_core = { - domain = var.core_services_config.ingress_internal_core.domain - subdomain_suffix = "${var.core_services_config.ingress_internal_core.subdomain_suffix}${trimspace(var.owner.name)}" // dns record suffix - public_dns = var.core_services_config.ingress_internal_core.public_dns + domain = local.core_services_config.ingress_internal_core.domain + subdomain_suffix = "${local.core_services_config.ingress_internal_core.subdomain_suffix}${trimspace(local.owner_name_initials)}" // dns record suffix + public_dns = local.core_services_config.ingress_internal_core.public_dns } } @@ -75,9 +58,4 @@ module "aks" { } logging = var.logging - - experimental = { - oms_agent = var.hpcc_log_analytics_enabled || var.experimental.oms_agent - oms_agent_log_analytics_workspace_id = fileexists("../logging/data/workspace_resource_id.txt") ? file("../logging/data/workspace_resource_id.txt") : var.experimental.oms_agent_log_analytics_workspace_id != null ? var.experimental.oms_agent_log_analytics_workspace_id : null - } } diff --git a/aks/automation.tf b/aks/automation.tf deleted file mode 100644 index 45e80f9..0000000 --- a/aks/automation.tf +++ /dev/null @@ -1,65 +0,0 @@ -resource "azurerm_automation_account" "automation_account" { - name = var.aks_automation.automation_account_name - location = local.location - resource_group_name = module.resource_groups["azure_kubernetes_service"].name - sku_name = var.sku_name - tags = local.tags - # local_authentication_enabled = var.aks_automation.local_authentication_enabled - public_network_access_enabled = var.aks_automation.public_network_access_enabled - - identity { - type = "SystemAssigned" - } -} - -resource "azurerm_role_assignment" "role_assignment" { - #scope = "${data.azurerm_subscription.primary.id}/resourceGroups/${module.resource_groups["azure_kubernetes_service"].name}" - scope = data.azurerm_subscription.current.id - role_definition_name = "Contributor" - principal_id = azurerm_automation_account.automation_account.identity[0].principal_id -} - -resource "azurerm_automation_runbook" "runbook" { - for_each = local.runbook - name = each.value.runbook_name - runbook_type = each.value.runbook_type - content = local.script[each.value.script_name] - location = local.location - resource_group_name = module.resource_groups["azure_kubernetes_service"].name - automation_account_name = azurerm_automation_account.automation_account.name - description = "Runbook for script ${each.value.script_name}" - log_progress = var.log_progress - log_verbose = var.log_verbose - tags = local.tags -} - -resource "azurerm_automation_schedule" "schedule" { - for_each = local.schedule - automation_account_name = azurerm_automation_account.automation_account.name - description = each.value.description - frequency = each.value.frequency - interval = each.value.frequency == "OneTime" ? null : each.value.interval - month_days = each.value.frequency != "Month" ? null : each.value.month_days - week_days = each.value.frequency != "Week" ? null : each.value.week_days - name = each.value.schedule_name - resource_group_name = module.resource_groups["azure_kubernetes_service"].name - # TODO: this assumes the timezone is "America/New_York" and doesn't account for DST - should be fixed - start_time = length(each.value.start_time) == 5 && contains(["Week", "Month"], each.value.frequency) ? contains(each.value.week_days, local.current_day) && tonumber(substr(each.value.start_time, 0, 2)) >= local.current_hour ? "${local.today}T${each.value.start_time}:15-0${local.utc_offset}:00" : "${local.tomorrow}T${each.value.start_time}:15-0${local.utc_offset}:00" : "${local.today}T${each.value.start_time}:15-0${local.utc_offset}:00" - timezone = var.timezone - # expiry_time = each.value.expiry_time -} - -resource "azurerm_automation_job_schedule" "job_schedule" { - for_each = local.schedule - runbook_name = azurerm_automation_runbook.runbook[each.value.runbook_name].name - schedule_name = azurerm_automation_schedule.schedule[each.value.schedule_name].name - resource_group_name = module.resource_groups["azure_kubernetes_service"].name - automation_account_name = azurerm_automation_account.automation_account.name - - parameters = { - resourcename = module.aks.cluster_name - resourcegroupname = module.resource_groups["azure_kubernetes_service"].name - operation = each.value.operation - automationaccount = var.aks_automation.automation_account_name - } -} diff --git a/aks/data.tf b/aks/data.tf index de069dc..9ed1b2a 100644 --- a/aks/data.tf +++ b/aks/data.tf @@ -11,9 +11,5 @@ data "http" "host_ip" { data "azurerm_subscription" "current" { } -data "azuread_group" "subscription_owner" { - display_name = "ris-azr-group-${data.azurerm_subscription.current.display_name}-owner" -} - data "azurerm_client_config" "current" { } diff --git a/aks/lite-locals.tf b/aks/lite-locals.tf new file mode 100644 index 0000000..cf18cdf --- /dev/null +++ b/aks/lite-locals.tf @@ -0,0 +1,35 @@ +locals { + internal_domain = var.aks_dns_zone_name + + dns_resource_group = var.aks_dns_zone_resource_group_name + + owner = { + name = var.aks_admin_name + email = var.aks_admin_email + } + + owner_name_initials = lower(join("",[for x in split(" ",local.owner.name): substr(x,0,1)])) + + core_services_config = { + alertmanager = { + smtp_host = "smtp-hostname.ds:25" + smtp_from = var.aks_admin_email + routes = [] + receivers = [] + } + + coredns = {} + + external_dns = { + public_domain_filters = [var.aks_dns_zone_name] + } + + cert_manager = {} + + ingress_internal_core = { + domain = var.aks_dns_zone_name + subdomain_suffix = "hpcc" // dns record suffix //must be unique accross subscription + public_dns = true + } + } +} diff --git a/aks/locals.tf b/aks/locals.tf index c8cb340..c54ea7a 100644 --- a/aks/locals.tf +++ b/aks/locals.tf @@ -1,4 +1,101 @@ +resource "random_string" "name" { + length = 3 + special = false + numeric = false + upper = false +} + locals { + roxiepool = { + ultra_ssd = false + node_os = "ubuntu" + node_type = "gp" + node_type_version = "v2" + node_size = var.aks_roxie_node_size + single_group = false + min_capacity = 0 + max_capacity = var.aks_nodepools_max_capacity + labels = { + "lnrs.io/tier" = "standard" + "workload" = "roxiepool" + } + taints = [] + tags = {} + } + + node_groups0 = { + thorpool = { + ultra_ssd = false + node_os = "ubuntu" + node_type = "gp" # gp, gpd, mem, memd, stor + node_type_version = "v2" # v1, v2 + node_size = var.aks_thor_node_size + single_group = false + min_capacity = 0 + max_capacity = var.aks_nodepools_max_capacity + labels = { + "lnrs.io/tier" = "standard" + "workload" = "thorpool" + } + taints = [] + tags = {} + }, + + servpool = { + ultra_ssd = false + node_os = "ubuntu" + node_type = "gpd" + node_type_version = "v1" + node_size = var.aks_serv_node_size + single_group = false + min_capacity = 3 + max_capacity = var.aks_nodepools_max_capacity + labels = { + "lnrs.io/tier" = "standard" + "workload" = "servpool" + } + taints = [] + tags = {} + }, + + spraypool = { + ultra_ssd = false + node_os = "ubuntu" + node_type = "gp" + node_type_version = "v1" + node_size = var.aks_spray_node_size + single_group = false + min_capacity = 0 + max_capacity = var.aks_nodepools_max_capacity + labels = { + "lnrs.io/tier" = "standard" + "workload" = "spraypool" + "spray-service" = "spraypool" + } + taints = [] + tags = {} + } + } + + hpccpool = { + ultra_ssd = false + node_os = "ubuntu" + node_type = "gp" # gp, gpd, mem, memd, stor + node_type_version = "v2" # v1, v2 + node_size = var.aks_serv_node_size + single_group = false + min_capacity = 3 + max_capacity = var.aks_nodepools_max_capacity + labels = { + "lnrs.io/tier" = "standard" + "workload" = "hpccpool" + } + taints = [] + tags = {} + } + + node_groups = var.aks_4nodepools? (var.aks_enable_roxie? merge( local.node_groups0, { roxiepool = local.roxiepool } ) : local.node_groups0) : { hpccpool = local.hpccpool } + azure_auth_env = { AZURE_TENANT_ID = data.azurerm_client_config.current.tenant_id AZURE_SUBSCRIPTION_ID = data.azurerm_client_config.current.subscription_id @@ -6,18 +103,18 @@ locals { names = var.disable_naming_conventions ? merge( { - business_unit = var.metadata.business_unit - environment = var.metadata.environment - location = var.metadata.location - market = var.metadata.market - subscription_type = var.metadata.subscription_type + business_unit = local.metadata.business_unit + environment = local.metadata.environment + location = local.metadata.location + market = local.metadata.market + subscription_type = local.metadata.subscription_type }, - var.metadata.product_group != "" ? { product_group = var.metadata.product_group } : {}, - var.metadata.product_name != "" ? { product_name = var.metadata.product_name } : {}, - var.metadata.resource_group_type != "" ? { resource_group_type = var.metadata.resource_group_type } : {} + local.metadata.product_group != "" ? { product_group = local.metadata.product_group } : {}, + local.metadata.product_name != "" ? { product_name = local.metadata.product_name } : {}, + local.metadata.resource_group_type != "" ? { resource_group_type = local.metadata.resource_group_type } : {} ) : module.metadata.names - tags = merge(var.metadata.additional_tags, { "owner" = var.owner.name, "owner_email" = var.owner.email }) + tags = { "owner" = local.owner.name, "owner_email" = local.owner.email } get_vnet_config = fileexists("../vnet/data/config.json") ? jsondecode(file("../vnet/data/config.json")) : null @@ -45,12 +142,8 @@ locals { current_hour = tonumber(formatdate("HH", local.current_time)) today = formatdate("YYYY-MM-DD", local.current_time) tomorrow = formatdate("YYYY-MM-DD", timeadd(local.current_time, "24h")) - # today = formatdate("YYYY-MM-DD", timeadd(local.current_time, "1h")) - - utc_offset = var.aks_automation.schedule[0].daylight_saving ? 4 : 5 script = { for item in fileset("${path.root}/scripts", "*") : (item) => file("${path.root}/scripts/${item}") } - schedule = { for s in var.aks_automation.schedule : "${s.schedule_name}" => s } az_command = "az aks get-credentials --name ${local.cluster_name} --resource-group ${module.resource_groups["azure_kubernetes_service"].name} --admin --overwrite-existing" is_windows_os = substr(pathexpand("~"), 0, 1) == "/" ? false : true diff --git a/aks/main.tf b/aks/main.tf index cfbe822..f96d390 100644 --- a/aks/main.tf +++ b/aks/main.tf @@ -24,17 +24,17 @@ module "metadata" { naming_rules = module.naming.yaml - market = var.metadata.market + market = local.metadata.market location = local.location - sre_team = var.metadata.sre_team - environment = var.metadata.environment - product_name = var.metadata.product_name - business_unit = var.metadata.business_unit - product_group = var.metadata.product_group - subscription_type = var.metadata.subscription_type - resource_group_type = var.metadata.resource_group_type + sre_team = local.metadata.sre_team + environment = local.metadata.environment + product_name = local.metadata.product_name + business_unit = local.metadata.business_unit + product_group = local.metadata.product_group + subscription_type = local.metadata.subscription_type + resource_group_type = local.metadata.resource_group_type subscription_id = module.subscription.output.subscription_id - project = var.metadata.project + project = local.metadata.project } module "resource_groups" { diff --git a/aks/misc.auto.tfvars.example b/aks/misc.auto.tfvars.example deleted file mode 100644 index c1040d3..0000000 --- a/aks/misc.auto.tfvars.example +++ /dev/null @@ -1,68 +0,0 @@ -owner = { - name = "demo" - email = "demo@lexisnexisrisk.com" -} - -metadata = { - project = "hpccplatform" - product_name = "hpccplatform" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "hpcc" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - additional_tags = { "justification" = "testing" } - location = "eastus" # Acceptable values: eastus, centralus -} - -resource_groups = { - azure_kubernetes_service = { - tags = { "enclosed resource" = "open source aks" } - } - # azure_log_analytics_workspace = { - # tags = { "enclosed resource" = "azure log analytics workspace" } - # } -} - -# # auto_connect - Automatically connect to the kubernetes cluster from the host machine. -auto_connect = true - -# # disable_naming_conventions - Disable naming conventions -# # disable_naming_conventions = true - -# azure_auth = { -# # AAD_CLIENT_ID = "" -# # AAD_CLIENT_SECRET = "" -# # AAD_TENANT_ID = "" -# # AAD_PRINCIPAL_ID = "" -# SUBSCRIPTION_ID = "" -# } - -aks_automation = { - local_authentication_enabled = false - public_network_access_enabled = false - automation_account_name = "aks-stop-demo-5" - - schedule = [ - { - schedule_name = "aks_stop" - description = "Stops the AKS weekday nights at 6PM EST" - frequency = "Week" //OneTime, Day, Hour, Week, or Month. - interval = "1" //cannot be set when frequency is `OneTime` - daylight_saving = true - start_time = "18:00" // At least 5 minutes in the future - week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] - }, - # { - # schedule_name = "aks_start" - # description = "Starts the AKS weekday nights at 6AM EST" - # frequency = "Week" //OneTime, Day, Hour, Week, or Month. - # interval = "1" //cannot be set when frequency is `OneTime` - # daylight_saving = true - # start_time = "06:00" // At least 5 minutes in the future - # week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] - # } - ] -} \ No newline at end of file diff --git a/aks/outputs.tf b/aks/outputs.tf index 5f97637..908d8a1 100644 --- a/aks/outputs.tf +++ b/aks/outputs.tf @@ -1,26 +1,25 @@ output "advisor_recommendations" { + description = "Advisor recommendations or 'none'" value = data.azurerm_advisor_recommendations.advisor.recommendations } output "aks_login" { + description = "Location of the aks credentials" value = "az aks get-credentials --name ${module.aks.cluster_name} --resource-group ${module.resource_groups["azure_kubernetes_service"].name}" } output "cluster_name" { - description = "The name of the Azure Kubernetes Service." + description = "Name of the Azure Kubernetes Service" value = module.aks.cluster_name } -output "hpcc_log_analytics_enabled" { - description = "Is Log Analytics enabled for HPCC?" - value = var.hpcc_log_analytics_enabled && fileexists("../logging/data/workspace_resource_id.txt") -} - output "cluster_resource_group_name" { - description = "The resource group where the cluster is deployed." + description = "Resource group where the cluster is deployed" value = module.resource_groups["azure_kubernetes_service"].name } resource "local_file" "output" { content = local.config filename = "${path.module}/data/config.json" + + depends_on = [ module.aks ] } diff --git a/aks/variables.tf b/aks/variables.tf index d2fa6f6..2daf996 100644 --- a/aks/variables.tf +++ b/aks/variables.tf @@ -1,35 +1,10 @@ -variable "owner" { - description = "Information for the user who administers the deployment." - type = object({ - name = string - email = string - }) - - validation { - condition = try( - regex("hpccdemo", var.owner.name) != "hpccdemo", true - ) && try( - regex("hpccdemo", var.owner.email) != "hpccdemo", true - ) && try( - regex("@example.com", var.owner.email) != "@example.com", true - ) - error_message = "Your name and email are required in the owner block and must not contain hpccdemo or @example.com." - } +variable "tags" { + description = "Tags to apply to all resources." + type = map(string) + nullable = false + default = {} } -# variable "azure_auth" { -# description = "Azure authentication" -# type = object({ -# AAD_CLIENT_ID = optional(string) -# AAD_CLIENT_SECRET = optional(string) -# AAD_TENANT_ID = optional(string) -# AAD_PRINCIPAL_ID = optional(string) -# SUBSCRIPTION_ID = string -# }) - -# nullable = false -# } - variable "auto_connect" { description = "Automatically connect to the Kubernetes cluster from the host machine by overwriting the current context." type = bool @@ -42,37 +17,6 @@ variable "disable_naming_conventions" { default = false } -variable "metadata" { - description = "Metadata module variables." - type = object({ - market = string - sre_team = string - environment = string - product_name = string - business_unit = string - product_group = string - subscription_type = string - resource_group_type = string - project = string - additional_tags = map(string) - location = string - }) - - default = { - business_unit = "" - environment = "" - market = "" - product_group = "" - product_name = "hpcc" - project = "" - resource_group_type = "" - sre_team = "" - subscription_type = "" - additional_tags = {} - location = "" - } -} - variable "resource_groups" { description = "Resource group module variables." type = any @@ -105,18 +49,6 @@ variable "use_existing_vnet" { default = null } -## DNS -######### -variable "internal_domain" { - description = "DNS Domain name" - type = string -} - -variable "dns_resource_group" { - description = "DNS resource group name" - type = string -} - ## Other AKS Vars ################## variable "cluster_ordinal" { @@ -132,14 +64,14 @@ variable "cluster_version" { } variable "sku_tier" { - description = "Pricing tier for the Azure Kubernetes Service managed cluster; \"free\" & \"paid\" are supported. For production clusters or clusters with more than 10 nodes this should be set to \"paid\"." + description = "Pricing tier for the Azure Kubernetes Service managed cluster; \"FREE\" & \"PAID\" are supported. For production clusters or clusters with more than 10 nodes this should be set to \"PAID\"." type = string nullable = false - default = "free" + default = "FREE" validation { - condition = contains(["free", "paid"], var.sku_tier) - error_message = "Available SKU tiers are \"free\" or \"paid\"." + condition = contains(["FREE", "PAID"], var.sku_tier) + error_message = "Available SKU tiers are \"FREE\" or \"PAID\"." } } @@ -154,118 +86,6 @@ variable "rbac_bindings" { default = {} } -variable "node_groups" { - description = "Node groups to configure." - type = map(object({ - node_arch = optional(string) - node_os = optional(string) - node_type = optional(string) - node_type_variant = optional(string) - node_type_version = optional(string) - node_size = string - single_group = optional(bool) - min_capacity = optional(number) - max_capacity = number - os_config = optional(map(any)) - ultra_ssd = optional(bool) - placement_group_key = optional(string) - max_pods = optional(number) - max_surge = optional(string) - labels = optional(map(string)) - taints = optional(list(object({ - key = string - value = string - effect = string - }))) - tags = optional(map(string)) - })) - nullable = false - default = {} -} - -variable "core_services_config" { - description = "Core service configuration." - type = object({ - alertmanager = object({ - smtp_host = string - smtp_from = string - receivers = optional(list(object({ - name = string - email_configs = optional(any, []) - opsgenie_configs = optional(any, []) - pagerduty_configs = optional(any, []) - pushover_configs = optional(any, []) - slack_configs = optional(any, []) - sns_configs = optional(any, []) - victorops_configs = optional(any, []) - webhook_configs = optional(any, []) - wechat_configs = optional(any, []) - telegram_configs = optional(any, []) - }))) - routes = optional(list(object({ - receiver = string - group_by = optional(list(string)) - continue = optional(bool) - matchers = list(string) - group_wait = optional(string) - group_interval = optional(string) - repeat_interval = optional(string) - mute_time_intervals = optional(list(string)) - # active_time_intervals = optional(list(string)) - }))) - }) - cert_manager = optional(object({ - acme_dns_zones = optional(list(string)) - additional_issuers = optional(map(any)) - default_issuer_kind = optional(string) - default_issuer_name = optional(string) - })) - coredns = optional(object({ - forward_zones = optional(map(any)) - })) - external_dns = optional(object({ - additional_sources = optional(list(string)) - private_domain_filters = optional(list(string)) - public_domain_filters = optional(list(string)) - })) - fluentd = optional(object({ - image_repository = optional(string) - image_tag = optional(string) - additional_env = optional(map(string)) - debug = optional(bool) - filters = optional(string) - route_config = optional(list(object({ - match = string - label = string - copy = optional(bool) - config = string - }))) - routes = optional(string) - outputs = optional(string) - })) - grafana = optional(object({ - admin_password = optional(string) - additional_plugins = optional(list(string)) - additional_data_sources = optional(list(any)) - })) - ingress_internal_core = optional(object({ - domain = string - subdomain_suffix = optional(string) - lb_source_cidrs = optional(list(string)) - lb_subnet_name = optional(string) - public_dns = optional(bool) - })) - prometheus = optional(object({ - remote_write = optional(any) - })) - storage = optional(object({ - file = optional(bool, true) - blob = optional(bool, false) - }), {}) - }) - nullable = false -} - variable "experimental" { description = "Configure experimental features." type = object({ @@ -298,27 +118,6 @@ variable "runbook" { default = [{}] } -variable "aks_automation" { - description = "Arguments to automate the Azure Kubernetes Cluster" - type = object({ - automation_account_name = string - local_authentication_enabled = optional(bool, false) - public_network_access_enabled = optional(bool, false) - - schedule = list(object({ - description = optional(string, "Stop the Kubernetes cluster.") - schedule_name = optional(string, "aks_stop") - runbook_name = optional(string, "aks_startstop_runbook") # name of the runbook - frequency = string - interval = string - start_time = string - week_days = list(string) - operation = optional(string, "stop") - daylight_saving = optional(bool, false) - })) - }) -} - variable "timezone" { description = "Name of timezone" type = string @@ -439,5 +238,5 @@ variable "availability_zones" { description = "Availability zones to use for the node groups." type = list(number) nullable = false - default = [1] + default = [2] } diff --git a/documentation/hpcc-tf-for-developers.md b/documentation/hpcc-tf-for-developers.md new file mode 100755 index 0000000..5fabb12 --- /dev/null +++ b/documentation/hpcc-tf-for-developers.md @@ -0,0 +1,149 @@ +# For Developers: Tutorial of HPCC Easy Deploy Terraform + +This tutorial explains the terraform code that deploys HPCC Systems on an Azure Kubernetes service (aks). The terraform code was designed to enable one to deploy HPCC Systems easily. +The terraform code can be found on Github. Here is a link to it ([https://github.com/hpccsystems-solutions-lab/terraform-azurerm-hpcc-lite]) + +From the root directory of the repository one can deploy all components of the HPCC cluster. Also, one can deploy individual components of the system from these subdirectories: `vnet`, `storage`, `aks`, and `hpcc`. If you want to deploy the individual components manually, here is the order you should do the deployment: 1st `vnet`, 2nd `storage` (if you want persistent storage), 3rd `aks`, and finally `hpcc`. + +The following sections will explain the terraform code in root directory and all subdirectories. + +## Root Directory +Here is the root directory's contents (**blue** names are subdirectories) and a description of each entry: + + +|Entry Name|Description| +|:-----|:----------| +| `lite-locals.tf` | Contains variables used my `hpcc` and `aks` | +| `lite-variables.tf` | Contains all input variables | +| `lite.auto.tfvars.example` |Is an example .auto.tfvars file | +| `main.tf` | Contains most of the terraform code that deploys all components of system | +| `providers.tf` | Contains one provider, azurerm | +| `scripts` | Directory containing scripts used in deployment | +| `aks` | Directory containing terraform code to deploy `aks` | +| `hpcc` | Directory containing terraform code to deploy `hpcc` | +| `storage` | Directory containing terraform code to deploy external or persistent `storage` | +| `vnet` | Directory containing terraform code to deploy virtual network used by `aks` | + + +The following table shows all the variables in the file, `lite-variables.tf`, and their types. Plus, the table gives a description of each variable. Also, when one deploys from the root directory the `deploy` script puts these variables (or some of them) in the subdirectory where the deployment takes place. + +|Variable|Type|Description| +|:-----|:---|:----------| +| `admin_username` | string | Username of the administrator of this HPCC Systems cluster. Example entry: "jdoe" | +| `aks_admin_email` | string | Email address of the administrator of this HPCC Systems cluster. Example entry: "jane.doe@hpccsystems.com" | +| `aks_admin_ip_cidr_map` | map of string | Map of name => CIDR IP addresses that can administrate this AKS. Format is '{"name"="cidr" [, "name"="cidr"]*}'. The 'name' portion must be unique. To add no CIDR addresses, use '{}'. The corporate network and your current IP address will be added automatically, and these addresses will have access to the HPCC cluster as a user. | +| `aks_admin_name` | string | Name of the administrator of this HPCC Systems cluster. Example entry: "Jane Doe" | +| `aks_azure_region` | string | The Azure region abbreviation in which to create these resources. Example entry: "eastus" | +| `aks_dns_zone_name` | string | Name of an existing dns zone. Example entry: "hpcczone.us-hpccsystems-dev.azure.lnrsg.io" | +| `aks_dns_zone_resource_group_name` | string | Name of the resource group of the above dns zone. Example entry: "app-dns-prod-eastus2" | +| `aks_enable_roxie` | boolean | Enable ROXIE? This will also expose port 8002 on the cluster. Example entry: false | +| `aks_max_node_count` | number | The maximum number of VM nodes to allocate for the HPCC Systems node pool. Must be 2 or more. | +| `aks_roxie_node_size ` | string | The VM size for each roxie node in the HPCC Systems. Example format `aks_roxie_node-size`="xlarge".| +| `aks_serv_node_size ` | string | The VM size for each serv node in the HPCC Systems. Example format `aks_serv_node-size`="2xlarge".| +| `aks_spray_node_size ` | string | The VM size for each spray node in the HPCC Systems. Example format `aks_spray_node-size`="2xlarge".| +| `aks_thor_node_size ` | string | The VM size for each thor node in the HPCC Systems. Example format `aks_thor_node-size`="2xlarge".| +| `authn_htpasswd_filename` | string | If you would like to use htpasswd to authenticate users to the cluster, enter the filename of the htpasswd file. This file should be uploaded to the Azure 'dllsshare' file share in order for the HPCC processes to find it. A corollary is that persistent storage is enabled. An empty string indicates that htpasswd is not to be used for authentication. Example entry: "htpasswd.txt" | +| `enable_code_security` | boolean | Enable code security? If true, only signed ECL code will be allowed to create embedded language functions, use PIPE(), etc. Example entry: false | +| `enable_premium_storage` | boolean | If true, premium ($$$) storage will be used for the following storage shares: Dali. OPTIONAL, defaults to false. | +| `enable_thor` | boolean | If you want a thor cluster then 'enable_thor' must be set to true Otherwise it is set to false | +| `external_storage_desired` | boolean | If you want external storage instead of ephemeral storage then set this variable to true otherwise set it to false. | +| `extra_tags` | map of string | Map of name => value tags that can will be associated with the cluster. Format is '{"name"="value" [, "name"="value"]*}'. The 'name' portion must be unique. To add no tags, use '{}'. | +| `hpcc_user_ip_cidr_list` | list of string | List of explicit CIDR addresses that can access this HPCC Systems cluster. To allow public access, specify "0.0.0.0/0". To add no CIDR addresses, use '[]'. | +| `hpcc_version` | string | The version of HPCC Systems to install. Only versions in nn.nn.nn format are supported. | +| `my_azure_id` | string | Your Azure account object id. Find this on Azure portal, by going to 'users' then search for your name and click on it. The account object id is called 'Object ID'. There is a link next to it that lets you copy it. | +| `storage_data_gb` | number | The amount of storage reserved for data in gigabytes. Must be 1 or more. If a storage account is defined (see below) then this value is ignored. | +| `storage_lz_gb` | number | The amount of storage reserved for the landing zone in gigabytes. Must be 1 or more. If a storage account is defined (see below) then this value is ignored. | +| `thor_max_jobs` | number | The maximum number of simultaneous Thor jobs allowed. Must be 1 or more. | +| `thor_num_workers` | number | The number of Thor workers to allocate. Must be 1 or more. | + + +The following table gives the name of each of the 5 `null_resource` in `main.tf` and gives a short description of what each does. + +|null_resource name|description| +|:-----------------|:----------| +| `deploy_vnet` | deploys aks' virtual network | +| `deploy_aks` | deploys aks | +| `deploy_storage` | deploys persistent storage | +| `external_storage` | waits for deployment of presistent storage | +| `deploy_hpcc` | deploys hpcc | + +The subfolders, except for `scripts`, create components needed by the full system. + +## scripts subdirectory + +|scripts subdirectory entry name|description| +|:--------------------------------|:----------| +| `deploy` | Used by each of the `deploy` `null_resource`s in main.tf. This script deploys any of the components, i.e. aks, hpcc, storage, or vnet | +| `destroy` | Destroys a single component, i.e. aks, hpcc, storage, or vnet. This script destorys 1) the component whose name is given on the command line after `deploy`, e.g. `destroy vnet`, and 2) any components that depends on it, e.g. before `vnet` is destroyed both `hpcc` and `aks` would be destroyed. | +| `external_storage` | Waits for presistent storage to be created (or if ephemeral storage is used this scripts exits) NOTE: HPCC is not deployed until `external_storage` exits successfully. | +| `extract-aks-variables` | the `deploy` script uses this script to copy from root directory the `lite-variables.tf` file contents used to deploy aks. | +| `get_rg_from_file` | Outputs the resource group name in the `config.json` file given on the command line | +| `mkplan` | Makes a unique name for the file that will contain the `terraform plan` of a component being deployed. | +| `needed-auto-tfvars-files` | Directory containing .auto.tfvars files needed by the `aks` and `storage` components. | + +## aks subdirectory + +The following table tells what files and subdirectories and in the `aks` subdirectory. The deployment of an `aks`happens in this directory. If one deploys from the root directory, the `deploy` script goes to this directory to deploy an `aks`. Also, if you deploy `aks` manually you do it from this directory. + +|aks subdirectory entry name|description| +|:------------------------------|:----------| +| `aks.tf` | This file contains most of the terraform code needed to deploy `aks`. The main module in this file is the `aks` module. | +| `data.tf` | This file contains `data` statements that gets resources needed that already exist. | +| `lite-locals.tf` | This file contains local variables that need variables given in lite.auto.tfvars. In Godson Fortil's repository, which this terraform code was forked, all the variables in this file were input variables defined in `variables.tf`. | +| `locals.tf` | This file contains local variables that were originally in Godson Fortil's repository. | +| `main.tf` | This file contains resources and modules needed for the deployment. They are: `resource "random_integer" "int`, `resource "random_string" "string`, `module "subscription`, `module "naming`, `module "metadata`, `module "resource_groups`, `resource "null_resource" "az`. | +| `outputs.tf` | This file contains `output` statement which outputs the following: `advisor_recommendations`,`aks_login`,`cluster_name`,`hpcc_log_analytics_enabled`,`cluster_resource_group_name`. | +| `providers.tf` | This file contains the following providers: `azurerm`,`azuread`,`kubernetes`,`kubernetes`,`kubectl`,`kubectl`,`helm`,`helm`,`shell`. | +| `variables.tf` | This file contains the variables described in the next table. | +| `versions.tf` | This file gives the version needed of each provider. | +| `scripts` | This directory contains scripts used in the `aks` terraform code. | + +## hpcc subdirectory + +The following table tells what files and subdirectories are in the hpcc subdirectory. The deployment of an hpcc cluster happens in this directory. If one deploys from the root directory, the `deploy` script goes to this directory to deploy an hpcc cluster. Also, if you deploy an hpcc cluster manually you do it from this directory. + +|hpcc subdirectory entry name|description| +|:--------------------------------|:----------| +| `data.tf` | Contains `data` statements providing information about existing resources. | +| `hpcc.tf` | Contains the `hpcc` module which does most of the work of deploying an hpcc cluster. | +| `locals.tf` | Contains local variables used in the deployment of the hpcc cluster. Variables in this file also use some of the easy deploy variables in lite-variables.tf. | +| `main.tf` | Contains modules and resources needed for the deployment of the hpcc cluster. | +| `outputs.tf` | Contains output statements that show the user important information, like the eclwatch url and the resource group used by most of the resources. | +| `providers.tf` | Contains providers needed for the hpcc cluster deployment. Also, some of these providers (`kubernetes` and `kubectl`) get credentials for the Kubernetes cluster for authenication. | +| `versions.tf` | Contains the versions needed for all providers. | +| `scripts` | This directory contains scripts used by the `hpcc` terraform code. | + +## storage subdirectory + +The following table tells what files and subdirectories and in the `storage` subdirectory. The deployment of an `storage` happens in this directory. If one deploys from the root directory, the `deploy` script goes to this directory to deploy `storage`. Also, if you deploy `storage` manually you do it from this directory. + +|storage subdirectory entry name|description| +|:--------------------------------|:----------| +| `README.md` | Contains a description of the `storage` module. | +| `data.tf` | Contains `data` statements providing information about existing resources. | +| `locals.tf` | Contains local variables used in the deployment of the `storage`. Variables in this file also use some of the easy deploy variables in lite-variables.tf. | +| `main.tf` | Contains only the `storage` module | +| `outputs.tf` | Contains only the resource `local_file` which outputs to a file config.json. This is done only when on a successful deployment of `storage`. | +| `providers.tf` | Contains only 2 providers: azurerm and azuread | +| `variables.tf` | Contains variables needed for `storage` deployment. | +| `versions.tf` | dummy description text | + +## vnet subdirectory + + +The following table tells what files and subdirectories are in the `vnet` subdirectory. The deployment of an `vnet` happens in this directory. If one deploys from the root directory, the `deploy` script goes to this directory to deploy `vnet`. Also, if you deploy `vnet` manually you do it from this directory. + +|vnet subdirectory entry name|description| +|:--------------------------------|:----------| +| `README.md` | Contains a description of the `vnet` module. | +| `data.tf` | Contains `data` statements providing information about existing resources. | +| `locals.tf` | Contains local variables used in the deployment of `vnet`. Variables in this file also use some of the easy deploy variables in lite-variables.tf. | +| `main.tf` | Contains modules and resources needed for the deployment of `vnet` | +| `outputs.tf` | Contains several output statements that output important information to the deployer. Also, this file contains an output state that outputs a file, config.json. This file is only output if there is a successful deployment of `vnet`. | +| `providers.tf` | Contains 2 providers: `random` and `azurerm`. | +| `variables.tf` | Contains only one variable, `disable_naming_conventions`. | +| `versions.tf` | Contains the required versions of `terraform`, `azurerm` and `random`. | +| `vnet.tf` | Contains the module `virtual_network` which deploys the virtual network used by `aks`, `hpcc`, and `storage`. | + + +​ diff --git a/hpcc/README.md b/hpcc/README.md deleted file mode 100644 index 67ef75a..0000000 --- a/hpcc/README.md +++ /dev/null @@ -1,732 +0,0 @@ -# Azure - HPCC AKS Root Module -
- -This module is intended as an example for development and test systems only. It can be used as a blueprint to develop your own production version that meets your organization's security requirements. -
-
- -## Introduction - -This module deploys an HPCC AKS cluster using remote modules that are listed below. -
- -## Remote Modules -These are the list of all the remote modules. - -| Name | Description | URL | Required | -| --------------- | ---------------------------------------------------- | -------------------------------------------------------------------------- | :------: | -| subscription | Queries enabled azure subscription from host machine | https://github.com/Azure-Terraform/terraform-azurerm-subscription-data.git | yes | -| naming | Enforces naming conventions | - | yes | -| metadata | Provides metadata | https://github.com/Azure-Terraform/terraform-azurerm-metadata.git | yes | -| resource_group | Creates a resource group | https://github.com/Azure-Terraform/terraform-azurerm-resource-group.git | yes | -| virtual_network | Creates a virtual network | https://github.com/Azure-Terraform/terraform-azurerm-virtual-network.git | yes | -| kubernetes | Creates an Azure Kubernetes Service Cluster | https://github.com/Azure-Terraform/terraform-azurerm-kubernetes.git | yes | -
- -## Supported Arguments -
- -### The `admin` block: -This block contains information on the user who is deploying the cluster. This is used as tags and part of some resource names to identify who deployed a given resource and how to contact that user. This block is required. - -| Name | Description | Type | Default | Required | -| ----- | ---------------------------- | ------ | ------- | :------: | -| name | Name of the admin. | string | - | yes | -| email | Email address for the admin. | string | - | yes | - -
-Usage Example: -
- - admin = { - name = "Example" - email = "example@hpccdemo.com" - } -
- -### The `disable_naming_conventions` block: -When set to `true`, this attribute drops the naming conventions set forth by the python module. This attribute is optional. - - | Name | Description | Type | Default | Required | - | -------------------------- | --------------------------- | ---- | ------- | :------: | - | disable_naming_conventions | Disable naming conventions. | bool | `false` | no | -
- -### The `metadata` block: -TThe arguments in this block are used as tags and part of resources’ names. This block can be omitted when disable_naming_conventions is set to `true`. - - | Name | Description | Type | Default | Required | - | ------------------- | ---------------------------- | ------ | ------- | :------: | - | project_name | Name of the project. | string | "" | yes | - | product_name | Name of the product. | string | hpcc | no | - | business_unit | Name of your bussiness unit. | string | "" | no | - | environment | Name of the environment. | string | "" | no | - | market | Name of market. | string | "" | no | - | product_group | Name of product group. | string | "" | no | - | resource_group_type | Resource group type. | string | "" | no | - | sre_team | Name of SRE team. | string | "" | no | - | subscription_type | Subscription type. | string | "" | no | -
- -Usage Example: -
- - metadata = { - project = "hpccdemo" - product_name = "example" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "contoso" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - } - -
- -### The `tags` argument: -The tag attribute can be used for additional tags. The tags must be key value pairs. This block is optional. - - | Name | Description | Type | Default | Required | - | ---- | ------------------------- | ----------- | ------- | :------: | - | tags | Additional resource tags. | map(string) | admin | no | -
- -### The `resource_group` block: -This block creates a resource group (like a folder) for your resources. This block is required. - - | Name | Description | Type | Default | Required | - | ----------- | ----------------------------------------------------------------- | ---- | ------- | :------: | - | unique_name | Will concatenate a number at the end of your resource group name. | bool | `true` | yes | -
- -Usage Example: -
- - resource_group = { - unique_name = true - } - -
- -### The `virtual_network` block: -This block imports metadata of a virtual network deployed outside of this project. This block is optional. - - | Name | Description | Type | Default | Required | - | ----------------- | --------------------------------------- | ------ | ------- | :------: | - | private_subnet_id | The ID of the private subnet. | string | - | yes | - | public_subnet_id | The ID of the public subnet. | string | - | yes | - | route_table_id | The ID of the route table for the AKS. | string | - | yes | - | location | The location of the virtual network | string | - | yes | -
- -Usage Example: -
- - virtual_network = { - private_subnet_id = "" - public_subnet_id = "" - route_table_id = "" - location = "" - } - -
- -## The `node_pools` block: -The `node-pools` block supports the following arguments:
-`system` - (Required) The system or default node pool. This node pool hosts the system pods by default. The possible arguments for this block are defined below. - -`addpool` - (Required) The additional node pool configuration. This block name is changeable and must be unique across all additional node pools. At least one additional node pool is required. The possible arguments for this block are defined below. - -### The `system` block: -This block creates a system node pool. This block is required. - -| Name | Optional, Required | Description | -| --------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| vm_size | Optional | The size of the Virtual Machine, such as Standard_A4_v2. | -| node_count | Optional | The initial number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000 and between min_count and max_count. | -| enable_auto_scalling | Optional | Should the Kubernetes Auto Scaler be enabled for this Node Pool? Defaults to false. | -| min_count | Optional | The minimum number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000. Can only be set when enable_auto_scalling is set to true. | -| max_count | Optional | The maximum number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000. Can only be set when enable_auto_scalling is set to true. | -| availability_zones | Optional | A list of Availability Zones across which the Node Pool should be spread. Changing this forces a new resource to be created. | -| enable_host_encryption | Optional | Should the nodes in the Default Node Pool have host encryption enabled? Defaults to false. Can only be enabled on new node pools. Requires VirtualMachineScaleSets as VM type. Can only be enabled in Azure regions that support server-side encryption of Azure managed disks and only with specific supported VM sizes. | -| enable_node_public_ip | Optional | Should nodes in this Node Pool have a Public IP Address? Defaults to false. | -| max_pods | Optional | The maximum number of pods that can run on each agent. | -| node_labels | Optional | A map of Kubernetes labels which should be applied to nodes in the Default Node Pool. | -| only_critical_addons_enable | Optional | Enabling this option will taint default node pool with CriticalAddonsOnly=true:NoSchedule taint. When set to true, only system pods will be scheduled on the system node pool. | -| orchestrator_version | Optional | Version of Kubernetes used for the Agents. If not specified, the latest recommended version will be used at provisioning time (but won't auto-upgrade). | -| os_disk_size_gb | Optional | The size of the OS Disk which should be used for each agent in the Node Pool. | -| os_disk_type | Optional | The type of disk which should be used for the Operating System. Possible values are Ephemeral and Managed. Defaults to Managed. | -| type | Optional | The type of Node Pool which should be created. Possible values are AvailabilitySet and VirtualMachineScaleSets. Defaults to VirtualMachineScaleSets. | -| tags | Optional | A mapping of tags to assign to the Node Pool. | -| subnet | Optional | The ID of a Subnet where the Kubernetes Node Pool should exist. | -
- -### The `addpool` block: -This block creates additional node pools. This block is optional. - -| Name | Optional, Required | Description | -| ---------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| node_taints | Optional | A list of Kubernetes taints which should be applied to nodes in the agent pool (e.g key=value:NoSchedule). Changing this forces a new resource to be created. | -| max_surge | Required | The maximum number or percentage of nodes which will be added to the Node Pool size during an upgrade. | -| eviction_policy | Optional | The Eviction Policy which should be used for Virtual Machines within the Virtual Machine Scale Set powering this Node Pool. Possible values are Deallocate and Delete. Will only be used when priority is set to Spot. Changing this forces a new resource to be created. | -| os_type | Optional | The Operating System which should be used for this Node Pool. Changing this forces a new resource to be created. Possible values are Linux and Windows. Defaults to Linux. | -| priority | Optional | The Priority for Virtual Machines within the Virtual Machine Scale Set that powers this Node Pool. Possible values are Regular and Spot. Defaults to Regular. Changing this forces a new resource to be created. | -| proximity_placement_group_id | Optional | The ID of the Proximity Placement Group where the Virtual Machine Scale Set that powers this Node Pool will be placed. Changing this forces a new resource to be created. | -| spot_max_price | Optional | The maximum price you're willing to pay in USD per Virtual Machine. Valid values are -1 (the current on-demand price for a Virtual Machine) or a positive value with up to five decimal places. Changing this forces a new resource to be created. | -| vm_size | Optional | The size of the Virtual Machine, such as Standard_A4_v2. | -| node_count | Optional | The initial number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000 and between min_count and max_count. | -| enable_auto_scalling | Optional | Should the Kubernetes Auto Scaler be enabled for this Node Pool? Defaults to false. | -| min_count | Optional | The minimum number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000. Can only be set when enable_auto_scalling is set to true. | -| max_count | Optional | The maximum number of nodes which should exist in this Node Pool. If specified this must be between 1 and 1000. Can only be set when enable_auto_scalling is set to true. | -| availability_zones | Optional | A list of Availability Zones across which the Node Pool should be spread. Changing this forces a new resource to be created. | -| enable_host_encryption | Optional | Should the nodes in the Default Node Pool have host encryption enabled? Defaults to false. Can only be enabled on new node pools. Requires VirtualMachineScaleSets as VM type. Can only be enabled in Azure regions that support server-side encryption of Azure managed disks and only with specific supported VM sizes. | -| enable_node_public_ip | Optional | Should nodes in this Node Pool have a Public IP Address? Defaults to false. | -| max_pods | Optional | The maximum number of pods that can run on each agent. | -| node_labels | Optional | A map of Kubernetes labels which should be applied to nodes in the Default Node Pool. | -| only_critical_addons_enable | Optional | Enabling this option will taint default node pool with CriticalAddonsOnly=true:NoSchedule taint. When set to true, only system pods will be scheduled on the system node pool. | -| orchestrator_version | Optional | Version of Kubernetes used for the Agents. If not specified, the latest recommended version will be used at provisioning time (but won't auto-upgrade). | -| os_disk_size_gb | Optional | The size of the OS Disk which should be used for each agent in the Node Pool. | -| os_disk_type | Optional | The type of disk which should be used for the Operating System. Possible values are Ephemeral and Managed. Defaults to Managed. | -| type | Optional | The type of Node Pool which should be created. Possible values are AvailabilitySet and VirtualMachineScaleSets. Defaults to VirtualMachineScaleSets. | -| tags | Optional | A mapping of tags to assign to the Node Pool. | -| subnet | Optional | The ID of a Subnet where the Kubernetes Node Pool should exist. | -
- -Usage Example: -
- - node_pools = { - system = { - vm_size = "Standard_D4_v4" - node_count = 1 - enable_auto_scaling = true - only_critical_addons_enabled = true - min_count = 1 - max_count = 1 - availability_zones = [] - subnet = "private" - enable_host_encryption = false - enable_node_public_ip = false - os_disk_type = "Managed" - type = "VirtualMachineScaleSets" - # max_pods = 10 - # node_labels = {"engine" = "roxie", "engine" = "roxie"} - # orchestrator_version = "2.9.0" - # os_disk_size_gb = 100 - # tags = {"mynodepooltag1" = "mytagvalue1", "mynodepooltag2" = "mytagvalue2"} - - } - - addpool1 = { - vm_size = "Standard_D4_v4" - enable_auto_scaling = true - node_count = 2 - min_count = 1 - max_count = 2 - availability_zones = [] - subnet = "public" - priority = "Regular" - spot_max_price = -1 - max_surge = "1" - os_type = "Linux" - priority = "Regular" - enable_host_encryption = false - enable_node_public_ip = false - only_critical_addons_enabled = false - os_disk_type = "Managed" - type = "VirtualMachineScaleSets" - # orchestrator_version = "2.9.0" - # os_disk_size_gb = 100 - # max_pods = 20 - # node_labels = {"engine" = "roxie", "engine" = "roxie"} - # eviction_policy = "Spot" - # node_taints = ["mytaint1", "mytaint2"] - # proximity_placement_group_id = "my_proximity_placement_group_id" - # spot_max_price = 1 - # tags = {"mynodepooltag1" = "mytagvalue1", "mynodepooltag2" = "mytagvalue2"} - } - - addpool2 = { - vm_size = "Standard_D4_v4" - enable_auto_scaling = true - node_count = 2 - min_count = 1 - max_count = 2 - availability_zones = [] - subnet = "public" - priority = "Regular" - spot_max_price = -1 - max_surge = "1" - os_type = "Linux" - priority = "Regular" - enable_host_encryption = false - enable_node_public_ip = false - only_critical_addons_enabled = false - os_disk_type = "Managed" - type = "VirtualMachineScaleSets" - # orchestrator_version = "2.9.0" - # os_disk_size_gb = 100 - # max_pods = 20 - # node_labels = {"engine" = "roxie", "engine" = "roxie"} - # eviction_policy = "Spot" - # node_taints = ["mytaint1", "mytaint2"] - # proximity_placement_group_id = "my_proximity_placement_group_id" - # spot_max_price = 1 - # tags = {"mynodepooltag1" = "mytagvalue1", "mynodepooltag2" = "mytagvalue2"} - } - } -
- -### The `disable_helm` argument: -This block disable helm deployments by Terraform. This block is optional and will stop HPCC from being installed. - - | Name | Description | Type | Default | Required | - | ------------ | -------------------------------------- | ---- | ------- | :------: | - | disable_helm | Disable Helm deployments by Terraform. | bool | `false` | no | -
- -### The `hpcc` block: -This block deploys the HPCC helm chart. This block is optional. - - | Name | Description | Type | Default | Required | - | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ------------------------------ | :------: | - | local_chart | Path to local chart directory name or tgz file. Example1: ~/HPCC-Platform/helm/hpcc Example2: https://github.com/hpcc-systems/helm-chart/raw/master/docs/hpcc-8.6.16-rc1.tgz | string | null | no | - | remote_chart | URL of the remote chart. Example: https://hpcc-systems.github.io/helm-chart | string | null | no | - | namespace | Namespace to use. | string | default | no | - | name | Release name of the chart. | string | myhpcck8s | no | - | values | List of desired state files to use similar to -f in CLI. | list(string) | values-retained-azurefile.yaml | no | - | version | Version of the HPCC chart. | string | latest | yes | - | image_root | Image root to use. | string | hpccsystems | no | - | image_name | Image name to use. | string | platform-core | no | - | atomic | If set, installation process purges chart on fail. The `wait` flag will be set automatically if `atomic` is used. | bool | false | no | - | recreate_pods | Perform pods restart during upgrade/rollback. | bool | false | no | - | reuse_values | When upgrading, reuse the last release's values and merge in any overrides. If `reset_values` is specified, this is ignored. | bool | false | no | - | reset_values | When upgrading, reset the values to the ones built into the chart. | bool | false | no | - | force_update | Force resource update through delete/recreate if needed. | bool | false | no | - | cleanup_on_fail | Allow deletion of new resources created in this upgrade when upgrade fails. | bool | false | no | - | disable_openapi_validation | If set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema. | bool | false | no | - | max_history | Maximum number of release versions stored per release. | number | 0 | no | - | wait | Will wait until all resources are in a ready state before marking the release as successful. It will wait for as long as `timeout` . | bool | true | no | - | dependency_update | Runs helm dependency update before installing the chart. | bool | false | no | - | timeout | Time in seconds to wait for any individual kubernetes operation (like Jobs for hooks). | number | 900 | no | - | wait_for_jobs | If wait is enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as `timeout`. | bool | false | no | - | lint | Run the helm chart linter during the plan. | bool | false | no | - | expose_eclwatch | Expose ECLWatch to the internet. This can cause the service to hang on pending state if external IPs are blocked by your organization's cloud policies. | bool | true | no | -
- - Usage Example: -
- - hpcc = { - expose_eclwatch = true - name = "myhpcck8s" - atomic = true - recreate_pods = false - reuse_values = false - reset_values = false - force_update = false - namespace = "default" - cleanup_on_fail = false - disable_openapi_validation = false - max_history = 0 - wait = true - dependency_update = true - timeout = 900 - wait_for_jobs = false - lint = false - remote_chart = "https://hpcc-systems.github.io/helm-chart" - # local_chart = "/Users/foo/work/demo/helm-chart/helm/hpcc" #Other examples: https://github.com/hpcc-systems/helm-chart/raw/master/docs/hpcc-8.6.16-rc1.tgz - # version = "8.6.14-rc2" - # values = ["/Users/foo/mycustomvalues1.yaml", "/Users/foo/mycustomvalues2.yaml"] - # image_root = "west.lexisnexisrisk.com" - # image_name = "platform-core-ln" - # image_version = "8.6.18-rc1" - } - -
- -### The `storage` block: -This block deploys the HPCC persistent volumes. This block is required. - - | Name | Description | Type | Default | Valid Options | Required | - | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------ | ------------------------------------------------------- | ---------------- | :---------: | - | default | Use AKS provided storage accounts? | bool | `false` | `true` , `false` | no | - | version | The version of the storage chart. | string | 0.1.0 | | no | - | local_chart | Path to local chart directory name or tgz file. Example1: /Users/foo/work/demo/helm-chart/helm/examples/azure/hpcc-azurefile Example2: https://github.com/hpcc-systems/helm-chart/raw/master/docs/hpcc-azurefile-0.1.0.tgz | string | null | no | - | remote_chart | URL of the remote chart. Example: https://hpcc-systems.github.io/helm-chart | name | Release name of the chart. | string | `myhpcck8s` | no | - | values | List of desired state files to use similar to -f in CLI. | list(string) | [] | no | - | storage_accounts | The storage account to use. | object | Queries attributes' values from storage_accounts module | - | no | - | version | Version of the storage chart. | string | 0.1.0 | no | - | atomic | If set, installation process purges chart on fail. The `wait` flag will be set automatically if `atomic` is used. | bool | false | no | - | recreate_pods | Perform pods restart during upgrade/rollback. | bool | false | no | - | reuse_values | When upgrading, reuse the last release's values and merge in any overrides. If `reset_values` is specified, this is ignored. | bool | false | no | - | reset_values | When upgrading, reset the values to the ones built into the chart. | bool | false | no | - | force_update | Force resource update through delete/recreate if needed. | bool | false | no | - | cleanup_on_fail | Allow deletion of new resources created in this upgrade when upgrade fails. | bool | false | no | - | disable_openapi_validation | If set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema. | bool | false | no | - | max_history | Maximum number of release versions stored per release. | number | 0 | no | - | wait | Will wait until all resources are in a ready state before marking the release as successful. It will wait for as long as `timeout` . | bool | true | no | - | dependency_update | Runs helm dependency update before installing the chart. | bool | false | no | - | timeout | Time in seconds to wait for any individual kubernetes operation (like Jobs for hooks). | number | 600 | no | - | wait_for_jobs | If wait is enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as `timeout`. | bool | false | no | - | lint | Run the helm chart linter during the plan. | bool | false | no | -
- -#### The `storage_accounts` block: -This block deploys the HPCC persistent volumes. This block is required. - - | Name | Description | Type | Default | Valid Options | Required | - | ------------------- | -------------------------------------------------------------------- | ------------ | --------------------------- | ------------- | :------: | - | name | Name of the storage account | string | - | - | yes | - | resource_group_name | The name of the resource group in which the storage account belongs. | string | - | - | yes | - | subscription_id | The ID of the subscription in which the storage account belongs. | string | Admin's active subscription | - | no | - | shares | The list of shares in the storage account | list(object) | - | - | yes | - | | -
- -#### The `shares` block: -This block defines the list of shares in the storage account. This block is required. - - | Name | Description | Type | Default | Valid Options | Required | - | -------- | ------------------------------------- | ------ | ------- | ------------- | :------: | - | name | The name of the share. | string | - | - | yes | - | sub_path | The sub path for the HPCC data plane. | string | - | - | yes | - | category | The category for the HPCC data plane | string | - | - | yes | - | sku | The sku for the HPCC data plane. | string | - | - | yes | - | quota | The size of the share in Gigabytes | number | - | - | yes | - -Usage Example: -
- - storage = { - default = false - atomic = true - recreate_pods = false - reuse_values = false - reset_values = false - force_update = false - namespace = "default" - cleanup_on_fail = false - disable_openapi_validation = false - max_history = 0 - wait = true - dependency_update = true - timeout = 600 - wait_for_jobs = false - lint = false - remote_chart = "https://hpcc-systems.github.io/helm-chart" - # local_chart = "/Users/foo/work/demo/helm-chart/helm/examples/azure/hpcc-azurefile" - # version = "0.1.0" - # values = ["/Users/foo/mycustomvalues1.yaml", "/Users/foo/mycustomvalues2.yaml"] - - /* - storage_accounts = { - # do not change the key names - dali = { - name = "dalikxgt" - resource_group_name = "app-storageaccount-sandbox-eastus-79735" - - shares = { - dali = { - name = "dalishare" - sub_path = "dalistorage" //do not change this value - category = "dali" //do not change this value - sku = "Premium_LRS" - quota = 100 - } - } - } - - sasha = { - name = "sashakxgt" - resource_group_name = "app-storageaccount-sandbox-eastus-79735" - - shares = { - sasha = { - name = "sashashare" - sub_path = "sasha" //do not change this value - category = "sasha" //do not change this value - sku = "Standard_LRS" - quota = 100 - } - } - } - - common = { - name = "commonkxgt" - resource_group_name = "app-storageaccount-sandbox-eastus-79735" - - shares = { - data = { - name = "datashare" - sub_path = "hpcc-data" //do not change this value - category = "data" //do not change this value - sku = "Standard_LRS" - quota = 100 - } - - dll = { - name = "dllshare" - sub_path = "queries" //do not change this value - category = "dll" //do not change this value - sku = "Standard_LRS" - quota = 100 - } - - mydropzone = { - name = "mydropzoneshare" - sub_path = "dropzone" //do not change this value - category = "lz" //do not change this value - sku = "Standard_LRS" - quota = 100 - } - } - } - } - */ - } -
- -### The `elastic4hpcclogs` block: -This block deploys the elastic4hpcclogs chart. This block is optional. - - | Name | Description | Type | Default | Required | - | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ----------------------- | :------: | - | local_chart | Path to local chart directory name or tgz file. Example1: /Users/foo/work/demo/helm-chart/helm/managed/logging/elastic Example2: https://github.com/hpcc-systems/helm-chart/raw/master/docs/elastic4hpcclogs-1.2.10.tgz | string | null | no | - | remote_chart | URL of the remote chart. Example: https://hpcc-systems.github.io/helm-chart | enable | Enable elastic4hpcclogs | bool | `true` | no | - | name | Release name of the chart. | string | myelastic4hpcclogs | no | - | version | The version of the elastic4hpcclogs | string | 1.2.8 | | no | - | values | List of desired state files to use similar to -f in CLI. | list(string) | - | no | - | version | Version of the elastic4hpcclogs chart. | string | 1.2.1 | no | - | atomic | If set, installation process purges chart on fail. The `wait` flag will be set automatically if `atomic` is used. | bool | false | no | - | recreate_pods | Perform pods restart during upgrade/rollback. | bool | false | no | - | reuse_values | When upgrading, reuse the last release's values and merge in any overrides. If `reset_values` is specified, this is ignored. | bool | false | no | - | reset_values | When upgrading, reset the values to the ones built into the chart. | bool | false | no | - | force_update | Force resource update through delete/recreate if needed. | bool | false | no | - | cleanup_on_fail | Allow deletion of new resources created in this upgrade when upgrade fails. | bool | false | no | - | disable_openapi_validation | If set, the installation process will not validate rendered templates against the Kubernetes OpenAPI Schema. | bool | false | no | - | max_history | Maximum number of release versions stored per release. | number | 0 | no | - | wait | Will wait until all resources are in a ready state before marking the release as successful. It will wait for as long as `timeout` . | bool | true | no | - | dependency_update | Runs helm dependency update before installing the chart. | bool | false | no | - | timeout | Time in seconds to wait for any individual kubernetes operation (like Jobs for hooks). | number | 900 | no | - | wait_for_jobs | If wait is enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as `timeout`. | bool | false | no | - | lint | Run the helm chart linter during the plan. | bool | false | no | - | expose | Expose myelastic4hpcclogs-kibana service to the internet. This can cause the service to hang on pending state if external IPs are blocked by your organization's cloud policies. | bool | true | no | -
- -Usage Example: -
- - elastic4hpcclogs = { - enable = true - expose = true - name = "myelastic4hpcclogs" - atomic = true - recreate_pods = false - reuse_values = false - reset_values = false - force_update = false - namespace = "default" - cleanup_on_fail = false - disable_openapi_validation = false - max_history = 0 - wait = true - dependency_update = true - timeout = 300 - wait_for_jobs = false - lint = false - remote_chart = "https://hpcc-systems.github.io/helm-chart" - #local_chart = "/Users/godji/work/demo/helm-chart/helm/managed/logging/elastic" - # version = "1.2.10" - # values = ["/Users/foo/mycustomvalues1.yaml", "/Users/foo/mycustomvalues2.yaml"] - } -
- -### The `registry` block: -This block authenticates a private Docker repository. This block is optional. - - | Name | Description | Type | Default | Required | - | -------- | -------------------------------------------------------------------------- | ------ | ------- | :------: | - | server | The server address of the private Docker repository. | string | - | yes | - | username | The username for the private Docker repository account. | string | - | yes | - | password | The password, token, or API key for the private Docker repository account. | string | - | yes | -
- -Usage Example: -
- - registry = { - password = "" - server = "" - username = "" - } -
- -### The `auto_connect` argument: -This block automatically connect your cluster to your local machine similarly to `az aks get-credentials`. - - | Name | Description | Type | Default | Required | - | ------------ | --------------------------------------------------------------------------------------------------------- | ---- | ------- | :------: | - | auto_connect | Automatically connect to the Kubernetes cluster from the host machine by overwriting the current context. | bool | `false` | no | -
- -## Outputs - -| Name | Description | -| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| aks_login | Get access credentials for the managed Kubernetes cluster. | -| recommendations | A list of security and cost recommendations for this deployment. Your environment has to have been deployed for several hours before Azure provides recommendations. | -
- -## Usage -### Deploy the Virtual Network Module -
    -
  1. - -Clone this repo: `git clone https://github.com/gfortil/terraform-azurerm-hpcc.git`.
  2. - -
  3. Linux and MacOS
  4. -
      -
    1. - -Change directory to terraform-azurerm-hpcc/modules/virtual_network: `cd terraform-azurerm-hpcc/modules/virtual_network`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc/modules/virtual_network: `cp examples/admin.tfvars .`
    4. -
    -
  5. Windows OS
  6. -
      -
    1. - -Change directory to terraform-azurerm-hpcc/modules/virtual_network: `cd terraform-azurerm-hpcc/modules/virtual_network`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc/modules/virtual_network: `copy examples\admin.tfvars .`
    4. -
    -
  7. - -Open `terraform-azurerm-hpcc/modules/virtual_network/admin.tfvars` file.
  8. -
  9. - -Set attributes to your preferred values.
  10. -
  11. - -Save `terraform-azurerm-hpcc/modules/virtual_network/admin.tfvars` file.
  12. -
  13. - -Run `terraform init`. This step is only required before your first `terraform apply`.
  14. -
  15. - -Run `terraform apply -var-file=admin.tfvars` or `terraform apply -var-file=admin.tfvars -auto-approve`.
  16. -
  17. - -Type `yes` if you didn't pass the flag `-auto-approve`.
  18. -
- -### Deploy the Storage Account Module -
    -
  1. Linux and MacOS
  2. -
      -
    1. - -Change directory to terraform-azurerm-hpcc/modules/storage_accounts: `cd terraform-azurerm-hpcc/modules/storage_accounts`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc/modules/storage_accounts: `cp examples/admin.tfvars .`
    4. -
    -
  3. Windows OS
  4. -
      -
    1. - -Change directory to terraform-azurerm-hpcc/modules/storage_accounts: `cd terraform-azurerm-hpcc/modules/storage_accounts`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc/modules/storage_accounts: `copy examples\admin.tfvars .`
    4. -
    -
  5. - -Open `terraform-azurerm-hpcc/modules/storage_accounts/admin.tfvars` file.
  6. -
  7. - -Set attributes to your preferred values.
  8. -
  9. - -Save `terraform-azurerm-hpcc/modules/storage_accounts/admin.tfvars` file.
  10. -
  11. - -Run `terraform init`. This step is only required before your first `terraform apply`.
  12. -
  13. - -Run `terraform apply -var-file=admin.tfvars` or `terraform apply -var-file=admin.tfvars -auto-approve`.
  14. -
  15. - -Type `yes` if you didn't pass the flag `-auto-approve`.
  16. -
- -### Deploy the AKS Module -
    -
  1. Linux and MacOS
  2. -
      -
    1. - -Change directory to terraform-azurerm-hpcc: `cd terraform-azurerm-hpcc`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc: `cp examples/admin.tfvars .`
    4. -
    -
  3. Windows OS
  4. -
      -
    1. - -Change directory to terraform-azurerm-hpcc: `cd terraform-azurerm-hpcc`
    2. -
    3. - -Copy examples/admin.tfvars to terraform-azurerm-hpcc: `copy examples\admin.tfvars .`
    4. -
    -
  5. - -Open `terraform-azurerm-hpcc/admin.tfvars` file.
  6. -
  7. - -Set attributes to your preferred values.
  8. -
  9. - -Save `terraform-azurerm-hpcc/admin.tfvars` file.
  10. -
  11. - -Run `terraform init`. This step is only required before your first `terraform apply`.
  12. -
  13. - -Run `terraform apply -var-file=admin.tfvars` or `terraform apply -var-file=admin.tfvars -auto-approve`.
  14. -
  15. - -Type `yes` if you didn't pass the flag `-auto-approve`.
  16. -
  17. - -If `auto_connect = true` (in admin.tfvars), skip this step.
  18. -
      -
    1. - -Copy aks_login command.
    2. -
    3. - -Run aks_login in your command line.
    4. -
    5. - -Accept to overwrite your current context.
    6. -
    -
  19. - -List pods: `kubectl get pods`.
  20. -
  21. - -Get ECLWatch external IP: `kubectl get svc --field-selector metadata.name=eclwatch | awk 'NR==2 {print $4}'`.
  22. -
  23. - -Delete cluster: `terraform destroy -var-file=admin.tfvars` or `terraform destroy -var-file=admin.tfvars -auto-approve`.
  24. -
  25. - -Type: `yes` if flag `-auto-approve` was not set.
  26. -
diff --git a/hpcc/dali.auto.tfvars.example b/hpcc/dali.auto.tfvars.example deleted file mode 100644 index e69de29..0000000 diff --git a/hpcc/data.tf b/hpcc/data.tf index ae24590..4a92803 100644 --- a/hpcc/data.tf +++ b/hpcc/data.tf @@ -11,3 +11,8 @@ data "azuread_group" "subscription_owner" { data "azurerm_client_config" "current" { } + +data "local_file" "aks" { + filename = "../aks/data/config.json" +} + diff --git a/hpcc/eclccserver.auto.tfvars.example b/hpcc/eclccserver.auto.tfvars.example deleted file mode 100644 index e69de29..0000000 diff --git a/hpcc/hpcc.tf b/hpcc/hpcc.tf index 82a047f..cc0c9dd 100644 --- a/hpcc/hpcc.tf +++ b/hpcc/hpcc.tf @@ -1,84 +1,84 @@ -resource "kubernetes_namespace" "hpcc" { - count = var.hpcc_namespace.create_namespace && !fileexists("${path.module}/modules/logging/data/hpcc_namespace.txt") ? 1 : 0 - - metadata { - labels = var.hpcc_namespace.labels - name = "${substr(trimspace(var.owner.name), 0, 5)}${random_integer.random.result}" - # generate_name = "${trimspace(var.owner.name)}" - } -} - module "hpcc" { - source = "github.com/gfortil/opinionated-terraform-azurerm-hpcc?ref=HPCC-27615" + #source = "git@github.com:hpccsystems-solutions-lab/tlh-opinionated-terraform-azurerm-hpcc.git" + source = "github.com/hpccsystems-solutions-lab/tlh-opinionated-terraform-azurerm-hpcc.git" + #source = "/home/azureuser/tlhumphrey2/RBA-terraform-azurerm-hpcc" - environment = var.metadata.environment - productname = var.metadata.product_name + environment = local.metadata.environment + productname = local.metadata.product_name - internal_domain = var.internal_domain - cluster_name = local.get_aks_config.cluster_name + a_record_name = var.a_record_name + internal_domain = local.internal_domain + cluster_name = jsondecode(file("../aks/data/config.json")).cluster_name + hpcc_version = var.hpcc_version hpcc_container = { - image_name = var.hpcc_container != null ? var.hpcc_container.image_name : null - image_root = var.hpcc_container != null ? var.hpcc_container.image_root : null - version = var.hpcc_container != null ? var.hpcc_container.version : null - custom_chart_version = var.hpcc_container != null ? var.hpcc_container.custom_chart_version : null - custom_image_version = var.hpcc_container != null ? var.hpcc_container.custom_image_version : null + image_name = local.hpcc_container != null ? local.hpcc_container.image_name : null + image_root = local.hpcc_container != null ? local.hpcc_container.image_root : null + version = local.hpcc_container != null ? local.hpcc_container.version : null + custom_chart_version = local.hpcc_container != null ? local.hpcc_container.custom_chart_version : null + custom_image_version = local.hpcc_container != null ? local.hpcc_container.custom_image_version : null } - hpcc_container_registry_auth = var.hpcc_container_registry_auth != null ? { - password = var.hpcc_container_registry_auth.password - username = var.hpcc_container_registry_auth.username + hpcc_container_registry_auth = local.hpcc_container_registry_auth != null ? { + password = local.hpcc_container_registry_auth.password + username = local.hpcc_container_registry_auth.username } : null + hpcc_user_ip_cidr_list = var.hpcc_user_ip_cidr_list + install_blob_csi_driver = false //Disable CSI driver resource_group_name = local.get_aks_config.resource_group_name - location = var.metadata.location + location = local.metadata.location tags = module.metadata.tags - # namespace = local.hpcc_namespace namespace = { create_namespace = false name = local.hpcc_namespace - labels = var.hpcc_namespace.labels + labels = { name = "hpcc" } } + #----------------------------------------------------------------------- + # Storage variables (internal (ephemeral) or external) + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - admin_services_storage_account_settings = { - replication_type = var.admin_services_storage_account_settings.replication_type - authorized_ip_ranges = merge(var.admin_services_storage_account_settings.authorized_ip_ranges, { host_ip = data.http.host_ip.response_body }) - delete_protection = var.admin_services_storage_account_settings.delete_protection + replication_type = local.admin_services_storage_account_settings.replication_type + authorized_ip_ranges = merge(local.admin_services_storage_account_settings.authorized_ip_ranges, { host_ip = data.http.host_ip.response_body }) + delete_protection = local.admin_services_storage_account_settings.delete_protection subnet_ids = merge({ aks = local.subnet_ids.aks }) } + internal_storage_enabled = local.internal_storage_enabled + + storage_data_gb = var.storage_data_gb + data_storage_config = { - internal = local.external_storage_config == null ? { + internal = (local.internal_storage_enabled == true) ? { blob_nfs = { - data_plane_count = var.data_storage_config.internal.blob_nfs.data_plane_count + data_plane_count = local.data_storage_config.internal.blob_nfs.data_plane_count storage_account_settings = { - replication_type = var.data_storage_config.internal.blob_nfs.storage_account_settings.replication_type - authorized_ip_ranges = merge(var.admin_services_storage_account_settings.authorized_ip_ranges, { host_ip = data.http.host_ip.response_body }) - delete_protection = var.data_storage_config.internal.blob_nfs.storage_account_settings.delete_protection + replication_type = local.data_storage_config.internal.blob_nfs.storage_account_settings.replication_type + authorized_ip_ranges = merge(local.admin_services_storage_account_settings.authorized_ip_ranges, { host_ip = data.http.host_ip.response_body }) + delete_protection = local.data_storage_config.internal.blob_nfs.storage_account_settings.delete_protection subnet_ids = merge({ aks = local.subnet_ids.aks }) } } - } : null + } : null - # external = local.internal_data_storage_enabled ? null : { - # blob_nfs = local.get_storage_config != null ? local.get_storage_config.data_storage_planes : var.data_storage_config.external.blob_nfs - # hpcc = null - # } external = null } external_storage_config = local.external_storage_config + #----------------------------------------------------------------------- - spill_volumes = var.spill_volumes - roxie_config = var.roxie_config - thor_config = var.thor_config - vault_config = var.vault_config - eclccserver_settings = var.eclccserver_settings - spray_service_settings = var.spray_service_settings - admin_services_node_selector = { all = { workload = var.spray_service_settings.nodeSelector } } + spill_volumes = local.spill_volumes + enable_roxie = var.aks_enable_roxie + roxie_config = local.roxie_config + thor_config = local.thor_config + vault_config = local.vault_config + eclccserver_settings = local.eclccserver_settings + spray_service_settings = local.spray_service_settings + admin_services_node_selector = var.aks_4nodepools? { all = { workload = "servpool" } } : { all = { workload = "hpccpool" } } esp_remoteclients = { @@ -96,7 +96,10 @@ module "hpcc" { } - helm_chart_timeout = var.helm_chart_timeout - helm_chart_files_overrides = concat(var.helm_chart_files_overrides, fileexists("${path.module}/modules/logging/data/logaccess_body.yaml") ? ["${path.module}/modules/logging/data/logaccess_body.yaml"] : []) - ldap_config = var.ldap_config + helm_chart_timeout = local.helm_chart_timeout + helm_chart_files_overrides = local.helm_chart_files_overrides + ldap_config = local.ldap_config + + enable_code_security = var.enable_code_security + authn_htpasswd_filename = var.authn_htpasswd_filename } diff --git a/hpcc/locals.tf b/hpcc/locals.tf index b81b494..9f57295 100644 --- a/hpcc/locals.tf +++ b/hpcc/locals.tf @@ -4,45 +4,34 @@ locals { AZURE_SUBSCRIPTION_ID = data.azurerm_client_config.current.subscription_id } - names = var.disable_naming_conventions ? merge( + hpcc_namespace = "default" + + names = try(local.disable_naming_conventions, false) ? merge( { - business_unit = var.metadata.business_unit - environment = var.metadata.environment - location = var.metadata.location - market = var.metadata.market - subscription_type = var.metadata.subscription_type + business_unit = local.metadata.business_unit + environment = local.metadata.environment + location = local.metadata.location + market = local.metadata.market + subscription_type = local.metadata.subscription_type }, - var.metadata.product_group != "" ? { product_group = var.metadata.product_group } : {}, - var.metadata.product_name != "" ? { product_name = var.metadata.product_name } : {}, - var.metadata.resource_group_type != "" ? { resource_group_type = var.metadata.resource_group_type } : {} + local.metadata.product_group != "" ? { product_group = local.metadata.product_group } : {}, + local.metadata.product_name != "" ? { product_name = local.metadata.product_name } : {}, + local.metadata.resource_group_type != "" ? { resource_group_type = local.metadata.resource_group_type } : {} ) : module.metadata.names - tags = merge(var.metadata.additional_tags, { "owner" = var.owner.name, "owner_email" = var.owner.email }) - - # external_services_storage_exists = fileexists("${path.module}/modules/storage/data/config.json") || var.external_services_storage_config != null - get_vnet_config = fileexists("../vnet/data/config.json") ? jsondecode(file("../vnet/data/config.json")) : null get_aks_config = fileexists("../aks/data/config.json") ? jsondecode(file("../aks/data/config.json")) : null - get_storage_config = local.external_storage_exists ? jsondecode(file("../storage/data/config.json")) : null - - external_storage_exists = fileexists("../storage/data/config.json") || var.external_storage_config != null - - subnet_ids = try({ - for k, v in var.use_existing_vnet.subnets : k => "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${var.use_existing_vnet.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${var.use_existing_vnet.name}/subnets/${v.name}" - }, { aks = local.get_vnet_config.private_subnet_id }) - location = var.use_existing_vnet != null ? var.use_existing_vnet.location : local.get_vnet_config.location + #--------------------------------------------------------------------------------------------------------------------------- + # Setup storage (either external storage of internal (ephemeral) storage + #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + get_storage_config = fileexists("../storage/data/config.json") ? jsondecode(file("../storage/data/config.json")) : null - # hpcc_chart_major_minor_point_version = var.helm_chart_version != null ? regex("[\\d+?.\\d+?.\\d+?]+", var.helm_chart_version) : "master" + external_storage_exists = local.external_storage_config != null - domain = coalesce(var.internal_domain, format("us-%s.%s.azure.lnrsg.io", "var.metadata.product_name", "dev")) + internal_storage_enabled = var.external_storage_desired == true ? false : true - internal_storage_enabled = local.external_storage_exists == true && var.ignore_external_storage == true ? true : local.external_storage_exists == true && var.ignore_external_storage == false ? false : true - # external_services_storage_enabled = local.external_services_storage_exists == true && var.ignore_external_services_storage == false ? true : local.external_services_storage_exists == true && var.ignore_external_services_storage == true ? false : true - - hpcc_namespace = var.hpcc_namespace.existing_namespace != null ? var.hpcc_namespace.existing_namespace : var.hpcc_namespace.create_namespace == true ? kubernetes_namespace.hpcc[0].metadata[0].name : fileexists("${path.module}/logging/data/hpcc_namespace.txt") ? file("${path.module}/logging/data/hpcc_namespace.txt") : "default" - - external_storage_config = local.get_storage_config != null && var.ignore_external_storage == false ? [ + external_storage_config = local.get_storage_config != null && var.external_storage_desired == true ? [ for plane in local.get_storage_config.external_storage_config : { category = plane.category @@ -56,8 +45,17 @@ locals { storage_type = plane.storage_type prefix_name = plane.prefix_name } - ] : [] + ] : [] + #--------------------------------------------------------------------------------------------------------------------------- + + subnet_ids = try({ + for k, v in local.use_existing_vnet.subnets : k => "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${local.use_existing_vnet.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${local.use_existing_vnet.name}/subnets/${v.name}" + }, { aks = local.get_vnet_config.private_subnet_id }) + + location = local.use_existing_vnet != null ? local.use_existing_vnet.location : local.get_vnet_config.location + + domain = coalesce(local.internal_domain, format("us-%s.%s.azure.lnrsg.io", "local.metadata.product_name", "dev")) - svc_domains = { eclwatch = var.auto_launch_svc.eclwatch ? "https://eclwatch-${local.hpcc_namespace}.${local.domain}:18010" : null } + svc_domains = { eclwatch = local.auto_launch_svc.eclwatch ? "https://eclwatch-${local.hpcc_namespace}.${local.domain}:18010" : null } is_windows_os = substr(pathexpand("~"), 0, 1) == "/" ? false : true } diff --git a/hpcc/main.tf b/hpcc/main.tf index b9846df..debdf88 100644 --- a/hpcc/main.tf +++ b/hpcc/main.tf @@ -17,24 +17,24 @@ module "metadata" { naming_rules = module.naming.yaml - market = var.metadata.market + market = local.metadata.market location = local.location - sre_team = var.metadata.sre_team - environment = var.metadata.environment - product_name = var.metadata.product_name - business_unit = var.metadata.business_unit - product_group = var.metadata.product_group - subscription_type = var.metadata.subscription_type - resource_group_type = var.metadata.resource_group_type + sre_team = local.metadata.sre_team + environment = local.metadata.environment + product_name = local.metadata.product_name + business_unit = local.metadata.business_unit + product_group = local.metadata.product_group + subscription_type = local.metadata.subscription_type + resource_group_type = local.metadata.resource_group_type subscription_id = module.subscription.output.subscription_id - project = var.metadata.project + project = local.metadata.project } -resource "null_resource" "launch_svc_url" { - for_each = module.hpcc.hpcc_status == "deployed" ? local.svc_domains : {} +/*resource "null_resource" "delete_ephemeral_storage_accounts" { + count = var.external_storage_desired && (local.external_storage_config != []) ? 1 : 0 provisioner "local-exec" { - command = local.is_windows_os ? "Start-Process ${each.value}" : "open ${each.value} || xdg-open ${each.value}" - interpreter = local.is_windows_os ? ["PowerShell", "-Command"] : ["/bin/bash", "-c"] + command = "scripts/delete_ephemeral_storage_accounts ${local.get_aks_config.resource_group_name}" } -} + depends_on = [module.hpcc] +}*/ diff --git a/hpcc/misc.auto.tfvars.example b/hpcc/misc.auto.tfvars.example deleted file mode 100644 index c313216..0000000 --- a/hpcc/misc.auto.tfvars.example +++ /dev/null @@ -1,205 +0,0 @@ -owner = { - name = "demo" - email = "demo@lexisnexisrisk.com" -} - -metadata = { - project = "hpccplatform" - product_name = "hpccplatform" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "hpcc" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - additional_tags = { "justification" = "testing", "enclosed resource" = "hpcc" } - location = "eastus" # Acceptable values: eastus, centralus -} - -# # disable_naming_conventions - Disable naming conventions -# # disable_naming_conventions = true - -# # auto_launch_svc - Automatically launch ECLWatch web interface. -auto_launch_svc = { - eclwatch = true -} - -# azure_auth = { -# # AAD_CLIENT_ID = "" -# # AAD_CLIENT_SECRET = "" -# # AAD_TENANT_ID = "" -# # AAD_PRINCIPAL_ID = "" -# SUBSCRIPTION_ID = "" -# } - -# hpcc_container = { -# version = "9.2.0" -# image_name = "platform-core-ln" -# image_root = "jfrog.com/glb-docker-virtual" -# # custom_chart_version = "9.2.0-rc1" -# # custom_image_version = "9.2.0-demo" -# } - -# hpcc_container_registry_auth = { -# username = "value" -# password = "value" -# } - -internal_domain = "" // Example: hpccplatform-dev.azure.com - -# external = { -# blob_nfs = [{ -# container_id = "" -# container_name = "" -# id = "" -# resource_group_name = "" -# storage_account_id = "" -# storage_account_name = "" -# }] -# hpcc = [{ -# name = "" -# planes = list(object({ -# local = "" -# remote = "" -# })) -# service = "" -# }] -# } - -admin_services_storage_account_settings = { - replication_type = "ZRS" #LRS only if using HPC Cache - # authorized_ip_ranges = { - # "default" = "0.0.0.0/0" //must be public IP - # } - - delete_protection = false -} - -azure_log_analytics_creds = { - scope = null - object_id = "" //AAD_PRINCIPAL_ID -} - -hpcc_namespace = { - # existing_namespace = "" - labels = { - name = "hpcc" - } - create_namespace = true -} - -data_storage_config = { - internal = { - blob_nfs = { - data_plane_count = 2 - storage_account_settings = { - replication_type = "ZRS" - delete_protection = false - } - } - } - external = null -} - -# external_services_storage_config = [ -# { -# category = "dali" -# container_name = "hpcc-dali" -# path = "dalistorage" -# plane_name = "dali" -# size = 100 -# storage_type = "azurefiles" -# storage_account = "" -# resource_group_name = "" -# }, -# { -# category = "debug" -# container_name = "hpcc-debug" -# path = "debug" -# plane_name = "debug" -# size = 100 -# storage_type = "blobnfs" -# storage_account = "" -# resource_group_name = "" -# }, -# { -# category = "dll" -# container_name = "hpcc-dll" -# path = "queries" -# plane_name = "dll" -# size = 100 -# storage_type = "blobnfs" -# storage_account = "" -# resource_group_name = "" -# }, -# { -# category = "lz" -# container_name = "hpcc-mydropzone" -# path = "mydropzone" -# plane_name = "mydropzone" -# size = 100 -# storage_type = "blobnfs" -# storage_account = "" -# resource_group_name = "" -# }, -# { -# category = "sasha" -# container_name = "hpcc-sasha" -# path = "sashastorage" -# plane_name = "sasha" -# size = 100 -# storage_type = "blobnfs" -# storage_account = "" -# resource_group_name = "" -# } -# ] - -ignore_external_data_storage = false -ignore_external_services_storage = false - -spill_volumes = { - spill = { - name = "spill" - size = 300 - prefix = "/var/lib/HPCCSystems/spill" - host_path = "/mnt" - storage_class = "spill" - access_mode = "ReadWriteOnce" - } -} - -spray_service_settings = { - replicas = 6 - nodeSelector = "spraypool" #"spraypool" -} - -# ldap = { -# ldap_server = "" //Server IP -# dali = { -# hpcc_admin_password = "" -# hpcc_admin_username = "" -# ldap_admin_password = "" -# ldap_admin_username = "" -# adminGroupName = "HPCC-Admins" -# filesBasedn = "ou=files,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# groupsBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# resourcesBasedn = "ou=smc,ou=espservices,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# systemBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# usersBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# workunitsBasedn = "ou=workunits,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# } -# esp = { -# hpcc_admin_password = "" -# hpcc_admin_username = "" -# ldap_admin_password = "" -# ldap_admin_username = "" -# adminGroupName = "HPCC-Admins" -# filesBasedn = "ou=files,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# groupsBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# resourcesBasedn = "ou=smc,ou=espservices,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# systemBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# usersBasedn = "OU=AADDC Users,dc=z0lpf,dc=onmicrosoft,dc=com" -# workunitsBasedn = "ou=workunits,ou=eclHPCCSysUser,dc=z0lpf,dc=onmicrosoft,dc=com" -# } -# } diff --git a/hpcc/outputs.tf b/hpcc/outputs.tf index 6e18fea..81f1964 100644 --- a/hpcc/outputs.tf +++ b/hpcc/outputs.tf @@ -1,9 +1,21 @@ -output "hpcc_namespace" { - description = "The namespace where the HPCC Platform is deployed." - value = local.hpcc_namespace +output "eclwatch_url" { + description = "Print the ECL Watch URL." + value = format("https://%s.%s",var.a_record_name, var.aks_dns_zone_name) } -output "eclwatch" { - description = "Print the ECL Watch domain out." - value = local.svc_domains.eclwatch +output "deployment_resource_group" { + description = "Print the name of the deployment resource group." + value = local.get_aks_config.resource_group_name +} + +output "external_storage_config_exists" { + description = "Print whether external storage exists, i.e. true of false." + value = fileexists("../storage/data/config.json") ? true : false +} + +resource "local_file" "config" { + content = "hpcc successfully deployed" + filename = "${path.module}/data/config.json" + + depends_on = [ module.hpcc ] } diff --git a/hpcc/roxie.auto.tfvars.example b/hpcc/roxie.auto.tfvars.example deleted file mode 100644 index cfc1bf4..0000000 --- a/hpcc/roxie.auto.tfvars.example +++ /dev/null @@ -1,11 +0,0 @@ -# Roxie Settings -################# - -roxie_config = [{ - disabled = false - traceLevel = 3 - - services = [{ - annotations = { "service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path" = "/control/alive" } - }] -}] diff --git a/hpcc/sasha.auto.tfvars.example b/hpcc/sasha.auto.tfvars.example deleted file mode 100644 index e69de29..0000000 diff --git a/hpcc/scripts/delete_ephemeral_storage_accounts b/hpcc/scripts/delete_ephemeral_storage_accounts new file mode 100755 index 0000000..3d58cbc --- /dev/null +++ b/hpcc/scripts/delete_ephemeral_storage_accounts @@ -0,0 +1,16 @@ +#!/bin/bash +if [ "$1" != "" ];then + rg=$1 +else + echo "$0 has no arguments. It must of 1 argument that is the name of a resource group. EXITING.";exit 1; +fi +echo "In $0. Inputted resource groups is \"$rg\""; +sleep 20; +estos=$(az resource list --resource-group $rg|egrep "id\":.*storageAccounts\/hpcc"|sed "s/^ *\"id\": \"//"|sed "s/\", *$//") +if [ "$estos" == "" ];then + echo "In $0 There are no hpcc storage accounts in the resource group, $rg. EXITING.";exit; +fi +for s in $estos;do + echo "Deleting storage account: $s" + az storage account delete --ids $s -y +done diff --git a/hpcc/thor.auto.tfvars.example b/hpcc/thor.auto.tfvars.example deleted file mode 100644 index 34ff029..0000000 --- a/hpcc/thor.auto.tfvars.example +++ /dev/null @@ -1,34 +0,0 @@ -# Thor Settings -################ - -thor_config = [{ - disabled = false - name = "thor" - prefix = "thor" - numWorkers = 5 - keepJobs = "none" - maxJobs = 4 - maxGraphs = 2 - maxGraphStartupTime = 172800 - numWorkersPerPod = 1 - # nodeSelector = {} - managerResources = { - cpu = 1 - memory = "2G" - } - workerResources = { - cpu = 3 - memory = "4G" - } - workerMemory = { - query = "3G" - thirdParty = "500M" - } - eclAgentResources = { - cpu = 1 - memory = "2G" - } - cost = { - perCpu = 1 - } -}] diff --git a/hpcc/variables.tf b/hpcc/variables.tf deleted file mode 100644 index 60de38c..0000000 --- a/hpcc/variables.tf +++ /dev/null @@ -1,1151 +0,0 @@ -variable "owner" { - description = "Information for the user who administers the deployment." - type = object({ - name = string - email = string - }) - - validation { - condition = try( - regex("hpccdemo", var.owner.name) != "hpccdemo", true - ) && try( - regex("hpccdemo", var.owner.email) != "hpccdemo", true - ) && try( - regex("@example.com", var.owner.email) != "@example.com", true - ) - error_message = "Your name and email are required in the owner block and must not contain hpccdemo or @example.com." - } -} - -# variable "azure_auth" { -# description = "Azure authentication" -# type = object({ -# AAD_CLIENT_ID = optional(string) -# AAD_CLIENT_SECRET = optional(string) -# AAD_TENANT_ID = optional(string) -# AAD_PRINCIPAL_ID = optional(string) -# SUBSCRIPTION_ID = string -# }) - -# nullable = false -# } - -variable "expose_services" { - description = "Expose ECLWatch and elastic4hpcclogs to the Internet. This is not secure. Please consider before using it." - type = bool - default = false -} - -variable "auto_launch_svc" { - description = "Auto launch HPCC services." - type = object({ - eclwatch = bool - }) - default = { - eclwatch = true - } -} - -variable "auto_connect" { - description = "Automatically connect to the Kubernetes cluster from the host machine by overwriting the current context." - type = bool - default = false -} - -variable "disable_naming_conventions" { - description = "Naming convention module." - type = bool - default = false -} - -variable "metadata" { - description = "Metadata module variables." - type = object({ - market = string - sre_team = string - environment = string - product_name = string - business_unit = string - product_group = string - subscription_type = string - resource_group_type = string - project = string - additional_tags = map(string) - location = string - }) - - default = { - business_unit = "" - environment = "" - market = "" - product_group = "" - product_name = "hpcc" - project = "" - resource_group_type = "" - sre_team = "" - subscription_type = "" - additional_tags = {} - location = "" - } -} - -variable "use_existing_vnet" { - description = "Information about the existing VNet to use. Overrides vnet variable." - type = object({ - name = string - resource_group_name = string - route_table_name = string - location = string - - subnets = object({ - aks = object({ - name = string - }) - }) - }) - - default = null -} - -## HPCC Helm Release -####################### -variable "hpcc_enabled" { - description = "Is HPCC Platform deployment enabled?" - type = bool - default = true -} - -variable "hpcc_namespace" { - description = "Kubernetes namespace where resources will be created." - type = object({ - existing_namespace = optional(string) - labels = optional(map(string), { name = "hpcc" }) - create_namespace = optional(bool, true) - }) - default = {} -} - -variable "helm_chart_strings_overrides" { - description = "Helm chart values as strings, in yaml format, to be merged last." - type = list(string) - default = [] -} - -variable "helm_chart_files_overrides" { - description = "Helm chart values files, in yaml format, to be merged." - type = list(string) - default = [] -} - -variable "helm_chart_timeout" { - description = "Helm timeout for hpcc chart." - type = number - default = 300 -} - -variable "hpcc_container" { - description = "HPCC container information (if version is set to null helm chart version is used)." - type = object({ - image_name = optional(string) - image_root = optional(string) - version = optional(string) - custom_chart_version = optional(string) - custom_image_version = optional(string) - }) - - default = null -} - -variable "hpcc_container_registry_auth" { - description = "Registry authentication for HPCC container." - type = object({ - password = string - username = string - }) - default = null - sensitive = true -} - -variable "vault_config" { - description = "Input for vault secrets." - type = object({ - git = map(object({ - name = optional(string) - url = optional(string) - kind = optional(string) - vault_namespace = optional(string) - role_id = optional(string) - secret_name = optional(string) # Should match the secret name created in the corresponding vault_secrets variable - })), - ecl = map(object({ - name = optional(string) - url = optional(string) - kind = optional(string) - vault_namespace = optional(string) - role_id = optional(string) - secret_name = optional(string) # Should match the secret name created in the corresponding vault_secrets variable - })), - ecluser = map(object({ - name = optional(string) - url = optional(string) - kind = optional(string) - vault_namespace = optional(string) - role_id = optional(string) - secret_name = optional(string) # Should match the secret name created in the corresponding vault_secrets variable - })) - esp = map(object({ - name = optional(string) - url = optional(string) - kind = optional(string) - vault_namespace = optional(string) - role_id = optional(string) - secret_name = optional(string) # Should match the secret name created in the corresponding vault_secrets variable - })) - }) - default = null -} - -## Roxie Config -################## -variable "roxie_config" { - description = "Configuration for Roxie(s)." - type = list(object({ - disabled = bool - name = string - nodeSelector = map(string) - numChannels = number - prefix = string - replicas = number - serverReplicas = number - acePoolSize = number - actResetLogPeriod = number - affinity = number - allFilesDynamic = bool - blindLogging = bool - blobCacheMem = number - callbackRetries = number - callbackTimeout = number - checkCompleted = bool - checkPrimaries = bool - checkFileDate = bool - clusterWidth = number - copyResources = bool - coresPerQuery = number - crcResources = bool - dafilesrvLookupTimeout = number - debugPermitted = bool - defaultConcatPreload = number - defaultFetchPreload = number - defaultFullKeyedJoinPreload = number - defaultHighPriorityTimeLimit = number - defaultHighPriorityTimeWarning = number - defaultKeyedJoinPreload = number - defaultLowPriorityTimeLimit = number - defaultLowPriorityTimeWarning = number - defaultMemoryLimit = number - defaultParallelJoinPreload = number - defaultPrefetchProjectPreload = number - defaultSLAPriorityTimeLimit = number - defaultSLAPriorityTimeWarning = number - defaultStripLeadingWhitespace = bool - diskReadBufferSize = number - doIbytiDelay = bool - egress = string - enableHeartBeat = bool - enableKeyDiff = bool - enableSysLog = bool - fastLaneQueue = bool - fieldTranslationEnabled = string - flushJHtreeCacheOnOOM = bool - forceStdLog = bool - highTimeout = number - ignoreMissingFiles = bool - indexReadChunkSize = number - initIbytiDelay = number - jumboFrames = bool - lazyOpen = bool - leafCacheMem = number - linuxYield = bool - localFilesExpire = number - localSlave = bool - logFullQueries = bool - logQueueDrop = number - logQueueLen = number - lowTimeout = number - maxBlockSize = number - maxHttpConnectionRequests = number - maxLocalFilesOpen = number - maxLockAttempts = number - maxRemoteFilesOpen = number - memTraceLevel = number - memTraceSizeLimit = number - memoryStatsInterval = number - minFreeDiskSpace = number - minIbytiDelay = number - minLocalFilesOpen = number - minRemoteFilesOpen = number - miscDebugTraceLevel = number - monitorDaliFileServer = bool - nodeCacheMem = number - nodeCachePreload = bool - parallelAggregate = number - parallelLoadQueries = number - perChannelFlowLimit = number - pingInterval = number - preabortIndexReadsThreshold = number - preabortKeyedJoinsThreshold = number - preloadOnceData = bool - prestartSlaveThreads = bool - remoteFilesExpire = number - roxieMulticastEnabled = bool - serverSideCacheSize = number - serverThreads = number - simpleLocalKeyedJoins = bool - sinkMode = string - slaTimeout = number - slaveConfig = string - slaveThreads = number - soapTraceLevel = number - socketCheckInterval = number - statsExpiryTime = number - systemMonitorInterval = number - traceLevel = number - traceRemoteFiles = bool - totalMemoryLimit = string - trapTooManyActiveQueries = bool - udpAdjustThreadPriorities = bool - udpFlowAckTimeout = number - udpFlowSocketsSize = number - udpInlineCollation = bool - udpInlineCollationPacketLimit = number - udpLocalWriteSocketSize = number - udpMaxPermitDeadTimeouts = number - udpMaxRetryTimedoutReqs = number - udpMaxSlotsPerClient = number - udpMulticastBufferSize = number - udpOutQsPriority = number - udpQueueSize = number - udpRecvFlowTimeout = number - udpRequestToSendAckTimeout = number - udpResendTimeout = number - udpRequestToSendTimeout = number - udpResendEnabled = bool - udpRetryBusySenders = number - udpSendCompletedInData = bool - udpSendQueueSize = number - udpSnifferEnabled = bool - udpTraceLevel = number - useAeron = bool - useDynamicServers = bool - useHardLink = bool - useLogQueue = bool - useRemoteResources = bool - useMemoryMappedIndexes = bool - useTreeCopy = bool - services = list(object({ - name = string - servicePort = number - listenQueue = number - numThreads = number - visibility = string - annotations = optional(map(string)) - })) - topoServer = object({ - replicas = number - }) - channelResources = object({ - cpu = string - memory = string - }) - })) - - default = [ - { - disabled = false - name = "roxie" - nodeSelector = {} - numChannels = 2 - prefix = "roxie" - replicas = 2 - serverReplicas = 0 - acePoolSize = 6 - actResetLogPeriod = 0 - affinity = 0 - allFilesDynamic = false - blindLogging = false - blobCacheMem = 0 - callbackRetries = 3 - callbackTimeout = 500 - checkCompleted = true - checkFileDate = false - checkPrimaries = true - clusterWidth = 1 - copyResources = true - coresPerQuery = 0 - crcResources = false - dafilesrvLookupTimeout = 10000 - debugPermitted = true - defaultConcatPreload = 0 - defaultFetchPreload = 0 - defaultFullKeyedJoinPreload = 0 - defaultHighPriorityTimeLimit = 0 - defaultHighPriorityTimeWarning = 30000 - defaultKeyedJoinPreload = 0 - defaultLowPriorityTimeLimit = 0 - defaultLowPriorityTimeWarning = 90000 - defaultMemoryLimit = 1073741824 - defaultParallelJoinPreload = 0 - defaultPrefetchProjectPreload = 10 - defaultSLAPriorityTimeLimit = 0 - defaultSLAPriorityTimeWarning = 30000 - defaultStripLeadingWhitespace = false - diskReadBufferSize = 65536 - doIbytiDelay = true - egress = "engineEgress" - enableHeartBeat = false - enableKeyDiff = false - enableSysLog = false - fastLaneQueue = true - fieldTranslationEnabled = "payload" - flushJHtreeCacheOnOOM = true - forceStdLog = false - highTimeout = 2000 - ignoreMissingFiles = false - indexReadChunkSize = 60000 - initIbytiDelay = 10 - jumboFrames = false - lazyOpen = true - leafCacheMem = 500 - linuxYield = false - localFilesExpire = 1 - localSlave = false - logFullQueries = false - logQueueDrop = 32 - logQueueLen = 512 - lowTimeout = 10000 - maxBlockSize = 1000000000 - maxHttpConnectionRequests = 1 - maxLocalFilesOpen = 4000 - maxLockAttempts = 5 - maxRemoteFilesOpen = 100 - memTraceLevel = 1 - memTraceSizeLimit = 0 - memoryStatsInterval = 60 - minFreeDiskSpace = 6442450944 - minIbytiDelay = 2 - minLocalFilesOpen = 2000 - minRemoteFilesOpen = 50 - miscDebugTraceLevel = 0 - monitorDaliFileServer = false - nodeCacheMem = 1000 - nodeCachePreload = false - parallelAggregate = 0 - parallelLoadQueries = 1 - perChannelFlowLimit = 50 - pingInterval = 0 - preabortIndexReadsThreshold = 100 - preabortKeyedJoinsThreshold = 100 - preloadOnceData = true - prestartSlaveThreads = false - remoteFilesExpire = 3600 - roxieMulticastEnabled = false - serverSideCacheSize = 0 - serverThreads = 100 - simpleLocalKeyedJoins = true - sinkMode = "sequential" - slaTimeout = 2000 - slaveConfig = "simple" - slaveThreads = 30 - soapTraceLevel = 1 - socketCheckInterval = 5000 - statsExpiryTime = 3600 - systemMonitorInterval = 60000 - totalMemoryLimit = "5368709120" - traceLevel = 1 - traceRemoteFiles = false - trapTooManyActiveQueries = true - udpAdjustThreadPriorities = true - udpFlowAckTimeout = 10 - udpFlowSocketsSize = 33554432 - udpInlineCollation = true - udpInlineCollationPacketLimit = 50 - udpLocalWriteSocketSize = 16777216 - udpMaxPermitDeadTimeouts = 100 - udpMaxRetryTimedoutReqs = 10 - udpMaxSlotsPerClient = 100 - udpMulticastBufferSize = 33554432 - udpOutQsPriority = 5 - udpQueueSize = 1000 - udpRecvFlowTimeout = 2000 - udpRequestToSendAckTimeout = 500 - udpResendTimeout = 100 - udpRequestToSendTimeout = 2000 - udpResendEnabled = true - udpRetryBusySenders = 0 - udpSendCompletedInData = false - udpSendQueueSize = 500 - udpSnifferEnabled = false - udpTraceLevel = 0 - useAeron = false - useDynamicServers = false - useHardLink = false - useLogQueue = true - useMemoryMappedIndexes = false - useRemoteResources = false - useTreeCopy = false - services = [ - { - name = "roxie" - servicePort = 9876 - listenQueue = 200 - numThreads = 30 - visibility = "local" - annotations = {} - } - ] - topoServer = { - replicas = 1 - } - channelResources = { - cpu = "1" - memory = "4G" - } - } - ] -} - -## Thor Config -################## -variable "thor_config" { - description = "Configurations for Thor." - type = list(object( - { - disabled = bool - eclAgentResources = optional(object({ - cpu = string - memory = string - } - ), - { - cpu = 1 - memory = "2G" - }) - keepJobs = optional(string, "none") - managerResources = optional(object({ - cpu = string - memory = string - }), - { - cpu = 1 - memory = "2G" - }) - maxGraphs = optional(number, 2) - maxJobs = optional(number, 4) - maxGraphStartupTime = optional(number, 172800) - name = optional(string, "thor") - nodeSelector = optional(map(string), { workload = "thorpool" }) - numWorkers = optional(number, 2) - numWorkersPerPod = optional(number, 1) - prefix = optional(string, "thor") - egress = optional(string, "engineEgress") - tolerations_value = optional(string, "thorpool") - workerMemory = optional(object({ - query = string - thirdParty = string - }), - { - query = "3G" - thirdParty = "500M" - }) - workerResources = optional(object({ - cpu = string - memory = string - }), - { - cpu = 3 - memory = "4G" - }) - cost = object({ - perCpu = number - }) - })) - - default = null -} - -## ECL Agent Config -####################### -variable "eclagent_settings" { - description = "eclagent settings" - type = map(object({ - replicas = number - maxActive = number - prefix = string - use_child_process = bool - spillPlane = optional(string, "spill") - type = string - resources = object({ - cpu = string - memory = string - }) - cost = object({ - perCpu = number - }) - egress = optional(string) - })) - - default = { - hthor = { - replicas = 1 - maxActive = 4 - prefix = "hthor" - use_child_process = false - type = "hthor" - spillPlane = "spill" - resources = { - cpu = "1" - memory = "4G" - } - egress = "engineEgress" - cost = { - perCpu = 1 - } - }, - } -} - -## ECLCCServer Config -######################## -variable "eclccserver_settings" { - description = "Set cpu and memory values of the eclccserver. Toggle use_child_process to true to enable eclccserver child processes." - type = map(object({ - useChildProcesses = optional(bool, false) - replicas = optional(number, 1) - maxActive = optional(number, 4) - egress = optional(string, "engineEgress") - gitUsername = optional(string, "") - defaultRepo = optional(string, "") - defaultRepoVersion = optional(string, "") - resources = optional(object({ - cpu = string - memory = string - })) - cost = object({ - perCpu = number - }) - listen_queue = optional(list(string), []) - childProcessTimeLimit = optional(number, 10) - gitUsername = optional(string, "") - legacySyntax = optional(bool, false) - options = optional(list(object({ - name = string - value = string - }))) - })) - - default = { - "myeclccserver" = { - useChildProcesses = false - maxActive = 4 - egress = "engineEgress" - replicas = 1 - childProcessTimeLimit = 10 - resources = { - cpu = "1" - memory = "4G" - } - legacySyntax = false - options = [] - cost = { - perCpu = 1 - } - } } -} - -## Dali Config -################## -variable "dali_settings" { - description = "dali settings" - type = object({ - coalescer = object({ - interval = number - at = string - minDeltaSize = number - resources = object({ - cpu = string - memory = string - }) - }) - resources = object({ - cpu = string - memory = string - }) - maxStartupTime = number - }) - - default = { - coalescer = { - interval = 24 - at = "* * * * *" - minDeltaSize = 50000 - resources = { - cpu = "1" - memory = "4G" - } - } - resources = { - cpu = "2" - memory = "8G" - } - maxStartupTime = 1200 - } -} - -## DFU Server Config -######################## -variable "dfuserver_settings" { - description = "DFUServer settings" - type = object({ - maxJobs = number - resources = object({ - cpu = string - memory = string - }) - }) - - default = { - maxJobs = 3 - resources = { - cpu = "1" - memory = "2G" - } - } -} - -## Spray Service Config -######################### -variable "spray_service_settings" { - description = "spray services settings" - type = object({ - replicas = number - nodeSelector = string - }) - - default = { - replicas = 3 - nodeSelector = "servpool" #"spraypool" - } -} - -## Sasha Config -################## -variable "sasha_config" { - description = "Configuration for Sasha." - type = object({ - disabled = bool - wu-archiver = object({ - disabled = bool - service = object({ - servicePort = number - }) - plane = string - interval = number - limit = number - cutoff = number - backup = number - at = string - throttle = number - retryinterval = number - keepResultFiles = bool - # egress = string - }) - - dfuwu-archiver = object({ - disabled = bool - service = object({ - servicePort = number - }) - plane = string - interval = number - limit = number - cutoff = number - at = string - throttle = number - # egress = string - }) - - dfurecovery-archiver = object({ - disabled = bool - interval = number - limit = number - cutoff = number - at = string - # egress = string - }) - - file-expiry = object({ - disabled = bool - interval = number - at = string - persistExpiryDefault = number - expiryDefault = number - user = string - # egress = string - }) - }) - - default = { - disabled = false - wu-archiver = { - disabled = false - service = { - servicePort = 8877 - } - plane = "sasha" - interval = 6 - limit = 400 - cutoff = 3 - backup = 0 - at = "* * * * *" - throttle = 0 - retryinterval = 6 - keepResultFiles = false - # egress = "engineEgress" - } - - dfuwu-archiver = { - disabled = false - service = { - servicePort = 8877 - } - plane = "sasha" - interval = 24 - limit = 100 - cutoff = 14 - at = "* * * * *" - throttle = 0 - # egress = "engineEgress" - } - - dfurecovery-archiver = { - disabled = false - interval = 12 - limit = 20 - cutoff = 4 - at = "* * * * *" - # egress = "engineEgress" - } - - file-expiry = { - disabled = false - interval = 1 - at = "* * * * *" - persistExpiryDefault = 7 - expiryDefault = 4 - user = "sasha" - # egress = "engineEgress" - } - } -} - -## LDAP Config -################## -variable "ldap_config" { - description = "LDAP settings for dali and esp services." - type = object({ - dali = object({ - adminGroupName = string - filesBasedn = string - groupsBasedn = string - hpcc_admin_password = string - hpcc_admin_username = string - ldap_admin_password = string - ldap_admin_username = string - ldapAdminVaultId = string - resourcesBasedn = string - sudoersBasedn = string - systemBasedn = string - usersBasedn = string - workunitsBasedn = string - ldapCipherSuite = string - }) - esp = object({ - adminGroupName = string - filesBasedn = string - groupsBasedn = string - ldap_admin_password = string - ldap_admin_username = string - ldapAdminVaultId = string - resourcesBasedn = string - sudoersBasedn = string - systemBasedn = string - usersBasedn = string - workunitsBasedn = string - ldapCipherSuite = string - }) - ldap_server = string - }) - - default = null - sensitive = true -} - -variable "ldap_tunables" { - description = "Tunable settings for LDAP." - type = object({ - cacheTimeout = number - checkScopeScans = bool - ldapTimeoutSecs = number - maxConnections = number - passwordExpirationWarningDays = number - sharedCache = bool - }) - - default = { - cacheTimeout = 5 - checkScopeScans = false - ldapTimeoutSecs = 131 - maxConnections = 10 - passwordExpirationWarningDays = 10 - sharedCache = true - } -} - -## Data Storage Config -######################### -variable "install_blob_csi_driver" { - description = "Install blob-csi-drivers on the cluster." - type = bool - default = true -} - -variable "spill_volumes" { - description = "Map of objects to create Spill Volumes" - type = map(object({ - name = string # "Name of spill volume to be created." - size = number # "Size of spill volume to be created (in GB)." - prefix = string # "Prefix of spill volume to be created." - host_path = string # "Host path on spill volume to be created." - storage_class = string # "Storage class of spill volume to be used." - access_mode = string # "Access mode of spill volume to be used." - })) - - default = { - "spill" = { - name = "spill" - size = 300 - prefix = "/var/lib/HPCCSystems/spill" - host_path = "/mnt" - storage_class = "spill" - access_mode = "ReadWriteOnce" - } - } -} - -variable "data_storage_config" { - description = "Data plane config for HPCC." - type = object({ - internal = optional(object({ - blob_nfs = object({ - data_plane_count = number - storage_account_settings = object({ - # authorized_ip_ranges = map(string) - delete_protection = bool - replication_type = string - # subnet_ids = map(string) - blob_soft_delete_retention_days = optional(number) - container_soft_delete_retention_days = optional(number) - }) - }) - })) - - external = optional(object({ - blob_nfs = list(object({ - container_id = string - container_name = string - id = string - resource_group_name = string - storage_account_id = string - storage_account_name = string - })) - hpcc = list(object({ - name = string - planes = list(object({ - local = string - remote = string - })) - service = string - })) - })) - }) - - default = null - # default = { - # internal = { - # blob_nfs = { - # data_plane_count = 1 - # storage_account_settings = { - # # authorized_ip_ranges = {} - # delete_protection = false - # replication_type = "ZRS" - # # subnet_ids = {} - # blob_soft_delete_retention_days = 7 - # container_soft_delete_retention_days = 7 - # } - # } - # } - # external = null - # } -} - -variable "external_storage_config" { - description = "External services storage config." - type = list(object({ - category = string - container_name = string - path = string - plane_name = string - protocol = string - resource_group = string - size = number - storage_account = string - storage_type = string - prefix_name = string - })) - - default = null -} - -variable "remote_storage_plane" { - description = "Input for attaching remote storage plane" - type = map(object({ - dfs_service_name = string - dfs_secret_name = string - target_storage_accounts = map(object({ - name = string - prefix = string - })) - })) - - default = null -} - -variable "onprem_lz_settings" { - description = "Input for allowing OnPrem LZ." - type = map(object({ - prefix = string - hosts = list(string) - })) - - default = {} -} - -variable "admin_services_storage" { - description = "PV sizes for admin service planes in gigabytes (storage billed only as consumed)." - type = object({ - dali = object({ - size = number - type = string - }) - debug = object({ - size = number - type = string - }) - dll = object({ - size = number - type = string - }) - lz = object({ - size = number - type = string - }) - sasha = object({ - size = number - type = string - }) - }) - - default = { - dali = { - size = 100 - type = "azurefiles" - } - debug = { - size = 100 - type = "blobnfs" - } - dll = { - size = 100 - type = "blobnfs" - } - lz = { - size = 100 - type = "blobnfs" - } - sasha = { - size = 100 - type = "blobnfs" - } - } - - validation { - condition = length([for k, v in var.admin_services_storage : v.type if !contains(["azurefiles", "blobnfs"], v.type)]) == 0 - error_message = "The type must be either \"azurefiles\" or \"blobnfs\"." - } - - validation { - condition = length([for k, v in var.admin_services_storage : v.size if v.type == "azurefiles" && v.size < 100]) == 0 - error_message = "Size must be at least 100 for \"azurefiles\" type." - } -} - -variable "admin_services_storage_account_settings" { - description = "Settings for admin services storage account." - type = object({ - authorized_ip_ranges = optional(map(string)) - delete_protection = bool - replication_type = string - # subnet_ids = map(string) - blob_soft_delete_retention_days = optional(number) - container_soft_delete_retention_days = optional(number) - file_share_retention_days = optional(number) - }) - - default = { - authorized_ip_ranges = {} - delete_protection = false - replication_type = "ZRS" - subnet_ids = {} - blob_soft_delete_retention_days = 7 - container_soft_delete_retention_days = 7 - file_share_retention_days = 7 - } -} - -variable "ignore_external_storage" { - description = "Should storage created using the storage module or var.external_storage_config be ignored?" - type = bool - default = false -} - -## Node Selector -#################### -variable "admin_services_node_selector" { - description = "Node selector for admin services pods." - type = map(map(string)) - default = {} - - validation { - condition = length([for service in keys(var.admin_services_node_selector) : - service if !contains(["all", "dali", "esp", "eclagent", "eclccserver"], service)]) == 0 - error_message = "The keys must be one of \"all\", \"dali\", \"esp\", \"eclagent\" or \"eclccserver\"." - } -} - -## DNS -######### -variable "internal_domain" { - description = "DNS Domain name" - type = string - default = null -} diff --git a/lite-locals.tf b/lite-locals.tf new file mode 100644 index 0000000..7d4e71d --- /dev/null +++ b/lite-locals.tf @@ -0,0 +1,472 @@ +locals { + thor_worker_cpus = 2 + + aks_node_sizes = { + roxie = var.aks_roxie_node_size + serv = var.aks_serv_node_size + spray = var.aks_spray_node_size + thor = var.aks_thor_node_size + } + + ns_spec = { + "large" = { + cpu = 2 + ram = 8 + } + "xlarge" = { + cpu = 4 + ram = 16 + } + "2xlarge" = { + cpu = 8 + ram = 32 + } + "4xlarge" = { + cpu = 16 + ram = 64 + } + } + + twpn = floor("${ local.ns_spec[local.aks_node_sizes.thor].cpu / local.thor_worker_cpus }") + thorWorkersPerNode = local.twpn > 0? local.twpn : 1 + + twr = floor("${local.ns_spec[local.aks_node_sizes.thor].ram / local.thorWorkersPerNode }") + thor_worker_ram = local.twr > 0? local.twr : 1 + + nodesPer1Job = ceil("${var.thor_num_workers / local.thorWorkersPerNode }") + + helm_chart_timeout=600 + + owner = { + name = var.admin_username + email = var.aks_admin_email + } + + owner_name_initials = lower(join("",[for x in split(" ",local.owner.name): substr(x,0,1)])) + + disable_naming_conventions = false + + auto_launch_svc = { + eclwatch = false + } + + internal_domain = var.aks_dns_zone_name // Example: hpcczone.us-hpccsystems-dev.azure.lnrsg.io + + + admin_services_storage_account_settings = { + replication_type = "ZRS" #LRS only if using HPC Cache + authorized_ip_ranges = { + "default" = "0.0.0.0/0" //must be public IP + } + + delete_protection = false + } + + azure_log_analytics_creds = { + scope = null + object_id = "" //AAD_PRINCIPAL_ID + } + + data_storage_config = { + internal = { + blob_nfs = { + data_plane_count = 2 + storage_account_settings = { + replication_type = "ZRS" + delete_protection = false + } + } + } + external = null + } + + + spill_volumes = { + spill = { + name = "spill" + size = 300 + prefix = "/var/lib/HPCCSystems/spill" + host_path = "/mnt" + storage_class = "spill" + access_mode = "ReadWriteOnce" + } + } + + spray_service_settings = { + replicas = 1 + nodeSelector = var.aks_4nodepools? "spraypool" : "hpccpool" + } + + roxie_internal_service = { + name = "iroxie" + servicePort = 9876 + listenQueue = 200 + numThreads = 30 + visibility = "local" + annotations = {} + } + + roxie_services = [local.roxie_internal_service] + + #======================================== + # defaults in godji original variables.tf + expose_services = false + + auto_connect = false + + use_existing_vnet = null + + hpcc_enabled = true + + helm_chart_strings_overrides = [] + + helm_chart_files_overrides = [] + + vault_config = null + + hpcc_container = null + + hpcc_container_registry_auth = null + + roxie_config = [ + { + disabled = (var.aks_enable_roxie == true)? false : true + name = "roxie" + nodeSelector = var.aks_4nodepools? { workload = "roxiepool" } : { workload = "hpccpool" } + numChannels = 1 + prefix = "roxie" + replicas = 2 + serverReplicas = 0 + acePoolSize = 6 + actResetLogPeriod = 0 + affinity = 0 + allFilesDynamic = false + blindLogging = false + blobCacheMem = 0 + callbackRetries = 3 + callbackTimeout = 500 + checkCompleted = true + checkFileDate = false + checkPrimaries = true + clusterWidth = 1 + copyResources = true + coresPerQuery = 0 + crcResources = false + dafilesrvLookupTimeout = 10000 + debugPermitted = true + defaultConcatPreload = 0 + defaultFetchPreload = 0 + defaultFullKeyedJoinPreload = 0 + defaultHighPriorityTimeLimit = 0 + defaultHighPriorityTimeWarning = 30000 + defaultKeyedJoinPreload = 0 + defaultLowPriorityTimeLimit = 0 + defaultLowPriorityTimeWarning = 90000 + defaultMemoryLimit = 1073741824 + defaultParallelJoinPreload = 0 + defaultPrefetchProjectPreload = 10 + defaultSLAPriorityTimeLimit = 0 + defaultSLAPriorityTimeWarning = 30000 + defaultStripLeadingWhitespace = false + diskReadBufferSize = 65536 + doIbytiDelay = true + egress = "engineEgress" + enableHeartBeat = false + enableKeyDiff = false + enableSysLog = false + fastLaneQueue = true + fieldTranslationEnabled = "payload" + flushJHtreeCacheOnOOM = true + forceStdLog = false + highTimeout = 2000 + ignoreMissingFiles = false + indexReadChunkSize = 60000 + initIbytiDelay = 10 + jumboFrames = false + lazyOpen = true + leafCacheMem = 500 + linuxYield = false + localFilesExpire = 1 + localSlave = false + logFullQueries = false + logQueueDrop = 32 + logQueueLen = 512 + lowTimeout = 10000 + maxBlockSize = 1000000000 + maxHttpConnectionRequests = 1 + maxLocalFilesOpen = 4000 + maxLockAttempts = 5 + maxRemoteFilesOpen = 100 + memTraceLevel = 1 + memTraceSizeLimit = 0 + memoryStatsInterval = 60 + minFreeDiskSpace = 6442450944 + minIbytiDelay = 2 + minLocalFilesOpen = 2000 + minRemoteFilesOpen = 50 + miscDebugTraceLevel = 0 + monitorDaliFileServer = false + nodeCacheMem = 1000 + nodeCachePreload = false + parallelAggregate = 0 + parallelLoadQueries = 1 + perChannelFlowLimit = 50 + pingInterval = 0 + preabortIndexReadsThreshold = 100 + preabortKeyedJoinsThreshold = 100 + preloadOnceData = true + prestartSlaveThreads = false + remoteFilesExpire = 3600 + roxieMulticastEnabled = false + serverSideCacheSize = 0 + serverThreads = 100 + simpleLocalKeyedJoins = true + sinkMode = "sequential" + slaTimeout = 2000 + slaveConfig = "simple" + slaveThreads = 30 + soapTraceLevel = 1 + socketCheckInterval = 5000 + statsExpiryTime = 3600 + systemMonitorInterval = 60000 + totalMemoryLimit = "5368709120" + traceLevel = 1 + traceRemoteFiles = false + trapTooManyActiveQueries = true + udpAdjustThreadPriorities = true + udpFlowAckTimeout = 10 + udpFlowSocketsSize = 33554432 + udpInlineCollation = true + udpInlineCollationPacketLimit = 50 + udpLocalWriteSocketSize = 16777216 + udpMaxPermitDeadTimeouts = 100 + udpMaxRetryTimedoutReqs = 10 + udpMaxSlotsPerClient = 100 + udpMulticastBufferSize = 33554432 + udpOutQsPriority = 5 + udpQueueSize = 1000 + udpRecvFlowTimeout = 2000 + udpRequestToSendAckTimeout = 500 + udpResendTimeout = 100 + udpRequestToSendTimeout = 2000 + udpResendEnabled = true + udpRetryBusySenders = 0 + udpSendCompletedInData = false + udpSendQueueSize = 500 + udpSnifferEnabled = false + udpTraceLevel = 0 + useAeron = false + useDynamicServers = false + useHardLink = false + useLogQueue = true + useMemoryMappedIndexes = false + useRemoteResources = false + useTreeCopy = false + services = local.roxie_services + topoServer = { + replicas = 1 + } + channelResources = { + cpu = "1" + memory = "4G" + } + } + ] + + eclagent_settings = { + hthor = { + replicas = 1 + maxActive = 4 + prefix = "hthor" + use_child_process = false + type = "hthor" + spillPlane = "spill" + resources = { + cpu = "1" + memory = "4G" + } + nodeSelector = var.aks_4nodepools? { workload = "servpool" } : { workload = "hpccpool" } + egress = "engineEgress" + cost = { + perCpu = 1 + } + }, + } + + eclccserver_settings = { + "myeclccserver" = { + useChildProcesses = false + maxActive = 4 + egress = "engineEgress" + replicas = 1 + childProcessTimeLimit = 10 + resources = { + cpu = "1" + memory = "4G" + } + nodeSelector = var.aks_4nodepools? { workload = "servpool" } : { workload = "hpccpool" } + legacySyntax = false + options = [] + cost = { + perCpu = 1 + } + } } + + dali_settings = { + coalescer = { + interval = 24 + at = "* * * * *" + minDeltaSize = 50000 + nodeSelector = var.aks_4nodepools? { workload = "servpool" } : { workload = "hpccpool" } + resources = { + cpu = "1" + memory = "4G" + } + } + resources = { + cpu = "2" + memory = "8G" + } + maxStartupTime = 1200 + } + + dfuserver_settings = { + maxJobs = 3 + nodeSelector = var.aks_4nodepools? { workload = "servpool" } : { workload = "hpccpool" } + resources = { + cpu = "1" + memory = "2G" + } + } + + sasha_config = { + disabled = false + nodeSelector = var.aks_4nodepools? { workload = "servpool" } : { workload = "hpccpool" } + wu-archiver = { + disabled = false + service = { + servicePort = 8877 + } + plane = "sasha" + interval = 6 + limit = 400 + cutoff = 3 + backup = 0 + at = "* * * * *" + throttle = 0 + retryinterval = 6 + keepResultFiles = false + } + + dfuwu-archiver = { + disabled = false + service = { + servicePort = 8877 + } + plane = "sasha" + interval = 24 + limit = 100 + cutoff = 14 + at = "* * * * *" + throttle = 0 + } + + dfurecovery-archiver = { + disabled = false + interval = 12 + limit = 20 + cutoff = 4 + at = "* * * * *" + } + + file-expiry = { + disabled = false + interval = 1 + at = "* * * * *" + persistExpiryDefault = 7 + expiryDefault = 4 + user = "sasha" + } + } + + ldap_config = null + + ldap_tunables = { + cacheTimeout = 5 + checkScopeScans = false + ldapTimeoutSecs = 131 + maxConnections = 10 + passwordExpirationWarningDays = 10 + sharedCache = true + } + + install_blob_csi_driver = true + + remote_storage_plane = null + + onprem_lz_settings = {} + + admin_services_node_selector = {} + + workerMemory_thirdParty = "500" + wmq = "${(local.thor_worker_ram * 1000000000) - (local.workerMemory_thirdParty * 1000000)}" + workerMemory_query = floor("${local.wmq / 1000000000}") + + thor_config = [{ + disabled = (var.enable_thor == true) || (var.enable_thor == null)? false : true + name = "thor" + prefix = "thor" + numWorkers = var.thor_num_workers + keepJobs = "none" + maxJobs = var.thor_max_jobs + maxGraphs = 2 + maxGraphStartupTime = 172800 + numWorkersPerPod = 1 + nodeSelector = var.aks_4nodepools? { workload = "thorpool" } : { workload = "hpccpool" } + egress = "engineEgress" + tolerations_value = "thorpool" + managerResources = { + cpu = 1 + memory = "2G" + } + workerResources = { + cpu = local.thor_worker_cpus + memory = format("%dG", local.thor_worker_ram) + } + workerMemory = { + query = format("%dG", local.workerMemory_query) + thirdParty = format("%dM", local.workerMemory_thirdParty) + } + eclAgentResources = { + cpu = 1 + memory = "2G" + } + cost = { + perCpu = 1 + } + }] + + admin_services_storage = { + dali = { + size = 100 + type = "azurefiles" + } + debug = { + size = 100 + type = "blobnfs" + } + dll = { + size = 100 + type = "blobnfs" + } + lz = { + size = var.storage_lz_gb + type = "blobnfs" + } + sasha = { + size = 100 + type = "blobnfs" + } + } + #======================================== +} diff --git a/lite-variables.tf b/lite-variables.tf new file mode 100644 index 0000000..799bdd6 --- /dev/null +++ b/lite-variables.tf @@ -0,0 +1,220 @@ +# All 'aks_' variables are before any other variables. +variable "aks_4nodepools" { + description = "If true 4 nodepools are used. If false 1 are used." + type = bool + default = false +} + +variable "aks_logging_monitoring_enabled" { + description = "Used to get logging and monitoring of kubernetes and hpcc cluster." + type = bool + default = false +} + +variable "aks_admin_email" { + type = string + description = "REQUIRED. Email address of the administrator of this HPCC Systems cluster.\nExample entry: jane.doe@hpccsystems.com" + validation { + condition = length(regexall("^[^@]+@[^@]+$", var.aks_admin_email)) > 0 + error_message = "Value must at least look like a valid email address." + } +} + +variable "aks_admin_name" { + type = string + description = "REQUIRED. Name of the administrator of this HPCC Systems cluster.\nExample entry: Jane Doe" +} + +variable "aks_azure_region" { + type = string + description = "REQUIRED. The Azure region abbreviation in which to create these resources.\nExample entry: eastus2" +} + +variable "aks_enable_roxie" { + description = "If you want roxie then this variable must be set to true. Enable ROXIE?\nThis will also expose port 18002 on the cluster.\nExample entry: false" + type = bool + default = false +} + +variable "aks_dns_zone_resource_group_name" { + type = string + description = "REQUIRED. Name of the resource group containing the dns zone." +} + +variable "aks_dns_zone_name" { + type = string + description = "REQUIRED. dns zone name. The name of existing dns zone." +} + +variable "aks_admin_ip_cidr_map" { + description = "OPTIONAL. Map of name => CIDR IP addresses that can administrate this AKS.\nFormat is '{\"name\"=\"cidr\" [, \"name\"=\"cidr\"]*}'.\nThe 'name' portion must be unique.\nDefault value is '{}' means no CIDR addresses.\nThe corporate network and your current IP address will be added automatically, and these addresses will have access to the HPCC cluster as a user." + type = map(string) + default = {} +} + +variable "aks_nodepools_max_capacity" { + type = number + description = "The max capacity (or maximum node count) of all hopcc nodepools." + default = 385 +} + +variable "aks_roxie_node_size" { + type = string + description = "The size of the roxie nodes. Possibilities are 'large', 'xlarge', '2xlarge', and '4xlarge'." + validation { + condition = (length(regexall("^[24]*x*large", var.aks_roxie_node_size)) == 1) + + error_message = "All node sizes must be one of the following: large, xlarge, 2xlarge, or 4xlarge." + } + default = "xlarge" +} + +variable "aks_serv_node_size" { + type = string + description = "The size of the serv nodes. Possibilities are 'large', 'xlarge', '2xlarge', and '4xlarge'." + validation { + condition = (length(regexall("^[24]*x*large", var.aks_serv_node_size)) == 1) + + error_message = "All node sizes must be one of the following: large, xlarge, 2xlarge, or 4xlarge." + } + default = "2xlarge" +} + +variable "aks_spray_node_size" { + type = string + description = "The size of the spray nodes. Possibilities are 'large', 'xlarge', '2xlarge', and '4xlarge'." + validation { + condition = (length(regexall("^[24]*x*large", var.aks_spray_node_size)) == 1) + + error_message = "All node sizes must be one of the following: large, xlarge, 2xlarge, or 4xlarge." + } + default = "large" +} + +variable "aks_thor_node_size" { + type = string + description = "The size of the thor nodes. Possibilities are 'large', 'xlarge', '2xlarge', and '4xlarge'." + validation { + condition = (length(regexall("^[24]*x*large", var.aks_thor_node_size)) == 1) + + error_message = "All node sizes must be one of the following: large, xlarge, 2xlarge, or 4xlarge." + } + default = "xlarge" +} +#===== end of aks variables ===== + +variable "my_azure_id" { + description = "REQUIRED. The id of your azure account." + type = string +} + +variable "external_storage_desired" { + description = "If you want external storage instead of ephemeral, this should be true. For ephemeral storage this should be false" + type = bool + default = false +} + +variable "enable_thor" { + description = "REQUIRED. If you want a thor cluster." + type = bool + default = true +} + +variable "a_record_name" { + type = string + description = "OPTIONAL: dns zone A record name" + default = "" +} + +variable "admin_username" { + type = string + description = "REQUIRED. Username of the administrator of this HPCC Systems cluster.\nExample entry: jdoe" + validation { + condition = length(var.admin_username) > 1 && length(regexall(" ", var.admin_username)) == 0 + error_message = "Value must at least two characters in length and contain no spaces." + } +} + +variable "enable_code_security" { + description = "REQUIRED. Enable code security?\nIf true, only signed ECL code will be allowed to create embedded language functions, use PIPE(), etc.\nExample entry: false" + type = bool + default = false +} + +variable "extra_tags" { + description = "OPTIONAL. Map of name => value tags that can will be associated with the cluster.\nFormat is '{\"name\"=\"value\" [, \"name\"=\"value\"]*}'.\nThe 'name' portion must be unique.\nTo add no tags, enter '{}'. This is OPTIONAL and defaults to an empty string map." + type = map(string) + default = {} +} + +variable "hpcc_user_ip_cidr_list" { + description = "OPTIONAL. List of additional CIDR addresses that can access this HPCC Systems cluster.\nDefault value is '[]' which means no CIDR addresses.\nTo open to the internet, add \"0.0.0.0/0\"." + type = list(string) + default = [] +} + +variable "hpcc_version" { + description = "The version of HPCC Systems to install.\nOnly versions in nn.nn.nn format are supported. Default is 'latest'" + type = string + validation { + condition = (var.hpcc_version == "latest") || can(regex("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(-rc\\d{1,3})?$", var.hpcc_version)) + error_message = "Value must be 'latest' OR in nn.nn.nn format and 8.6.0 or higher." + } + default = "latest" +} + +variable "storage_data_gb" { + type = number + description = "REQUIRED. The amount of storage reserved for data in gigabytes.\nMust be 10 or more.\nIf a storage account is defined (see below) then this value is ignored." + validation { + condition = var.storage_data_gb >= 10 + error_message = "Value must be 10 or more." + } + default = 100 +} + +variable "storage_lz_gb" { + type = number + description = "REQUIRED. The amount of storage reserved for the landing zone in gigabytes.\nMust be 1 or more.\nIf a storage account is defined (see below) then this value is ignored." + validation { + condition = var.storage_lz_gb >= 1 + error_message = "Value must be 1 or more." + } + default = 25 +} + +variable "thor_max_jobs" { + type = number + description = "REQUIRED. The maximum number of simultaneous Thor jobs allowed.\nMust be 1 or more." + validation { + condition = var.thor_max_jobs >= 1 + error_message = "Value must be 1 or more." + } + default = 1 +} + +variable "thor_num_workers" { + type = number + description = "REQUIRED. The number of Thor workers to allocate.\nMust be 1 or more." + validation { + condition = var.thor_num_workers >= 1 + error_message = "Value must be 1 or more." + } + default = 2 +} + +############################################################################### +# Optional variables +############################################################################### + +variable "authn_htpasswd_filename" { + type = string + description = "OPTIONAL. If you would like to use htpasswd to authenticate users to the cluster, enter the filename of the htpasswd file. This file should be uploaded to the Azure 'dllsshare' file share in order for the HPCC processes to find it.\nA corollary is that persistent storage is enabled.\nAn empty string indicates that htpasswd is not to be used for authentication.\nExample entry: htpasswd.txt" + default = "" +} + +variable "enable_premium_storage" { + type = bool + description = "OPTIONAL. If true, premium ($$$) storage will be used for the following storage shares: Dali.\nDefaults to false." + default = false +} diff --git a/lite.auto.tfvars.example b/lite.auto.tfvars.example new file mode 100644 index 0000000..db412a2 --- /dev/null +++ b/lite.auto.tfvars.example @@ -0,0 +1,262 @@ +#----------------------------------------------------------------------------- + +# Name of the A record, of following dns zone, where the ecl watch ip is placed +# This A record will be created and therefore should not exist in the following +# dns zone. +# Example entry: "my-product". This should be something project specific rather +# than something generic. +# Value type: string +# Updatable: Y (Y means YES, is updatable) + +a_record_name="" + +#----------------------------------------------------------------------------- + +# Name of an existing dns zone. +# Example entry: "hpcczone.us-hpccsystems-dev.azure.lnrsg.io" +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_dns_zone_name="" + +#----------------------------------------------------------------------------- + +# Name of the resource group of the above dns zone. +# Example entry: "app-dns-prod-eastus2" +# Value type: string +# Updatable: N (N means NO, not updatable) + + +aks_dns_zone_resource_group_name="" + +#------------------------------------------------------------------------------ + +# The version of HPCC Systems to install. +# Only versions in nn.nn.nn format the 'latest' are supported. +# Value type: string +# Updatable: Y (Y means YES, is updatable) + +hpcc_version="latest" + +#------------------------------------------------------------------------------ + +# Enable ROXIE? +# This will also expose port 18002 on the cluster. +# Example entry: false +# Value type: boolean +# Updatable: Y (Y means YES, is updatable) + +aks_enable_roxie=false + +#------------------------------------------------------------------------------ + +# Enable code security? +# If true, only signed ECL code will be allowed to create embedded language functions, use PIPE(), etc. +# Example entry: false +# Value type: boolean +# Updatable: Y (Y means YES, is updatable) + +enable_code_security=false + +#------------------------------------------------------------------------------ + +# If you want a thor cluster then 'enable_thor' must be set to true +# Otherwise it is set to false +# Value type: boolean +# Updatable: Y (Y means YES, is updatable) + +enable_thor=true + +#------------------------------------------------------------------------------ + +# The number of Thor workers to allocate. +# Must be 1 or more. +# Value type: number +# Updatable: Y (Y means YES, is updatable) + +thor_num_workers=2 + +#------------------------------------------------------------------------------ + +# The maximum number of simultaneous Thor jobs allowed. +# Must be 1 or more. +# Value type: number +# Updatable: Y (Y means YES, is updatable) + +thor_max_jobs=1 + +#------------------------------------------------------------------------------ + +# The amount of storage reserved for the landing zone in gigabytes. +# Must be 1 or more. +# If a storage account is defined (see below) then this value is ignored. +# Value type: number +# Updatable: Y (Y means YES, is updatable) + +storage_lz_gb=25 + +#------------------------------------------------------------------------------ + +# The amount of storage reserved for data in gigabytes. +# Must be 1 or more. +# If a storage account is defined (see below) then this value is ignored. +# Value type: number +# Updatable: Y (Y means YES, is updatable) + +storage_data_gb=100 + +#------------------------------------------------------------------------------ + +# Map of name => value tags that can will be associated with the cluster. +# Format is '{"name"="value" [, "name"="value"]*}'. +# The 'name' portion must be unique. +# To add no tags, use '{}'. +# Value type: map of string +# Updatable: Y (Y means YES, is updatable) + +extra_tags={} + +#------------------------------------------------------------------------------ + +# The VM size for each roxie node in the HPCC Systems node pool. +# Possible values are: large, xlarge, 2xlarge, and 4xlarge +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_roxie_node_size = "xlarge" + +#------------------------------------------------------------------------------ + +# The VM size for each serv node in the HPCC Systems node pool. +# Possible values are: large, xlarge, 2xlarge, and 4xlarge +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_serv_node_size = "2xlarge" + +#------------------------------------------------------------------------------ + +# The VM size for each spray node in the HPCC Systems node pool. +# Possible values are: large, xlarge, 2xlarge, and 4xlarge +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_spray_node_size = "large" + +#------------------------------------------------------------------------------ + +# The VM size for each thor node in the HPCC Systems node pool. +# Possible values are: large, xlarge, 2xlarge, and 4xlarge +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_thor_node_size = "xlarge" + +#------------------------------------------------------------------------------ + +# Email address of the administrator of this HPCC Systems cluster. +# Example entry: "jane.doe@hpccsystems.com" +# Value type: string +# Updatable: Y (Y means YES, is updatable) + +aks_admin_email="jane.doe@hpccsystems.com" + +#------------------------------------------------------------------------------ + +# Name of the administrator of this HPCC Systems cluster. +# Example entry: "Jane Doe" +# Value type: string +# Updatable: Y (Y means YES, is updatable) + +aks_admin_name="Jane Doe" + +#------------------------------------------------------------------------------ + +# Username of the administrator of this HPCC Systems cluster. +# Example entry: "jdoe" +# Value type: string +# Updatable: N (N means NO, not updatable) + +admin_username="jdoe" + +#------------------------------------------------------------------------------ + +# The Azure region abbreviation in which to create these resources. +# Example entry: "eastus" +# Value type: string +# Updatable: N (N means NO, not updatable) + +aks_azure_region="eastus" + +#------------------------------------------------------------------------------ + +# Map of name => CIDR IP addresses that can administrate this AKS. +# Format is '{"name"="cidr" [, "name"="cidr"]*}'. +# The 'name' portion must be unique. +# To add no CIDR addresses, use '{}'. +# The corporate network and your current IP address will be added automatically, and these addresses will have access to the HPCC cluster as a user. +# Value type: map of string +# Updatable: Y (Y means YES, is updatable) + +aks_admin_ip_cidr_map={} + +#------------------------------------------------------------------------------ + +# List of explicit CIDR addresses that can access this HPCC Systems cluster. +# To allow public access, set value to ["0.0.0.0/0"] or []. +# Value type: list of string +# Updatable: Y (Y means YES, is updatable) + +hpcc_user_ip_cidr_list=[] + +#------------------------------------------------------------------------------ + +# If you would like to use htpasswd to authenticate users to the cluster, enter +# the filename of the htpasswd file. This file should be uploaded to the Azure +# 'dllsshare' file share in order for the HPCC processes to find it. +# A corollary is that persistent storage is enabled. +# An empty string indicates that htpasswd is not to be used for authentication. +# Example entry: "htpasswd.txt" +# Value type: string +# Updatable: Y (Y means YES, is updatable) + +authn_htpasswd_filename="" + +#------------------------------------------------------------------------------ + +# If 'aks_4nodepools` is true then 4 nodepools are used. Otherwise only 1 is +# used. Using 4 nodepools increases multi-processing and the cost. +# Value type: boolean +# Updatable: N (Y means YES, is updatable) + +aks_4nodepools=false + +#------------------------------------------------------------------------------ + +# If you want external storage instead of ephemeral storage then +# set this variable to true otherwise set it to false. +# Value type: boolean +# Updatable: Y (Y means YES, is updatable) + +external_storage_desired=false + +#------------------------------------------------------------------------------ + +# This variable enable you to ask for logging and monitoring of the kubernetes +# and hpcc cluster (true means enable logging and monitoring, false means don't. +# Value type: boolean +# Updatable: N (N means NO, not updatable) + +aks_logging_monitoring_enabled=false + +#------------------------------------------------------------------------------ + +# Your azure account object id. Find this on azure portal, by going to 'users' +# then search for your name and click on it. The account object id is called +# 'Object ID'. There is a link next to it that lets you copy it. +# Value type: string +# Updatable: N (N means NO, not updatable) + +my_azure_id="" + +#------------------------------------------------------------------------------ diff --git a/logging/LICENSE b/logging/LICENSE deleted file mode 100644 index f596f91..0000000 --- a/logging/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 HPCC Systems® - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall 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. diff --git a/logging/data.tf b/logging/data.tf deleted file mode 100644 index 5584491..0000000 --- a/logging/data.tf +++ /dev/null @@ -1,2 +0,0 @@ -data "azurerm_subscription" "current" { -} diff --git a/logging/elastic4hpcc.auto.tfvars.example b/logging/elastic4hpcc.auto.tfvars.example deleted file mode 100644 index e7672ed..0000000 --- a/logging/elastic4hpcc.auto.tfvars.example +++ /dev/null @@ -1 +0,0 @@ -elastic4hpcclogs = {} diff --git a/logging/locals.tf b/logging/locals.tf deleted file mode 100644 index 0e4a7bc..0000000 --- a/logging/locals.tf +++ /dev/null @@ -1,5 +0,0 @@ -locals { - tags = merge(var.metadata.additional_tags, { "owner" = var.owner.name, "owner_email" = var.owner.email }) - get_aks_config = fileexists("../aks/data/config.json") ? jsondecode(file("../aks/data/config.json")) : null - hpcc_namespace = var.hpcc.existing_namespace != null ? var.hpcc.existing_namespace : var.hpcc.create_namespace == true ? kubernetes_namespace.hpcc[0].metadata[0].name : "default" -} diff --git a/logging/log_analytics.auto.tfvars.example b/logging/log_analytics.auto.tfvars.example deleted file mode 100644 index 24a7787..0000000 --- a/logging/log_analytics.auto.tfvars.example +++ /dev/null @@ -1,15 +0,0 @@ -azure_log_analytics_workspace = { - name = "my-hpcc-log-analytics-workspace" - internet_query_enabled = true - internet_ingestion_enabled = true - tags = { - "app" = "hpcc" - } -} - -azure_log_analytics_creds = { - AAD_CLIENT_ID = "" - AAD_CLIENT_SECRET = "" - AAD_PRINCIPAL_ID = "" - AAD_TENANT_ID = "" -} diff --git a/logging/logging.tf b/logging/logging.tf deleted file mode 100644 index e6fec02..0000000 --- a/logging/logging.tf +++ /dev/null @@ -1,47 +0,0 @@ -module "logging" { - source = "github.com/gfortil/terraform-azurerm-hpcc-logging.git?ref=HPCC-29420" - - azure_log_analytics_workspace = var.azure_log_analytics_workspace != null ? { - unique_name = true - daily_quota_gb = var.azure_log_analytics_workspace.daily_quota_gb - internet_ingestion_enabled = var.azure_log_analytics_workspace.internet_ingestion_enabled - internet_query_enabled = var.azure_log_analytics_workspace.internet_query_enabled - location = var.location - name = var.azure_log_analytics_workspace.name - resource_group_name = module.resource_group.name - reservation_capacity_in_gb_per_day = var.azure_log_analytics_workspace.reservation_capacity_in_gb_per_day - retention_in_days = var.azure_log_analytics_workspace.retention_in_days - sku = var.azure_log_analytics_workspace.sku - use_existing_workspace = var.azure_log_analytics_workspace.use_existing_workspace - tags = merge(local.tags, var.azure_log_analytics_workspace.tags) - } : null - - // Should be set as an environment variable or stored in a key vault - azure_log_analytics_creds = var.azure_log_analytics_creds - - hpcc = { - namespace = local.hpcc_namespace - version = var.hpcc.version - } - - elastic4hpcclogs = var.azure_log_analytics_workspace == null ? { - internet_enabled = var.elastic4hpcclogs.internet_enabled - name = var.elastic4hpcclogs.name - atomic = var.elastic4hpcclogs.atomic - recreate_pods = var.elastic4hpcclogs.recreate_pods - reuse_values = var.elastic4hpcclogs.reuse_values - reset_values = var.elastic4hpcclogs.reset_values - force_update = var.elastic4hpcclogs.force_update - cleanup_on_fail = var.elastic4hpcclogs.cleanup_on_fail - disable_openapi_validation = var.elastic4hpcclogs.disable_openapi_validation - max_history = var.elastic4hpcclogs.max_history - wait = var.elastic4hpcclogs.wait - dependency_update = var.elastic4hpcclogs.dependency_update - timeout = var.elastic4hpcclogs.timeout - wait_for_jobs = var.elastic4hpcclogs.wait_for_jobs - lint = var.elastic4hpcclogs.lint - remote_chart = var.elastic4hpcclogs.remote_chart - local_chart = var.elastic4hpcclogs.local_chart - version = var.elastic4hpcclogs.version - } : null -} diff --git a/logging/main.tf b/logging/main.tf deleted file mode 100644 index 40948c2..0000000 --- a/logging/main.tf +++ /dev/null @@ -1,49 +0,0 @@ -module "subscription" { - source = "github.com/Azure-Terraform/terraform-azurerm-subscription-data.git?ref=v1.0.0" - subscription_id = data.azurerm_subscription.current.subscription_id -} - -module "naming" { - source = "github.com/Azure-Terraform/example-naming-template.git?ref=v1.0.0" -} - -module "metadata" { - source = "github.com/Azure-Terraform/terraform-azurerm-metadata.git?ref=v1.5.1" - - naming_rules = module.naming.yaml - - market = var.metadata.market - location = var.location - sre_team = var.metadata.sre_team - environment = var.metadata.environment - product_name = var.metadata.product_name - business_unit = var.metadata.business_unit - product_group = var.metadata.product_group - subscription_type = var.metadata.subscription_type - resource_group_type = var.metadata.resource_group_type - subscription_id = data.azurerm_subscription.current.subscription_id - project = var.metadata.project -} - -module "resource_group" { - source = "github.com/Azure-Terraform/terraform-azurerm-resource-group.git?ref=v2.0.0" - - unique_name = true - location = var.location - names = module.metadata.names - tags = local.tags -} - -resource "kubernetes_namespace" "hpcc" { - count = var.hpcc.create_namespace ? 1 : 0 - - metadata { - annotations = { - description = "Created by the logging module." - } - - labels = var.hpcc.labels - - generate_name = "${trimspace(var.owner.name)}" - } -} diff --git a/logging/misc.auto.tfvars.example b/logging/misc.auto.tfvars.example deleted file mode 100644 index 1c62736..0000000 --- a/logging/misc.auto.tfvars.example +++ /dev/null @@ -1,25 +0,0 @@ -owner = { - name = "demo" - email = "demo@lexisnexisrisk.com" -} - -metadata = { - project = "hpccdemo" - product_name = "aks" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "contoso" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - additional_tags = { "justification" = "testing", "enclosed resource" = "open source logs" } -} - -location = "eastus2" - -hpcc = { - # existing_namespace = "" - version = "9.2.12-rc1" - create_namespace = true -} diff --git a/logging/outputs.tf b/logging/outputs.tf deleted file mode 100644 index 6fc8231..0000000 --- a/logging/outputs.tf +++ /dev/null @@ -1,36 +0,0 @@ -output "logaccess_body" { - description = "logaccess configuration to apply to the HPCC helm deployment." - value = module.logging.logaccess_body -} - -output "workspace_resource_id" { - description = "The resource ID of the workspace" - value = module.logging.workspace_resource_id -} - -output "workspace_id" { - description = "The Azure Analytics Workspace ID" - value = module.logging.workspace_id -} - -output "hpcc_namespace" { - description = "The namespace where the Kubernetes secret has been created and in which HPCC must be deployed." - value = var.hpcc.create_namespace ? kubernetes_namespace.hpcc[0].metadata[0].name : var.hpcc.namespace_prefix -} - -resource "local_file" "logaccess_body" { - content = module.logging.logaccess_body - filename = "${path.module}/data/logaccess_body.yaml" -} - -resource "local_file" "workspace_resource_id" { - content = module.logging.workspace_resource_id - filename = "${path.module}/data/workspace_resource_id.txt" -} - -resource "local_file" "hpcc_namespace" { - count = var.hpcc.create_namespace ? 1 : 0 - - content = var.hpcc.create_namespace ? kubernetes_namespace.hpcc[0].metadata[0].name : var.hpcc.namespace_prefix - filename = "${path.module}/data/hpcc_namespace.txt" -} diff --git a/logging/providers.tf b/logging/providers.tf deleted file mode 100644 index 3af0a7d..0000000 --- a/logging/providers.tf +++ /dev/null @@ -1,33 +0,0 @@ -provider "azurerm" { - features {} - use_cli = true -} - -provider "http" {} - -provider "helm" { - alias = "default" - - kubernetes { - host = module.aks.cluster_endpoint - cluster_ca_certificate = base64decode(module.aks.cluster_certificate_authority_data) - - exec { - api_version = "client.authentication.k8s.io/v1beta1" - command = "kubelogin" - args = ["get-token", "--server-id", "6dae42f8-4368-4678-94ff-3960e28e3630", "--login", "azurecli"] - env = local.azure_auth_env - } - } - - experiments { - manifest = true - } -} - -provider "kubernetes" { - host = local.get_aks_config.kube_admin_config[0].host - client_certificate = base64decode(local.get_aks_config.kube_admin_config[0].client_certificate) - client_key = base64decode(local.get_aks_config.kube_admin_config[0].client_key) - cluster_ca_certificate = base64decode(local.get_aks_config.kube_admin_config[0].cluster_ca_certificate) -} diff --git a/logging/variables.tf b/logging/variables.tf deleted file mode 100644 index bd35a38..0000000 --- a/logging/variables.tf +++ /dev/null @@ -1,116 +0,0 @@ -variable "owner" { - description = "Information for the user who administers the deployment." - type = object({ - name = string - email = string - }) - - validation { - condition = try( - regex("hpccdemo", var.owner.name) != "hpccdemo", true - ) && try( - regex("hpccdemo", var.owner.email) != "hpccdemo", true - ) && try( - regex("@example.com", var.owner.email) != "@example.com", true - ) - error_message = "Your name and email are required in the owner block and must not contain hpccdemo or @example.com." - } -} - -variable "metadata" { - description = "Metadata module variables." - type = object({ - market = string - sre_team = string - environment = string - product_name = string - business_unit = string - product_group = string - subscription_type = string - resource_group_type = string - project = string - additional_tags = optional(map(string)) - }) - - nullable = false -} - -variable "location" { - description = "Azure location" - type = string - - default = "eastus" -} - -variable "azure_log_analytics_workspace" { - description = "Azure log analytics workspace attributes" - type = object({ - unique_name = optional(bool) - name = string - daily_quota_gb = optional(number) - internet_ingestion_enabled = optional(bool) - internet_query_enabled = optional(bool) - reservation_capacity_in_gb_per_day = optional(number) - retention_in_days = optional(number) - sku = optional(string) - tags = optional(map(string)) - use_existing_workspace = optional(object({ - name = string - resource_group_name = string - })) - }) - - default = null -} - -variable "azure_log_analytics_creds" { - description = "Credentials for the Azure log analytics workspace" - type = object({ - AAD_TENANT_ID = string - AAD_CLIENT_ID = string - AAD_CLIENT_SECRET = string - AAD_PRINCIPAL_ID = string - - }) - - sensitive = true - default = null -} - -variable "hpcc" { - description = "HPCC Platform attributes" - type = object({ - version = optional(string, "latest") - existing_namespace = optional(string) - labels = optional(object({ name = string }), { name = "hpcc" }) - create_namespace = optional(bool, false) - }) - - nullable = false -} - -variable "elastic4hpcclogs" { - description = "The attributes for elastic4hpcclogs." - type = object({ - internet_enabled = optional(bool, true) - name = optional(string, "myelastic4hpcclogs") - atomic = optional(bool) - recreate_pods = optional(bool) - reuse_values = optional(bool) - reset_values = optional(bool) - force_update = optional(bool) - cleanup_on_fail = optional(bool) - disable_openapi_validation = optional(bool) - max_history = optional(number) - wait = optional(bool, true) - dependency_update = optional(bool, true) - timeout = optional(number, 300) - wait_for_jobs = optional(bool) - lint = optional(bool) - remote_chart = optional(string, "https://hpcc-systems.github.io/helm-chart") - local_chart = optional(string) - version = optional(string, "latest") - }) - - default = null -} diff --git a/logging/versions.tf b/logging/versions.tf deleted file mode 100644 index e5a15eb..0000000 --- a/logging/versions.tf +++ /dev/null @@ -1,15 +0,0 @@ -terraform { - required_version = ">= 1.4.6" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = ">= 3.63.0" - } - - http = { - source = "hashicorp/http" - version = ">=3.2.1" - } - } -} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..16fba90 --- /dev/null +++ b/main.tf @@ -0,0 +1,45 @@ +resource "null_resource" "deploy_vnet" { + + provisioner "local-exec" { + command = "scripts/deploy vnet" + } +} + +resource "null_resource" "deploy_aks" { + + provisioner "local-exec" { + command = "scripts/deploy aks ${var.my_azure_id}" + } + + depends_on = [ null_resource.deploy_vnet ] +} + +resource "null_resource" "deploy_storage" { + count = (var.external_storage_desired == true)? 1 : 0 + + provisioner "local-exec" { + command = "scripts/deploy storage" + } + + depends_on = [ null_resource.deploy_vnet, null_resource.deploy_aks ] +} + +# if external storage is desired, this resource makes sure it exists. 'deploy_hpcc' depends on this. +resource "null_resource" "external_storage" { + count = (var.external_storage_desired == true)? 1 : 0 + + provisioner "local-exec" { + command = "scripts/external_storage ${path.module} ${var.external_storage_desired}" + } + + depends_on = [ null_resource.deploy_vnet ] +} + +resource "null_resource" "deploy_hpcc" { + + provisioner "local-exec" { + command = "scripts/deploy hpcc" + } + + depends_on = [ null_resource.deploy_aks, null_resource.deploy_vnet, null_resource.external_storage, null_resource.deploy_storage ] +} diff --git a/providers.tf b/providers.tf new file mode 100644 index 0000000..e27a382 --- /dev/null +++ b/providers.tf @@ -0,0 +1,5 @@ +provider "azurerm" { + features {} + use_cli = true + storage_use_azuread = true +} diff --git a/scripts/deploy b/scripts/deploy new file mode 100755 index 0000000..97bfb8b --- /dev/null +++ b/scripts/deploy @@ -0,0 +1,126 @@ +#!/bin/bash +thisdir=$(pwd)/$(dirname $0) +repodir=$(echo $thisdir|sed "s/\/scripts\/*//") +if [ "$1" != "" ] && [[ $1 =~ hpcc|aks|vnet|storage ]];then + name=$1 + if [ "$name" == "aks" ];then + if [ "$2" != "" ];then + my_azure_id=$2 + echo "Second argument, i.e. \$2(or my_azure_id)=\"$2\"" + else + echo "ERROR: name=\"$name\". Need a 2nd argument (my_azure_id) but none given.";exit 1; + fi + fi +else + echo "$0 has no arguments. It must of 1 argument that is 'vnet' or 'storage' or 'aks' or 'hpcc'. EXITING.";exit 1; +fi +if [ "$1" == "aks" ];then + my_azure_id=$2 + cp -v $thisdir/needed-auto-tfvars-files/aks/aks.auto.tfvars.example $repodir/aks/aks.auto.tfvars + cp -v $thisdir/needed-auto-tfvars-files/aks/misc.auto.tfvars.example $repodir/aks/misc.auto.tfvars + sed -i "s//$my_azure_id/" $repodir/aks/aks.auto.tfvars +fi +#======================================================================== +function assert_fail () { + echo ">>>>>>>>>>>>>>> EXECUTING: $*" + if "$@"; then + echo;echo ">>>>>>>>>>>>>>> Successful: $*";echo + else + echo;echo ">>>>>>>>>>>>>>> FAILED: $*. EXITING!";echo + rm -vrf data + cd $repodir + rm *.tfstate*;rm .terraform.lock.hcl ;sudo rm -r .terraform + exit 1 + fi +} +#======================================================================== +# If kubernetes cluster doesn't exist then make sure aks/data/config.json +# and hpcc/data/config.json doesn't exist +# Delete both hpcc/data and aks/data if kubernetes cluster doesn't exist +ns=$(kubectl get ns 2>&1|egrep -v NAME|sed "s/ *.*$//") +pods=$(kubectl get pods 2>&1) +if [[ "$ns" == *"Unable"* ]];then # kubenetes doesn't exist of there are no namespaces + rm -vrf hpcc/data;cd hpcc; rm *.tfstate*;rm .terraform.lock.hcl ;sudo rm -r .terraform;cd .. + rm -vrf aks/data;cd aks; rm *.tfstate*;rm .terraform.lock.hcl ;sudo rm -r .terraform;cd .. +# If kubernetes cluster does exist but there are no pods in the default namespace +# then delete only hpcc/data +elif [[ "$pods" == *"Unable"* ]] || [[ "$pods" == *"No resources found in default namespace"* ]];then + # force rm data/config.json in hpcc only + echo "Forcibly delete hpcc/data only" + rm -vrf hpcc/data;cd hpcc; rm *.tfstate*;rm .terraform.lock.hcl ;sudo rm -r .terraform;cd .. +fi +#------------------------------------------------------------------------ +# See if $dir/data/config.json exists, where $dir is vnet or aks or storage. +# If $dir/data/config.json does exist then from the file get +# the resource group name and then check to see if resource group exists. +# if it doesn't exists then delete $dir/data/config.json +#------------------------------------------------------------------------ +for dir in aks vnet storage;do + if [ -e "$dir/data/config.json" ];then + # Get resource group name from file + rg=$($thisdir/get_rg_from_file $dir/data/config.json) + rgexist=$(az group exists --name $rg) + if [ "$rgexist" == "false" ]; then + echo "In $0. $dir resource group, \"$rg\" does not exists. So deleting vnet/data and any tfstate files id $dir." + rm -vrf $dir/data + cd $dir; rm *.tfstate*;rm .terraform.lock.hcl ;sudo rm -r .terraform;cd .. + else + echo "In $0. $dir resource group, \"$rg\" DOES exists. So NOT deleting vnet/data." + fi + fi +done +#------------------------------------------------------------------------ + +cd $name; # cd into vnet or storage or aks or hpcc + +echo "Copy metadata.tf in root directory to this directory." +cp -v ../scripts/needed-auto-tfvars-files/metadata.tf . +if [ "$name" == "storage" ];then + sed -i "s/#additional_tags/additional_tags/" metadata.tf +fi + +# put the root directory's lite.auto.tfvars (either all or part) in either aks or hpcc +# directory. +if [ -e "../lite.auto.tfvars" ];then + # Check if there has been a change since last apply. + if [ -e "/tmp/${name}.lite.auto.tfvars" ];then + tfvarsdiff=$(diff /tmp/${name}.lite.auto.tfvars ../lite.auto.tfvars) + else + tfvarsdiff="" + fi +else + echo "In $0. The root directory does not have a file called 'lite.aute.tfvars'. It must. EXITING";exit 1; +fi +if [ "$name" == "hpcc" ];then + echo "Coping root's lite.auto.tfvars to /tmp and $name directory. Also, coping root's lite-locals.tf and lite-variables.tf to $name directory." + cp -v ../lite.auto.tfvars /tmp/${name}.lite.auto.tfvars + cp -v ../lite.auto.tfvars . + cp -v ../lite-locals.tf . + cp -v ../lite-variables.tf . +elif [ "$name" == "aks" ] || [ "$name" == "vnet" ] || [ "$name" == "storage" ];then + ../scripts/extract-aks-tfvars ../lite.auto.tfvars > /tmp/${name}.lite.auto.tfvars + ../scripts/extract-aks-tfvars ../lite.auto.tfvars > lite.auto.tfvars + ../scripts/extract-aks-variables ../lite-variables.tf > lite-variables.tf + if [ "$name" == "storage" ];then + cp -v $thisdir/needed-auto-tfvars-files/storage/storage.auto.tfvars.example ./storage.auto.tfvars + fi +fi +#------------------------------------------------------------------------ +if [ ! -d "$HOME/tflogs" ];then + mkdir $HOME/tflogs +fi + +plan=$($thisdir/mkplan deploy_${name}.plan) + +if [ "$tfvarsdiff" == "" ] && [ -d "data" ] && [ -f "data/config.json" ]; then echo "Complete! $name is already deployed";exit 0; fi + +echo "=============== Deploy $name. Executing 'terraform init' ==============="; +assert_fail terraform init +echo "=============== Deploy $name. Executing 'terraform plan -out=$plan' ==============="; +assert_fail terraform plan -out=$plan +if [ -e "$plan" ];then + echo "=============== Deploy $name. Executing 'terraform apply $plan' ==============="; + assert_fail terraform apply -auto-approve $plan +else + echo "@@@@@@@@@@ No changes. Your infrastructure matches the configuration. So, terraform apply for $name will not be done. @@@@@@@@@@" +fi diff --git a/scripts/destroy b/scripts/destroy new file mode 100755 index 0000000..b1bd96c --- /dev/null +++ b/scripts/destroy @@ -0,0 +1,39 @@ +#!/bin/bash +thisdir=$(d=$(dirname $0);cd $d;pwd) +repodir=$(echo $thisdir|sed "s/\/scripts//") +#======================================================================== +function assert_fail () { + echo ">>>>>>>>>>>>>>>>>>> EXECUTING: $*" + if "$@"; then + echo;echo ">>>>>>>>>>>>>>>>>>> Successful: $*";echo + else + echo;echo ">>>>>>>>>>>>>>>>>>> FAILED: $*. EXITING!";echo + rm -vrf data + exit 1 + fi +} +#======================================================================== + +if [ "$1" == "vnet" ];then + assert_fail scripts/destroy hpcc + assert_fail scripts/destroy aks +elif [ "$1" == "aks" ];then + assert_fail scripts/destroy hpcc +fi +cd $repodir/$1; +name=$(basename $(pwd)) +if [ "$name" == "hpcc" ];then + assert_fail kubectl delete pods --all --force +fi +if [ ! -d "$HOME/tflogs" ];then + mkdir $HOME/tflogs +fi +plan=$($thisdir/mkplan ${name}_destroy.plan) +if [ ! -d "data" ] || [ ! -f "data/config.json" ]; then echo "$name is already destroyed";exit 0; fi + +echo "=============== Destroying $name. Executing 'terraform destroy' ==============="; +assert_fail terraform destroy -auto-approve +rm -vr data +cd .. +r=$(terraform state list|egrep "_$name") +terraform state rm $r diff --git a/scripts/external_storage b/scripts/external_storage new file mode 100755 index 0000000..3334373 --- /dev/null +++ b/scripts/external_storage @@ -0,0 +1,15 @@ +#!/bin/bash +repopath=$1 +external_storage_desired=$2 + +if [ "$external_storage_desired" == "false" ];then + #echo "DEBUG: EXITING because ignore_external_storage is true." + exit 0 +else + #echo "DEBUG: EXITING because ignore_external_storage is NOT true." + while [ ! -e "$repopath/storage/data/config.json" ];do + echo "This file does not exist, yet: $repopath/storage/data/config.json" + sleep 20; + done + exit 0; +fi diff --git a/scripts/extract-aks-tfvars b/scripts/extract-aks-tfvars new file mode 100755 index 0000000..6e332e8 --- /dev/null +++ b/scripts/extract-aks-tfvars @@ -0,0 +1,43 @@ +#!/bin/bash +# USAGE: scripts/extract-aks-tfvars lite.auto.tfvars +declare -A endbracket; +endbracket["{"]="}"; +endbracket["["]="]"; +if [ $# -le 0 ];then + echo "FATAL ERROR: $0: lite.auto.tfvars file name must be given on command line" + exit 1 +fi +tfvarsfile=$1; +while read line;do + re1='(aks_[A-Za-z0-9_][A-Za-z0-9_]* *= *)(..*)' + if [[ "$line" =~ ^$re1 ]];then + if [ "$var_plus_equal_plus_value" != "" ];then + echo $var_plus_equal_plus_value; + endbrack=""; + var_plus_equal_plus_value=""; + fi + var_plus_equal=${BASH_REMATCH[1]} + val=${BASH_REMATCH[2]} + var_plus_equal_plus_value="$var_plus_equal$val"; + re2='\([\{\[]\)' + result=$(echo $val|sed "s/$re2 *$/\1/") + #echo "DEBUG: var_plus_equal={$var_plus_equal}, val={$val}, result={$result}" + if [ "$result" == "{" ] || [ "$result" == "[" ];then + endbrack=${endbracket[$result]} + #echo "DEBUG: result is either '{' or '[': {$result}, endbrack={$endbrack}" + else + echo $var_plus_equal_plus_value; + fi + elif [ "$endbrack" == "}" ] || [ "$endbrack" == "]" ];then + var_plus_equal_plus_value="$var_plus_equal_plus_value $line"; + if [[ "$line" =~ "$endbrack" ]];then + echo $var_plus_equal_plus_value; + endbrack=""; + var_plus_equal_plus_value=""; + fi + else + endbrack=""; + var_plus_equal_plus_value=""; + fi + #echo "DEBUG: End of while read" +done <$tfvarsfile diff --git a/scripts/extract-aks-variables b/scripts/extract-aks-variables new file mode 100755 index 0000000..30d105e --- /dev/null +++ b/scripts/extract-aks-variables @@ -0,0 +1,9 @@ +#!/bin/bash +if [ $# -gt 0 ];then + variable_file=$1 +else + echo "FATAL ERROR: Variable file name must be given on command line" + exit 1 +fi + +sed '/#===== end of aks variables =====/q' $variable_file diff --git a/scripts/get_rg_from_file b/scripts/get_rg_from_file new file mode 100755 index 0000000..334b506 --- /dev/null +++ b/scripts/get_rg_from_file @@ -0,0 +1,13 @@ +#!/bin/bash +if [ $# -gt 0 ];then + config_file=$1 +else + echo "FATAL ERROR: In $0. Config file path must be given on command line" + exit 1 +fi + +rg=$(sed "/\"resource_group\": *\"|\"resource_group_name\": *\"/q" $config_file|sed "s/^.*\"resource_group_name\": *\"//"|sed "s/\".*$//") +if [[ "$rg" != *"hpccplatform"* ]];then + rg=$(sed "/\"resource_group\": *\"|\"resource_group_name\": *\"/q" $config_file|sed "s/^.*\"resource_group\": *\"//"|sed "s/\".*$//") +fi +echo $rg diff --git a/scripts/mkplan b/scripts/mkplan new file mode 100755 index 0000000..8cb4a58 --- /dev/null +++ b/scripts/mkplan @@ -0,0 +1,28 @@ +#!/bin/bash +month_date=$(date -d "$D" '+%Y';date -d "$D" '+%m';date -d "$D" '+%d') +timezone_difference=6 +H=$(date +'%H') +#echo "H=\"$H\", timezone_difference=\"$timezone_difference\"" 1>&2 +if [ $H -le $timezone_difference ];then + H=$((25 - $timezone_difference)); +else + H=$(($H-$timezone_difference)); +fi +#echo "After timezone_difference is subtracted: H=\"$H\"" 1>&2 +printf -v H "%02d" $H +M=$(date +'%M') +printf -v M "%02d" $M +month_date=$(echo $month_date|sed "s/ *//g") +month_date="$month_date-$H$M" +repo_name=""; +if [ $# -gt 0 ];then + repo_name=$1 +else + cdir=$(pwd) + reHOME=$(echo $HOME|sed "s/[/]/./g") + repo_name=$(echo $cdir|sed "s/^$reHOME.//"|sed "s/[/]/-/g") + #echo "DEBUG: No arguments: cdir=\"$cdir\", reHOME=\"$reHOME\", repo_name=\"$repo_name\"" 1>&2 +fi +plan_name="$HOME/tflogs/$repo_name-$month_date.plan" +echo $plan_name + diff --git a/scripts/needed-auto-tfvars-files/aks/aks.auto.tfvars.example b/scripts/needed-auto-tfvars-files/aks/aks.auto.tfvars.example new file mode 100644 index 0000000..cbae554 --- /dev/null +++ b/scripts/needed-auto-tfvars-files/aks/aks.auto.tfvars.example @@ -0,0 +1,19 @@ +cluster_version = "1.26" # latest version +cluster_ordinal = 1 //cluster name suffix +sku_tier = "FREE" +hpcc_log_analytics_enabled = false + +rbac_bindings = { + cluster_admin_users = { + # "service_principal1" = "", + # "user1" = "" + "admin" = "" + } + + cluster_view_users = {} + cluster_view_groups = [] +} + +cluster_endpoint_access_cidrs = ["0.0.0.0/0"] + +availability_zones = [2] diff --git a/scripts/needed-auto-tfvars-files/aks/misc.auto.tfvars.example b/scripts/needed-auto-tfvars-files/aks/misc.auto.tfvars.example new file mode 100644 index 0000000..714bb43 --- /dev/null +++ b/scripts/needed-auto-tfvars-files/aks/misc.auto.tfvars.example @@ -0,0 +1,8 @@ +resource_groups = { # rg + azure_kubernetes_service = { + tags = { "enclosed resource" = "open source aks" } + } +} + +# # auto_connect - Automatically connect to the kubernetes cluster from the host machine. +auto_connect = true diff --git a/scripts/needed-auto-tfvars-files/metadata.tf b/scripts/needed-auto-tfvars-files/metadata.tf new file mode 100644 index 0000000..e04bd52 --- /dev/null +++ b/scripts/needed-auto-tfvars-files/metadata.tf @@ -0,0 +1,15 @@ +locals { + metadata = { + project = format("%shpccplatform", local.owner_name_initials) + product_name = format("%shpccplatform", local.owner_name_initials) + business_unit = "commercial" + environment = "sandbox" + market = "us" + product_group = format("%shpcc", local.owner_name_initials) + resource_group_type = "app" + sre_team = format("%shpccplatform", local.owner_name_initials) + subscription_type = "dev" + location = var.aks_azure_region # Acceptable values: eastus, centralus + #additional_tags = {} + } +} diff --git a/storage/storage.auto.tfvars.example b/scripts/needed-auto-tfvars-files/storage/storage.auto.tfvars.example similarity index 98% rename from storage/storage.auto.tfvars.example rename to scripts/needed-auto-tfvars-files/storage/storage.auto.tfvars.example index fa23ec0..feaec01 100644 --- a/storage/storage.auto.tfvars.example +++ b/scripts/needed-auto-tfvars-files/storage/storage.auto.tfvars.example @@ -1,4 +1,4 @@ -storage_accounts = { +storage_accounts = { # storage account adminsvc1 = { delete_protection = false //Set to false to allow deletion prefix_name = "adminsvc1" diff --git a/storage/locals.tf b/storage/locals.tf index 4e26af1..458572b 100644 --- a/storage/locals.tf +++ b/storage/locals.tf @@ -1,6 +1,12 @@ locals { + owner = { + name = var.aks_admin_name + email = var.aks_admin_email + } + + owner_name_initials = lower(join("",[for x in split(" ",local.owner.name): substr(x,0,1)])) + get_vnet_config = fileexists("../vnet/data/config.json") ? jsondecode(file("../vnet/data/config.json")) : null - # get_aks_config = fileexists("../aks/data/config.json") ? jsondecode(file("../aks/data/config.json")) : null virtual_network = var.virtual_network != null ? var.virtual_network : [ { diff --git a/storage/main.tf b/storage/main.tf index 8fb9353..36c2f84 100644 --- a/storage/main.tf +++ b/storage/main.tf @@ -1,9 +1,9 @@ module "storage" { - source = "github.com/gfortil/terraform-azurerm-hpcc-storage?ref=HPCC-27615" + source = "git@github.com:hpccsystems-solutions-lab/terraform-azurerm-hpcc-storage.git" - owner = var.owner + owner = local.owner disable_naming_conventions = var.disable_naming_conventions - metadata = var.metadata + metadata = local.metadata subnet_ids = local.subnet_ids storage_accounts = var.storage_accounts } diff --git a/storage/misc.auto.tfvars.example b/storage/misc.auto.tfvars.example deleted file mode 100644 index f01112f..0000000 --- a/storage/misc.auto.tfvars.example +++ /dev/null @@ -1,23 +0,0 @@ -owner = { - name = "demo" - email = "demo@lexisnexisrisk.com" -} - -metadata = { - project = "hpccplatform" - product_name = "hpccplatform" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "hpcc" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - additional_tags = { "justification" = "testing" } - location = "eastus" # Acceptable values: eastus, centralus -} - -# disable_naming_conventions = false # true will enforce all the arguments of the metadata block above - -# Provide an existing virtual network deployed outside of this project - diff --git a/storage/outputs.tf b/storage/outputs.tf index 49e6fc4..9e5808a 100644 --- a/storage/outputs.tf +++ b/storage/outputs.tf @@ -1,4 +1,6 @@ resource "local_file" "config" { content = module.storage.config filename = "${path.module}/data/config.json" + + depends_on = [ module.storage ] } diff --git a/storage/providers.tf b/storage/providers.tf index 80eb367..e609c7e 100644 --- a/storage/providers.tf +++ b/storage/providers.tf @@ -5,10 +5,3 @@ provider "azurerm" { } provider "azuread" {} - -# provider "kubernetes" { -# host = local.get_aks_config.kube_admin_config[0].host -# client_certificate = base64decode(local.get_aks_config.kube_admin_config[0].client_certificate) -# client_key = base64decode(local.get_aks_config.kube_admin_config[0].client_key) -# cluster_ca_certificate = base64decode(local.get_aks_config.kube_admin_config[0].cluster_ca_certificate) -# } \ No newline at end of file diff --git a/storage/variables.tf b/storage/variables.tf index 8333e88..e5e3946 100644 --- a/storage/variables.tf +++ b/storage/variables.tf @@ -1,59 +1,9 @@ -variable "owner" { - description = "Information for the user who administers the deployment." - type = object({ - name = string - email = string - }) - - validation { - condition = try( - regex("hpccdemo", var.owner.name) != "hpccdemo", true - ) && try( - regex("hpccdemo", var.owner.email) != "hpccdemo", true - ) && try( - regex("@example.com", var.owner.email) != "@example.com", true - ) - error_message = "Your name and email are required in the owner block and must not contain hpccdemo or @example.com." - } -} - variable "disable_naming_conventions" { description = "Naming convention module." type = bool default = false } -variable "metadata" { - description = "Metadata module variables." - type = object({ - market = string - sre_team = string - environment = string - product_name = string - business_unit = string - product_group = string - subscription_type = string - resource_group_type = string - project = string - additional_tags = map(string) - location = string - }) - - default = { - business_unit = "" - environment = "" - market = "" - product_group = "" - product_name = "hpcc" - project = "" - resource_group_type = "" - sre_team = "" - subscription_type = "" - additional_tags = {} - location = "" - } -} - variable "virtual_network" { description = "Subnet IDs" type = list(object({ diff --git a/vnet/locals.tf b/vnet/locals.tf index 776e751..0f5b365 100644 --- a/vnet/locals.tf +++ b/vnet/locals.tf @@ -1,18 +1,31 @@ locals { + owner = { + name = var.aks_admin_name + email = var.aks_admin_email + } + + owner_name_initials = lower(join("",[for x in split(" ",local.owner.name): substr(x,0,1)])) + + resource_groups = { + virtual_network = { + tags = { "enclosed resource" = "open source vnet" } + } + } + names = var.disable_naming_conventions ? merge( { - business_unit = var.metadata.business_unit - environment = var.metadata.environment - location = var.resource_groups.location - market = var.metadata.market - subscription_type = var.metadata.subscription_type + business_unit = local.metadata.business_unit + environment = local.metadata.environment + location = local.metadata.location + market = local.metadata.market + subscription_type = local.metadata.subscription_type }, - var.metadata.product_group != "" ? { product_group = var.metadata.product_group } : {}, - var.metadata.product_name != "" ? { product_name = var.metadata.product_name } : {}, - var.metadata.resource_group_type != "" ? { resource_group_type = var.metadata.resource_group_type } : {} + local.metadata.product_group != "" ? { product_group = local.metadata.product_group } : {}, + local.metadata.product_name != "" ? { product_name = local.metadata.product_name } : {}, + local.metadata.resource_group_type != "" ? { resource_group_type = local.metadata.resource_group_type } : {} ) : module.metadata.names - tags = merge(var.metadata.additional_tags, { "owner" = var.owner.name, "owner_email" = var.owner.email }) + tags = { "owner" = local.owner.name, "owner_email" = local.owner.email } private_subnet_id = module.virtual_network.aks.hpcc.subnets["private"].id diff --git a/vnet/main.tf b/vnet/main.tf index b64712c..7ff07dd 100644 --- a/vnet/main.tf +++ b/vnet/main.tf @@ -12,23 +12,23 @@ module "metadata" { naming_rules = module.naming.yaml - market = var.metadata.market - location = var.metadata.location - sre_team = var.metadata.sre_team - environment = var.metadata.environment - product_name = var.metadata.product_name - business_unit = var.metadata.business_unit - product_group = var.metadata.product_group - subscription_type = var.metadata.subscription_type - resource_group_type = var.metadata.resource_group_type + market = local.metadata.market + location = local.metadata.location + sre_team = local.metadata.sre_team + environment = local.metadata.environment + product_name = local.metadata.product_name + business_unit = local.metadata.business_unit + product_group = local.metadata.product_group + subscription_type = local.metadata.subscription_type + resource_group_type = local.metadata.resource_group_type subscription_id = data.azurerm_subscription.current.id - project = var.metadata.project + project = local.metadata.project } module "resource_groups" { source = "github.com/Azure-Terraform/terraform-azurerm-resource-group.git?ref=v2.1.0" - for_each = var.resource_groups + for_each = local.resource_groups unique_name = true location = module.metadata.location diff --git a/vnet/misc.auto.tfvars.example b/vnet/misc.auto.tfvars.example deleted file mode 100644 index 1838b44..0000000 --- a/vnet/misc.auto.tfvars.example +++ /dev/null @@ -1,24 +0,0 @@ -owner = { - name = "demo" - email = "demo@lexisnexisrisk.com" -} - -metadata = { - project = "hpccplatform" - product_name = "hpccplatform" - business_unit = "commercial" - environment = "sandbox" - market = "us" - product_group = "hpcc" - resource_group_type = "app" - sre_team = "hpccplatform" - subscription_type = "dev" - additional_tags = { "justification" = "testing" } - location = "eastus" # Acceptable values: eastus, centralus -} - -resource_groups = { - virtual_network = { - tags = { "enclosed resource" = "open source vnet" } - } -} diff --git a/vnet/outputs.tf b/vnet/outputs.tf index 7c79d01..497f99c 100644 --- a/vnet/outputs.tf +++ b/vnet/outputs.tf @@ -1,34 +1,41 @@ output "advisor_recommendations" { + description = "Advisor recommendations or 'none'." value = data.azurerm_advisor_recommendations.advisor.recommendations } output "private_subnet_id" { + description = "ID of private subnet." value = module.virtual_network.aks.hpcc.subnets["private"].id } output "public_subnet_id" { + description = "ID of public subnet." value = module.virtual_network.aks.hpcc.subnets["public"].id } output "route_table_id" { + description = "ID of route table." value = module.virtual_network.aks.hpcc.route_table_id } output "route_table_name" { + description = "Route table name." value = "${module.virtual_network.vnet.resource_group_name}-aks-hpcc-routetable" } output "resource_group_name" { + description = "Virtual network resource group name." value = module.virtual_network.vnet.resource_group_name } output "vnet_name" { + description = "Virtual network name." value = module.virtual_network.vnet.name } resource "local_file" "output" { content = local.config filename = "${path.module}/data/config.json" -} - + depends_on = [ module.virtual_network ] +} diff --git a/vnet/variables.tf b/vnet/variables.tf index fd5d060..4d334a2 100644 --- a/vnet/variables.tf +++ b/vnet/variables.tf @@ -1,66 +1,5 @@ -variable "owner" { - description = "Information for the user who administers the deployment." - type = object({ - name = string - email = string - }) - - validation { - condition = try( - regex("hpccdemo", var.owner.name) != "hpccdemo", true - ) && try( - regex("hpccdemo", var.owner.email) != "hpccdemo", true - ) && try( - regex("@example.com", var.owner.email) != "@example.com", true - ) - error_message = "Your name and email are required in the owner block and must not contain hpccdemo or @example.com." - } -} - variable "disable_naming_conventions" { description = "Naming convention module." type = bool default = false } - -variable "metadata" { - description = "Metadata module variables." - type = object({ - market = string - sre_team = string - environment = string - product_name = string - business_unit = string - product_group = string - subscription_type = string - resource_group_type = string - project = string - additional_tags = map(string) - location = string - }) - - default = { - business_unit = "" - environment = "" - market = "" - product_group = "" - product_name = "hpcc" - project = "" - resource_group_type = "" - sre_team = "" - subscription_type = "" - additional_tags = {} - location = "" - } -} - -variable "resource_groups" { - description = "Resource group module variables." - type = any - - default = { - azure_kubernetes_service = { - tags = { "apps" = "vnet" } - } - } -}